-
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 Offset0xFFFF
wählt. Dies liefert dann über die bekannte FormelAdresse = 16 * Segment + Offset
die Adresse: 0x10FFEF. Über die 20 Adressleitungen der 8086-Prozessoren konnte die vordere 1 (auf dem 21. Bit) nicht übertragen werden.