Reputation: 63
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
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
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