流控制 - ARM汇编指令(三)

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} 
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值