ARM 汇编指令中有分支跳转指令和条件执行指令,但是没有类似于C/C++中给出的流控制指令。实际在代码开发过程中,复杂的流控制过程都是通过跳转和条件实行来实现的。
1. 分支和条件执行
1.1. 分支指令
b{条件} <地址>直接跳转到某个地址位置,这个地址位置一般是通过标签的方式来定义。
bl{条件} <地址> 跳转到某个地址执行程序,过程中会自动将R15寄存器中的内容保存在R14寄存器中。
1.2. 条件执行
条件执行是汇编特有的属性,可以在分支跳转指令后链接条件执行命令,实现相关命令条件的跳转。这种方式相比较其他汇编指令使用jmp这些指令灵活性会大很多。
EQ : 等于。如果一次比较之后设置了 Z 标志。
NE : 不等于。如果一次比较之后清除了 Z 标志。
VS : 溢出设置。如果在一次算术操作之后设置了 V 标志,计算的结果不适合放入一个 32bit 目标寄存器中。
VC : 溢出清除。如果清除了 V 标志,与 VS 相反。
HI : 高于(无符号)。如果一次比较之后设置了 C 标志并清除了 Z 标志。
LS : 低于或同于(无符号)。如果一次比较操作之后清除了 C 标志或设置了 Z 标志。
PL : 正号。如果一次算术操作之后清除了 N。出于定义‘正号’的目的,零是正数的原因是它不是负数...
MI : 负号。如果一次算术操作之后设置了 N 标志。
CS : 进位设置。如果一次算术操作或移位操作之后设置了 C 标志,操作的结果不能表示为 32bit。你可以把 C 标志当作结果的第 33 位。
CC : 进位清除。与 CS 相反。
GE : 大于或等于(有符号)。如果一次比较之后...设置了 N 标志并设置了 V 标志。或者...清除了 N 标志并清除了 V 标志。
GT : 大于(有符号)。如果一次比较之后...设置了 N 标志并设置了 V 标志。或者...清除了 N 标志并清除了 V 标志,并且...清除了 Z 标志。
LE : 小于或等于(有符号)。如果一次比较之后...设置了 N 标志并清除了 V 标志。或者...清除了 N 标志并设置了 V 标志,并且...设置了 Z 标志。
LT : 小于(有符号)。如果一次比较之后...,设置了 N 标志并清除了 V 标志。或者...清除了 N 标志并设置了 V 标志。
AL : 总是。缺省条件,所以不用明显声明。
NV : 从不。不是特别有用,它表示应当永远不执行这个指令。是穷人的 NOP。包含 NV 是为了完整性(与 AL 相对),你不应该在你的代码中使用它。
条件循环if在汇编中是不存在的,其只有通过CMP,配合jmpeq等这种跳转判断指令。
2. 流控制
可以通过命令组合的形式实现if/while/for流控制内容,具体通过实际的C代码和对应的汇编代码比较查看实现过程。汇编语言中Loop是实现流控制的基础方法,通过不同的loop组合可以完成。在ARM汇编语言中循环通过loop指令来实现,再复杂的while和for循环也是基于loop循环来实现。
2.1. if else条件
int c_asm()
{
int a=10;
int b=11;
if(a>b)
a++;
else
b++;
}
mov ro,#0xa
mov r1,#0xb
cmp r0,r1
addht r0,#1
addls r1,#1
int c_asm()
{
if(a!=10&&b!=20)
a=a+b;
}
mov r0,#3
mov r1,#1
cmp r0,#10
cmpne r1,#20
addne r0,r0,r1
2.2. for
int GetSum(int val) //使用汇编求1+2+3+...+val的值
{
int sum = 0;
__asm__ __volatile__(
"MOV R5 , %1\n"//val放入寄存器r5
"MOV R1 , #0\n" //sum = 0
"MOV R2 , #1\n"//i = 1
"LOOP:\n"
" ADD R1 , R1 ,R2\n" //sum = sum + i
" ADD R2 , R2 ,#1\n" //i++
" CMP R5 , R2\n" //判断 i 是否等于val if(i==val)
" BEQ END\n" //若相等 跳转至END处 break
" B LOOP\n" //若不相等 跳转至LOOP处进入下次循环 else continue
"END:\n"
"MOV %0 , R1\n" //sum = R1
:"=r"(sum)//输出
:"r"(val)//输入
:"memory"
);
return sum;
}
随便写了个求和的例子 其余的循环大同小异 不懂可以继续探讨 运行之前请交叉编译然后在ARM平台上运行
2.3. while
.section .data
.output:
.ascii "%d\n\000"
.section .text
.global main
main:
mov ip, sp
stmfd sp!, {fp,ip,lr,pc}
sub fp, ip, #4
sub sp, sp, #80
@memory and register
mov r3, # 1
mov r0,r3
loop:
cmp r0,# 15
bge stop
mov r1,# 1
add r2, r0, r1
mov r0, r2
@保护现场
str r0, [fp,#-16]
str r0,[fp,# -20 ]
ldr r0, =.output
ldr r1,[fp,# -20 ]
bl printf
@恢复现场
ldr r0,[fp,#-16]
b loop
stop:
ldmea fp, {fp,sp,pc}