arm汇编lr pc b bl ret指令函数调用和返回gif动图演示

47 篇文章 1 订阅
22 篇文章 5 订阅

pc 寄存器

pc保存着当前指令执行的地址,相当于win32汇编里的eip寄存器

lr寄存器 (x30)

lr存储函数的返回地址,每次遇到ret返回指令,都会跳转到lr寄存器里保存的地址,这个地址是函数调用的下一条指令,就是应该要执行的指令,cpu遇到ret之后,会把lr赋值给pc,这样cpu了pc里的地址,就是执行函数调用的下一条指令

ret返回指令

作用是返回,
本质上的操作:执行ret之后,会把lr寄存器里的值赋值给pc,这样cpu就会执行到lr地址里的指令了.

bl 跳转指令,带返回

bl执行跳转之前,会把bl的下一条指令地址,赋值给lr,这样,跳转之后的lr就是跳转之前的下一条指令了.当执行到ret指令的时候,会把lr的值赋值给pc,这样就会跳回到bl的下一条指令.

b 跳转,不带返回

b跳转的时候因为没有给lr赋值,所以跳转之后,lr还是跳转之前的lr值,所以跳转之后遇到ret指令以后会跳转到b之前的 lr的地址.

下面用汇编写的fn1方法里面有b和bl 2种跳转,注释掉其中一种,得到不同的结果

//.h中的声明
void fn1(int *a);

oc中的调用,传入一个int类型的地址


//oc调用
    int a = 11;
    fn1(&a);
    NSLog(@"a=%d",a);

汇编中的函数实现

.text
.global _fn1
_fn1:
str wzr,[x0]
mov x10,lr//保存之前的lr值,这样可以返回到调用fn1()的位置
bl label1 //bl跳转到label1之前,会把lr赋值成下一条指令,这样.遇到label1的ret会返回到下面的指令mov w3,0x10
mov lr,x10 //还原之前的lr地址,这样能返回到调用fn1()的位置
mov w3,0x10
str w3,[x0]
ret
label1:
mov w3,0xf
str w3,[x0]
ret//这句执行完以后会把lr赋值给pc,因为lr已经被bl赋值了bl之后指令的地址,所以会跳转到上面的mov w3,0x10指令,这样,变量a就会赋值成了0x10,打印结果a=16

上面代码注释已经写了在执行到bl之后跳转到label1,然后给变量a赋值0xF,再返回到bl label1的下一条指令,再还原之前的lr值,这样再遇到ret的时候就返回到fn1(&a)的调用位置了
下面的gif图片,录制了这段代码的执行过程,其中re read lr 查看了lr的改变,包括执行完fn1之后a被赋值成了0x10 = 16
请添加图片描述

b 跳转以后不会改变lr的值,遇到ret以后就会返回之前的lr里的地址里的指令,如下图gif

.text
.global _fn1
_fn1:
str wzr,[x0]
mov x10,lr//保存之前的lr值,这样可以返回到调用fn1()的位置
b label1//b跳转到label1之后,lr没有被赋值,而是保持这之前的值,这样label1执行到遇到ret之后,就会返回到现在lr的值,就是调用_fn1的指令的下一条指令
mov lr,x10 //还原之前的lr地址,这样能返回到调用fn1()的位置
mov w3,0x10
str w3,[x0]
ret
label1:
mov w3,0xf
str w3,[x0]
ret

请添加图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值