Running my code with qemu, right after calling switch_to_32_pm
, Qemu starts going crazy and constantly clearing the screen & displaying 'Booting from hard disk'. (I must add that I can't run with -curses
for some reason (-curses: curses or iconv support is disabled
) (i should really switch to linux...).
This is the relevant code:
boot.asm
[org 0x7c00]
[bits 16]
; initialise stack
mov bp, 0x9000
mov sp, bp
call switch_to_32_pm
jmp $
%include "gdt.asm"
%include "switch_to_pm.asm"
[bits 32]
BEGIN_PM:
jmp $
; bootsector padding
times 510-($-$$) db 0
dw 0xaa55
gdt.asm
gdt_start:
gdt_null: ; null descriptor
dd 0x0
dd 0x0
gdt_code: ; code segment descriptor
dw 0xffff ; limit (bits 0-15)
dw 0x0 ; base (bits 0-15)
db 0x0 ; base (bits 16 -23)
db 10011010b ; 1st flags, type flags
db 11001111b ; 2nd flags, Limit (bits 16-19)
db 0x0 ; base (bits 24 - 31)
gdt_data: ; data segment descriptor
dw 0xffff ; limit (bits 0-15)
dw 0x0 ; base (bits 0-15)
db 0x0 ; base (bits 16 -23)
db 10010010b ; 1st flags, type flags
db 11001111b ; 2nd flags, Limit (bits 16-19)
db 0x0 ; base (bits 24 - 31)
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of the gdt
dd gdt_start ; gdt start address
; some handy constants
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
switch_to_pm.asm
[bits 16]
; switch to 32bit protected mode
switch_to_32_pm:
; disable interrupts
cli
; switch to 32bit protected mode
lgdt [gdt_descriptor]
mov eax, cr0 ; move cr0 to eax
or eax, 0x1 ; set the first bit of eax
mov cr0 , eax ; update cr0
jmp CODE_SEG:init_32_pm ; make a far jump
; this forces the cpu to flush it's cache
; of pre fetched instructions
[bits 32]
; We're now in 32bit mode! 4gb hip hip hooray!
; init stack
init_32_pm:
mov ax, DATA_SEG ; point all segment regs to our data sector in gdt
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; set the stack at the top of free space
mov esp, ebp
call BEGIN_PM