Assembly x86中断服务程序导致一般保护故障
我将我的通用isr存根定义为: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_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示例: