You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM v7(QEMU树莓派模拟)中断处理:是否需跳回故障指令?

ARM v7异常处理返回地址说明

先直接给结论:返回地址取决于异常类型,不是所有异常都要回到故障指令,分情况明确:

同步异常(未定义指令、软中断、预取中止、数据中止)

这类异常由指令执行直接触发,返回逻辑需按异常类型区分:

  • 未定义指令、预取中止:进入异常时,LR已指向故障指令的下一条指令(ARM状态下偏移+4字节)。如果你的处理逻辑是修复故障后重新执行这条指令,给LR减4是合理的;如果不需要重试(比如直接跳过故障指令),则无需调整LR。你代码里这部分的处理是正确的。
  • 软中断(SWI):进入异常时,LR已经指向SWI指令的下一条指令——这才是正确的返回地址。你当前代码里给LR减4会导致返回后重复执行SWI指令,直接触发无限循环,必须去掉sub lr, #4这一行。
  • 数据中止:进入异常时,LR指向故障指令的下下条指令(ARM状态下偏移+8字节),这是ARM流水线特性导致的。如果要重新执行故障指令,给LR减8是正确的,你代码里这部分没问题。

异步异常(IRQ、FIQ)

这类异常由外部触发(比如外设中断),触发时当前正在执行的指令已经完成,LR已指向原本要执行的下一条指令,这就是正确的返回地址。你代码里给IRQ的LR减8、FIQ的LR减4都是错误的,会导致回到之前的指令重复执行,直接去掉这些sub lr, #x操作即可。

另外,你用LDMIA sp!, {r0-r12,pc}^完成返回是正确的,这个指令会自动把SPSR的值恢复到CPSR,同时跳转到指定地址,符合ARM异常返回的规范。

修正后的关键代码片段

software_interrupt:
    ; 移除sub lr, #4,LR已是正确返回地址
    stmfd sp!, {r0-r12,lr}
    mov r0, sp
    bl software_interrupt_C
    LDMIA sp!, {r0-r12,pc}^

irq:
    ; 移除sub lr, #8
    stmfd sp!, {r0-r12,lr}
    mov r0, sp
    bl irq_C
    LDMIA sp!, {r0-r12,pc}^

fiq:
    ; 移除sub lr, #4
    stmfd sp!, {r0-r12,lr}
    mov r0, sp
    bl fiq_C
    LDMIA sp!, {r0-r12,pc}^

内容的提问来源于stack exchange,提问作者user25858014

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:05:54