M0函数调用和中断触发时 LR寄存器的处理

环境: keil 5.14

MCU: 一款M0的处理器

 

主要是解决以下问题: 函数嵌套调用过程中LR的处理,以及中断发生时LR的处理。

 

 

测试代码如下

uint8_t add(uint8_t a, uint8_t b){

         uint8_t c;

         c = a+b;

         return c;

}

 

uint8_t test_fun(uint8_t a,uint8_t b, uint8_t c, uint8_t d,uint8_t e){

         uint8_t ret;    

         ret = add(a,b);        

         return ret;

}

int main(void){

         uint8_t i;

         uint8_t k;

        

         i = add(1,2);

         k = test_fun(2,3,4,5,6);

        

         while(1);        

         return 0;

}


Main函数汇编代码

main汇编代码来看,参数12放入r0r1中然后调用add函数,

BL指令在调用add函数时会同时将返回地址存入LR寄存器中


Add汇编代码如下:

计算了r0+r1的和 之后保存到r0,因为 bl调用add的时候就在lr中自动保存了返回地址,所以这里直接通过bx lr就可以让函数返回到main



之后main执行test_fun函数

main汇编中看到,参数 2 3 4 依次被保存到r0-r3中,参数6被保存到栈中,这也遵循ATPCS规定的函数传参规则




 

最后是test_fun的汇编代码,因为test_fun中用到了r4-r7所以 首先push保存了一下这几个寄存器的值,以方便后面恢复。 同时也将 LR的值压栈了。 前面add的汇编中我们看到是没有对LR压栈的,这里却有是因为test_fun里面还调用了add函数,通过BL函数调用时回改变LR的值,所以test_fun的第一句就 将这个LR保存了。

 

之后提取参数a e两个参数,然后调用add函数,最后通过pop来返回到man

 

对参数e的提取,因为 M0 栈向低地址增长,而函数入口将r4-r7,lr又入栈了,所以之前存的参数e,即数据6SP+4*5地址处



综上:

          对于LR的处理,主要是看 函数内部是否有其他函数的调用,如add函数,其内部并无其他函数调用,而 BL add时就已经将返回地址存入LR中了,所以整个过程中LR就没处理,最后函数返回直接 BX LR就可以了

         test_fun函数内部存在其他函数调用,既然存在其他函数调用就会破坏LR的值,所以函数第一句就先将 LR保存在栈中,而函数返回直接出栈将值放入PC中即可。

 

PS:对于中断,M0,M3等会自动将r0-r3 r12,LR, 返回地址PC,程序状态寄存器自动压栈。

即中断并不像普通的函数调用,中断的返回地址是在PC中并被入栈,那么LR保存的意义何在?

 

原因在于,M0M3等处理器的中断返回机制,在将上面所说的中断发生后 自动将一些寄存器值入栈后,LR的会被更新为异常返回特殊值(EXC_RETURN),作用是中断返回时,LR将这个值放入PC便可以触发返回机制。具体的查阅M0,M3相关手册

 

也就是发生中断后,LR的值会被修改。

 

那么如果中断是 在test_fun这种内部有其他函数调用的函数 执行时发生的,并且第一句PUSH已经执行了,那么因为LR中的返回地址其实已经被push到栈中了,这个时候中断发生了,保不保存并不影响,即使中断触发会导致LR的值被破坏,但是毕竟我们已经保存了。

 

但是如果中断发生在add这类函数内部没有其他函数调用的 函数中时,因为add函数中并未自己在函数一开始就保存好自己的返回值,这个时候中断发生如果不保存LR的值,LR的值随后又会被修改,那么就会导致出错了。

 

综上,对于中断触发时保存LR的 目的在于  LR虽然不是中断自己的返回值,但是之前一个状态的返回值。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值