mirror of
https://github.com/Microsoft/MS-DOS.git
synced 2025-08-14 10:47:14 -07:00
MS-DOS v2.0 Release
This commit is contained in:
parent
fce0f75959
commit
80ab2fddfd
156 changed files with 56403 additions and 0 deletions
530
v2.0/source/ROM.ASM
Normal file
530
v2.0/source/ROM.ASM
Normal file
|
@ -0,0 +1,530 @@
|
|||
;
|
||||
; Disk utilities of MSDOS
|
||||
;
|
||||
|
||||
INCLUDE DOSSEG.ASM
|
||||
|
||||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||||
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
||||
|
||||
.XLIST
|
||||
.xcref
|
||||
INCLUDE DOSSYM.ASM
|
||||
INCLUDE DEVSYM.ASM
|
||||
.cref
|
||||
.list
|
||||
|
||||
TITLE ROM - miscellaneous routines
|
||||
NAME ROM
|
||||
|
||||
i_need CLUSNUM,WORD
|
||||
i_need NEXTADD,WORD
|
||||
i_need LASTPOS,WORD
|
||||
i_need SECCLUSPOS,BYTE
|
||||
i_need FATBYT,WORD
|
||||
i_need RECPOS,4
|
||||
i_need THISFCB,DWORD
|
||||
i_need TRANS,BYTE
|
||||
i_need BYTCNT1,WORD
|
||||
i_need CURBUF,DWORD
|
||||
i_need BYTSECPOS,WORD
|
||||
i_need DMAADD,WORD
|
||||
i_need SECPOS,WORD
|
||||
i_need VALSEC,WORD
|
||||
|
||||
procedure GET_random_record,NEAR
|
||||
entry GETRRPOS1
|
||||
MOV CX,1
|
||||
entry GetRRPos
|
||||
MOV DI,DX
|
||||
CMP BYTE PTR [DI],-1
|
||||
JNZ NORMFCB1
|
||||
ADD DI,7
|
||||
NORMFCB1:
|
||||
MOV AX,WORD PTR [DI.fcb_RR]
|
||||
MOV DX,WORD PTR [DI.fcb_RR+2]
|
||||
return
|
||||
GET_random_record ENDP
|
||||
|
||||
SUBTTL FNDCLUS -- Skip over allocation units
|
||||
PAGE
|
||||
procedure FNDCLUS,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; CX = No. of clusters to skip
|
||||
; ES:BP = Base of drive parameters
|
||||
; [THISFCB] point to FCB
|
||||
; Outputs:
|
||||
; BX = Last cluster skipped to
|
||||
; CX = No. of clusters remaining (0 unless EOF)
|
||||
; DX = Position of last cluster
|
||||
; DI destroyed. No other registers affected.
|
||||
|
||||
PUSH ES
|
||||
LES DI,[THISFCB]
|
||||
MOV BX,ES:[DI.fcb_LSTCLUS] ; fcb_lstclus is packed with dir clus
|
||||
AND BX,0FFFh ; get rid of dir nibble
|
||||
MOV DX,ES:[DI.fcb_CLUSPOS]
|
||||
OR BX,BX
|
||||
JZ NOCLUS
|
||||
SUB CX,DX
|
||||
JNB FINDIT
|
||||
ADD CX,DX
|
||||
XOR DX,DX
|
||||
MOV BX,ES:[DI.fcb_FIRCLUS]
|
||||
FINDIT:
|
||||
POP ES
|
||||
JCXZ RET10
|
||||
entry SKPCLP
|
||||
invoke UNPACK
|
||||
CMP DI,0FF8H
|
||||
JAE RET10
|
||||
XCHG BX,DI
|
||||
INC DX
|
||||
LOOP SKPCLP
|
||||
RET10: return
|
||||
|
||||
NOCLUS:
|
||||
POP ES
|
||||
INC CX
|
||||
DEC DX
|
||||
return
|
||||
FNDCLUS ENDP
|
||||
|
||||
SUBTTL BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER
|
||||
PAGE
|
||||
procedure BUFSEC,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; AH = priority of buffer
|
||||
; AL = 0 if buffer must be read, 1 if no pre-read needed
|
||||
; ES:BP = Base of drive parameters
|
||||
; [CLUSNUM] = Physical cluster number
|
||||
; [SECCLUSPOS] = Sector position of transfer within cluster
|
||||
; [BYTCNT1] = Size of transfer
|
||||
; Function:
|
||||
; Insure specified sector is in buffer, flushing buffer before
|
||||
; read if necessary.
|
||||
; Outputs:
|
||||
; ES:DI = Pointer to buffer
|
||||
; SI = Pointer to transfer address
|
||||
; CX = Number of bytes
|
||||
; [NEXTADD] updated
|
||||
; [TRANS] set to indicate a transfer will occur
|
||||
|
||||
MOV DX,[CLUSNUM]
|
||||
MOV BL,[SECCLUSPOS]
|
||||
CALL FIGREC
|
||||
invoke GETBUFFR
|
||||
MOV BYTE PTR [TRANS],1 ; A transfer is taking place
|
||||
MOV SI,[NEXTADD]
|
||||
MOV DI,SI
|
||||
MOV CX,[BYTCNT1]
|
||||
ADD DI,CX
|
||||
MOV [NEXTADD],DI
|
||||
LES DI,[CURBUF]
|
||||
ADD DI,BUFINSIZ ; Point to buffer
|
||||
ADD DI,[BYTSECPOS]
|
||||
return
|
||||
BUFSEC ENDP
|
||||
|
||||
SUBTTL BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE
|
||||
PAGE
|
||||
procedure BUFRD,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Do a partial sector read via one of the system buffers
|
||||
; ES:BP Points to DPB
|
||||
|
||||
PUSH ES
|
||||
MOV AX,LBRPRI SHL 8 ; Assume last byte read
|
||||
CALL BUFSEC
|
||||
MOV BX,ES
|
||||
MOV ES,[DMAADD+2]
|
||||
MOV DS,BX
|
||||
ASSUME DS:NOTHING
|
||||
XCHG DI,SI
|
||||
SHR CX,1
|
||||
JNC EVENRD
|
||||
MOVSB
|
||||
EVENRD:
|
||||
REP MOVSW
|
||||
POP ES
|
||||
LDS DI,[CURBUF]
|
||||
LEA BX,[DI.BufInSiz]
|
||||
SUB SI,BX ; Position in buffer
|
||||
invoke PLACEBUF
|
||||
CMP SI,ES:[BP.dpb_sector_size]
|
||||
JB RBUFPLACED
|
||||
invoke PLACEHEAD
|
||||
RBUFPLACED:
|
||||
PUSH SS
|
||||
POP DS
|
||||
return
|
||||
BUFRD ENDP
|
||||
|
||||
procedure BUFWRT,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Do a partial sector write via one of the system buffers
|
||||
; ES:BP Points to DPB
|
||||
|
||||
MOV AX,[SECPOS]
|
||||
INC AX ; Set for next sector
|
||||
MOV [SECPOS],AX
|
||||
CMP AX,[VALSEC] ; Has sector been written before?
|
||||
MOV AL,1
|
||||
JA NOREAD ; Skip preread if SECPOS>VALSEC
|
||||
XOR AL,AL
|
||||
NOREAD:
|
||||
PUSH ES
|
||||
CALL BUFSEC
|
||||
MOV DS,[DMAADD+2]
|
||||
ASSUME DS:NOTHING
|
||||
SHR CX,1
|
||||
JNC EVENWRT
|
||||
MOVSB
|
||||
EVENWRT:
|
||||
REP MOVSW
|
||||
POP ES
|
||||
LDS BX,[CURBUF]
|
||||
MOV BYTE PTR [BX.BUFDIRTY],1
|
||||
LEA SI,[BX.BufInSiz]
|
||||
SUB DI,SI ; Position in buffer
|
||||
MOV SI,DI
|
||||
MOV DI,BX
|
||||
invoke PLACEBUF
|
||||
CMP SI,ES:[BP.dpb_sector_size]
|
||||
JB WBUFPLACED
|
||||
invoke PLACEHEAD
|
||||
WBUFPLACED:
|
||||
PUSH SS
|
||||
POP DS
|
||||
return
|
||||
BUFWRT ENDP
|
||||
|
||||
SUBTTL NEXTSEC -- Compute next sector to read or write
|
||||
PAGE
|
||||
procedure NEXTSEC,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Compute the next sector to read or write
|
||||
; ES:BP Points to DPB
|
||||
|
||||
TEST BYTE PTR [TRANS],-1
|
||||
JZ CLRET
|
||||
MOV AL,[SECCLUSPOS]
|
||||
INC AL
|
||||
CMP AL,ES:[BP.dpb_cluster_mask]
|
||||
JBE SAVPOS
|
||||
MOV BX,[CLUSNUM]
|
||||
CMP BX,0FF8H
|
||||
JAE NONEXT
|
||||
invoke UNPACK
|
||||
MOV [CLUSNUM],DI
|
||||
INC [LASTPOS]
|
||||
MOV AL,0
|
||||
SAVPOS:
|
||||
MOV [SECCLUSPOS],AL
|
||||
CLRET:
|
||||
CLC
|
||||
return
|
||||
NONEXT:
|
||||
STC
|
||||
return
|
||||
NEXTSEC ENDP
|
||||
|
||||
SUBTTL OPTIMIZE -- DO A USER DISK REQUEST WELL
|
||||
PAGE
|
||||
procedure OPTIMIZE,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; BX = Physical cluster
|
||||
; CX = No. of records
|
||||
; DL = sector within cluster
|
||||
; ES:BP = Base of drives parameters
|
||||
; [NEXTADD] = transfer address
|
||||
; Outputs:
|
||||
; AX = No. of records remaining
|
||||
; BX = Transfer address
|
||||
; CX = No. or records to be transferred
|
||||
; DX = Physical sector address
|
||||
; DI = Next cluster
|
||||
; [CLUSNUM] = Last cluster accessed
|
||||
; [NEXTADD] updated
|
||||
; ES:BP unchanged. Note that segment of transfer not set.
|
||||
|
||||
PUSH DX
|
||||
PUSH BX
|
||||
MOV AL,ES:[BP.dpb_cluster_mask]
|
||||
INC AL ; Number of sectors per cluster
|
||||
MOV AH,AL
|
||||
SUB AL,DL ; AL = Number of sectors left in first cluster
|
||||
MOV DX,CX
|
||||
MOV CX,0
|
||||
OPTCLUS:
|
||||
; AL has number of sectors available in current cluster
|
||||
; AH has number of sectors available in next cluster
|
||||
; BX has current physical cluster
|
||||
; CX has number of sequential sectors found so far
|
||||
; DX has number of sectors left to transfer
|
||||
; ES:BP Points to DPB
|
||||
; ES:SI has FAT pointer
|
||||
invoke UNPACK
|
||||
ADD CL,AL
|
||||
ADC CH,0
|
||||
CMP CX,DX
|
||||
JAE BLKDON
|
||||
MOV AL,AH
|
||||
INC BX
|
||||
CMP DI,BX
|
||||
JZ OPTCLUS
|
||||
DEC BX
|
||||
FINCLUS:
|
||||
MOV [CLUSNUM],BX ; Last cluster accessed
|
||||
SUB DX,CX ; Number of sectors still needed
|
||||
PUSH DX
|
||||
MOV AX,CX
|
||||
MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size
|
||||
MOV SI,[NEXTADD]
|
||||
ADD AX,SI ; Adjust by size of transfer
|
||||
MOV [NEXTADD],AX
|
||||
POP AX ; Number of sectors still needed
|
||||
POP DX ; Starting cluster
|
||||
SUB BX,DX ; Number of new clusters accessed
|
||||
ADD [LASTPOS],BX
|
||||
POP BX ; BL = sector postion within cluster
|
||||
invoke FIGREC
|
||||
MOV BX,SI
|
||||
return
|
||||
BLKDON:
|
||||
SUB CX,DX ; Number of sectors in cluster we don't want
|
||||
SUB AH,CL ; Number of sectors in cluster we accepted
|
||||
DEC AH ; Adjust to mean position within cluster
|
||||
MOV [SECCLUSPOS],AH
|
||||
MOV CX,DX ; Anyway, make the total equal to the request
|
||||
JMP SHORT FINCLUS
|
||||
OPTIMIZE ENDP
|
||||
|
||||
SUBTTL FIGREC -- Figure sector in allocation unit
|
||||
PAGE
|
||||
procedure FIGREC,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; DX = Physical cluster number
|
||||
; BL = Sector postion within cluster
|
||||
; ES:BP = Base of drive parameters
|
||||
; Outputs:
|
||||
; DX = physical sector number
|
||||
; No other registers affected.
|
||||
|
||||
PUSH CX
|
||||
MOV CL,ES:[BP.dpb_cluster_shift]
|
||||
DEC DX
|
||||
DEC DX
|
||||
SHL DX,CL
|
||||
OR DL,BL
|
||||
ADD DX,ES:[BP.dpb_first_sector]
|
||||
POP CX
|
||||
return
|
||||
FIGREC ENDP
|
||||
|
||||
SUBTTL GETREC -- Figure record in file from fcb
|
||||
PAGE
|
||||
procedure GETREC,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; DS:DX point to FCB
|
||||
; Outputs:
|
||||
; CX = 1
|
||||
; DX:AX = Record number determined by fcb_EXTENT and fcb_NR fields
|
||||
; DS:DI point to FCB
|
||||
; No other registers affected.
|
||||
|
||||
MOV DI,DX
|
||||
CMP BYTE PTR [DI],-1 ; Check for extended FCB
|
||||
JNZ NORMFCB2
|
||||
ADD DI,7
|
||||
NORMFCB2:
|
||||
MOV CX,1
|
||||
MOV AL,[DI.fcb_NR]
|
||||
MOV DX,[DI.fcb_EXTENT]
|
||||
SHL AL,1
|
||||
SHR DX,1
|
||||
RCR AL,1
|
||||
MOV AH,DL
|
||||
MOV DL,DH
|
||||
MOV DH,0
|
||||
return
|
||||
GETREC ENDP
|
||||
|
||||
SUBTTL ALLOCATE -- Assign disk space
|
||||
PAGE
|
||||
procedure ALLOCATE,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; BX = Last cluster of file (0 if null file)
|
||||
; CX = No. of clusters to allocate
|
||||
; DX = Position of cluster BX
|
||||
; ES:BP = Base of drive parameters
|
||||
; [THISFCB] = Points to FCB
|
||||
; Outputs:
|
||||
; IF insufficient space
|
||||
; THEN
|
||||
; Carry set
|
||||
; CX = max. no. of records that could be added to file
|
||||
; ELSE
|
||||
; Carry clear
|
||||
; BX = First cluster allocated
|
||||
; FAT is fully updated including dirty bit
|
||||
; fcb_FIRCLUS field of FCB set if file was null
|
||||
; SI,BP unchanged. All other registers destroyed.
|
||||
|
||||
PUSH BX ; save the fat byte
|
||||
XOR BX,BX
|
||||
invoke UNPACK
|
||||
MOV [FATBYT],DI
|
||||
POP BX
|
||||
|
||||
PUSH DX
|
||||
PUSH CX
|
||||
PUSH BX
|
||||
MOV AX,BX
|
||||
CLUSALLOC:
|
||||
MOV DX,BX
|
||||
FINDFRE:
|
||||
INC BX
|
||||
CMP BX,ES:[BP.dpb_max_cluster]
|
||||
JLE TRYOUT
|
||||
CMP AX,1
|
||||
JG TRYIN
|
||||
POP BX
|
||||
MOV DX,0FFFH
|
||||
invoke RELBLKS
|
||||
POP AX ; No. of clusters requested
|
||||
SUB AX,CX ; AX=No. of clusters allocated
|
||||
POP DX
|
||||
invoke RESTFATBYT
|
||||
INC DX ; Position of first cluster allocated
|
||||
ADD AX,DX ; AX=max no. of cluster in file
|
||||
MOV DL,ES:[BP.dpb_cluster_mask]
|
||||
MOV DH,0
|
||||
INC DX ; DX=records/cluster
|
||||
MUL DX ; AX=max no. of records in file
|
||||
MOV CX,AX
|
||||
SUB CX,WORD PTR [RECPOS] ; CX=max no. of records that could be written
|
||||
JA MAXREC
|
||||
XOR CX,CX ; If CX was negative, zero it
|
||||
MAXREC:
|
||||
STC
|
||||
return
|
||||
|
||||
TRYOUT:
|
||||
invoke UNPACK
|
||||
JZ HAVFRE
|
||||
TRYIN:
|
||||
DEC AX
|
||||
JLE FINDFRE
|
||||
XCHG AX,BX
|
||||
invoke UNPACK
|
||||
JZ HAVFRE
|
||||
XCHG AX,BX
|
||||
JMP SHORT FINDFRE
|
||||
HAVFRE:
|
||||
XCHG BX,DX
|
||||
MOV AX,DX
|
||||
invoke PACK
|
||||
MOV BX,AX
|
||||
LOOP CLUSALLOC
|
||||
MOV DX,0FFFH
|
||||
invoke PACK
|
||||
POP BX
|
||||
POP CX ; Don't need this stuff since we're successful
|
||||
POP DX
|
||||
invoke UNPACK
|
||||
invoke RESTFATBYT
|
||||
XCHG BX,DI
|
||||
OR DI,DI
|
||||
retnz
|
||||
PUSH ES
|
||||
LES DI,[THISFCB]
|
||||
AND BX,0FFFh
|
||||
MOV ES:[DI.fcb_FIRCLUS],BX
|
||||
AND ES:[DI.fcb_LSTCLUS],0F000h ; clear out old lstclus
|
||||
OR ES:[DI.fcb_LSTCLUS],BX ; or the new guy in...
|
||||
POP ES
|
||||
return
|
||||
ALLOCATE ENDP
|
||||
|
||||
procedure RESTFATBYT,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
PUSH BX
|
||||
PUSH DX
|
||||
PUSH DI
|
||||
XOR BX,BX
|
||||
MOV DX,[FATBYT]
|
||||
invoke PACK
|
||||
POP DI
|
||||
POP DX
|
||||
POP BX
|
||||
return
|
||||
RESTFATBYT ENDP
|
||||
|
||||
SUBTTL RELEASE -- DEASSIGN DISK SPACE
|
||||
PAGE
|
||||
procedure RELEASE,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; BX = Cluster in file
|
||||
; ES:BP = Base of drive parameters
|
||||
; Function:
|
||||
; Frees cluster chain starting with [BX]
|
||||
; AX,BX,DX,DI all destroyed. Other registers unchanged.
|
||||
|
||||
XOR DX,DX
|
||||
entry RELBLKS
|
||||
; Enter here with DX=0FFFH to put an end-of-file mark
|
||||
; in the first cluster and free the rest in the chain.
|
||||
invoke UNPACK
|
||||
retz
|
||||
MOV AX,DI
|
||||
invoke PACK
|
||||
CMP AX,0FF8H
|
||||
MOV BX,AX
|
||||
JB RELEASE
|
||||
RET12: return
|
||||
RELEASE ENDP
|
||||
|
||||
SUBTTL GETEOF -- Find the end of a file
|
||||
PAGE
|
||||
procedure GETEOF,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; ES:BP Points to DPB
|
||||
; BX = Cluster in a file
|
||||
; DS = CS
|
||||
; Outputs:
|
||||
; BX = Last cluster in the file
|
||||
; DI destroyed. No other registers affected.
|
||||
|
||||
invoke UNPACK
|
||||
CMP DI,0FF8H
|
||||
JAE RET12
|
||||
MOV BX,DI
|
||||
JMP SHORT GETEOF
|
||||
GETEOF ENDP
|
||||
|
||||
do_ext
|
||||
|
||||
CODE ENDS
|
||||
END
|
||||
|