I'm trying to write bootloader that loads next sector and jump to execute it after enable a20 and go to protected mode. I had created this code:
;NOTE: Im assuming that dl is hard drive number when executing bootloader
org 0x7C00
bits 16
jmp 0:kernel_load
;setup gdt
gdt_start:
gdt_null:
dd 0x0
dd 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:
gdt_descriptor:
dw gdt_end - gdt_start
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
kernel_load:
;load kernel
reset:
mov ah,0
int 0x13
jc reset
mov ax,0x7E00
mov es,ax
xor bx,bx
read:
mov ah,0x02
mov al, 1
mov ch, 1
mov cl, 2
mov dh, 0
int 0x13
jc read
check_a20:
pushf
push ds
push es
push di
push si
cli
xor ax,ax
mov es,ax
not ax; ax = 0xFFFF
mov ds,ax
mov di,0x0500
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 check_a20_end
mov ax,1
check_a20_end:
pop si
pop di
pop es
pop ds
popf
ret
a20_enable:
inc bx
call check_a20
cmp ax,1
je a20_enable_end
mov ax,0x2401
int 0x15
call check_a20
cmp ax,1
je a20_enable_end
in al, 0x92
or al, 2
out 0x92, al
call check_a20
cmp ax,1
je a20_enable_end
jnz a20_enable
cmp bx,0x3
je boot_error
a20_enable_end:
;a20 enabled
;set gdt
lgdt[gdt_descriptor]
;clear registers
reload:
jmp 0x08:.reload_cs
.reload_cs:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret
;go to Pmode
mov eax, cr0
or al, 1
mov cr0, eax
;jump to kernel
jmp 0x7E00
boot_error:
mov bx,ErrorMSG
.print:
pusha
jmp .print1
.print1:
lodsb
or al,al
jz .print2
mov ah,0x0e
int 0x10
jmp .print1
.print2:
popa
ret
hlt
ErrorMSG db "Bootloader failure"
times 510-($-$$) db 0x0
db 0x55
db 0xAA
;==========
;Sector 2
;==========
bits 32
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
MSG db "working", 0
print:
pusha
mov edx, VIDEO_MEMORY
.loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je .done
mov [edx], ax
add ebx, 1
add edx, 2
jmp .loop
.done:
popa
ret
mov ebx,MSG
call print
hlt
when I trying to turn on this code on Bochs, its says "using of nonexisting segment register 7". When I trying to run this code on real computer, computer generate Triple Fault and restarts.
I based this code on following sources:
Enable A20 - http://wiki.osdev.org/A20
Load sector from disk - http://www.brokenthorn.com/Resources/OSDev5.html
Go to Protected Mode - http://wiki.osdev.org/Pmode
I am not really advanced programmer with assembly so I would be really thankful if someone could point my mistake thats generate Truple Fault, and explain why does this code don't work.
I also read somewhere that I need to jump to execution of 32 bit code after enabling A20, I tried to swap loading kernel, A20 and going to Protected Mode but with no success.
Update:
I had make some improvements to Jester comment. The code has been updated, but still I'm getting issue with it.
For now only to check does I had used gdt from code that was linked by Jester
I also used this source to help with GDT: http://wiki.osdev.org/GDT_Tutorial
Bochs could turn on now but it keep saying "using of nonexisting segment register 7". In debugger mode it stuck at mov bp, ??