I'm currently developing a simple os and I decided to write all from scratch. In the second stage of the boot loader when I switch to protected mode it get stuck right after switching, and the emulator (QEMU) reboots.
Here's the boot loader stage 1:
org 0x7C00
;SEGMENTS
;bootloadter stage 1: 0x0000:0x7C00
;bootloader stage 2: 0x07E0:0x0100
;public data segment: 0x08E0:0x0000
;gdt: 0x1000:0x0000
;idt: 0x1000:0x0200
;kernel: 0x2000:0x0000
init:
;sets up the temporary data segment
xor ax,ax
mov ds, ax
;set up the stack
xor ax, ax
mov ss, ax
mov sp, 0x7C00
<<save the drive number>>
;reset the drive
call drive_reset
;loads IDT but does not load the idtr until we're in protected mode
call load_idt
;loads GDT
call load_gdt
lgdt [0x9E]
call load_stage2
call _wait
jmp 0x07E0:0x0100
jmp $
load_data_segment:
<<loads the shared data segment from disk>>
ret
load_stage2:
<<loads second stage from disk>>
ret
print:
<<print function>>
boot_failure:
<<boot failure function (alerts the user and halts the system)>>
_wait:
<<wait function (wait for the user to press a key)>>
reboot:
<<reboot function>>
;loads the initial gdt table from sector 9 to 0x1000:0x0000 (512 byte)
load_gdt:
mov si, 0x00
call print
mov ah, 0x2 ;subroutine
mov al, 0x1 ;numbers of sectors to be read
mov dl, [0xAA] ;drive number
mov ch, 0 ;cylinder number
mov dh, 0 ;head number
mov cl, 9 ;start sector (the first sector has index 1)
mov bx, 0x1000 ;segment
mov es, bx
mov bx, 0x0000 ;segment offset
int 0x13 ;drive low level routines
jc process_error
call drive_reset
call process_done
ret
;loads the initial idt table from sector 10 to 0x1000:0x0200 (512 bytes)
load_idt:
mov si, 0x10
call print
mov ah, 0x2 ;subroutine
mov al, 0x4 ;numbers of sectors to be read
mov dl, [0xAA] ;drive number
mov ch, 0 ;cylinder number
mov dh, 0 ;head number
mov cl, 0xA ;start sector (the first sector has index 1)
mov bx, 0x1000 ;segment
mov es, bx
mov bx, 0x200 ;segment offset (512 bytes), right after gdt
int 0x13 ;drive low level routines
jc process_error
call drive_reset
call process_done
ret
process_done:
<<print "[DONE]">>
process_error:
<<print "[ERROR]" and halts the system>>
drive_reset:
<<drive reset function>>
drive_number: db 0
times 510-($-$$) db 0x0
dw 0xAA55
Boot loader stage 2:
org 0x0100
;segment 0x07E0
;offset 0x0100
init:
cli
;sets up the data segment
mov ax, 0x08E0
mov ds, ax
;sets up the stack
mov ax, 0x07E0
mov ss, ax
mov sp, 0x0100
sti
;loads the kernel
mov si, 0x63 ;loading kernel...
call print
call load_kernel
call process_done
;enable A20
checkA20:
mov si, 0x20 ;checking A20...
call print
call A20_test
cmp ax, 1
je A20_enabled_func
jmp A20_disabled_func
continue: ;return point from A20 procedures
jmp enable_protected
_wait:
mov si, 0xB7
call print
mov ah, 0
int 0x16
ret
A20_disabled_func:
<<calls enable_A20 procedure and jumps to 'continue'>>
A20_enabled_func:
<<print "ENABLED">>
print:
<<print function>>
process_done:
<<prints "[DONE]">>
process_error:
<<prints "[ERROR]" and halts the system>>
A20_test:
pushf
push ds
push es
push di
push si
cli
xor ax, ax
mov es, ax
mov di, 0x0500
mov ax, 0xffff
mov ds, ax
mov si, 0x0510
mov al, byte es:[di]
push ax
mov al, byte ds:[si]
push ax
mov byte es:[di], 0x00
mov byte ds:[si], 0xFF
cmp byte es:[di], 0xFF
pop ax
mov byte ds:[si], al
pop ax
mov byte es:[di], al
mov ax, 0
je A20_test_exit
mov ax, 1
A20_test_exit:
pop si
pop di
pop es
pop ds
popf
ret
enable_A20:
cli
call a20wait
mov al, 0xAD
out 0x64, al
call a20wait
mov al, 0xD0
out 0x64, al
call a20wait2
in al, 0x60
push eax
call a20wait
mov al, 0xD1
out 0x64, al
call a20wait
pop eax
or al, 2
out 0x60, al
call a20wait
mov al, 0xAE
out 0x64, al
call a20wait
sti
ret
a20wait:
in al, 0x64
test al, 2
jnz a20wait
ret
a20wait2:
in al, 0x64
test al, 1
jz a20wait2
ret
load_kernel:
mov ah, 0x2 ;subroutine
mov al, 0x1 ;numbers of sectors to be read
mov dl, [0xAA] ;drive number
mov ch, 0 ;cylinder number
mov dh, 0 ;head number
mov cl, 21 ;start sector (the first sector has index 1)
mov bx, 0x2000 ;segment
mov es, bx
mov bx, 0x0 ;segment offset
int 0x13 ;drive low level routines
jc process_error
ret
enable_protected:
mov si, 0x43 ;switching to protected mode...
call print
call _wait
mov eax, cr0
or eax, 1
mov cr0, eax ;--------HERE IS THE PROBLEM--------
bits 32
mov ax, 0x8
mov cs, ax
jmp 0x2000
times 2560-($-$$) db 0xAE
I use the nasm compiler and qemu as emulator on x86 architecture. I thank anyone who has read this far without changing their mind :D I wish I could post everything but the site says it looks like spam...