Perhaps you missed the fact that I trash AX in that code (Ie the value of AX going into it is
not the value of AX that comes out of it. So you need a push/pop ax pair around it otherwise you will (As you have discovered) end up with an infinite loop reading the same sector.
You're probably better off doing something like this:
Code: Select all
read_kernel:
pusha
call reset
mov ax, 0x4000 ;Target is 0x4000:0000
mov es, ax
xor bx, bx
mov ax, 0x02 ;Sector to start reading at
.1:
push ax
;
; Do the translation
;
xor dx, dx
div word [BPB_SecPerTrk]
inc dx
mov cl, dl
div word [BPB_NumHeads]
mov ch, al
mov dh, dl
;
; Do the actual read
;
.2:
mov dl, [drive]
mov ax, 0x0201 ;Setup for disk read, 1 sector at a time
int 0x13
jnc .3
;
; Handle a read error by reseting the drive and trying again
;
call reset ;On error reset the drive
jmp .2
;
; Get the stored value of the current sector
; Increment and check to see if all sectors are read
; If not then go around again
;
.3:
pop ax ;Pop the stored value of AX off the stack
inc ax
cmp ax, KERNEL_SIZE
jnz .1
;
; End by returning to wherever you called read_kernel from
;
popa
ret
;
; Resets the disk drive
;
reset:
xor ax, ax
mov dl, [drive]
int 0x13
jc reset
ret
Should be called from somewhere. That looks about right, but I haven't bothered testing it. The downside here is that you're reading in 1 sector at a time. The extension to reading in full tracks at a time is fairly logical so I'll leave you to figure it out on your own. 1 sector at a time will work, it just stresses the floppy disk more and is slower. Also be aware of the trap that is KERNEL_SIZE not being equal to the last sector you read in because you start your count at the 2nd sector

.
Anyhow, hope that helps a bit, or at least clears up why you had an infinite loop.