Read sectors from FAT16
Posted: Thu Sep 17, 2015 9:38 pm
Ok, I have hit the wall on this. Basically, I have implemented a routine that is supposed to read sectors from the hard disk into memory based on the input sector number that is pasted into the routine. The issue is that when the sector number gets large (for example, 12,700), the routine returns data from the wrong sector on disk.
Below is my code:
Below is my code:
Code: Select all
File.ReadSectors.Params.DestinationSegment: equ 10 ; 2 bytes
File.ReadSectors.Params.ReadSector: equ 8 ; 2 bytes
File.ReadSectors.Params.SectorCount: equ 6 ; 2 bytes
File.ReadSectors.Params.MemoryOffset: equ 4 ; 2 bytes
File.ReadSectors.ParamsSize: equ 8
File.ReadSectors.LocalsSize: equ 0
File.ReadSectors:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: File.ReadSectors.read_sectors
; action: reads one or more disk sectors into memory
; in: ES:0=address of memory where sectors should be read
; DX:AX=first sector to read
; CX=number of sectors to read
; out (disk error): CY=1
; out (success): CY=0
; modifies: DX, CX, AX
; minimum CPU: 8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Prologue
enter File.ReadSectors.LocalsSize, 0
pushad
call Memory.ClearGeneralRegisters
mov word ax, word [ebp + File.ReadSectors.Params.DestinationSegment]
mov word es, word ax
mov word cx, word [ebp + File.ReadSectors.Params.SectorCount]
mov word ax, word [ebp + File.ReadSectors.Params.ReadSector]
xor word dx, word dx
File.ReadSectors.read_sectors:
push es
push bx
;xor bx,bx
mov bx, word [ebp + File.ReadSectors.Params.MemoryOffset]
; add partition start
;xchg bx, bx
add ax, word [File.FatInfo.HiddenSectors + 0] ; [bp - (over - hidden_sectors) + 0]
adc dx, word [File.FatInfo.HiddenSectors + 2]
File.ReadSectors.read_sectors_1:
push dx
push cx
push ax
; DX:AX=LBA sector number
push ax
mov ax,dx
xor dx,dx
; divide LBA by sectors_per_track (spt).
; Use a two-step 32-bit/16-bit divide to avoid overflow.
; See "9.3.5 Extended Precision Division" in Randall Hyde's "Art of Assembly"
div word [File.FatInfo.SectorsPerTrack] ; [bp- (over - sectors_per_track)]
; DX=high LBA % spt, AX=high LBA / spt
mov cx,ax
pop ax
; DX=high LBA % spt, CX=high LBA / spt, AX=low LBA
; New 32-bit dividend is DX:AX
div word [File.FatInfo.SectorsPerTrack] ; [bp- (over - sectors_per_track)]
; CX:AX=LBA / spt, DX=LBA % spt
xchg cx,dx
inc cx ; CL=sector
; DX:AX=LBA / spt, do normal one-step divide by heads value
div word [File.FatInfo.NumberOfHeads] ; [bp - (over - heads)]
mov dh,dl ; DH=head
mov ch,al ; CH=cylinder 7:0
mov dl, byte [File.FatInfo.DriveLetter] ; [bp - (over - boot_drive)]
shl cl,1
shl cl,1 ; trying to use only...
shr ah,1 ; ...8088 asm here
rcr cl,1
shr ah,1
rcr cl,1 ; CL7:6=cyl 9:8, CL5:0=sector
; now: read one sector
mov ax,0201h
int 13h
jnc File.ReadSectors.read_sectors_3
; disk error; recalibrate/reset drive
mov ah,0
int 13h
jc File.ReadSectors.read_sectors_2
; try the read again. If it fails a second time, give up.
mov ax,0201h
int 13h
jnc File.ReadSectors.read_sectors_3
File.ReadSectors.read_sectors_2:
pop ax
pop cx
pop dx
jmp short File.ReadSectors.read_sectors_5
; advance memory pointer
File.ReadSectors.read_sectors_3:
mov ax,es
add ax, 32 ; [File.FatInfo.ParagrahsPerSector] ; [bp - (over - para_per_sector)]
mov es,ax
pop ax
pop cx
pop dx
; increment DX:AX to advance to next sector
inc ax
jne File.ReadSectors.read_sectors_4
inc dx
File.ReadSectors.read_sectors_4:
loop File.ReadSectors.read_sectors_1
; clear CY bit to signal success
clc
File.ReadSectors.read_sectors_5:
pop bx
pop es
;ret
File.ReadSectors.End:
; Epilogue
popad
leave
ret File.ReadSectors.ParamsSize