From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/ROM.ASM | 530 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 530 insertions(+) create mode 100644 v2.0/source/ROM.ASM (limited to 'v2.0/source/ROM.ASM') diff --git a/v2.0/source/ROM.ASM b/v2.0/source/ROM.ASM new file mode 100644 index 0000000..f668986 --- /dev/null +++ b/v2.0/source/ROM.ASM @@ -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 + \ No newline at end of file -- cgit v1.2.3