Autor Thema: Probleme mit der GDT  (Gelesen 4698 mal)

bartim

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« am: 02. January 2012, 03:25 »
Hi,

ich sitze nun schon seit mehreren Stunden vor folgendem Fetzen Code:

.global load_gdt

.section .rodata

gdt:
.quad $0x00000000
.quad $0x00cf8a000000ffff
.quad $0x00cf82000000ffff
.quad $0x00cfea000000ffff
.quad $0x00cfe2000000ffff

loader:
limit:
.word $0x107
base:
.int $gdt

.section .bss

loader_addr:
.space 1

.section .text


load_gdt:
mov $loader, %al
shl $2, %al
mov %al, loader_addr
mov $loader_addr, %eax
lgdt %eax
mov $0x0b, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
ret

GCC gibt mir beim Versuch, das zu assemblieren, folgende Fehlermeldung:

Zitat
gdt.S:31: Error: unsupported for `lgdt'

Kann da mal jemand einen Blick drauf werfen, der ein wenig mehr Ahnung von dem Thema hat als ich? Ich denke, ich werde nur irgendwo einen Anfängerfehler gemacht haben, für mich ist Assembler noch ziemliches Neuland...  :-)

mfg
bartim

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 02. January 2012, 04:24 »
Moin,
ich nehm das mal auseinander, ohne es zu testen:

Die Fehlermeldung wird davon verursacht, dass du nicht lgdt (%eax) schreibst. Der Befehl lgdt erwartet nämlich eine Speicherreferenz. Zum Beispiel wäre einfach lgdt loader_addr unter den meisten Umständen auch möglich gewesen.

Anschließend sollte dir dein Assembler eine Fehlermeldung geben, dass die $-Zeichen in den .quad-Anweisungen nicht funktionieren. Diese sind ebenso wie die bei .word $0x107 und .int $gdt fehlerhaft. Die $'s müssen in diesen Befehlen weg.

Wie bist du auf die Deskriptoren in der GDT gekommen? Für Kernel und User Space 4 GB Flat Memory musst du folgendes nehmen:
.quad 0x00000000
.quad 0x00cf9a000000ffff
.quad 0x00cf92000000ffff
.quad 0x00cffa000000ffff
.quad 0x00cff2000000ffff

Das hat dann diese Einteilung, die deiner GDT am nächsten kommt:
0x08 - Kernel Code
0x10 - Kernel Data
0x18 - User Code
0x20 - User Data
Wenn du die User Deskriptoren verwendest, musst du auf beide 3 addieren (weil User Mode = Ring 3), dann musst du CS und die anderen Segmentregister mit 0x1b bzw. 0x23 laden.

Dann ist noch das Limit der GDT zu groß. Der Wert sollte 5*8-1=39 (bzw. 0x27) sein.

Das Laden von $0x0b in die Datensegmente ist nicht korrekt. Vermutlich willst du erstmal eine Weile im Kernel Mode bleiben. Dann ist der korrekte Wert $0x10. (Wenn du irgendwann in den User Mode wechseln willst, ist 0x23 richtig.)

Was du mit dem folgenden Abschnitt bezweckst, ist mir nicht klar. mov $loader, %al
shl $2, %al
mov %al, loader_addr
Du dividierst da das untere Byte der Adresse der GDT durch 4 und schreibst es wieder irgendwo hin. Der Linker wird das vermutlich nicht akzeptieren.
« Letzte Änderung: 02. January 2012, 04:30 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

bartim

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 03. January 2012, 03:58 »
Hi,

hui, doch mehr Fehler, als ich dachte... Naja, wird schon noch werden.

Ich habe jetzt alles in meinen Quellcode eingearbeitet, und er kompiliert schon mal. Aktuell hängt sich der Kernel leider noch nach dem Laden der GDT auf, aber ich denke, jetzt komme ich alleine klar. Falls nicht, werd ich mich noch mal melden. Danke jedenfalls für deine Hilfe.  :-)

mfg
bartim

 

Einloggen