I was using int 13h 08 to load disk parameters and got an invalid value from the disk base table (dbt).
The value in question was 0xF0.
note: dbt is returned in es:di
Reference to int 13h 08: https://stanislavs.org/helppc/int_13-8.html
Reference to dbt: https://stanislavs.org/helppc/dbt.html
repo link: https://github.com/The3Null4Player613310/RealOS
Code in question:
disk_get_params: ; get primary disk params
push es
push es
mov dl, [addr_svs_pdv]
mov ah, 0x08
int 13h
push ds ; get dbt
push es
pop ds
mov si, di
pop ax ; set es
pop es
push ax
shr dx, 0x08 ; set total head count
inc dx
mov [addr_svs_thc], dx
call disk_get_sector ; set sectors per track
inc ax
mov [addr_svs_spt], ax
call disk_get_cylindar ; set tracks per head
mov [addr_svs_tph], ax
;add si, 0x03
xor ah, ah ; set bytes per sector
lodsb
lodsb
lodsb
lodsb
mov cx, ax
mov bx, 0x80
shl bx, cl
mov [addr_svs_bps], bx
pop ds
pop es
jmp disk_return
The code snippet in the question is wrong in the way it uses the segment registers. It's not possible to draw any conclusions about the F0-issue from it. However the same code on your GitHub repository seems OK.
The BIOS.ReturnDiskDriveParameters function 08h will only return in ES:DI
a far pointer to the DisketteParameterTable if the drive number that you specified in DL
on entry referred to a floppy drive (DL < 128
).
I have looked at your project on GitHub and believe that what happens here, is that this BIOS function did neither touch ES
nor DI
, and because both happen to contain 0 on entry (*), the code that follows will be using a NULL-pointer. An instruction like mov cl, [es:di+3]
(or similar) will therefore read the 4th byte of linear memory which so happens to hold F0. The first vector of the InterruptVectorTable is the DivideException and points to somewhere in the BIOS code. A typical value being F000:EF6F (6F, EF, 00, F0).
(*) In your boot.asm on GitHub, you setup the DS
and ES
segment registers via push cs
push cs
pop es
pop ds
. This is dangerous! There's absolutely no guarantee that the CS
segment register will hold the 0 that you need in accordance with your ORG 7C00h
directive. It would be perfectly allright for the BIOS to reach your bootloader with CS:IP = 07C0h:0000h
. The only valid way to setup is:
xor ax, ax
mov ds, ax
mov es, ax
Always check the status that was reported by the system functions. The BIOS.ReturnDiskDriveParameters function 08h sets the carry flag if something was wrong. Don't omit a check for this situation!
There exists a newer BIOS function that will report the drive parameters for hard drives exclusively.
Read about the BIOS.GetDriveParameters function 48h in this wikipedia article.
It would be a very safe assumption to just consider BytesPerSector = 512. Many people have never seen anything else and for an hobby OS it might be the simplification you need...