assemblybootloaderbootfasm

FASM bootloader in bochs hlp


I was trying to write my own bootloader on fasm assembly, but unsucces.

Result: Prefetch: EIP 00010000 > CS.limit 0000ffff

Code:

org 0x7C00

mov ax, 0x02

int 0x10

mov si, boot_msg

call printf

mov al, 0x01 ; secror to read
mov bx, 0x7E00 ; dest
mov cx, 0x0002 ; cylinder:sector
mov dl, 0x01 ; floppy
call disk_read

mov ax, 0x7E00
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x7E00:0x0000

include 'disk.asm'
include 'printh.asm'

boot_msg db 'R-OS BOOTLOADER       
              ',\
'KERNEL CHS 0 0 1', 0x00

times 510-$+$$ db 0x00
dw 0xAA55
;;;;;;;;; kernel! ;;;;;;;;;;
org 0x7E00

mov ah, 0x0E
mov al, 'X'
int 0x10
cli hlt

times 4096-512-$+$$ db 0x00

disk.asm:

disk_read:
  pusha
  mov si, 0x02
.top:
  mov ah, 0x02
  int 0x13
  jnc .end
  xor ah, ah
  int 0x13
  jnc .top
  jc .err
.end:
  popa
  ret
.msg db 'disk rw err', 0x00
.err:
  popa
  pusha
  mov ah, 0x0E
  mov si, .msg
  jmp .l
.l:
  lodsb
  cmp al, 0x00
  je .end
  int 0x10

printh.asm just have print functions.

I cant understand, why it is doesn't work. I was trying a lot of variants of solve, but not one working in this list.

please, help


Solution

  • To successfully use the BIOS.ReadSectors function 02h, you need to setup all its parameters! You didn't initialize the ES segment register, nor did you specify the head number in the DH register. Presumably you think that all registers start out with zero, but this is not the case! The only register that your bootloader receives is the DL register that holds the number for the boot drive. That will be the number that you need to provide to this function.

    You are loading the additional sector at offset address 0x7E00. Because ES=0 (assuming), this is segmented address 0x0000:0x7E00. You can jmp to this address in a number of ways, but if you want to do it with a zero offset, then the segment part will have to be 0x07E0. That's how segmentation works.

    You can read more about bootloaders in my answer at (https://stackoverflow.com/questions/34216893/disk-read-error-while-loading-sectors-into-memory/34382681?r=SearchResults&s=21|9.2814#34382681) and in Michael Petch's answer at (https://stackoverflow.com/questions/32701854/boot-loader-doesnt-jump-to-kernel-code/32705076?r=SearchResults&s=46|10.4269#32705076).

    This is an improved version:

    ORG  0x7C00
    
    xor  ax, ax     ; Setup segment registers in accordance with the `ORG 0x7C00`
    mov  ds, ax
    mov  es, ax
    mov  ss, ax
    mov  sp, 0x7C00
    cld             ; Once at the top of every program
    
    mov  ax, 0x0003
    int  0x10
    
    mov  si, boot_msg
    call printf
    
    mov  al, 1      ; Number of sectors to read
    mov  bx, 0x7E00 ; ES:BX
    mov  cx, 0x0002 ; Cylinder, Sector
    mov  dh, 0      ; Head, DL is bootdrive
    call disk_read
    
    mov  ax, 0x07E0 ; How segmentation works!
    mov  ds, ax
    mov  es, ax
    jmp  0x07E0:0x0000
    
    include 'disk.asm'
    include 'printh.asm'
    
    boot_msg db 'R-OS BOOTLOADER       
                  ',\
    'KERNEL CHS 0 0 1', 0
    
    times 510-($-$$) db 0
    dw 0xAA55
    ;;;;;;;;; kernel! ;;;;;;;;;;
    ORG  0x7E00
    
    mov  bh, 0        ; Don't forget to mention the DisplayPage
    mov  ah, 0x0E
    mov  al, 'X'
    int  0x10
    
    cli
    hlt
    jmp  $-2
    
    times 4096-512-($-$$) db 0
    

    In the disk.asm file, you are trying to implement a retry count, but you forget to actually decrement the counter if an error occured.
    Also if you display an error message here, it's kinda fatal, so make the code halt.

    Again an improved version:

    disk_read:
      pusha
      mov  si, 5     ; Retry count
    .top:
      mov  ah, 0x02
      int  0x13
      jnc  .OK
      mov  ah, 0x00
      int  0x13
      dec  si
      jnz  .top      ; More tries
      jmp  .fatal
    .OK:
      popa
      ret
    
    .msg db 'disk rw err', 0
    
    .fatal:
      mov  bh, 0        ; Don't forget to mention the DisplayPage
      mov  ah, 0x0E
      mov  si, .msg
      lodsb
    .next:
      int  0x10
      lodsb
      cmp  al, 0
      jne  .next
    
      cli
      hlt
      jmp  $-2
    

    printh.asm just have print functions.

    It is important to include as much information as possible! In my above improved code I assumed that printf does not destroy the DL register. Please make sure it preserves at least DX.
    If you would have included the code in the printh.asm file, I would have verified this already for you...