I have a bootsector which is meant to load a file called BOOT.BIN from a floppy disk image. However I can not figure out how to read more than one sector from the file. The FAT 12 is at 0x10000. The BOOT.BIN file will be put at 0x40000. The code:
foundfile:
mov word ax,[es:di 0x0f]
push ax ;save file cluster
;now to parse the fat
mov dx,second_boot_segment
mov es,dx
xor bx,bx
read_file_sector:
pop ax ;retrieve file cluster
mov byte dl,[drive_num]
mov cx,ax
add cx,31
push ax ;save cluster number
mov al,1
call readdisk
pop ax ;retrieve cluster number
find_clusters:
push es
push bx
mov cx,fat_segment
mov es,cx
xor bx,bx
xor dx,dx
mov cx,3
mul cx
shr ax,1
;ax is now (clusternum*3)/2
test ax,1
jz short evennum
oddnum:
shr ax,4
jmp short find_clusters_continued
evennum:
and ax,0x0fff
find_clusters_continued:
cmp ax,0x0ff0
jae short finishedread ;read all of file
mov word ax,[es:bx]
pop bx
pop es
push ax
add bx,512 ;next sector
jmp short read_file_sector
finishedread:
jmp second_boot_segment:0000
jmp fatalerror
======================================================================== readdisk and other functions:
readdisk: ;input: es:bx for where disk data is stored, al for sectors, cx for lba, drive_num for drive output: carry flag on error, ah is return type, al is the number of sectors read
push dx ;save dx
call lbatochs
mov byte dl,[drive_num]
mov ah,2
int 13h
jc short resetdisk
mov byte dl,[drive_num]
pop dx ;restore dx
ret
resetdisk:
push ax
mov ah,0
int 13h
jc short fatalerror
pop ax
jmp short readdisk
fatalerror:
mov ax,0x0003 ;ah = 0 al = 3
int 10h
mov si,boot_error
mov ax,0xb800
mov es,ax
xor bx,bx
cld
printloop:
lodsb
or al,al ;is the last character read
jz short infloop
mov ah,0x0f ;color
mov word [es:bx],ax ;write to vram
add bl,2 ;as long a the text is less than 256 bytes this works
jmp short printloop
lbatochs: ;input: cx for lba, output: cx for cylinder and sector, and dh for head
push ax ;save for later
push bx ;save bx
;find temp variable
xor dx,dx
mov ax,cx ;ax now has lba
push ax ;save lba
mov word bx,[sects_per_track] ;sectors per track
div bx ;ax is now temp
;cylinder
push ax ;save temp
xor dx,dx
mov word bx,[num_heads] ;number of heads
div bx ;ax is now cylinder
mov cx,ax ;cx stores cylinder
pop ax ;retrieve temp
;cx is now cylinder
;head
push dx ;heads already in dx
;sector
pop dx ;pop dx to get stack value underneath it
pop ax ;retrieve lba
push dx ;push dx back on
push cx ;save cylinder
xor dx,dx
mov word bx,[sects_per_track]
div bx
inc dx ;dx now has sectors
mov bx,dx ;now bx has sectors
pop cx
pop dx
;put params together
mov ch,cl ;cylinder in ch
mov cl,bl ;sector in cl
mov dh,dl ;head in dh
mov dl,0 ;erase dl
pop bx ;load old bx
pop ax ;load old ax
ret
``` This read disk code likely is not causing the issues as I have loaded many other sectors with this.
CodePudding user response:
int 13h
with ah=02
is supposed to take the number of sections in al
, see http://www.ctyme.com/intr/rb-0607.htm. Currently you do mov al, 1
before calling readdisk
, and that value is preserved through the call of lbatochs
, so you read 1 sector.
If you want 42 sectors, change it to mov al, 42
. Or refactor readdisk
in some other way.
CodePudding user response:
readfat: mov byte dl,[es:bx]
This instruction makes no sense! There's nothing useful to read (yet) at that spot.
However I can not figure out how to read more than one sector from the file.
The reason is that your code forgets to actually loop back to the readfat label. Once you've loaded a next clusternumber you need to jump back to the top of the loop instead of immediately far jumping to the BOOT.BIN binary.
Note that it will not be enough to just insert the missing jmp
! Because the necessary add bx, 512
gets destroyed by the pop bx
instruction, all the sectors will arrive on top of each other.
Because of
This read disk code likely is not causing the issues as I have loaded many other sectors with this.
I did not investigate that part of your code. See if next rewrite works for you:
foundfile:
mov ax, [es:di 0x0F] ; dirFirstCluster
mov bx, 0x4000
mov es, bx
xor bx, bx
READSECTOR:
push es ; (1)
push bx ; (2)
push ax ; (3)
add ax, 31
mov cx, ax
mov al, 1
call readdisk
pop ax ; (3)
mov dx, 3
mul dx
shr ax, 1
jnc short evenclus
oddclus:
shr ax, 4
evenclus:
and ax, 0x0FFF
cmp ax, 0x0FF8
jae finishedread
mov bx, 0x1000 ; FAT
mov es, bx
mov bx, ax
mov ax, [es:bx] ; Following cluster number
pop bx ; (2)
pop es ; (1)
ADD BX, 512 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
JMP READSECTOR <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
finishedread:
jmp 0x4000:0000
jmp fatalerror
CodePudding user response:
I have figured out how to write the loop by myself.
Here is the code if you want to see it:
foundfile:
mov word ax,[es:di 0x0f]
push ax ;save file cluster
;now to parse the fat
mov dx,second_boot_segment
mov es,dx ;second_boot_segment
xor bx,bx ;offset for es
xor di,di ;offset for es when reading the fat
read_file_sector:
pop cx ;get file cluster and put in cx
add cx,31
push ax ;save cluster again
mov byte al,[sects_per_cluster] ;cluster size
call readdisk
pop ax ;retrieve cluster
push es
find_cluster:
mov cx,3
xor dx,dx
mul cx ;multiply cluster number by 3
shr ax,1 ;divide cluster number by 2
mov cx,fat_segment
mov es,cx
mov di,ax
mov word ax,[es:di]
jnc short evenclus
oddclus:
shr ax,4
jmp short continue_findcluster
evenclus:
and ax,0x0fff
continue_findcluster:
cmp ax,0x0ff0
jae finishedread
add bx,512
pop es
push ax ;save cluster for loop
jmp short read_file_sector
finishedread:
jmp second_boot_segment:0000
jmp fatalerror