• Programmable Interrupt Controller

    Nachdem wir zuletzt die IDT angelegt haben, wollen wir jetzt nicht mehr nur CPU-Interrupts, sondern auch andere Hardware-Interrupts empfangen. Diese gehen über den sogenannten Programmable Interrupt Controller. Dieser leitet die Interrupts von den einzelnen Hardware-Geräten an die CPU weiter.

  • Interrupt Descriptor Table

    Ähnlich wie die Global Descriptor Table müssen wir auch noch die Interrupt Descriptor Table anlegen. Aufmerksame Programmierer erinnern sich, dass wir zuvor die Interrupts deaktiviert haben mittels cli. Bevor wir diese reaktivieren können, müssen wir zwei Dinge erledigen:

  • Die Global Descriptor Table von C aus anlegen

    Bisher haben wir die GDT direkt in unserem Assembler-Code angelegt. Da unser Kernel jetzt in C programmiert ist, wollen wir auch die GDT in C anlegen.

  • Wir starten mit dem Kernel in C

    Fast alles, was wir bisher gemacht haben, wird üblicherweise gar nicht zum Bereich des Kernels gezählt, sondern zum Bootloader. Der Bootloader setzt die A20-Line und wechselt in den Protected Mode. Einzig das Einstellen der GDT ist dann noch Sache des Kernels. Weil für den Protected Mode eine GDT benötigt wird, initialisiert der Bootloader aber auch noch eine temporäre GDT, die der Kernel aber nach eigenen Wünschen überschreiben muss.

  • Die A20-Line aktivieren

    Wie ich im letzten Artikel geschrieben habe, gibt es aus historischen Gründen noch ein Problem mit der Speicheradressierung. Und zwar konnte man in den alten 8086-Prozessoren über 20 Adressleitungen den Speicher adressieren, also exakt 1MB. Das Adressierungsschema des Realmode erlaubt jedoch einen größeren Adressierungsbereich, nämlich wenn man das Segment 0xFFFF und den Offset 0xFFFF wählt. Dies liefert dann über die bekannte Formel Adresse = 16 * Segment + Offset die Adresse: 0x10FFEF. Über die 20 Adressleitungen der 8086-Prozessoren konnte die vordere 1 (auf dem 21. Bit) nicht übertragen werden.