C语言调用子函数时入/出栈(保护/恢复现场)全过程分析:以Cortex-M3为例

0 参考资料&工具

c 复制代码
Cortex M3权威指南(中文).pdf
keil5(用于仿真查看寄存器、栈变化)

1 C语言调用子函数时出入/出栈(保护/恢复现场)全过程分析

使用C语言调用子函数是如何保护/恢复现场的呢?本文以Cortex-M3为例,逐行汇编代码分析C语言调用子函数时入/出栈(保护/恢复现场)全过程。

准备工作:

(1)使用keil5新建一个基于stm32f103的工程

(2)将栈底值设置为0x20000400(Cortex-M3栈从上往下生长),也就是将栈大小设置为0x400

1.1 C代码

本文用来调试分析的C代码如下:

c 复制代码
typedef unsigned int u32;


u32 fun2(u32 p1, u32 p2, u32 p3, u32 p4)
{
    return p1 + p2 + p3 + p4;
}

/**
 *   主函数
 */
int main(void)
{
	u32 x;
    fun2(1, 2, 3, 4);
	x = 0x778899AA;
}


void SystemInit(void)
{
}

说明:

使用主函数调用fun2子函数,查看Cortex-M3的保护、恢复现场过程。

1.2 C代码编译生成的汇编指令

以上C代码使用0级优化(不优化)生成的汇编指令如下,我们重点关注执行fun2函数前后的操作。

(1)执行fun2函数前传递变量

执行fun2函数前首先将第4、3、2、1个参数依次传递给r3、r2、r1、r0寄存器。

(2)跳转到fun2函数

参数传递完之后跳转到fun2函数。之所以不先保护现场而是先跳转到fun2函数,是因为使用BL指令会自动将跳转指令的下一条指令地址保存到LR。

BL function1 ;

使用"分支并连接"指令呼叫 function1 ; PC= function1,并且 LR=main的下一条指令地址

也就是说,在跳转到子函数前LR寄存器会被设置为子函数下一条指令地址

这里保存到LR的并非是0x0800021A,也就是fun2函数的下一条指令,反而保存的是0x0800021B。

这样操作的原因可以参考Cortex M3权威指南(中文).pdf:

也就是说,每次使用跳转指令跳转到子函数时,LR保存的实际上是子函数下一条指令地址+1 ,避免产生fault 异常。地址+1的值写入PC,PC会自动将最低位设置为0。

(3)执行fun2函数前保护现场

在执行fun2函数前,CPU会执行一条入栈指令PUSH,至少会将lr寄存器(程序链接寄存器,保存了子函数返回地址)入栈。使用keil的单步仿真功能,我们观察执行这条指令前后栈的变化:

(3.1)执行到fun2函数保护现场前栈内从顶到底依次保存了局部变量x(此时还未赋值,栈内值为0x08000234)、mian函数返回地址0x080001D9。此时栈指针值为0x200003F8。

(3.2)PUSH指令依次将lr、r4的值压入栈内。也就是依次向栈顶写入值0x0800021B、0x08000234。

此时栈指针值为0x200003F0。

此时,寄存器组内容如下:

(4)执行完fun2函数后恢复现场

执行POP指令出栈,从栈顶开始依次将栈值写入r4、PC。执行完该语句后栈的内容如下:

可以看到出入栈的部分已经被绿色标记出来,至此就算完成了C语言调用子函数保护/恢复现场操作。

此时寄存器组内容如下:

2 总结

C语言在调用函数时保护/恢复现场操作如下:

(1)保护现场

(1.1)传递函数参数

(1.2)跳转到子函数,自动将子函数下一条指令地址保存到LR

(1.3)保护现场,至少要将LR(程序链接寄存器,保存有子函数返回地址)入栈

(2)恢复现场

至少要将LR(程序链接寄存器,保存有子函数返回地址)出栈,将LR的值写入到PC,跳转到子函数下一条指令位置继续执行

相关推荐
Stone.Wu4 天前
快速理解ARM Cortex-M流水线:指令执行过程通俗解释
arm
我在人间贩卖青春5 天前
汇编之分支跳转指令
汇编·arm·分支跳转
我在人间贩卖青春5 天前
汇编之加载存储指令
汇编·arm·寄存器加载存储
我在人间贩卖青春5 天前
汇编之状态寄存器访问指令
汇编·arm·状态寄存器
我在人间贩卖青春5 天前
汇编之软中断指令和协处理指令
汇编·arm·软中断·协处理
我在人间贩卖青春5 天前
汇编之数据处理指令
汇编·arm·数据处理指令
fly的fly8 天前
浅析 QT远程部署及debug方案
qt·物联网·arm
切糕师学AI10 天前
ARM标准汇编(armasm)中的标号(Label)
汇编·arm
CHENG-JustDoIt11 天前
嵌入式开发 | ARM Cortex-M 系列中M3、M4、M23 和 M33四款处理器的深度对比分析
arm开发·单片机·嵌入式硬件·arm
toradexsh19 天前
在NXP iMX8QM上使用 Jailhouse
arm·nxp·toradex·imx8mp·jailhouse