Ausgabe 5 — Änderungen 1717 → 1862

Zeile 51: Zeile 51:
  
 
Hier sind einige weitere Warnungen zum Gebrauch von gcc und ld (obwohl das potentiell für jeden anderen Compiler / Linker zutrifft). Erstens setzt gcc gern die Stringliterale (Konstanten vom Stringtyp), die von Funktionen genutzt werden, einfach vor den Funktionscode. Normalerweise ist das kein Problem, aber ein paar Leute verheddern sich bei dem Versuch ihre Kernel "Hello, world" ausgeben zu lassen. Beachtet dieses Beispiel:
 
Hier sind einige weitere Warnungen zum Gebrauch von gcc und ld (obwohl das potentiell für jeden anderen Compiler / Linker zutrifft). Erstens setzt gcc gern die Stringliterale (Konstanten vom Stringtyp), die von Funktionen genutzt werden, einfach vor den Funktionscode. Normalerweise ist das kein Problem, aber ein paar Leute verheddern sich bei dem Versuch ihre Kernel "Hello, world" ausgeben zu lassen. Beachtet dieses Beispiel:
−
    int main(void)
+
<c>    int main(void)
 
     {
 
     {
 
         char *str = "Hello, world", *ch;
 
         char *str = "Hello, world", *ch;
Zeile 62: Zeile 62:
 
         for (;;)
 
         for (;;)
 
             ;
 
             ;
−
     }
+
     }</c>
  
 
Dieser Quelltext soll die Zeichenkette "Hello, World" in den Videospeicher schreiben, in weißem Text auf schwarzem Hintergrund, in der oberen liken Ecke des Bildschirms. Jedoch wird gcc, wenn es kompiliert ist, den Literalstring "Hello, world!" genau vor dem Code für main ausgeben. Wenn das nun als flaches Bnärformat gelinkt und ausgeführt wird, dann beginnt die Ausführung dort, wo sich der String befindet und die Maschine wird wahrscheinlich abstürzen. Es gibt ein paar Möglichkeiten, das zu umgehen:
 
Dieser Quelltext soll die Zeichenkette "Hello, World" in den Videospeicher schreiben, in weißem Text auf schwarzem Hintergrund, in der oberen liken Ecke des Bildschirms. Jedoch wird gcc, wenn es kompiliert ist, den Literalstring "Hello, world!" genau vor dem Code für main ausgeben. Wenn das nun als flaches Bnärformat gelinkt und ausgeführt wird, dann beginnt die Ausführung dort, wo sich der String befindet und die Maschine wird wahrscheinlich abstürzen. Es gibt ein paar Möglichkeiten, das zu umgehen:
Zeile 136: Zeile 136:
 
Die Information, die vom Loader angefordert wird, wird in einer Struktur gespeichert, welche wiederum irgendwo im Speicher abgelegt wird. Die Adresse wird vom Loader in EBX gespeichert. Das ist allerdings nur für Leute von Interesse, die vorhaben, ihrem C-Kernel noch ein Assembler-Script voranzustellen. Sie könnten dann einfach EBX `pushen` und den Pointer in main() übernehmen, etwa mit dem Funktionskopf
 
Die Information, die vom Loader angefordert wird, wird in einer Struktur gespeichert, welche wiederum irgendwo im Speicher abgelegt wird. Die Adresse wird vom Loader in EBX gespeichert. Das ist allerdings nur für Leute von Interesse, die vorhaben, ihrem C-Kernel noch ein Assembler-Script voranzustellen. Sie könnten dann einfach EBX `pushen` und den Pointer in main() übernehmen, etwa mit dem Funktionskopf
  
−
    int main(multiboot_info *mbi) { ... };  
+
<c>    int main(multiboot_info *mbi) { ... };</c>
  
 
Die Struktur `multiboot_info` ist in multiboot.h definiert, welche GRUB beiliegen sollte.
 
Die Struktur `multiboot_info` ist in multiboot.h definiert, welche GRUB beiliegen sollte.
Zeile 146: Zeile 146:
 
Zunächst einmal brauchen wir einen Prototyp von main(), da wir ja deren Offset in den Header schreiben wollen.
 
Zunächst einmal brauchen wir einen Prototyp von main(), da wir ja deren Offset in den Header schreiben wollen.
  
−
    void main(void);  
+
<c>    void main(void);</c>
  
 
Wunderbar. Jetzt zum Header.
 
Wunderbar. Jetzt zum Header.
  
−
    const unsigned MultibootHeader[12] = {
+
<c>    const unsigned MultibootHeader[12] = {
 
       0x1BADB002, // der magische Wert
 
       0x1BADB002, // der magische Wert
 
       0x00000000, // die Flags
 
       0x00000000, // die Flags
Zeile 163: Zeile 163:
 
       0x00000019, // 25 Zeilen
 
       0x00000019, // 25 Zeilen
 
       0x00000000 // 0 BPP, wir sind im Text-Modus
 
       0x00000000 // 0 BPP, wir sind im Text-Modus
−
     };
+
     };</c>
  
 
Da hätten wir unseren Multiboot Header. So lange der Kernel nicht zu groß wird, sollte alles funktionieren.
 
Da hätten wir unseren Multiboot Header. So lange der Kernel nicht zu groß wird, sollte alles funktionieren.
Zeile 175: Zeile 175:
 
Ja, und wenn der Kernel doch mal zu groß wird, lässt sich der Header ganz einfach am Anfang halten, indem man ihn folgendermaßen erstellt:
 
Ja, und wenn der Kernel doch mal zu groß wird, lässt sich der Header ganz einfach am Anfang halten, indem man ihn folgendermaßen erstellt:
  
−
    const unsigned  MultibootHeader[12] __attribute__  
+
<c>    const unsigned  MultibootHeader[12] __attribute__  
−
           ((section(".text"))) = { /* Header Information */ };
+
           ((section(".text"))) = { /* Header Information */ };</c>
  
 
Nach der entsprechenden Änderung meldet mbchk (das Multiboot Header Checksum Check Programm, boah!) den Header konstant bei 4096. (Danke an den hilfreichen Mensch vom BuHaBoard, der mir diesen Trick gezeigt hat. Leider fällt mir der Name nicht mehr ein...)
 
Nach der entsprechenden Änderung meldet mbchk (das Multiboot Header Checksum Check Programm, boah!) den Header konstant bei 4096. (Danke an den hilfreichen Mensch vom BuHaBoard, der mir diesen Trick gezeigt hat. Leider fällt mir der Name nicht mehr ein...)
Zeile 254: Zeile 254:
 
lizer@gmx.net
 
lizer@gmx.net
  
−
    /*
+
<c>    /*
 
       Memory Printing Example
 
       Memory Printing Example
 
       Written 2003 by Jonas Kramer
 
       Written 2003 by Jonas Kramer
Zeile 307: Zeile 307:
 
         putchar(*(s++));
 
         putchar(*(s++));
 
       return;
 
       return;
−
     };  
+
     };</c>
  
 
== Icy Wolf`s Kolumne ==
 
== Icy Wolf`s Kolumne ==