Page 1 of 1
FASM Bootloader Woes
Posted: Thu Jun 04, 2009 10:34 pm
by xvedejas
Problem:
Bootloader just causes the machine to restart, doesn't really boot or load...
Desired effect:
Load and jump to binary on second sector of the bootdisk, as well as entering 32-bit protected mode.
How to Reproduce:
Compile following code with fasm, run in qemu.
Code: Select all
use16
jmp main
nop
times 59 db 0ffh
nSectors db 1 ; number of sectors to load
main:
mov ax,0002h ; set video mode
int 10h
mov byte [0xB8000],"1"
mov byte [0xB8001],07h
@@: mov ax,0 ; reset floppy device
mov dl,0
int 13h
jc @b ; try again
loadKernel: ; Load the kernel to physical addresss 0:1000h
mov bx,0
mov es,bx
mov bx,1000h
mov ah,2 ; read sector function code
mov al,1 ; read 1 sector at a time
mov ch,0 ; read from track 0
mov dl,0 ; read from drive 0 (floopy)
mov dh,0 ; read from head 0
mov cl,2 ; sector counter - start from the second sector (first sector is bootloader)
@@: int 13h ; do it!
jc loadKernel ; try again.
cmp cl,[2 + nSectors] ; did we load enough?
je @f ; yep, continue
add bx,200h ; nope, do more
inc cl
jmp @b
@@: mov byte [0xB8002],"2"
mov byte [0xB8003],07h
cli ; no interrupts beyond this point
sub ax,ax
mov ds,ax ; set ds to zero for gdt
lgdt [gdt_desc]
mov eax,cr0
or al,1
mov cr0,eax
use32
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 00h:1000h ; Jump to the kernel
; Gdt
gdt:
gdt_null:
dd 0
dd 0
gdt_code:
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
times 510-$ db 00h
dw 0aa55h
I've been trying to figure this out for a while and done searches and looked at other's code and stuff but can't figure it out. Oh, and by the way, first post
Re: FASM Bootloader Woes
Posted: Thu Jun 04, 2009 10:54 pm
by geppyfx
Code: Select all
org 7c00h ;before 'jmp main '
...
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 7000h
...
push 0xb800h
pop es
mov byte [es:0], 'v'
mov byte [es:1], 7
;now add "jmp $" and test if you see the symbol
Code: Select all
loadKernel: ; Load the kernel to physical addresss 0:1000h
mov bx,0
mov es,bx
mov bx,1000h
mov ah,2 ; read sector function code
mov al,1 ; read 1 sector at a time
mov ch,0 ; read from track 0
mov dl,0 ; read from drive 0 (floopy)
mov dh,0 ; read from head 0
mov cl,2 ; sector counter - start from the second sector (first sector is bootloader)
@@: int 13h ; do it!
jc loadKernel ; try again.
infinite loop this is if int13 always fails
Code: Select all
use32
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 00h:1000h ; Jump to the kernel
jmp 00h:1000h refers to gdt_null
use
jmp 8:1000h or
jmp (gdt_code-gdt):1000h
and why use32 ?
Code: Select all
@@: int 13h ; do it!
jc loadKernel ; try again.
cmp cl,[2 + nSectors] ; did we load enough?
je @f ; yep, continue
add bx,200h ; nope, do more
inc cl
jmp @b
int13 might change CL, better use memory variable
after int13 AH has to be 0(if successful) which means you need to set it to 2h again, AL will be changed as well
Code: Select all
@@: mov ax,0 ; reset floppy device
mov dl,0
int 13h
jc @b ; try again
I personally wouldn't do any checking here at all, you check for errors after int13 ah=2
Re: FASM Bootloader Woes
Posted: Thu Jun 04, 2009 11:59 pm
by geppyfx
Code: Select all
nSectors db 1 ; number of sectors to load
...
cmp cl,[2 + nSectors] ; did we load enough?
je @f ; yep, continue
its either
nSectors = 1
or
Code: Select all
mov al, [nSectors]
add al, 2
cmp cl, al; did we load enough?
Re: FASM Bootloader Woes
Posted: Fri Jun 05, 2009 1:42 pm
by geppyfx
Hello again and welcome to both Fasm & osdev communities.
since you added "org 7c00h" your "times 510-$ db 00h" will no longer work
so:
Code: Select all
org 7c00h
use16
boot_sector:
jmp main
...
times 510-$+boot_sector db 00h
dw 0aa55h
and in the code where you jumping you should have "org 1000h"
maybe like this
Code: Select all
org 7c00h
use16
boot_sector:
jmp main
...
times 510-$+boot_sector db 00h
dw 0aa55h
;----------second sector starts---------
org 1000h
use32
; your code
this can be compiled as a single file and put at the beginning of floppy/usb
Re: FASM Bootloader Woes
Posted: Fri Jun 05, 2009 5:03 pm
by xvedejas
Thanks for your help guys, but no matter what I try the code seems to restart qemu at the long jump...
Re: FASM Bootloader Woes
Posted: Fri Jun 05, 2009 6:06 pm
by mathematician
Where do you reload ds after switching into protected mode? Unless ds contains an index into the gdt (referencing the data segment) any memory references will get you a general protection error. If there is no interrupt handler to service the exception, you are well on your way to a triple fault.
Re: FASM Bootloader Woes
Posted: Fri Jun 05, 2009 6:57 pm
by b.zaar
xvedejas wrote:
Code: Select all
cli ; no interrupts beyond this point
sub ax,ax
mov ds,ax ; set ds to zero for gdt
lgdt [gdt_desc]
mov eax,cr0
or al,1
mov cr0,eax
use32
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 00h:1000h ; Jump to the kernel
; Gdt
gdt:
gdt_null:
dd 0
dd 0
gdt_code:
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
times 510-$ db 00h
dw 0aa55h
I haven't checked it but a quick look at this shows me your using 32 bit code before you've jumped to a 32 bit descriptor/segment. The jump should be in 16 bit still.
Re: FASM Bootloader Woes
Posted: Sat Jun 06, 2009 3:09 am
by mathematician
Code: Select all
use32
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 00h:1000h ; Jump to the kernel
Looking again, that jump will load cs with zero, which will also get you a general protection error. Remember, you are in protected mode now, and the jump ought to load cs with a valid index into the gdt (such as 8 ).
Re: FASM Bootloader Woes
Posted: Sat Jun 06, 2009 5:59 am
by mathematician
Try this
Code: Select all
mov eax, cr0
or eax, 1
mov cr0, eax ;switch to protected mode
;--------- THIS IS THE VERY FIRST THING YOU SHOULD DO ONCE YOU ARE IN PROTECTED MODE| -------
db 0eah ;opcode for a far jump
dw offset label ;at least that's how masm would do it. fasm might be "dw label"
;in either case, it is the offset for the far jump
dw 8 ;code seg descriptor is eight bytes into the gdt (and what the
;far jump loads into cs)
label:
;---------------------AND THIS IS THE SECOND -------------------------
mov ax, 10h ;data seg descriptor is 16 bytes into the gdt
mov ds,ax ;load ds with valid seg selector
mov ss,ax ;load ss with valid seg selector
mov esp, 65534 ;or wherever you want to put your stack
......---------------------------------------------------------------------------------------------------------------------------------------------
......
......
......
jump to kernel
Re: FASM Bootloader Woes
Posted: Sat Jun 06, 2009 12:45 pm
by geppyfx
i think you didn't look good enough, there should be plenty of simple real -> protected mode sources in fasm or nasm.
Code: Select all
org 7c00h
boot_sector:
use16
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 7000h
;BIOS will put drive # for int13h in DL, save it !!
mov [_drive], dl
sti
mov dword [_signature], 0
mov ax, 3
int 10h
movzx dx, [_drive] ; DH = Head number (0-15), DL = Drive number
mov cx, 2 ; CH = Cylinder number (0-1023), CL = Sector number (1-17)
mov ax, 201h ;load single sector
mov bx, 1000h
int 13h
jc .error
cmp dword [_signature], 77bbbb77h
je .switch
.error:
push 0b800h
pop es
mov word [es:0], 0404h ;single red diamond
jmp $
.switch:
cli
mov eax, cr0
or eax, 1
lgdt [GDT.reg]
mov cr0, eax
jmp 8h:kernel_32bit
_drive db 0
GDT.reg:
.limit dw GDT.ends-GDT-1
GDT:
.addr dq GDT
; [ LIMIT | BASE | PDLSTYPE GD0ALIMT | BASE ]
.code32: db 0ffh, 0ffh, 0, 0, 0, 10011010b, 11001111b, 00 ; 8h
.data: db 0ffh, 0ffh, 0, 0, 0, 10010010b, 11001111b, 00 ; 10h
.ends:
times 510-$+boot_sector db 00h
dw 0aa55h
;----------second sector starts---------
org 1000h ;if loaded to 1000h
_signature dd 77bbbb77h ;preplaced signature
use32
kernel_32bit:
mov ax, 10h
mov ds, ax
mov dword [0b8000h+4], 0e040e04h ;2 yellow diamons displayed
jmp $
is it your switch to PM not working or maybe int 13h failed
Re: FASM Bootloader Woes
Posted: Sat Jun 06, 2009 11:34 pm
by kop99
Here is your code...
Code: Select all
mov eax,cr0
or al,1
mov cr0,eax
use32
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 00h:1000h
Change upper code by following and retry...
Code: Select all
mov eax,cr0
or al,1
mov cr0,eax
jmp 0x08:code_32
[bits 32]
code_32:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov gs, ax
mov byte [ds:0B8004h], '3'
mov byte [ds:0B8005h], 07h
jmp 08h:1000h