识别常规保护错误(x86)上的错误地址

rah*_*dev 6 x86 operating-system osdev interrupt-handling

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

Job*_*Job 10

我在这里所做的所有参考都来自AMD64架构程序员手册第2卷:系统编程,它也描述了传统的保护模式(即x86)行为.

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

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

在8.2.14节中,您可以看到#GP提供错误代码,以下内容也是您感兴趣的:

程序重启. #GP是故障类型的例外.在大多数情况下,保存的指令指针指向导致该指令的指令 #GP.有关在任务切换期间发生此异常时的后果的说明,请参见第230页中的"任务切换期间的异常".

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

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

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

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

movl 4(%esp), %eax
movw 8(%esp), %ebx
Run Code Online (Sandbox Code Playgroud)

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

编辑:当然,正如Alex评论中指出的那样,如果#GP是由内存访问引起的,并且您需要访问内存的地址,则需要解码故障指令.