Einrichten von Interrupts im geschützten Modus (x86)

Wie werden Interrupts für den geschützten Modus eingerichtet?

Die link sagt man sollte:

Platz für die Interrupt-Deskriptor-Tabelle schaffen Teilen Sie der CPU mit, wo sich dieser Speicherplatz befindet (siehe GDT-Tutorial: lidt funktioniert genauso wie lgdt)Sagen Sie dem PIC, dass Sie die BIOS-Standardeinstellungen nicht mehr verwenden möchten (siehe Programmieren der PIC-Chips).Schreiben Sie einige ISR-Handler (siehe Interrupt-Serviceroutinen) für IRQs und Ausnahmen. Tragen Sie die Adressen der ISR-Handler in die entsprechenden Deskriptoren einAlle unterstützten Interrupts in der IRQ-Maske (des PIC) aktivieren

Der dritte Schritt macht für mich keinen Sinn (ich sahDie link, aber es gab nichts, was ich dem PIC hätte sagen können), also habe ich es ignoriert und die nächsten beiden Schritte ausgeführt, nur um wieder ahnungslos zu sein, als ich den letzten Schritt erreichte. Nach meinem Verständnis der Interrupts beziehen sich beide Schritte, die ich nicht verstanden habe, auf Hardware-Interrupts vom PIC-Controller und sollten sich nicht auf die Interrupts auswirken, die vom PIT im IRQ 0 ausgelöst wurden. Ich habe diesen Schritt daher auch ignorier

Wenn ich meinen Code laufen ließ, kompilierte er gut und lief sogar in einer virtuellen Maschine, aber der Interrupt schien nur einmal auszulösen. Dann wurde mir klar, dass ich keine EOI an den PIC sendete, wodurch verhindert wurde, dass er weitere Interrupts auslöst. Hinzufügen vonmov al, 0x20 undout 0x20, al kurz vor demiret Befehl bringt die virtuelle Maschine zum Absturz.

Hier ist meine IDT:

; idt
idt_start :

    dw 0x00         ; The interrupt handler is located at absolute address 0x00
    dw CODE_SEG     ; CODE_SEG points to the GDT entry for code
    db 0x0          ; The unused byte
    db 0b11101001   ; 1110 Defines a 32 bit Interrupt gate, 0 is mandatory, privilege level = 0 (0b00), the last bit is one so that the CPU knows that the interrupt will be used
    dw 0x00         ; The higher part of the offset (0x00) is 0x00

idt_end:

idt_descriptor :
    dw idt_end - idt_start - 1 ; Size of our idt, always one less than the actual size
    dd idt_start ; Start address of our idt

Hier ist mein Interrupt-Handler (an der absoluten Position 0x00 im Speicher):

ISR_0:
    push eax
    add [0x300], byte 
    mov al, 0x20
    out 0x20, al
    pop eax
    iret    
    times 512-($-$) db 0

Dies ist der Code, den ich verwende, um in den geschützten Modus zu wechseln und GDT und IDT in den Speicher zu laden:

[bits 16]

switch_to_pm:

    cli
    lgdt [gdt_descriptor]
    lidt [idt_descriptor]
    mov eax, cr0
    or eax, 1
    mov cr0,eax
    jmp CODE_SEG:init_pm

[bits 32]

init_pm :

    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ebp, 0x90000
    mov esp, ebp
    sti
    call BEGIN_PM

Meine Hauptfunktion (die den Wert von 0x300 überprüft) lautet wie folgt:

void main() {
    char iii[15];
    int * aa = (int *)0x300;
    for (;;)
    {
        setCursor(0, 0);
        print(itoab(*aa, iii));
    }
}

Übrigens habe ich mithilfe eines Speicherauszugs überprüft, dass alles an der richtigen Adresse geladen wird und genau dort ist, wo es erwartet wird. Zum Beispiel ist 0x300 ein freier Teil des Speichers, der lediglich zur Vereinfachung meines Codes verwendet wird.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage