STM32F013 单片机属于 ARM Cortex-M0 内核架构,其压栈行为主要发生在 异常处理(如中断、异常进入)或者手动使用栈(如函数调用时的局部变量、寄存器保存)时。以下是两种情况的详细分析:
1. 异常或中断触发时的自动压栈
当 STM32F013 发生 中断 或 异常 时,Cortex-M0 内核会自动将以下 8 个寄存器压入栈中(顺序如下):
寄存器 | 说明 |
---|---|
R0 | 通用寄存器 R0 (函数参数) |
R1 | 通用寄存器 R1 |
R2 | 通用寄存器 R2 |
R3 | 通用寄存器 R3 |
R12 | 通用寄存器 R12 |
LR (R14) | 链接寄存器(返回地址) |
PC | 程序计数器(异常发生时的 PC) |
xPSR | 程序状态寄存器 |
压栈顺序(从低地址到高地址)
低地址↓
[ xPSR ] --> 最高位 (最先压入栈)
[ PC ]
[ LR ]
[ R12 ]
[ R3 ]
[ R2 ]
[ R1 ]
[ R0 ] --> 最低位 (最后压入栈)↑
高地址
说明:
- 进入中断或异常时,处理器会自动保存这些寄存器,以便返回时恢复现场。
- 退出中断时,Cortex-M0 内核会自动从栈中弹出这些寄存器并恢复 CPU 状态。
2. 函数调用时的手动压栈
当函数调用时,编译器和汇编代码可能会手动将一些寄存器压入栈中,以保存调用者的环境。这遵循 ARM AAPCS (ARM Procedure Call Standard) 规则,包括:
-
函数参数和局部变量
- ARM 规定,前 4 个参数传递给
R0-R3
,超过 4 个的参数需要压入栈中。 - 局部变量可能存放在
R4-R7
,超出部分也会放入栈中。
- ARM 规定,前 4 个参数传递给
-
保存寄存器
- 如果函数内部使用了
R4-R7
或其他非易失性寄存器 (如LR
),需要手动压栈。
- 如果函数内部使用了
示例
push {r4-r7, lr} ; 进入函数时,保存 r4-r7 和 lr
...
pop {r4-r7, lr} ; 离开函数时,恢复寄存器
bx lr ; 返回调用方
说明:
push {r4-r7, lr}
手动压栈,保护R4-R7
和LR
(返回地址)。pop {r4-r7, lr}
退出函数时恢复现场。
3. 总结
(1) 进入中断时,Cortex-M0 自动压栈
寄存器 | 内容 |
---|---|
R0-R3 | 通用寄存器(函数参数) |
R12 | 通用寄存器 |
LR (R14) | 链接寄存器(异常返回地址) |
PC | 异常发生时的地址 |
xPSR | 程序状态寄存器 |
(2) 普通函数调用,手动压栈
- 保护
R4-R7
或LR
需要push
指令手动压栈。 - 超过 4 个的函数参数和局部变量可能会被压入栈中。
这样 STM32F013(Cortex-M0)在不同场景下的压栈机制就清楚了!你具体是想分析哪种情况呢?