zufalige daten
zufalige daten

Reputation: 63

Entering 32-bit protected mode does not work as intended

So recently, I decided to try using 32-bit code instead of 16-bit code for my basic OS kernel. I tried to enter 32-bit protected mode, but it doesn't seem to work correctly. I use NASM for building and qemu for debugging, but when I debug it, the qemu window begins to glitch a lot.

And it keeps glitching in what seems to be consistent bursts every half a second.

This is my kernel's code:

bits 32
org 0x7E00

 ; attempting to enter 32 bit protected mode
cli
lgdt [gdtr]
mov eax, cr0
or al, 1
mov cr0, eax
jmp 08h:kernel_main

gdt_start:
    dq 0x0
gdt_code:
    dw 0xFFFF
    dw 0x0
    db 0x0
    db 10011010b
    db 11001111b
    db 0x0
gdt_data:
    dw 0xFFFF
    dw 0x0
    db 0x0
    db 10010010b
    db 11001111b
    db 0x0
gdt_end:
gdtr:
    dw gdt_end - gdt_start
    dd gdt_start

 ; main kernel code

kernel_main:
     ; Display hi in grey at top of screen
    mov dword [0xb8000], 0x07690748
    hlt
    ret
times 1024-($-$$) db 0

It is supposed to display "Hi" in grey at the top of the screen, but that doesn't seem to be working.
I did some tests and found out that it probably has something to do with the way I tried to enter 32-bit protected mode. I searched everywhere online, but I couldn't find anything that works.

Upvotes: 2

Views: 317

Answers (2)

Sep Roland
Sep Roland

Reputation: 39166

Only put your bits 32 directive where the protected mode code actually starts. And once that happens, load the segment registers from the gdt_data selector. You might want to zero the upper 16 bits of the ESP register as well.

To save some space, you can put the GDT pointer over the NULL descriptor.
Do note that the correct GDT limit is gdt_end - gdt_start - 1

bits 16
org 0x7E00

    ; attempting to enter 32 bit protected mode
    cli
    lgdt  [gdtr]
    mov   eax, cr0
    or    al, 1
    mov   cr0, eax
    jmp   08h:kernel_main

gdt_start:
gdtr:
    dw gdt_end - gdt_start - 1
    dd gdt_start
    dw 0
gdt_code:
    dw 0xFFFF
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
gdt_data:
    dw 0xFFFF
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_end:

bits 32

kernel_main:
    ; main kernel code
    mov   eax, 0x10
    mov   ds, eax 
    mov   es, eax
    mov   fs, eax
    mov   gs, eax
    mov   ss, ax
    movzx esp, sp

    ; Display hi in grey at top of screen
    mov   dword [0xB8000], 0x07690748
    jmp   $

times 1024-($-$$) db 0

Upvotes: 1

TheNNX
TheNNX

Reputation: 26

You have to initialize the segment registers after the far jump to protected mode. Change you kernel_main to something like this

kernel_main:
    mov eax, 0x10
    mov ds, eax 
    mov es, eax
    mov fs, eax
    mov gs, eax
    mov ss, eax

     ; Display hi in grey at top of screen
    mov dword [0xb8000], 0x07690748
    hlt
    ret

Upvotes: 0

Related Questions