2016-05-04 10 views
1

Ich entwickle ein Betriebssystem. Mein GDT hat drei Einträge. Ich habe den IDT erstellt und ISR und IQR implementiert. Ich habe auch den PIC neu zugeordnet. Das Problem ist, dass nach jedem Interrupt-Handler eine allgemeine Schutzverletzung folgt. Dies ist der Assembler-Code, der die Interrupts ruft:Jeder IRQ und ISR verursacht einen GPF

.extern fault_handler 
isr_common_stub: 
    pusha 
    push %ds 
    push %es 
    push %fs 
    push %gs 
    movw $0x10,%ax # Load the Kernel Data Segment descriptor! 
    movw %ax,%ds 
    movw %ax,%es 
    movw %ax,%fs 
    movw %ax,%gs 
    movl %esp,%eax # Push us the stack 
    pushl %eax 
    movl $fault_handler, %eax 
    call *%eax  # A special call, preserves the 'eip' register 
    popl %eax 
    popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 
    popa 
    addl $8,%esp # Cleans up the pushed error code and pushed ISR number 
    iret   # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP! 

.extern irq_handler 
irq_common_stub: 
    pusha 
    push %ds 
    push %es 
    push %fs 
    push %gs 
    movw $0x10,%ax 
    movw %ax,%ds 
    movw %ax,%es 
    movw %ax,%fs 
    movw %ax,%gs 
    movl %esp,%eax 
    pushl %eax 
    movl $irq_handler, %eax 
    call *%eax 
    popl %eax 
    popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 
    popa 
    addl $8,%esp 
    iret 

ich seltsam etwas herausgefunden. Wenn ich das Betriebssystem mit QEMU als .iso Disk-Image ausführen, funktioniert es nicht. Aber als ich es als Kernel nannte, indem ich die -kernel Option anwendete, funktionierte es wie erwartet. Ich beschloss, den Code unten zu ändern:

popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 

ich oben dazu den Code geändert:

pop %gs 
    pop %fs 
    pop %es 
    pop %ds 

Ich bin immer noch die GPF bekommen. Mache ich etwas falsch? Irgendwelche Vorschläge?

+2

Eine seltsame Sache ist, dass Sie 'push' machen, aber dann' popl' ... generell sollten Sie das gleiche 'push' /' pop' oder 'pushl' /' popl' verwenden. – Buddy

+2

Ist Ihre 'gs' richtig initialisiert? ? Wenn es im Real-Modus noch einen Restwert hat, führt das Zurückspringen zu einem GPF. PS: lernen, einen Debugger PS # 2 zu verwenden: 'spezieller Anruf, konserviert das 'eip' Register' LOL? – Jester

Antwort

3

Wenn mein alter Speicher mir richtig dient, sind die Segmentregister 16 Bit, und Sie versuchen, eine popl zu machen, die einen 32-Bit-Wert knallt ... das ist also ein Problem.

Da Sie eine push %gs oben tun, sollten Sie auch eine pop %gs tun. Gleich mit den anderen Registern, stellen Sie sicher, dass Sie pop ihnen die gleiche Weise Sie push ihnen.

3
addl $8,%esp # Cleans up the pushed error code and pushed ISR number 

Ihre isr_common_stub Routine denkt, dass ein Codefehler wird immer da sein. Einige Fehler drücken keinen Fehlercode! Nur Fehler im Zusammenhang mit den Interrupt-Nummern 10, 11, 12, 13, 14 und 17 verwenden einen Fehlercode.

Von http://www.brokenthorn.com/Resources/OSDev15.html erfahren wir:

Wenn die Prozedur auf einem niedrigeren Berechtigungsstufe (Bits 42-45 von Descriptor) ausgeführt werden wird, ein Stapel Schalter auftritt.
Der Segmentselektor und der Stapelzeiger für den Stapel, der vom Handler verwendet werden soll, werden vom TSS für die aktuell ausgeführte Aufgabe erhalten. Der Prozessor schiebt den Stapelsegmentselektor und den Stapelzeiger des Interrupthandlers auf diesen neuen Stapel. Der Prozessor speichert den aktuellen Zustand von EFLAGS, CS und EIP auf dem neuen Stapel.
Wenn eine Ausnahme zum Speichern eines Fehlercodes führt, wird der Fehlercode nach EIP auf den neuen Stapel übertragen.

und auch

Falls die Behandlungsroutine auf der gleiche Berechtigungsebene ausgeführt werden wird (aktuelle Privilegebene (CPL) ist das gleiche wie (Bits 42-45 des Deskriptors)
Der Prozessor speichert den aktuellen Zustand des EFLAGS, CS, EIP auf dem aktuellen Stapel.
Wenn eine Ausnahme ein Fehlercode verursacht gespeichert wird, wird der Fehlercode auf dem aktuellen Stack nach EIP

geschoben

Es ist sehr wichtig zu wissen, wie der Stack gedrückt wird, wenn unser Interrupt-Handler aufgerufen wird und welche Ausnahmen auch Fehlercodes drücken.

Verwandte Themen