8

我正在尝试为 x86 上的一般保护故障 (GP#13) 编写 ISR。我无法从 INTEL 文档中找出如何找出导致异常的错误地址。我知道对于页面错误异常(GP#14),cr2 寄存器保存错误地址。任何帮助表示赞赏。

4

1 回答 1

11

我在此引用的所有参考资料均来自AMD64 Architecture Programmer's Manual Volume 2: System Programming,其中还描述了传统的保护模式(即 x86)行为。

第 240 页上的图 8-8 显示了相同特权级别的中断后的堆栈布局(即进入 ISR 时的堆栈布局):

中断后堆栈到相同的特权级别

在第 8.2.14 节中,您可以看到它#GP提供了一个错误代码,并且以下内容也很有趣:

程序重启。 #GP是错误类型的异常。在大多数情况下,保存的指令指针指向导致 #GP. 有关在任务切换期间发生此异常时的后果的描述,请参见第 230 页的“任务切换期间的异常”。

引用的部分提到以下内容:

在加载段选择器时任务切换期间可能会发生异常。访问 TSS 时也可能发生页面错误。在这些情况下,硬件任务切换机制完成从 TSS 加载新任务状态,然后触发相应的异常机制。不执行其他检查。发生这种情况时,保存的指令指针指向新任务中的第一条指令。

因此,除非您使用硬件任务切换,否则保存的指令指针始终指向故障指令。

要获取错误指令的地址,只需从 ISR 中的堆栈中获取保存的值EIP和值。CS(如果您使用的是平面内存模型并且您的所有段都覆盖了整个 4GB,那么保存CS的内容当然没有意义)。

movl 4(%esp), %eax
movw 8(%esp), %ebx

现在,EAX包含已保存EIPEBX已保存的CS.

编辑:当然,正如亚历克斯评论中指出的那样,如果#GP是由内存访问引起的并且您想要访问内存的地址,您将需要解码错误指令。

于 2012-04-28T08:02:02.650 回答