为什么ARM异常中的预取中止和数据中止的返回地址不同?

wen*_*jon 7 arm exception

对于预取,返回地址为:R14_abt =中止指令的地址+4

对于数据中止,返回地址为:R14_abt =中止指令的地址+8

Dan*_*Dan 14

这些偏移是由处理器的流水线操作和提取/解码/执行阶段引起的.

处理器的程序计数器(PC)在执行期间的特定点更新.在获取/解码/执行的不同阶段期间可能发生异常.

在预取中止的情况下,指令不能(尚未执行); 仅当处理器实际尝试执行指令时才会发生异常(某些预取指令可能无法执行).

在数据中止的情况下,正在执行指令,并且指令的执行导致异常.

从ARM文档:

关于预取中止:

[预取中止异常]当处理器尝试执行从非法地址预取的指令时发生,即,在当前模式下,处理器无法访问存储器管理子系统已确定的地址.

...已经在管道中的指令继续执行,直到达到无效指令,此时生成预取中止.

...因为在发出预取中止时程序计数器没有更新,lr_ABT指向导致异常的指令之后的指令.处理程序必须返回到lr_ABT - 4

关于数据中止:

[数据中止例外]当数据传输指令尝试在非法地址加载或存储数据时发生.

当加载或存储指令试图访问存储器时,程序计数器已​​更新.lr_ABT中的存储值(pc-4)指向超出生成异常的地址的第二条指令.当MMU已将适当的地址加载到物理内存中时,处理程序应返回到原始的中止指令,以便可以再次尝试执行它.因此,返回地址比lr_ABT中的两个字(八个字节)小

换句话说,对于数据中止,处理程序必须返回到lr_ABT - 8(之前的两个单词/指令)


Igo*_*sky 2

我不记得看到过官方的解释,但如果你仔细想想,这是非常合乎逻辑的。

让我们考虑这个例子:

00000 INSN1 [PC = 08]
00004 INSN2 [PC = 0C]
00008 INSN3 [PC = 10]
Run Code Online (Sandbox Code Playgroud)

如果处理器无法获取INSN3,则在执行它之前发生中止,因此PC值仍然是INSN2的值,即0C。

如果在 INSN3 执行期间发生数据中止,则 PC 值已更新为 10。