Cortex-M处理器中异常返回时BX LR指令的工作机制
ARMv7-M 异常返回的原理:特殊LR值与BX指令的作用
ARMv7-M进入异常时,会在栈推送完成后设置LR值:
if CurrentMode==Mode_Handler then LR = Ones(28):'0001'; // 对应 0xFFFFFFF1 else LR = Ones(29):CONTROL.SPSEL:'01'; // 比如SPSEL=1时为0xFFFFFFF9
这些值看起来不是有效内存地址,但实际上是ARM架构定义的异常返回控制编码,而非普通分支地址。
一、异常返回的触发逻辑
根据ARMv7-M架构手册:
BX也可用于异常返回。
当处理器处于Handler模式,且以下指令之一将0xFXXXXXXX值加载至PC时,会发生异常返回:
- 包含加载PC的POP/LDM指令。
- 以PC为目标的LDR指令。
- 使用任意寄存器的BX指令。
这里的0xFXXXXXXX是异常返回标记的特征(高4位为1),当BX LR执行时,处理器识别到LR中的值符合这个特征,就会触发异常返回流程,而非尝试跳转到这个“地址”。
二、BX LR如何完成返回?
执行BX LR时,处理器不会把LR的值当作分支地址,而是执行以下操作:
- 读取LR中的控制编码,确定返回后使用的栈指针(MSP/PSP)和执行模式
- 从栈中自动恢复NVIC之前保存的上下文(包括中断前的PC返回地址、寄存器状态等)
- 将栈中保存的返回地址加载到PC,回到中断发生前的执行位置
三、为什么需要BX指令?
NVIC负责的是上下文的自动压栈与出栈,但异常返回的触发必须通过显式指令:
- 架构要求必须通过“加载PC”的操作来触发返回流程,这是处理器识别异常返回的唯一方式
BX LR是最便捷的触发方式,因为LR在异常进入时已经被自动配置好了返回控制编码- 没有这条指令,处理器会一直停留在Handler模式,无法回到原执行流程
简单总结:LR里的是“触发异常返回”的控制暗号,BX LR是启动这个流程的开关,真正的返回地址早就存在栈中,处理器会自动读取栈中的值完成跳转。
内容的提问来源于stack exchange,提问作者smwikipedia
相关产品推荐
相关产品推荐

