1

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, ??

vakus
  • 732
  • 1
  • 10
  • 24
  • You need to use a far jump to reload `CS` and you need to reload the other registers too. You also need to set up a GDT first. See [this answer](http://stackoverflow.com/a/28645943/547981) for an example. – Jester Sep 02 '15 at 18:46
  • After setting up the lgdt you should go into protected mode and then do the far jmp to reload cs. – Michael Petch Sep 03 '15 at 04:25

1 Answers1

0

Your program already has some flaws early on.

  • Shouldn't you be reading the second sector from cylinder 0 instead of 1 ?
  • You forgot to jump over the check_a20 routine. Now you fall through and the ret has nowhere to go!
  • There's something amiss with the following code

    call check_a20
    cmp ax,1
    je a20_enable_end
    jnz a20_enable
    cmp bx,0x3
    je boot_error
    

    It will not retry based on a set maximum retries! The cmp bx,0x3 will never get executed.

  • Why does the next code block end with a ret? It is not a subroutine.

    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    mov ss,ax
    ret
    
  • When trying to display an error message you wrote mov bx,ErrorMSG but the code uses lodsb to retrieve the characters. You have to use the SI register.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76