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, ??
CSand you need to reload the other registers too. You also need to set up a GDT first. See this answer for an example. - Jester