在哪下载免费的英文版网站模板,建站 网站程序有哪些,沧州哪家做网站好,公司网页设计作业下载Part 6#xff1a;条件状态和分支在探讨CPSR时我们已经接触了条件状态。我们通过跳转#xff08;分支#xff09;或者一些只有满足特定条件才执行的指令来控制程序在运行时的执行流。通过CPSR寄存器中的特定bit位来表示条件状态。这些位根据指令每次执行的结果而不断变化。例…Part 6条件状态和分支在探讨CPSR时我们已经接触了条件状态。我们通过跳转分支或者一些只有满足特定条件才执行的指令来控制程序在运行时的执行流。通过CPSR寄存器中的特定bit位来表示条件状态。这些位根据指令每次执行的结果而不断变化。例如比较运算时如果两个数相等那么就置CPSR中的Zero位Z1实际上是因为a - b 0这种情况下就是相等状态。如果第一个数大那么就是大于状态。如果第二个数大就是小于状态。除此之外还有小于等于、大于等于等等。下面的表格列出了可用的条件状态码描述和标志位在下面代码片段中看一下执行条件加法时的实际用法L.global main
main:mov r0, #2 /* 初始化变量 */cmp r0, #3 /* 将R0中的值与3比较负数位置1 */addlt r0, r0, #1 /* 如果上一条比较结果是小于查看CPSR则将R0加1 */cmp r0, #3 /* 将R0中的值再与3比较 零位置1同时负数位重置为0 */addlt r0, r0, #1 /* 如果上一条比较结果是小于查看CPSR则将R0加1 */bx lr第一条cmp指令结果导致CPSR中的负数位置12- 3 -1意思是R0小于R3。因为满足小于条件CPSR中的溢出位不等于负数位V ! N所以接下来的ADDLT指令执行。在执行下一条cmp指令时R0 3。所以清除负数位3 - 3 0负数位清零零位置位Z 1。现在溢出位是0负数位是0不满足小于条件。所以最后一条ADDLT指令不执行R0值保持3不变。Thumb模式下的条件执行我们在介绍指令集的章节讨论了Thumb状态下的不同。具体而言是Thumb-2版本支持条件执行。某些 ARM 处理器版本支持IT指令允许在 Thumb 状态下支持多达4个条件执行指令。参考http://infocenter.arm.com/help/index.jsp?topic/com.arm.doc.dui0552a/BABIJDIC.html。语法IT{x{y{z}}} condcond 指定 IT 块的第一个指令的条件。x 指定 IT 块中第二个指令的条件开关。y 指定 IT 块中第三个指令的条件开关。z 指定 IT 块中第四个指令的条件开关。其实IT指令的结构就是“IF-Then-(Else)”语法都是由字母“T”和“E”构成ITIf-Then下一条指令是条件的ITTIf-Then-Then后两条指令是条件的ITEIf-Then-Else后两条指令是条件的ITTEIf-Then-Then-Else后三条指令是条件的ITTEEIf-Then-Then-Else-Else后四条指令是条件的IT块中的每条指令必须指定相同或逻辑相反的条件后缀。意思是如果使用ITE那么前两个指令必须有相同的后缀而第三个必须是逻辑相反的后缀。下面是 ARM 参考手册中的一些示例说明了这些逻辑ITTE NE ; 接下来的3条指令都是有条件的。
ANDNE R0, R0, R1 ; ANDNE不更新条件标志。
ADDSNE R2, R2, #1 ; ADDSNE更新条件标志。
MOVEQ R2, R3 ; 有条件的移动
ITE GT ; 接下来的2条指令都是有条件的。
ADDGT R1, R0, #55 ; 条件满足大于时进行相加。
ADDLE R1, R0, #48 ; 条件不满足大于时进行相加。
ITTEE EQ ; 接下来的4条指令都是有条件的。
MOVEQ R0, R1 ; 有条件的MOV
ADDEQ R2, R2, #10 ; 有条件的ADD
ANDNE R3, R3, #1 ; 有条件的AND
BNE.W dloop ; 分支指令只能在IT块的最后一个指令中使用。错误示例IT NE ; 下一条指令是条件的。
ADD R0, R0, R1 ; 语法错误不是有条件的指令。下面是条件代码和相反代码现在使用以下代码来测试.syntax unified 非常重要!
.text
.global _start
_start:.code 32add r3, pc, #1 PC的值加1并存储到R3。bx r3 跳转到R3中的地址处并切换运行模式 -切换到Thumb模式因为R3最低有效位LSB 1。
.code 16 Thumb模式cmp r0, #10 ite eq 如果R0等于10...addeq r1, #2 ... 那么 R1 R1 2addne r1, #3 ... 否则 R1 R1 3bkpt.code 32示例中的代码开始在ARM模式下第一条指令将PC中的地址值加1并存储到R3然后bx指令跳转到R3中的地址位置并且模式切换成Thumb模式因为R3中的值最低有效位为10不切换。为此使用bx分支交换非常重要。.code 16在Thumb模式下首先比较R0和10结果将负数位N置位0 - 10 -10。之后使用If-Then-Else块因为零位ZZero没有被置位所以ADDEQ指令被跳过然后因为结果不相等所以执行ADDNE指令。在 GDB 中单步执行此代码会干扰结果因为你要在 ITE 块中执行这两个指令。 但是在 GDB 中运行代码而不设置断点并单步执行每个指令将生成正确的结果设置 R1 3。分支分支跳转允许我们跳转到另一个代码段。当你需要跳过或者重复某块代码或者跳转到指定的函数的时候分支很有用。此类情形中最佳的示例是IF和循环。先来看看IF案例。.global main
main:mov r1, #2 /* 设置初始变量a */mov r2, #3 /* 设置初始变量b */cmp r1, r2 /* 比较两个变量值看哪个更大 */blt r1_lower /* 因为R2更大(N1)跳转到r1_lower */mov r0, r1 /* 如果没有跳转, 例如R1的值更大(或者相等)则将R1的值存储到R0 */b end /* 结束 */
r1_lower:mov r0, r2 /* R1小于R2时跳转到此处, 将R2的值存储到R0 */b end /* 结束 */
end:bx lr /* THE END */上面代码是比较两个初始值并返回最大值C语言伪代码int main() {int max 0;int a 2;int b 3;if(a b) {max b;}else {max a;}return max;
}现在再看一下怎么使用条件分支实现循环.global main
main:mov r0, #0 /* 设置初始变量a */
loop:cmp r0, #4 /* 比较a4 */beq end /* 如果a4结束 */add r0, r0, #1 /* 否则将R0中的值递增1 */b loop /* 跳转到loop开始位置 */
end:bx lr /* THE END */C语言伪代码int main() {int a 0;while(a 4) {a a1;}return a;
}B、BX、BLX指令有三种类型的分支指令普通分支B简单的跳转到一个函数。带链接的跳转BL将PC4的值保存到LR寄存器然后跳转。带状态切换的跳转BX和带状态切换及链接的跳转BLX与B和BL一致只是添加了工作状态的切换ARM模式-Thumb模式。需要寄存器作为第一个操作数。BX、BLX用来切换ARM模式到Thumb模式。.text
.global _start
_start:.code 32 ARM modeadd r2, pc, #1 put PC1 into R2bx r2 branch exchange to R2
.code 16 Thumb modemov r0, #1这里的技巧是获得当前PC的值加1然后保存到一个寄存器然后跳转并且切换状态模式到这个寄存器内的地址。可以看到加指令add r2, pc, #1获取到有效的PC地址值当前PC内的值80x805C然后加10x805C 1 0x805D。接下来我们跳转的地址 0x805D 10000000 01011101最低有效位为1那么意味着地址不是4字节32bit对齐的。跳转到这样的地址不会导致非对齐问题。在GDB中运行的样子含GEF注意上面的gif图片是在低版本的GEF下创建的所以你的显示界面可能不一样但是逻辑是一样的。条件分支分支也可以有条件地执行用于在满足特定条件时跳转到函数。我们看一个使用BEQ应用条件分支的例子这是一段没太有用的汇编代码只不过是在寄存器等于特定值时将一个值移动到寄存器并跳转到另一个函数的过程。.text
.global _start
_start:mov r0, #2mov r1, #2add r0, r0, r1cmp r0, #4beq func1add r1, #5b func2
func1:mov r1, r0bx lr
func2:mov r0, r1bx lrend