2014-08-28 34 views
1

我定义我的共同ISR存根:x86的中断服务程序的原因一般保护错误

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覆盖整个4G地址空间与0特权级别的数据和代码描述符(和空描述符)。任何帮助表示赞赏。

+1

在ISR中做“sti”并不是一个好主意。典型的中断在ISR中被禁用。在“iret”之前的“sti”只能为一个指令启用中断,因为“iret”将恢复“中断使能”位的旧状态。 – 2014-08-28 05:20:50

+1

在从中断返回之前,未将中断信号的结束(OCW 2 的EOI位4)发送到主PIC命令寄存器(端口20h)。 – 2014-08-28 05:51:47

+0

@DirkWolfgangGlomp isrs是否需要isrs?我认为这只会需要irqs。 – 2014-08-28 06:37:09

回答

1

在这里,我们去...

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自己的虚假中断的处理程序外)。

+0

谢谢。得到它的工作。 – 2014-08-29 05:26:53

相关问题