Lowlevel
Lowlevel => Das Wiki => Thema gestartet von: rejooh am 15. June 2013, 21:49
-
Zunächst mal einen wunderschönen guten Abend euch allen und ein gigantisches Lob für das Wiki, welches es mir ermöglicht hat, mit der Programmierung meines eigenen kleinen Betriebsystem zu beginnen. Vor Allem der ausführliche Erläuterungsstil der das Tutorial ergänzenden Artikel hat es mir ermöglicht fast jede Zeile nachzuvollziehen und selbstständig einige zusätzliche Features wie das auslesen der aktuellen Zeit der RTC und das verarbeiten von Tastatureingaben einzubauen. Aktuell bin ich dabei Multitasking (Tutorial Teil 6) hinzuzufügen und bin dabei bei folgenden Zeilen hängen geblieben, welche ich mir einfach nicht erklären kann:
/* Ring-0-Segmentregister */
.cs = 0x08,
, sowie:
/* Ring-3-Segmentregister */
.cs = 0x18 | 0x03,
.ss = 0x20 | 0x03,
woher kenne ich die Werte, auf welche ich die Segmentregister setzen muss? In der GDT habe ich doch festgelegt, dass alle Basis 0 und Limit 4GB haben. Oder rühren die Werte von einer anderen Quelle, die ich komplett übersehen, überlesen habe.
Meine zweite Frage bezieht sich auf die IDT. Im IDT Artikel sind Werte für die verschiedenen Interrupt Tyen angegeben. Interrupt Gate: 0b110 (0x6), Trap Gate: 0b111 (0x7), sowie Task Gate: 0b101 (0x5). Nutze ich diese allerdings in meiner IDT erhalte ich eine Global Protection Fault. Nach Recherche im Internet und Vergleich mit dem Beispiel Code bin ich neben diesen als 16Bit deklarierten Werten auch auf 32Bit Werte gestoßen: Interrupt Gate: 0xe, Trap Gate: 0xf. Mit diesen funktioniert alles einwandfrei. Jetzt habe ich die Frage, wo liegt der Unterschied?
Ich würde mich freuen wenn jemand meine Fragen beantworten könnte.
rejooh
-
Hallo,
wenn Du deine GDT anlegst dann schreibst Du neben der Basis und dem Limit auch einige andere Flags, u.a. in welchen Ring Du gerade arbeitest. Außerdem gibst Du eine Reihenfolge an. Segment 0 bleibt immer leer, in Segment 1 steht glaube ich dann das Code-Segment von Ring 0, in Segment 3 das Code-Segment von Ring 3 und in Segment 4 das Daten-Segment von Ring 3.
Da die Segmentregister aber nur 16 Bit haben, trägt man dort folgendes ein: Die unteren 2 Bit stehen für den Ring in dem man sich befinden möchte, also 0x0 für Ring 0 und 0x3 für Ring 3. Dann kommt ein Bit mit dem man angibt ob man mit GDT (Bit = 0) oder LDT (Bit = 1) arbeiten möchte. Die restlichen 13 Bit geben dann den Eintrag in Deine GDT/LDT an, also 0x1 für dein Code-Segment aus Ring 0. Da man aber die vorderen 3 Bit auch beachten sollte ergibt sich ein Wert von (0x1 << 3) | 0x0 = 0x8. Für Ring 3 ergibt sich dann (0x3 << 3) | 0x3 = 0x18 -> 0x18 | 0x3 = 0x1B.
Zu deiner IDT-Frage: 0xF = 0b1111, 0xe = 0b1110. Normalerweise gelten die 3 Bit Werte, und mit denen wird auch nomalerweise auch gearbeitet (zumindest ich tue das). Mit 0xf und 0xe überschreibst du nämlich schon das nächste Flag. Dieses gib an, ob du im Real- oder im Prodected-Mode arbeitest. Dieses Bit würde ich immer extra setzten, da es wieder auf 0 gestzt wird wenn man im Long-Mode arbeitet. Wenn du nur die 3 Bit Werte genommen hast ohne dieses Flag zu beschreiben dann kann Dein Code nicht funktionieren, da Du dich im Protected-Mode befindest und Deine IDT für eine CPU im Real-Mode gedacht wäre.
Gruß,
Streetrunner
-
wenn Du deine GDT anlegst dann schreibst Du neben der Basis und dem Limit auch einige andere Flags, u.a. in welchen Ring Du gerade arbeitest. Außerdem gibst Du eine Reihenfolge an. Segment 0 bleibt immer leer, in Segment 1 steht glaube ich dann das Code-Segment von Ring 0, in Segment 3 das Code-Segment von Ring 3 und in Segment 4 das Daten-Segment von Ring 3.
Um nochmal klarzustellen, woher diese Indizes kommen: Die sind der erste Parameter von set_entry in Teil 5 (http://www.lowlevel.eu/wiki/Teil_5_-_Interrupts#Global_Descriptor_Table) der Tutorials.
Real-Mode
16-Bit Protected Mode, aber ansonsten stimmt das.
-
Vielen dank für die schnellen Antworten, damit haben sich beide Fragen erübrigt.
Gute Nacht!