Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly x86中断服务程序导致一般保护故障_Assembly_X86_Interrupt_Interrupt Handling_Gdt - Fatal编程技术网

Assembly x86中断服务程序导致一般保护故障

Assembly x86中断服务程序导致一般保护故障,assembly,x86,interrupt,interrupt-handling,gdt,Assembly,X86,Interrupt,Interrupt Handling,Gdt,我将我的通用isr存根定义为: isr_common_stub: pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax mov ax, ds ; Lower 16-bits of eax = ds. push eax ; save the data segment descriptor mov ax, 0x10 ; load the kernel dat

我将我的通用isr存根定义为:

isr_common_stub:
pusha                    ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

mov ax, ds               ; Lower 16-bits of eax = ds.
push eax                 ; save the data segment descriptor

mov ax, 0x10  ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

call isr_handler
;call saySomething
pop ebx        ; reload the original data segment descriptor
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
;call saySomething
popa                     ; Pops edi,esi,ebp...
;add esp, 8     ; Cleans up the pushed error code and pushed ISR number
;sti
;call saySomething
;iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
ret ;Return to the caller. Iret and interrupt enabling is handled within caller.
从每个中断调用此代码,如下所示:

%macro ISR_NOERRCODE 1
global isr%1
isr%1:
   cli                         ; Disable interrupts firstly.
   push byte 0                 ; Push a dummy error code.
   push byte %1                ; Push the interrupt number.
   jmp isr_common_stub         ; Go to our common handler code.
   sub esp, 2 ;Removes 2 bytes from stack
   ;sti ;Iret enables interrupts again
   iret ;Return from interrupt
%endmacro
此代码适当地调用外部处理方法,但从外部处理方法返回后会导致gpf中断

此外,我还将我的gdt映射为使用0个特权级别的数据和代码描述符(以及空描述符)覆盖整个4G地址空间。非常感谢您的帮助。

我们开始

a) 在宏中,执行
cli
是愚蠢的。使用“中断门”(而不是“陷阱门”),CPU将自动为您禁用IRQ,而不存在争用条件的风险(例如,中断处理程序启动后但在完成执行
cli
之前的IRQ)

b) 在宏中,
jmp
后面的代码永远不会执行,因此毫无意义

c) 如果您将2个字节推到堆栈上,那么您就搞乱了堆栈对齐,应该受到性能方面的惩罚。而是按2个DWORD以避免出现这种情况

d) CPU为某些异常提供32位错误代码;因此,虚拟错误代码也应该是32位的

e) 您没有向ISR传递任何信息。大多数异常处理程序都需要知道发生异常时通用寄存器等的状态

f) 您不能期望
ret
从中断返回,并且需要取消对
iret
的注释

g) 丢弃所有段寄存器(DS、ES、FS、GS)可能是个坏主意。要么操作系统将它们视为常量,而您在从ISR返回之前没有理由加载它们,要么必须保存它们,然后正确地重新加载

h) 不同的异常有不同的需求,所以拥有一个“公共异常处理程序”是愚蠢的。最好为不同的异常使用不同的异常处理程序,这是IDT提供的(在这种情况下,在堆栈上推一个“中断号”是没有意义的)


j) IRQ与例外情况不同。对于IRQ,中断处理程序从不需要无意义的错误代码(或中断代码的状态)。请注意,在汇编存根中处理/隐藏PIC芯片的“伪IRQ”很好,这意味着检查PIC的“服务寄存器”,以区分真实IRQ7和伪IRQ7之间的差异,以及真实IRQ15和伪IRQ15之间的差异。对于伪IRQ15,您需要将EOI发送给主控,而不是从控,对于伪IRQ7,您根本不能发送任何EOI。如果您使用的是IO APIC,那么没有明智的方法来禁用/屏蔽PIC芯片的伪IRQ,因此您仍然需要两个PIC芯片的伪IRQ处理程序(除了APIC自己的伪中断处理程序之外)。

在ISR中执行“sti”不是一个好主意。通常在ISR中禁用中断。“iret”之前的“sti”将启用一条指令的中断,因为“iret”将恢复“中断启用”位的旧状态。在中断返回之前,缺少向主PIC命令寄存器(端口20h)发送中断结束信号(OCW 2的EOI位4)的功能。@dirkwolgangglomp是ISR所必需的吗?我认为这只适用于IRQ。最小IDT示例: