2 ; Disk utilities of MSDOS
7 CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
17 TITLE ROM
- miscellaneous routines
23 i_need SECCLUSPOS
,BYTE
35 procedure GET_random_record
,NEAR
44 MOV AX,WORD PTR [DI.fcb_RR
]
45 MOV DX,WORD PTR [DI.fcb_RR
+2]
47 GET_random_record ENDP
49 SUBTTL FNDCLUS
-- Skip over allocation units
51 procedure FNDCLUS
,NEAR
52 ASSUME
DS:DOSGROUP
,ES:NOTHING
55 ; CX = No. of clusters to skip
56 ; ES:BP = Base of drive parameters
57 ; [THISFCB] point to FCB
59 ; BX = Last cluster skipped to
60 ; CX = No. of clusters remaining (0 unless EOF)
61 ; DX = Position of last cluster
62 ; DI destroyed. No other registers affected.
66 MOV BX,ES:[DI.fcb_LSTCLUS
] ; fcb_lstclus is packed with dir clus
67 AND BX,0FFFh ; get rid of dir nibble
68 MOV DX,ES:[DI.fcb_CLUSPOS
]
75 MOV BX,ES:[DI.fcb_FIRCLUS
]
95 SUBTTL BUFSEC
-- BUFFER A SECTOR
AND SET UP A TRANSFER
98 ASSUME
DS:DOSGROUP
,ES:NOTHING
101 ; AH = priority of buffer
102 ; AL = 0 if buffer must be read, 1 if no pre-read needed
103 ; ES:BP = Base of drive parameters
104 ; [CLUSNUM] = Physical cluster number
105 ; [SECCLUSPOS] = Sector position of transfer within cluster
106 ; [BYTCNT1] = Size of transfer
108 ; Insure specified sector is in buffer, flushing buffer before
111 ; ES:DI = Pointer to buffer
112 ; SI = Pointer to transfer address
113 ; CX = Number of bytes
115 ; [TRANS] set to indicate a transfer will occur
121 MOV BYTE PTR [TRANS
],1 ; A transfer is taking place
128 ADD DI,BUFINSIZ
; Point to buffer
133 SUBTTL BUFRD
, BUFWRT
-- PERFORM BUFFERED READ
AND WRITE
136 ASSUME
DS:DOSGROUP
,ES:NOTHING
138 ; Do a partial sector read via one of the system buffers
139 ; ES:BP Points to DPB
142 MOV AX,LBRPRI
SHL 8 ; Assume last byte read
157 SUB SI,BX ; Position in buffer
159 CMP SI,ES:[BP.dpb_sector_size
]
168 procedure BUFWRT
,NEAR
169 ASSUME
DS:DOSGROUP
,ES:NOTHING
171 ; Do a partial sector write via one of the system buffers
172 ; ES:BP Points to DPB
175 INC AX ; Set for next sector
177 CMP AX,[VALSEC
] ; Has sector been written before?
179 JA NOREAD
; Skip preread if SECPOS>VALSEC
193 MOV BYTE PTR [BX.BUFDIRTY
],1
195 SUB DI,SI ; Position in buffer
199 CMP SI,ES:[BP.dpb_sector_size
]
208 SUBTTL NEXTSEC
-- Compute next sector to read
or write
210 procedure NEXTSEC
,NEAR
211 ASSUME
DS:DOSGROUP
,ES:NOTHING
213 ; Compute the next sector to read or write
214 ; ES:BP Points to DPB
216 TEST BYTE PTR [TRANS
],-1
220 CMP AL,ES:[BP.dpb_cluster_mask
]
239 SUBTTL OPTIMIZE
-- DO A USER DISK REQUEST WELL
241 procedure OPTIMIZE
,NEAR
242 ASSUME
DS:DOSGROUP
,ES:NOTHING
245 ; BX = Physical cluster
246 ; CX = No. of records
247 ; DL = sector within cluster
248 ; ES:BP = Base of drives parameters
249 ; [NEXTADD] = transfer address
251 ; AX = No. of records remaining
252 ; BX = Transfer address
253 ; CX = No. or records to be transferred
254 ; DX = Physical sector address
256 ; [CLUSNUM] = Last cluster accessed
258 ; ES:BP unchanged. Note that segment of transfer not set.
262 MOV AL,ES:[BP.dpb_cluster_mask
]
263 INC AL ; Number of sectors per cluster
265 SUB AL,DL ; AL = Number of sectors left in first cluster
269 ; AL has number of sectors available in current cluster
270 ; AH has number of sectors available in next cluster
271 ; BX has current physical cluster
272 ; CX has number of sequential sectors found so far
273 ; DX has number of sectors left to transfer
274 ; ES:BP Points to DPB
275 ; ES:SI has FAT pointer
287 MOV [CLUSNUM
],BX ; Last cluster accessed
288 SUB DX,CX ; Number of sectors still needed
291 MUL ES:[BP.dpb_sector_size
] ; Number of sectors times sector size
293 ADD AX,SI ; Adjust by size of transfer
295 POP AX ; Number of sectors still needed
296 POP DX ; Starting cluster
297 SUB BX,DX ; Number of new clusters accessed
299 POP BX ; BL = sector postion within cluster
304 SUB CX,DX ; Number of sectors in cluster we don't want
305 SUB AH,CL ; Number of sectors in cluster we accepted
306 DEC AH ; Adjust to mean position within cluster
308 MOV CX,DX ; Anyway, make the total equal to the request
312 SUBTTL FIGREC
-- Figure sector
in allocation unit
314 procedure FIGREC
,NEAR
315 ASSUME
DS:NOTHING
,ES:NOTHING
318 ; DX = Physical cluster number
319 ; BL = Sector postion within cluster
320 ; ES:BP = Base of drive parameters
322 ; DX = physical sector number
323 ; No other registers affected.
326 MOV CL,ES:[BP.dpb_cluster_shift
]
331 ADD DX,ES:[BP.dpb_first_sector
]
336 SUBTTL GETREC
-- Figure record
in file from fcb
338 procedure GETREC
,NEAR
339 ASSUME
DS:NOTHING
,ES:NOTHING
345 ; DX:AX = Record number determined by fcb_EXTENT and fcb_NR fields
347 ; No other registers affected.
350 CMP BYTE PTR [DI],-1 ; Check for extended FCB
356 MOV DX,[DI.fcb_EXTENT
]
366 SUBTTL ALLOCATE
-- Assign disk space
368 procedure ALLOCATE
,NEAR
369 ASSUME
DS:DOSGROUP
,ES:NOTHING
372 ; BX = Last cluster of file (0 if null file)
373 ; CX = No. of clusters to allocate
374 ; DX = Position of cluster BX
375 ; ES:BP = Base of drive parameters
376 ; [THISFCB] = Points to FCB
378 ; IF insufficient space
381 ; CX = max. no. of records that could be added to file
384 ; BX = First cluster allocated
385 ; FAT is fully updated including dirty bit
386 ; fcb_FIRCLUS field of FCB set if file was null
387 ; SI,BP unchanged. All other registers destroyed.
389 PUSH BX ; save the fat byte
403 CMP BX,ES:[BP.dpb_max_cluster
]
410 POP AX ; No. of clusters requested
411 SUB AX,CX ; AX=No. of clusters allocated
414 INC DX ; Position of first cluster allocated
415 ADD AX,DX ; AX=max no. of cluster in file
416 MOV DL,ES:[BP.dpb_cluster_mask
]
418 INC DX ; DX=records/cluster
419 MUL DX ; AX=max no. of records in file
421 SUB CX,WORD PTR [RECPOS
] ; CX=max no. of records that could be written
423 XOR CX,CX ; If CX was negative, zero it
448 POP CX ; Don't need this stuff since we're successful
458 MOV ES:[DI.fcb_FIRCLUS
],BX
459 AND ES:[DI.fcb_LSTCLUS
],0F000h ; clear out old lstclus
460 OR ES:[DI.fcb_LSTCLUS
],BX ; or the new guy in...
465 procedure RESTFATBYT
,NEAR
466 ASSUME
DS:DOSGROUP
,ES:NOTHING
480 SUBTTL RELEASE
-- DEASSIGN DISK SPACE
482 procedure RELEASE
,NEAR
483 ASSUME
DS:DOSGROUP
,ES:NOTHING
486 ; BX = Cluster in file
487 ; ES:BP = Base of drive parameters
489 ; Frees cluster chain starting with [BX]
490 ; AX,BX,DX,DI all destroyed. Other registers unchanged.
494 ; Enter here with DX=0FFFH to put an end-of-file mark
495 ; in the first cluster and free the rest in the chain.
506 SUBTTL GETEOF
-- Find the
end of a
file
508 procedure GETEOF
,NEAR
509 ASSUME
DS:DOSGROUP
,ES:NOTHING
512 ; ES:BP Points to DPB
513 ; BX = Cluster in a file
516 ; BX = Last cluster in the file
517 ; DI destroyed. No other registers affected.