Assembly 来自x86中断处理程序的意外跳转
我正在制作定制的8x86 64位操作系统,对于中断处理程序,我遇到了一些问题 当我为常见异常和中断添加中断处理程序时,我通过“sti”指令启用了中断 然后,“一般保护故障”在启用中断后立即发生 所以,我检查了GDB 堆栈是Assembly 来自x86中断处理程序的意外跳转,assembly,x86,gdb,stack,interrupt,Assembly,X86,Gdb,Stack,Interrupt,我正在制作定制的8x86 64位操作系统,对于中断处理程序,我遇到了一些问题 当我为常见异常和中断添加中断处理程序时,我通过“sti”指令启用了中断 然后,“一般保护故障”在启用中断后立即发生 所以,我检查了GDB 堆栈是 (gdb) bt #0 kISR::kISRGeneralProtection () at /home/xaliver/WorkSpace/kOdin/kernel64/./ISR.cpp:70 #1 0x000000000000fee8 in ?? () #2 0x0
(gdb) bt
#0 kISR::kISRGeneralProtection () at /home/xaliver/WorkSpace/kOdin/kernel64/./ISR.cpp:70
#1 0x000000000000fee8 in ?? ()
#2 0x0000000000202e30 in _kISRTimer ()
Backtrace stopped: frame did not save the PC
奇怪的部分是0xfee8。我使用0x10000以下的内存作为32位保护模式的堆栈。现在,系统处于64位模式,因此值为空为“00”
所以,我检查了第二帧,_kISRTimer
0xfee8的保存rip为0x202e30。这是(u kISRTimer)的"iretq"指令
下面是汇编代码
; #32, Timer ISR
_kISRTimer:
KSAVECONTEXT ; Store the context and change selector to
202dd3: 55 push %rbp
202dd4: 48 89 e5 mov %rsp,%rbp
202dd7: 50 push %rax
202dd8: 53 push %rbx
202dd9: 51 push %rcx
202dda: 52 push %rdx
202ddb: 57 push %rdi
202ddc: 56 push %rsi
202ddd: 41 50 push %r8
202ddf: 41 51 push %r9
202de1: 41 52 push %r10
202de3: 41 53 push %r11
202de5: 41 54 push %r12
202de7: 41 55 push %r13
202de9: 41 56 push %r14
202deb: 41 57 push %r15
202ded: 66 8c d8 mov %ds,%ax
202df0: 50 push %rax
202df1: 66 8c c0 mov %es,%ax
202df4: 50 push %rax
202df5: 0f a0 pushq %fs
202df7: 0f a8 pushq %gs
202df9: 66 b8 10 00 mov $0x10,%ax
202dfd: 8e d8 mov %eax,%ds
202dff: 8e c0 mov %eax,%es
202e01: 8e e8 mov %eax,%gs
202e03: 8e e0 mov %eax,%fs
; kernel data descriptor
; Insert interrupt number to the hander and call the handler
mov rdi, 32
202e05: bf 20 00 00 00 mov $0x20,%edi
call _kCommonInterruptHandler
202e0a: e8 75 e3 ff ff callq 201184 <_kCommonInterruptHandler>
KLOADCONTEXT ; Restore the context
202e0f: 0f a9 popq %gs
202e11: 0f a1 popq %fs
202e13: 58 pop %rax
202e14: 8e c0 mov %eax,%es
202e16: 58 pop %rax
202e17: 8e d8 mov %eax,%ds
202e19: 41 5f pop %r15
202e1b: 41 5e pop %r14
202e1d: 41 5d pop %r13
202e1f: 41 5c pop %r12
202e21: 41 5b pop %r11
202e23: 41 5a pop %r10
202e25: 41 59 pop %r9
202e27: 41 58 pop %r8
202e29: 5e pop %rsi
202e2a: 5f pop %rdi
202e2b: 5a pop %rdx
202e2c: 59 pop %rcx
202e2d: 5b pop %rbx
202e2e: 58 pop %rax
202e2f: 5d pop %rbp
iretq ; Return the event point after interrupt
202e30: 48 cf iretq
#32,定时器ISR
_基斯蒂默:
环境;存储上下文并将选择器更改为
202dd3:55%按需付费
202dd4:4889E5MOV%rsp%rbp
202dd7:50%推力rax
202dd8:53推送%rbx
202dd9:51推力%rcx
202dda:52推送%rdx
202ddb:57%推送rdi
202ddc:56%相对标准偏差
202ddd:41 50%推力r8
202ddf:41 51推力%r9
202de1:41 52推送率r10
202de3:41 53推送%r11
202de5:41 54推送率r12
202de7:41 55%r13
202de9:41 56推送率r14
202deb:41 57%推力r15
202d:66 8c d8 mov%ds,%ax
202df0:50推力%rax
202df1:66 8c c0 mov%es,%ax
202df4:50%推力rax
202df5:0f a0推力Q%fs
202df7:0f a8推送质量%gs
202df9:66 b8 10 00 mov$0x10,%ax
202dfd:8e d8 mov%eax,%ds
202dff:8e c0 mov%eax,%es
202e01:8e e8移动百分比eax,%gs
202e03:8e e0 mov%eax,%fs
; 内核数据描述符
; 将中断号插入处理程序并调用处理程序
mov rdi,32岁
202e05:bf 20 00 mov$0x20,%edi
调用kCommonInterruptHandler
202e0a:e8 75 e3 ff呼叫201184
KLOADCONTEXT;恢复上下文
202e0f:0f a9 popq%gs
202e11:0f a1 popq%fs
202e13年:58%平均收益率
202e14:8e c0 mov%eax,%es
202e16年:58%平均收益率
202e17:8e d8 mov%eax,%ds
202e19:41 5f pop%r15
202e1b:41 5e pop%r14
202e1d:41 5d pop%r13
202e1f:41 5c pop%r12
202e21年:41.5亿美元,占11%
202e23:41 5a pop%r10
202e25年:41 59%r9
202e27年:41 58%r8
202e29年:5e波普%rsi
202e2a:5f pop%rdi
202e2b:5a pop%rdx
202e2c:59%持久性有机污染物循环利用率
202e2d:50亿波普%rbx
202e2e:58%平均收益率
202e2f:5d pop%rbp
iretq;中断后返回事件点
202e30:48 cf iretq
我认为跳下去没有意义
我还试图删除计时器的中断处理程序。但是,“GPF”出现在其他中断处理程序中。另一个中断处理程序与_kISRTimer相同,但调用函数不同
你知道为什么GPF会从代码中出现吗?
或者,跳转不是来自代码?
请让我知道为什么会发生这个问题。
谢谢。,或从中断处理程序返回64位地址,期望返回地址和标志位于堆栈顶部,如果返回地址无效(例如,因为它指向无执行内存页),则会产生一般保护故障。因此,当处理程序被调用时,您应该检查堆栈上的值、调用代码和CS选择器。如果其中任何一个发生了更改,堆栈可能包含垃圾。您关于“内存低于0x10000作为32位保护模式的堆栈”的评论表明,其中一个或两个可能都是这种情况。如果堆栈上的返回地址(以及标志)无效,IRETQ将引发#GP异常。您是否从其他模式调用中断?它有不同的堆栈吗?当处理程序被调用时,检查堆栈顶部的内容。@Lorehead,谢谢你的回答。这对我有帮助。中断调用函数是C++,它通过C调用汇编代码,所以C代码还有一个堆栈。当我看了看堆栈顶部时,我认出了它。如果你写一个答案,我会选择它。再次感谢你。