Skip to content

Commit 9699c65

Browse files
committed
disk.asm: more accurate FAT32 size calculation, integer overflow fix
1 parent e757516 commit 9699c65

1 file changed

Lines changed: 30 additions & 19 deletions

File tree

drbio/disk.asm

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,7 +3217,7 @@ hd_bpb20: ; cluster size determined
32173217
sub ax,1+(512*32/SECSIZE) ; subtract reserved+root directory
32183218
sbb dx,0 ; (note: 32 bytes per entry)
32193219
xor cx,cx
3220-
mov ch,BPB.ALLOCSIZ[bx] ; CX = (256 * # of clusters on drive)
3220+
mov ch,BPB.ALLOCSIZ[bx] ; CX = (256 * sectors per cluster)
32213221
dec cx
32223222
add ax,cx ; add in for rounding error
32233223
adc dx,0
@@ -3265,27 +3265,36 @@ hd_bpb30: ; build BPB for FAT32
32653265
32663266
; Now follows the calculation of the sector count per FAT.
32673267
; It is calculated after the formula
3268-
; (total_sec + (sec_per_clust-1) - reserved) /
3269-
; (sect_per_clust * entries_per_FAT_sector)
3270-
; This is somewhat inefficient, because the FATs are unnecessarily
3271-
; treated as data area.
3272-
hd_bpb40: ; DX:AX = total sectors
3273-
sub ax,BPB.FATADD[bx] ; subtract reserved
3268+
; ((ts-res+1)/2+spc) / (64*spc+1) + 1
3269+
; where ts = total sectors, spc = sectors per cluster and
3270+
; res = reserved sectors
3271+
; See https://github.com/boeckmann/fatdocs on how the formula was
3272+
; derived.
3273+
hd_bpb40: ; DX:AX = ts
3274+
sub ax,BPB.FATADD[bx] ; DX:AX = ts - res
32743275
sbb dx,0
3276+
add ax,1
3277+
adc dx,0 ; DX:AX = ts - res + 1
3278+
shr dx,1
3279+
rcr ax,1 ; DX:AX = (ts - res + 1) / 2
32753280
xor cx,cx
3276-
mov ch,BPB.ALLOCSIZ[bx]
3277-
shr cx,1 ; CX = sectors per cluster * 128
3278-
; If CX is now zero this means that we are dealing with
3279-
; 256 sectors per cluster. We set CX to:
3280-
; 256 sectors per cluster * 128 FAT entries per sector = 8000h
3281-
jnz hd_bpb41
3282-
mov ch,80h
3281+
mov cl,BPB.ALLOCSIZ[bx] ; CX = spc
3282+
test cl,cl ; CL = zero means spc=256
3283+
jnz hd_bpb41
3284+
mov ch,1
32833285
hd_bpb41:
3284-
dec cx
3285-
add ax,cx ; add in for rounding error
3286-
adc dx,0
3287-
inc cx
3288-
; div cx ; AX = # of fat sectors
3286+
add ax,cx
3287+
adc dx,0 ; DX:AX = (ts - res + 1) / 2 + spc
3288+
xchg ch,cl
3289+
shr cx,1
3290+
shr cx,1 ; CX = spc * 64
3291+
; If CX is zero this means that we are dealing with 256 sectors per
3292+
; cluster. We set CX to = 256 * 64 = 4000h
3293+
test cx,cx
3294+
jnz hd_bpb42
3295+
mov ch,40h
3296+
hd_bpb42:
3297+
add cx,1 ; CX = 64 * spc + 1
32893298
push bp
32903299
push dx
32913300
push ax
@@ -3299,6 +3308,8 @@ hd_bpb41:
32993308
pop dx
33003309
add sp,8
33013310
pop bp
3311+
add ax,1
3312+
adc dx,0 ; DX:AX = FAT size in sectors
33023313
mov word ptr BPB.BFATSEC[bx],ax ; remember FAT size
33033314
mov word ptr BPB.BFATSEC+2[bx],dx
33043315
and word ptr BPB.FATSEC[bx], 0 ; clear small FAT size field

0 commit comments

Comments
 (0)