FASM Bootloader Woes

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

FASM Bootloader Woes

Post 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 :)
Last edited by xvedejas on Fri Jun 05, 2009 5:58 pm, edited 1 time in total.
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: FASM Bootloader Woes

Post 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
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: FASM Bootloader Woes

Post 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?
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: FASM Bootloader Woes

Post 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
User avatar
xvedejas
Member
Member
Posts: 168
Joined: Thu Jun 04, 2009 5:01 pm

Re: FASM Bootloader Woes

Post by xvedejas »

Thanks for your help guys, but no matter what I try the code seems to restart qemu at the long jump...
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: FASM Bootloader Woes

Post 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.
The continuous image of a connected set is connected.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: FASM Bootloader Woes

Post 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.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: FASM Bootloader Woes

Post 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 ).
The continuous image of a connected set is connected.
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: FASM Bootloader Woes

Post 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
Last edited by mathematician on Sat Jun 06, 2009 1:44 pm, edited 1 time in total.
The continuous image of a connected set is connected.
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: FASM Bootloader Woes

Post 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
User avatar
kop99
Member
Member
Posts: 120
Joined: Fri May 15, 2009 2:58 am

Re: FASM Bootloader Woes

Post 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
Post Reply