brenden
brenden

Reputation: 604

Reading Sector From Drive Fails

I am trying to make a very basic 2 stage boot loader and I am running into issues reading the second stage. When I try to use int 13h with ah = 2, The interrupt fails with return code 1 (Invalid Command). I am compiling with nasm and testing with qemu. I have been testing to see if it has worked using qemu's console to check address 0x8C00 and see ax and the carry flag. I always see that the memory around 0x8C00 is zeroed, ax = 0x0101 and the carry flag is set.

bootloader.s

[org 0x7c00]
[bits 16]
mov [driveNum], dl
mov ah, 0x0A
mov al, '-'
mov cx, 80
int 0x10
;read drive
mov ax, 0
mov es, ax
mov ah, 2
mov al, 1 ;sectors to read
mov ch, 0 ;cylinder
mov cl, 0 ;sector
mov dh, 0 ;head
mov dl, byte [driveNum] ; drive
mov bx, 0x8c00

int 13h


hang:
jmp $

driveNum: db 0xAA
times (510 - ($ - $$)) db 0
db 0x55
db 0xAA

secondstage.s

jmp $
times 512 db 0xFF

Compiled With

nasm -f bin bootloader.s -o bootloader
nasm -f bin secondstage.s -o secondstage
cat bootloader secondstage > boot

Run Using

qemu-system-x86_64 -fda boot

Upvotes: 1

Views: 382

Answers (1)

Sep Roland
Sep Roland

Reputation: 39166

Problem1 (solved by Michael Petch)

BIOS returns with the "Invalid Command" error because you've asked to load the non-existent disk sector 0. In the CHS notation Cylinder numbers start at 0, Head numbers start at 0, but Sector numbers start at 1.
The sector that contains your bootloader is at (0,0,1). If your secondstage is in the next higher sector (but it could be anywhere else if you chose so!) then you need to ask for sector (0,0,2).

mov cx, 0002h    ;Cylinder 0, Sector 2

Problem2

Your dangerously working with the assumption that the DS segment register points to your bootloader. You cannot trust BIOS in this respect! The only thing that you can assume is that your bootloader sits in memory at linear address 0000h:7C00h and that the DL register holds the code for the boot drive.

Because you wrote [org 0x7c00] the setup that is missing is setting DS=0

xor ax, ax             <<===
mov ds, ax             <<===
mov [driveNum], dl

Problem3

The video BIOS function "WriteCharacterAtCursorPosition" additionally requires a display page number in BH and if the video mode is a graphical one then also a color in BL. Please don't rely on any register contents that you didn't check. All it takes is writing:

mov ax, 0A00h + '-'
mov bx, 0007h          <<===
mov cx, 80
int 10h

jmp $
times 512 db 0xFF

This creates 514 bytes which is 2 bytes more than a complete sector. Your bootloader will read 1 sector of 512 bytes. Technically there's no error here, but it might be indicative for some misconception.

jmp $
times (512 - ($ - $$)) db 255

Upvotes: 2

Related Questions