Protected Mode - Bootloader
Posted: Tue May 08, 2001 11:23 pm
First off - great site!!!!
I am an assembly beginner, I can seem to work out what's wrong with the bootloader listed below. I used to use just a simple call to int 0x13 to load in the sectors (ignoring track's etc..) until the kernel size got to about 50 sectors - it would no longer work :-)
Having looked at various bootloaders out there I have changed it to load in a track at a time - but this does not work - anyone any ideas??
%define KERNEL_SIZE 60
[BITS 16]
[ORG 0]
jmp short start
nop
driveSectors db 18
driveHeads db 1
start: cli ; disable interrupts
mov ax, 0x7c0 ; BIOS sticks us here
mov ds, ax ;
mov ax, 0x9000 ; setup stack
mov ss, ax
sti ; enable interrupts
mov [bootdrive], dl ; save the bootdrive
mov si, bootmsg ; display bootmsg
call writechars
mov ah, 0
int 0x13
jc reseterror
startloadKernel:
mov ax, KERNEL_SIZE
div byte [ds:driveSectors]
mov si, ax
and si, 0xff
inc si
mov ax, 0x200 ; kernel load addr
mov es, ax
xor bx, bx
mov al, [ds:driveSectors] ; number of sectors to read
mov cx, 0x0002
loadKernel:
mov ah, 2
mov dl, [bootdrive]
int 0x13
jc loadKernel
dec si ; sectors to read --
jz readDone ; are we finished?
mov bx, es ;
add bx, 9216
mov es, bx
mov al, [ds:driveSectors]
xor bx, bx
readNextTrack:
mov cl, 1 ; reset back to sector 1
cmp dh, [ds:driveHeads]
je resetHeads
inc dh ; head++
jmp loadKernel
resetHeads:
xor dh, dh ; back to head 0, inc track
inc ch ; track++
jmp loadKernel
readDone:
mov si, kernelmsg ; display kernel loaded msg
call writechars
mov al, 0xff ; disable all irq's
out 0x21, al ; write to PIC controller
lgdt [gdt_ptr]
mov eax, cr0 ; get into protected mode
or al, 1
mov cr0, eax
mov ax, datasel ; setup segments to new selector
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov gs, ax
jmp codesel:0x2000 ; jump into prot mode
jmp $
reseterror:
mov si, reseterrormsg
call writechars
jmp $
writechars:
lodsb
or al, al
jz .done
mov ah, 0x0e
mov bx, 7 ; write text
int 0x10
jmp writechars
.done:
ret
; data section
bootmsg db 0dh, 0ah, "Booting..", 00h
kernelmsg db 0dh, 0ah, "Kernel loaded", 00h
resetfloppymsg db 0dh, 0ah, "Reset Floppy", 00h
reseterrormsg db 0dh, 0ah, "Reset error", 00h
loaderrormsg db 0dh, 0ah,"Unable to load operating system kernel.", 0dh, 0ah, 00h
dotmsg db "."
bootdrive db 0
gdt_ptr
dw end_gdt - start_gdt - 1
dd start_gdt
start_gdt
dd 0x00000000 ; dummy selector
dd 0x00000000
codesel equ $-start_gdt
code0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x9a ; priv level 0, code
db 0xcf ; granurlarity
db 0x00 ; base address
datasel equ $-start_gdt
data0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x92 ; priv level 0, data
db 0xcf ; gran
db 0x00 ; base address
stacksel equ $-start_gdt
stack0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x92 ; 0, data
db 0xcf ; gran
db 0x00 ; base address
end_gdt
; pad out sector
outside: times (510-($-$$)) db 0
; boot signature (last 2 bytes)
dw 0x55AA
I am an assembly beginner, I can seem to work out what's wrong with the bootloader listed below. I used to use just a simple call to int 0x13 to load in the sectors (ignoring track's etc..) until the kernel size got to about 50 sectors - it would no longer work :-)
Having looked at various bootloaders out there I have changed it to load in a track at a time - but this does not work - anyone any ideas??
%define KERNEL_SIZE 60
[BITS 16]
[ORG 0]
jmp short start
nop
driveSectors db 18
driveHeads db 1
start: cli ; disable interrupts
mov ax, 0x7c0 ; BIOS sticks us here
mov ds, ax ;
mov ax, 0x9000 ; setup stack
mov ss, ax
sti ; enable interrupts
mov [bootdrive], dl ; save the bootdrive
mov si, bootmsg ; display bootmsg
call writechars
mov ah, 0
int 0x13
jc reseterror
startloadKernel:
mov ax, KERNEL_SIZE
div byte [ds:driveSectors]
mov si, ax
and si, 0xff
inc si
mov ax, 0x200 ; kernel load addr
mov es, ax
xor bx, bx
mov al, [ds:driveSectors] ; number of sectors to read
mov cx, 0x0002
loadKernel:
mov ah, 2
mov dl, [bootdrive]
int 0x13
jc loadKernel
dec si ; sectors to read --
jz readDone ; are we finished?
mov bx, es ;
add bx, 9216
mov es, bx
mov al, [ds:driveSectors]
xor bx, bx
readNextTrack:
mov cl, 1 ; reset back to sector 1
cmp dh, [ds:driveHeads]
je resetHeads
inc dh ; head++
jmp loadKernel
resetHeads:
xor dh, dh ; back to head 0, inc track
inc ch ; track++
jmp loadKernel
readDone:
mov si, kernelmsg ; display kernel loaded msg
call writechars
mov al, 0xff ; disable all irq's
out 0x21, al ; write to PIC controller
lgdt [gdt_ptr]
mov eax, cr0 ; get into protected mode
or al, 1
mov cr0, eax
mov ax, datasel ; setup segments to new selector
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov gs, ax
jmp codesel:0x2000 ; jump into prot mode
jmp $
reseterror:
mov si, reseterrormsg
call writechars
jmp $
writechars:
lodsb
or al, al
jz .done
mov ah, 0x0e
mov bx, 7 ; write text
int 0x10
jmp writechars
.done:
ret
; data section
bootmsg db 0dh, 0ah, "Booting..", 00h
kernelmsg db 0dh, 0ah, "Kernel loaded", 00h
resetfloppymsg db 0dh, 0ah, "Reset Floppy", 00h
reseterrormsg db 0dh, 0ah, "Reset error", 00h
loaderrormsg db 0dh, 0ah,"Unable to load operating system kernel.", 0dh, 0ah, 00h
dotmsg db "."
bootdrive db 0
gdt_ptr
dw end_gdt - start_gdt - 1
dd start_gdt
start_gdt
dd 0x00000000 ; dummy selector
dd 0x00000000
codesel equ $-start_gdt
code0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x9a ; priv level 0, code
db 0xcf ; granurlarity
db 0x00 ; base address
datasel equ $-start_gdt
data0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x92 ; priv level 0, data
db 0xcf ; gran
db 0x00 ; base address
stacksel equ $-start_gdt
stack0
dw 0xffff ; segment limit
dw 0x0000 ; base address
db 0x00 ;
db 0x92 ; 0, data
db 0xcf ; gran
db 0x00 ; base address
end_gdt
; pad out sector
outside: times (510-($-$$)) db 0
; boot signature (last 2 bytes)
dw 0x55AA