pmode die n-te



  • Ein sorry vorweg, ich wette das Thema hängt euch langsam zum Hals raus 🙂 -
    aber leider hat die Suche mir auch nicht weitergeholfen...
    Ich leide beim Versuch einen Code hinzukriegen, der ordentlich in den pmode schaltet, unter den ständig anderen und immer unerklärlicheren Fehlermeldungen von Bochs....

    Dabei gibt es mir folgende Fehlermeldung aus:

    00000485357p[CPU  ] >>PANIC<< jump_protected: tss_selector.ti=1
    00000485357i[SYS  ] Last time is 1076004264
    00000485357i[CPU  ] protected mode
    00000485357i[CPU  ] CS.d_b = 16 bit
    00000485357i[CPU  ] SS.d_b = 16 bit
    

    Nach meinem eher bescheidenem "Verständnis" des pmode dürfte so eine Meldung jedoch niemals zurückgegeben werden, da ich keinerlei Gates und ähnliches anlege, lediglich einfache Deskriptoren.

    Durch auskommentieren habe ich herausgefunden, dass sich der Fehler auf den jmp bezieht, der den prefetch - queue leeren soll - was mir jedoch auch nicht großartig weiterhilft, aber vieleicht ja euch?!?

    Hier mein Nasmcode:

    [BITS 16]       ; We need 16-bit intructions for Real mode
    
    [ORG 0x7C00]    ; The BIOS loads the boot sector into memory location 0x7C00
    
    start:         
    
    ; Codesegment Basisadresse in gdt_code und gdt_data eintragen
       	xor ebx,ebx
    	mov bx,ds                       ; BX=segment
    	shl ebx,4                       ; BX="linear" address of segment base
    	mov eax,ebx
    	mov [gdt_code + 2],ax               ; set base address of 32-bit segments
    	mov [gdt_data + 2],ax               
    	shr eax,16
    	mov [gdt_code + 4],al
    	mov [gdt_data + 4],al
    
    	mov [gdt_code + 7],ah
    	mov [gdt_data + 7],ah
    
    	;gdt_base eintragen   
       	xor ebx,ebx
       	mov bx,cs
       	shl ebx,4
       	mov eax,ebx        
     	lea eax,[ebx + gdt]         ; EAX=PHYSICAL address of gdt
       	mov [gdt_desc+2],eax
       	mov eax, 0x18
       	mov [gdt_desc], eax ;Limit setzen
    
    	cli  
    
    	lgdt  [gdt_desc]         ; Load the GDT descriptor
    
    	mov eax, cr0            ; Copy the contents of CR0 into EAX
            or eax, 1               ; Set bit 0
            mov cr0, eax            ; Copy the contents of EAX into CR0
    
         	db 0x0EA
       	dw pmode
       	dw 0x08    
    
    [BITS 32]                       ; We now need 32-bit instructions
    pmode:
    	mov eax, 0x10             ; Move a valid data segment into the data segment register
            mov ds, eax             
            mov ss, eax
            mov es,eax
            mov fs, eax 
    
               	;mov byte [ds:0B8000h], 'P'      ; Move the ASCII-code of 'P' into first video memory
               	;mov byte [ds:0B8001h], 1Bh      ; Assign a color code
    
    gdt:                   
    
    gdt_null:               ; Null Segment
            times 8 db 0
    
    gdt_code:               
            dw 0xFFFF
            dw 0
            db 0
            db 10011010
            db 11000000
            db 0
    
    gdt_data:               
            dw 0xFFFF
            dw 0
            db 0
            db 10010110
            db 11000000
            db 0
    
    gdt_end:                ; Used to calculate the size of the GDT
    
    gdt_desc:                       ; The GDT descriptor
    dw  0  ; Limit (size)
    dd   0              ; Address of the GDT
    
    times 510-($-$$) db 0
    dw 0AA55h
    

    Wird irgendwer aus der Fehlermeldung in dem Zusammenhang schlau?!? Ich verstehe jedenfalls nicht, wie das kommt, das er so ein Deskriptor fürn Tss-gate hält.



  • Hi.

    An deinem Code stimmt tatsaechlich was nicht. :p
    Ich werde das mal von oben nach unten durchgehen und Optimierungsvorschlaege sowie Fehlerbeschreibungen auflisten:

    Erstmal kannst du dir die Codezeilen 10 bis 32 komplett schenken.
    Die physikalischen Speicheradressen in deinem Bootblock sind immer die selben, also brauchst du sie nicht jedes mal neu berechnen zu lassen.
    Da die Basisadressen vom Code und Datensegment eigentlich schon richtig eingetragen sind (0), reicht es, wenn du einfach og. Codezeilen loeschst.
    Lediglich die Daten bei "gdt_desc:" muesstest du dann noch aendern.
    Also statt 0, gleich die richtige Groesse der GDT (die ist schliesslich auch bekannt) und die Basisadresse eintragen (das waere hier einfach gdt_desc).

    Mal abgesehen davon, dass dieser Code eh ueberfluessig ist, werde ich ihn trotzdem nochmal durchgehen:
    Wieso schiebst du in Zeile 14 ebx nach eax? Diese Codekonstruktion macht IMHO keinen Sinn.
    Das gleiche eigentlich auch in Zeile 28.
    In Zeile 29 haette es dann auch ein "lea ebx, [ebx + gdt]" oder ein einfaches "add ebx, gdt" getan. 😉

    In den Zeilen 31/32 liegt dann vermutlich der Fehler, der deinen Code crashen laesst: Du schreibst eax (bekanntlich 32Bit lang) in das nur 16Bit lange "Limit"-Feld von gdtr, und zwar nachdem du dahinter bereits die Basisadresse eingetragen hast. => Die Basisadresse wird auf 0x00000000 zurueckgesetzt.

    In den Zeilen 49 bis 52 versuchst du ein 32Bit-Register in 16Bit lange Segmentregister zu stauchen?

    Die auskommentierten Zeilen 55/56 wuerden in deinem urspruenglichen Code wohl auch nicht zum Gewuenschten Erebnis fuehren, da dein Datensegment bei der Basisadresse von ds beginnt und nicht bei 0.

    Und zum Schluss noch zu den Descriptoren selbst:
    Wieso ist dein Datensegment nach unten erweiterbar, wenn es bei 0 anfaengt? Das macht keinen Sinn. Benutze hier besser ein normales Datensegment (Typ 001).

    So, ich hoffe, dass ich nichts vergessen habe. 😃


Anmelden zum Antworten