ARMv7汇编R6寄存器被破坏问题求助(CPULATOR环境)
解决思路
严格遵守ARMv7异常服务程序的寄存器保护规则
ARMv7的IRQ异常触发时,硬件仅自动保存R0-R3、R12、LR、PC和CPSR到异常栈。R4-R11(包括你用的R6)属于非易失性寄存器,必须由软件手动保存/恢复。如果ISR中直接使用这些寄存器而不先入栈保存,中断返回后原程序的寄存器值会被覆盖,触发"clobbered register"错误。修改KEY_ISR的模板如下:KEY_ISR: PUSH {R6, LR} ; 先将用到的R6和LR入栈保存 ; 你的逻辑:加载SEQ到R6 LDR R6, =SEQ ; 其他按键处理代码 POP {R6, LR} ; 恢复R6和LR的值 SUBS PC, LR, #4 ; IRQ异常返回(必须减去4修正返回地址)如果你还用到其他
R4-R11寄存器,要把它们也加入PUSH/POP列表。排查SEQ的存储与访问合法性
确认SEQ的定义位置:如果是在.text段(代码段),可能被后续指令意外覆盖;建议将SEQ放在.data或.bss段。同时检查主循环、其他ISR中是否有修改SEQ内存地址的代码,导致R6加载的内容异常。验证中断返回逻辑的正确性
确保中断返回指令正确:IRQ异常必须用SUBS PC, LR, #4返回,而非BX LR——因为LR在IRQ触发时会自动保存返回地址+4,需要减去4修正。如果返回指令错误,会导致上下文混乱,寄存器值被破坏。检查主程序对寄存器的使用规范
即使更换了寄存器,若主程序在中断可能触发的代码段中未正确保护寄存器(比如主循环中直接使用R6而未考虑中断会修改它),也会出现同样问题。确保主程序中使用R6时,要么在临界区关闭中断,要么在使用前保存、使用后恢复。分步调试定位问题点
在CPULATOR中设置断点:- KEY_ISR入口处,查看
R6的初始值; - 加载
SEQ到R6后,检查R6的值是否正确; - ISR结束前,确认
POP操作后R6恢复为初始值; - MODE1标签处,查看
R6的值是否被意外修改。
通过跟踪寄存器值的变化,确定是ISR内部未保护寄存器,还是主程序或其他代码破坏了R6。
- KEY_ISR入口处,查看
内容的提问来源于stack exchange,提问作者PeppeBz
相关产品推荐
相关产品推荐

