嵌入式函数调用入栈与出栈

简单的例程,几个函数调用,来查看寄存器状态,主要是学习一下cortem-M核中LR寄存器的理解:
在这里插入图片描述
例程源码:

static uint32_t count_test = 0;

static void fun3()
{
	count_test++;
	
}

static void fun2()
{
	count_test++;
	fun3();
    count_test++;
}

static void fun1()
{
	count_test++;
	fun2();
	count_test++;
}

int main(void)
{
    fun1();

    return 0;
}

通过单步调试来查看各个寄存器状态:

step1

进入调试界面
在这里插入图片描述

  1. c源代码
  2. 对应的汇编代码
  3. 对应的当前寄存器
step2

记录当前进入main函数所要做的动作和记录的状态
1、因main()函数中还有子函数,所以需将r4,lr寄存器压入栈中,对应的汇编:

0x0800017A B510      PUSH     {r4,lr}

2、记住当前main函数中return 0处的代码地址:0x08000180
在这里插入图片描述
在进入fun1()函数后,会将返回地址的指针加1保存到LR寄存器中,即0x08000181,请记住这个值。

step3

进入fun1()
在这里插入图片描述
1、查看当前LR寄存器为0x08000181,与上述分析一致;
2、进入当前fun1()函数中后,因为有子函数要执行,所以依然将r4,lr寄存器压入栈中
3、记录代码中counnt_test++代码对应的地址:0x0800172,那么进入到fun2()函数之后的LR值应为:0x0800173
在这里插入图片描述

step4

进入fun2()
在这里插入图片描述
分析同上,

step5

进入与退出fun3()
在这里插入图片描述
1、因fun3()函数中,没有子函数,r4,lr寄存器没有再进行入栈操作,执行结束之后直接返回,根据LR寄存器保存的返回地址:
在这里插入图片描述

step6

退出到fun2()并准备进入fun3()
在这里插入图片描述
1、退出到fun2()时,因当前LR寄存器保存的还是进入fun3()时的值,现在要从退出到fun2()到退出到fun1(),那么对应的LR肯定就不对了,需进行出栈操作,如上图的汇编,将r4,pc出栈操作(pc就是lr,直接将lr的值赋给pc并执行),栈中存放的就是退出到fun1()地址处的值:

0x08000162 BD10      POP      {r4,pc}
step7

退出到fun1()并准备进入main()
在这里插入图片描述
道理同上。

step8

最终进入main()函数。
在这里插入图片描述

所以要记住的是:
1、每次调用子函数,都会将返回的地址加1保存到LR寄存器中;
2、如当前函数中还有子函数,则在进入子函数前需先压栈r4,lr,进行保护现场操作;
3、而从函数中退出时,如果当前函数中有子函数,有过入栈操作,则在退出此函数时需进行出栈操作,根据出栈中保存的lr寄存器来返回需要退出的函数位置处。

  本文只是做了简单的记录,方便日后查看,后续再学习一下cortex-M核的几种工作模式及权限。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值