protected mode - ist er wirklich drin?
-
Ich habe heute endlich mal wieder seit langem meinen prekernel ohne Fehler kompilieren können. Da das Debuggen so verdammt schwer ist wollte ich mal ein paar Freaks von euch fragen, ob mein Code einen echten GDT setzt und ob der Prozessor wirklich in den PMode kommt (kompiliert mit NASM):
[BITS 16] ;16 BITS [org 0] struc GDTSTRUCT .limit: resw 1 .baseaddr: resd 1 endstruc struc DESCRIPTORSTRUCT .segment_size: resw 1 .segment_baddr_low: resw 1 .segment_baddr_high: resb 1 .access_flags: resb 1 .segment_size_high: resb 1 .segment_baddr_xhigh resb 1 endstruc struc SELECTORSTRUCT .flags_and_index resw 1 endstruc mov ax, 9000h mov ds, ax mov es, ax start: call cls mov si, secondstage_ok call putstr mov si, pmode_init call putstr pmode_initialize: cli cld setgdtr: global_table: istruc GDTSTRUCT at GDTSTRUCT.limit, dw 0x0000 at GDTSTRUCT.baseaddr, dd 0x00000000 iend lgdt [global_table] selector_dummy: istruc SELECTORSTRUCT at SELECTORSTRUCT.flags_and_index, dw 0x0000 iend lesen: mov ah, 0 int 0x16 retn putstr: lodsb or al, al jz short putstrd mov ah, 0x0E mov bx, 0x0007 int 0x10 jmp putstr putstrd: retn cls: ;Bildschrim löschen mov ax,0600h mov bh,07h xor cx,cx mov dx,1950h int 10h call jump200 retn jump200: mov ah, 0x02 mov bh, 0x00 mov dl, 0x00 mov dh, 0x00 int 10h retn reset: jmp 0xFFFF:0x0000 secondstage_ok db "[Second stage Bootloader successfully loaded...]", 13, 10, 0 pmode_init db "[Now setting up protected mode...]", 13, 10, 0 times 1024-($-$$) db 0
-
Also, folgende Sache vergisst du auf jeden Fall: Das PE-Bit setzen. Das geht so:
mov eax, cr0
or eax, 1
mov cr0, eaxOhne dem geht's auf keinen Fall. Genauer hab ich mir deinen Code aber noch nicht angeschaut, heißt also nicht dass alles richtig ist, dies ist mir jetzt gerade bloß sofort aufgefallen.
Ach ja: Ich finde keine Stelle wo du den Kernel (oder was das ist) in einen Stillsatnd bringst, so wie du es jetzt machst würde der Code einfach an den Stellen wo die Prozeduren sind fortgeführt, füge zum Testen also eine endlosschleife oder ähnliches hinzu.
-
Ich gehe jetzt folgendermaßen vor:
1. Einen leeren Global Description Table setzen
2. PE Bit setzenBOCHS meldet folgenden Abbruch:
3rd (13) exception with no resolutionIrgendwie habe ich das System noch nicht begriffen. Man erstellt also einen GDT. In den schiebt man dann irgendwie deskriptoren rein, die die einzelnen Segmente beschreiben. Was kommt dann? Und wozu sind Selektoren gut?
Und meine Endlosschleife will NASM garnicht akzeptieren:
loop:
jmp loopexpression syntax error
[ Dieser Beitrag wurde am 20.03.2003 um 20:41 Uhr von hackbert editiert. ]
-
Original erstellt von hackbert:
**Und meine Endlosschleife will NASM garnicht akzeptieren:
loop:
jmp loopexpression syntax error
***g* loop ist auch ein Assembler-Befehl.
-
shit, habe ich vergessen!
-
Original erstellt von hackbert:
**Ich gehe jetzt folgendermaßen vor:
1. Einen leeren Global Description Table setzen
**Leer ist garnicht gut. Jede GDT muss MINDESTENS den ersten Eintrag als dummyeintrag auf 0 haben, ein Code-Segment für den Kernel und ein Daten-Segment für den Kernel (wo dann auch der Stack reinkommt)
**
Irgendwie habe ich das System noch nicht begriffen. Man erstellt also einen GDT. In den schiebt man dann irgendwie deskriptoren rein, die die einzelnen Segmente beschreiben. Was kommt dann? Und wozu sind Selektoren gut?
**Dann schieb man erstmal vernünftige Deskriptoren rein
Die Selektoren sind dann die Werte die man in CS, DS, ES, etc. reinschreibt. Davon werden die untersten 2 Bits genommen um den Privileglevel zu bestimmen den der Anfrager haben will und der Rest um den passenden Deskriptor zu suchen.
Um noch einen Bug aufzuzeigen:
**```
pmode_initialize:
cli
cldsetgdtr:
global_table:
istruc GDTSTRUCT
at GDTSTRUCT.limit, dw 0x0000
at GDTSTRUCT.baseaddr, dd 0x00000000
iendlgdt [global_table]
Wenn ich das richtig sehe, packst du die Daten über die GDT mitten zwischen den Code. Das wird den Prozessor dazu verleiten, das dort steende versuchen, auszuführen. Pack die Daten lieber ganz am Ende, wo sie nicht ausgeführt werden können.
Ansonsten empfehle ich http://www.fh-zwickau.de/doc/prmo/pmtutor/text/ da wird das alles ganz gut beschrieben finde ich.
-
Original erstellt von TriPhoenix:
**
Leer ist garnicht gut. Jede GDT muss MINDESTENS den ersten Eintrag als dummyeintrag auf 0 haben, ein Code-Segment für den Kernel und ein Daten-Segment für den Kernel (wo dann auch der Stack reinkommt)
**Hat jemand dazu ein Codebeispiel. Das Tutorial habe ich übrigens schon gelesen und finde es etwas unübersichtlich, Codebeispiele wären gut.
[ Dieser Beitrag wurde am 21.03.2003 um 13:29 Uhr von hackbert editiert. ]
-
Hast du nicht mehr den Code von dem OS das ich damals angefangen hab? Dort wurde auch der PMode eingeschaltet, guck dir das mal an!
Ansontsne, ein gutes Tutorial ist auch noch dies hier (finde ich): http://my.execpc.com/~geezer/os/pm-de.htm
-
Original erstellt von hackbert:
**Hat jemand dazu ein Codebeispiel. Das Tutorial habe ich übrigens schon gelesen und finde es etwas unübersichtlich, Codebeispiele wären gut.
**Dann guck mal genau hin
Unter "Einschalten des Protected Mode" versteckt sich ein komplettes Beispiel