Assembly 来自x86中断处理程序的意外跳转

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

我正在制作定制的8x86 64位操作系统,对于中断处理程序,我遇到了一些问题

当我为常见异常和中断添加中断处理程序时,我通过“sti”指令启用了中断

然后,“一般保护故障”在启用中断后立即发生

所以,我检查了GDB

堆栈是

(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代码还有一个堆栈。当我看了看堆栈顶部时,我认出了它。如果你写一个答案,我会选择它。再次感谢你。