Search code examples
assemblyoperating-systemx86nasmosdev

How to load a kernel from disk with BIOS int 13h in NASM assembly?


I've been stuck with this for weeks now and have no idea where I'm going wrong because NASM hasn't given me any errors. The code is pretty self explanatory because of the comments.

this is the code that is loaded from the BIOS

 ;--------------------------------------------
 ; 'boot.asm'
 ; loaded from BIOS

 [org 0x7C00]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

 resetdisk:
  mov ah, 0x00  ; reset function
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc resetdisk

 readdisk:
  mov bx, 0x8000  ; segment
  mov es, bx
  mov bx, 0x0000  ; offset

  mov ah, 0x02  ; read function
  mov al, 0x03  ; sectors
  mov ch, 0x00  ; cylinder
  mov cl, 0x02  ; sector
  mov dh, 0x00  ; head
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc readdisk
  jmp [es:bx]   ; buffer

 ;--------------------------------------------

 times 510 - ($ - $$) db 0x00
 db 0x55, 0xAA

This is the code that should be (but isn't) loaded

 ;--------------------------------------------
 ; 'load.asm'
 ; loaded from 'boot.asm'

 [org 0x8000]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

  jmp $    ; hang

Any help would be much appreciated.

Patrick


Solution

  • jmp [es:bx] doesn't jump to the address es:bx. This command does a near jump to the address stored in the word at es:bx. This is why lots of older assemblers made you spell this kind of instruction as jmp word ptr [es:bx] or even jmp near ptr [es:bx]; it's clearer this way what is going to happen. What you probably want here is a far jump to a fixed location:

    ; jmp far 8000:0000
    db 0eah
    dw 00000h ; offset
    dw 08000h ; segment
    

    If you do want to jump to es:bx, use retf:

    push es
    push bx
    retf