Protected Mode lässt sich nicht aktivieren



  • Hallo,
    also ich habe ein real-mode OS gebastelt, was über ein Konsole verfügt und somit Eingaben vom Nutzer entgegen nehmen kann. Der Bootvorgang sieht eigentlich so aus, dass sich im ersten Sektor der Diskette der Bootloader befindet und dieser einfach die Sektoren 2-19 an die Adresse 0X1000:0x0000 im Arbeitsspeicher lädt und an diese Stelle springt und somit mein real-mode OS startet. Das klappt soweit wunderbar. Nun soll, wenn der Nutzer auf der Konsole PM eingibt, der Protected Mode gestartet werden. Allerdings stürzt das System ab und der PC startet sich neu (CPU error wahrscheinlich). Ich weiß leider nicht was ich falsch gemacht habe, da ich das pmode Tutorial befolgt habe, aber vielleicht habe ich ja was übersehen. Hier mal der Code

    ; Code ist an der Stelle 0x1000x0x0000 im Speicher
    
    ; Hier befindet sich ganz viel Code von meinem real-mode OS
    
    ; Benutzer macht Eingabe 'PM':
    
            jmp kernel_pmode:
    
    ; Hier sind zum Teil noch weiter Funktionen des real-mode OS
    
    ; Hier gehts nun los
    kernel_pmode:
    
    	jmp p_start
    
    gdt:
    
    gdt_null:
        dd 0x00
        dd 0x00
    
    gdt_code:
        dw 0xFFFF		; Größe von 65535
        dw 0x00
        db 0x1000		;Programmcode befindet sich ja momentan an der Stelle 0x1000:0x0000
        db 10011010b	;Segment ist im Speicher, hat die Privilegstufe 0, ist ausführbar und lesbar
        db 11001111b	;Einheit 4096 KB, 80386 Segment
        db 0x00
    
    gdt_data:
    	dw 0xFFFF		; Größe von 65535
        dw 0x00
        db 0x1000		;Programmcode befindet sich ja momentan an der Stelle 0x1000:0x0000
        db 10010010b	;Segment ist im Speicher, hat die Privilegstufe 0, lesbar und schreibbar 
        db 11001111b	;Einheit ist 4096 KB, 80386 Segment
        db 0x00
    
    gdt_end:
    
    GDT32:
    	Limit	dw gdt_end - gdt - 1    ; Limit (size)
        BaseAdr	dd gdt
    
    p_start:
    	lgdt [GDT32]
    
    	cli
    
    	mov eax, 000000011h
    	mov cr0, eax
    
    	; "FAR-JMP" zu Selektor:Offset (entspricht jmp 8:pmode)
        db 0eah
        dw now_in_prot
        dw 0x08
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; 32-Bit protected mode
    ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    now_in_prot:
    
    	jmp $
    


  • gdt_code:
        dw 0xFFFF		; Größe von 65535
        dw 0x00
        db 0x1000		;Programmcode befindet sich ja momentan an der Stelle 0x1000:0x0000
    

    Die letzte Zeile laesst sich so assemblieren? Ueberraschend - muss entweder ein Fehler im Assembler sein, oder wird automatisch als binaer interpraetiert.
    Wie auch immer: In beiden faellen kommt mit Sicherheit nicht das raus, was du dir dabei gedacht hast.
    Ein byte (angezeigt durch db) hat einen Wertebereich von 0x00 bis 0xFF. 0x1000 passt nicht in ein Byte.
    Die Basisadresse wuerde stimmen, wenn du 0x10 eintraegst. ... Das selbe bei gdt_data.

    GDT32:
    	Limit	dw gdt_end - gdt - 1    ; Limit (size)
        BaseAdr	dd gdt
    

    Die -1 gehoert da IMHO nicht hin. Weiters brauchst du dir auch gar nicht gross mit irgendwelchen Label-Frickeleien einen abzubrechen. Das Limit ist einfach die Anzahl deiner Deskriptoren (inkl. des 0.) * 8 - also in deinem Fall 3*8.
    Bei der Basisadresse musst du bedenken, dass es sich hier um die 32Bit breite physikalische Adresse deiner GDT handelt. Wenn du in diesem Segment relativ zu Segment 1000h adressierst, spuckt der Assembler hier wahrscheinlich auch ein zu 1000h relatives Offset aus - das ist natuerlich nicht gleich der physikalischen Adresse! Wenn du also 0x10000 zu dem Offset addierst, sollte es stimmen. Was fuer speziellere Anweisungen zum Aendern von relativen Offsets dein Assembler bietet, bitte selbst in der Anleitung nachlesen.

    mov eax, 000000011h
    	mov cr0, eax
    

    Du solltest es nach Moeglichkeit vermeiden, CR0 so komplett um zu kraempeln.
    Besser zuerst cr0 nach eax kopieren, eax mit 1 verodern und dann zurueck nach cr0 schieben.

    Das ist erstmal alles, was mir aufgefallen ist.



  • Hab nun alles nach deinen Kritikpunkten geändert (übrigens nutze ich NASM mal am Rande erwähnt). Klappt leider immer noch nicht. Könnte es vielleicht Probleme mit der ORG Anweisung geben? Ich meien mein Bootloader ist ja bei ORG 0x7C00 und läd von dort aus mit int 13h die daten nach 0x1000:0x0000. Sollte da vielleicht noch ein zusätzliche org Anweisung in den Kernel? Habe da mal eine drin gehabt (org 0x1000), aber da lief der Kernel dann gar nicht mehr und deswegen habe ich sie wieder weggelassen.

    Ein kleiner Fortschriit sollte wohl die Tatsache sein, dass der Rechner nicht sofort rebootet, sondern jetzt ca 3-4 Sekunden scheinbar im protected mode ist (oder darin umschaltet), dann aber trotzdem neustartet.



  • org laesst dich einfach gesagt das aktuelle Offset festlegen.
    Wenn du also an den Anfang deines Kernels org 1000h schreibst, bedeutet das praktisch, dass das erste Label das offset 1000h hat. Genaueres steht in der NASM-Anleitung.
    Weiters solltest du, wenn du 32Bit-Code ausfuehren willst, dem Assembler auch mitteilen, dass er 32Bit-Code erzeugen soll (siehe wieder Anleitung).
    Sonst kann ich keine Fehler entdecken. Jag das alles ggf. doch mal durch bochs oder irgendeinen aehnlichen Debugger.



  • Hi,
    also bin die Sache nun mit Bochs durchgegangen und hier ist das Resultat

    00200832996i[CPU0 ] BxError: instruction with opcode=0xff
    00200832996i[CPU0 ] mod was c0, nnn was 7, rm was 7
    00200832996i[CPU0 ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
    00200832996i[CPU0 ] protected mode
    00200832996i[CPU0 ] CS.d_b = 32 bit
    00200832996i[CPU0 ] SS.d_b = 16 bit
    00200832996i[CPU0 ] EFER   = 0x00000000
    00200832996i[CPU0 ] | RAX=0000000000000011  RBX=0000000000000001
    00200832996i[CPU0 ] | RCX=0000000000000607  RDX=0000000000000e00
    00200832996i[CPU0 ] | RSP=000000000000fffc  RBP=0000000000000000
    00200832996i[CPU0 ] | RSI=00000000ffff0849  RDI=0000000000080000
    00200832996i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
    00200832996i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
    00200832996i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
    00200832996i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
    00200832996i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
    00200832996i[CPU0 ] | SEG selector     base    limit G D
    00200832996i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
    00200832996i[CPU0 ] |  CS:0008( 0001| 0|  0) 10010aac 000fffff 1 1
    00200832996i[CPU0 ] |  DS:1000( 0005| 0|  0) 00010000 0000ffff 0 0
    00200832996i[CPU0 ] |  SS:9000( 0005| 0|  0) 00090000 0000ffff 0 0
    00200832996i[CPU0 ] |  ES:0000( 0005| 0|  0) 00000000 0000ffff 0 0
    00200832996i[CPU0 ] |  FS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
    00200832996i[CPU0 ] |  GS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
    00200832996i[CPU0 ] |  MSR_FS_BASE:0000000000000000
    00200832996i[CPU0 ] |  MSR_GS_BASE:0000000000000000
    00200832996i[CPU0 ] | RIP=0000000000000af1 (0000000000000af1)
    00200832996i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
    00200832996i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
    00200832996i[CPU0 ] >> (invalid)  : FFFF
    00200832996e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
    

    Und zum besseren Vergleich hier nochmal der modifizierte Quellcode meines OS:

    ...
    ...
    ...
    ...
    
    kernel_pmode:
    
        jmp p_start
    
    gdt:
    
    gdt_null:
        dd 0x00
        dd 0x00
    
    gdt_code:
        dw 0xFFFF       
        dw 0x00
        db 0x10         
        db 10011010b    
        db 11001111b    
        db 0x10
    
    gdt_data:
        dw 0xFFFF       
        dw 0x00
        db 0x10         
        db 10010010b    
        db 11001111b    
        db 0x00
    
    gdt_end:
    
    GDT32:
        Limit		dw 3 * 8
        BaseAdr		dd gdt + 0x10000
    
    p_start:
    	mov ax,cs
        and eax,0FFFFh
        shl eax,4
        add ax,p_start
    
        mov word [gdt_code+2],ax
        shr eax,16
        mov byte [gdt_code+4],al
    
        mov ax,cs
        and eax,0FFFFh
        shl eax,4
        add ax,p_start
    
        mov word [gdt_data+2],ax
        shr eax,16
        mov byte [gdt_data+4],al
    
        lgdt [GDT32]
    
        cli
    
        mov eax, cr0
    	or al,1
    	mov cr0,eax
    
        ; "FAR-JMP"
        db 0eah
        dw now_in_prot
        dw 0x08
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; 32-Bit protected mode
    ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    [BITS 32]
    now_in_prot:
    
    	jmp $
    

Anmelden zum Antworten