| Zeile 76: | Zeile 76: | ||
=== Kompilieren === | === Kompilieren === | ||
Der C-Kernel wird mit diesem Befehl kompiliert: | Der C-Kernel wird mit diesem Befehl kompiliert: | ||
| − | $ gcc -m32 -ffreestanding -o kernel_c.o -c kernel.c -Wall -Werror - | + | $ gcc -m32 -ffreestanding -o kernel_c.o -c kernel.c -Wall -Werror -nostdinc |
| − | Damit erstellen wir eine Objektdatei, mit der wir nachher noch linken können. Es ist wichtig, dass keine | + | Damit erstellen wir eine Objektdatei, mit der wir nachher noch linken können. Es ist wichtig, dass keine Includes und damit auch keine Funktionen aus der Standardbibliothek des Hostsystems benutzt werden. Diese müssen erst selbst implementiert werden. |
| + | Eine genau Beschreibung der einzelnen Kommandozeilenparameter findet sich im [http://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html#Invoking-GCC GCC Handbuch (englisch)]. An dieser Stelle nur so viel: | ||
| + | * -m32 weißt gcc an den Code für den 32Bit Protected-Mode (im Gegensatz zu -m64) zu erstellen | ||
| + | * -ffreestanding weißt gcc an nicht davon auszugehen, dass eine Standardbibliothek zur Verfügung steht | ||
| + | * -nostdinc weißt gcc an keine Header aus der Standardbibliothek des Hostsystems bereitzustellen | ||
=== Linken === | === Linken === | ||
| − | Meiner Meinung nach ist dies der schwierigste Teil des "Zusammenbauens". Beim Linken wird unser Assembler-Kernel und unser C-Kernel miteinander verbunden und es wird z.B dem Assembler-Kernel auch gesagt wo die main-Funktion des C-Kernels liegt. Wir brauchen erstmal eine Konfigurationsdatei für ''ld'': | + | Meiner Meinung nach ist dies der schwierigste Teil des "Zusammenbauens". Beim Linken wird unser Assembler-Kernel und unser C-Kernel miteinander verbunden und es wird z.B dem Assembler-Kernel auch gesagt wo die main-Funktion des C-Kernels liegt. Wir brauchen erstmal eine Konfigurationsdatei/[[Linkerscript]] für ''ld'': |
<pre> | <pre> | ||
| Zeile 113: | Zeile 117: | ||
} | } | ||
</pre> | </pre> | ||
| − | |||
| − | |||
Nun wird gelinkt: | Nun wird gelinkt: | ||
$ ld -T <LD-Konfigurationsdatei> -o kernel.bin kernel_asm.o kernel_c.o | $ ld -T <LD-Konfigurationsdatei> -o kernel.bin kernel_asm.o kernel_c.o | ||
Wenn man später mehr Dateien hat, können diese natürlich auch dazugelinkt werden. Man sollte den fertigen Kernel jetzt in einer Datei namens ''kernel.bin'' haben. | Wenn man später mehr Dateien hat, können diese natürlich auch dazugelinkt werden. Man sollte den fertigen Kernel jetzt in einer Datei namens ''kernel.bin'' haben. | ||
| + | |||
| + | Mehr Informationen was genau dieses Linkerscript genau macht und warum es notwendig bzw. sinnvoll ist findet ihr im Artikel [[Linkerscript]]. An dieser Stelle nur so viel: | ||
| + | |||
| + | Mit "ENTRY(loader)" wird ld mitgeteilt, dass der Kernel bei der Funktion loader (siehe [[Kernel - Assembler | Assemblerteil des Kernels]]) beginnt. Dies wird in einem Datenfeld in der ELF-Header der "kernel.bin" festgehalten und von GRUB benötigt um zur richtigen Adresse zu springen. | ||
| + | |||
| + | Der Rest des Linkerscripts gibt an wo die Sektionen, das sind die Bereiche welche man in Assembler mittels des ".section .text" beispielsweise direkt angeben kann, aus den ELF-Objektdateien (kernel_asm.o und kernel_c.o) in der ELF-Binärdatei "kernel.bin" bzw. nach dem Laden im Speicher landen. Das ". = 0x00100000;" gibt an, dass die "kernel.bin" an Adresse 1MB gelinkt wird, d.h. sich nach dem Laden durch GRUB an Adresse 1MB und folgende im (physischen) Speicher befindet. | ||
| + | |||
| + | TODO: Rest | ||
== GRUB-Image erstellen == | == GRUB-Image erstellen == | ||