diff --git a/86DOS.ASM b/86DOS.ASM new file mode 100644 index 0000000..e4a0d5d --- /dev/null +++ b/86DOS.ASM @@ -0,0 +1,2243 @@ +; 86-DOS High-performance operating system for the 8086 version 0.11 +; by Tim Paterson + + +; Interrupt Entry Points: + +; INTBASE: ABORT +; INTBASE+4: COMMAND +; INTBASE+8: BASE EXIT ADDRESS +; INTBASE+C: CONTROL-C ABORT +; INTBASE+10H: FATAL ERROR ABORT +; INTBASE+14H: BIOS DISK READ +; INTBASE+18H: BIOS DISK WRITE +; INTBASE+40H: Long jump to CALL entry point + +ESCCH EQU 1BH +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X + +MAXCALL EQU 36 +MAXCOM EQU 40 +INTBASE EQU 80H +INTTAB EQU 20H +ENTRYPOINTSEG EQU 0CH +ENTRYPOINT EQU INTBASE+40H +CONTC EQU INTTAB+3 +EXIT EQU INTBASE+8 +LONGJUMP EQU 0EAH +LONGCALL EQU 9AH +SAVEXIT EQU 10 + +; Field definition for FCBs + +FNAME EQU 0 ;Drive code and name +EXTENT EQU 12 +ENTPOS EQU 16 ;Position of entry in directory +DRVBP EQU 18 ;BP for SEARCH FIRST and SEARCH NEXT +FIRCLUS EQU 20 ;First cluster of file +LSTCLUS EQU 22 ;Last cluster accessed +FILSIZ EQU 24 ;Size of file in records +CLUSPOS EQU 26 ;Position of last cluster accessed +FLSFLG EQU 28 ;Flush flag +SIZCHG EQU 29 ;Size change flag +NR EQU 32 ;Next record +RR EQU 33 ;Random record + +; Description of 16-byte directory entry (same as returned by SEARCH FIRST +; and SEARCH NEXT, functions 17 and 18). +; +; Location bytes Description +; +; 0 11 File name and extension ( 0E5H if empty) +; 11 2 First allocation unit ( < 4080 ) +; 13 3 File size, in bytes (LSB first, 24 bits max.) +; +; The File Allocation Table uses a 12-bit entry for each allocation unit on +; the disk. These entries are packed, two for every three bytes. The contents +; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +; to the base address of the Allocation Table; 3) fetching the 16-bit word at +; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +; zero is used as an end-of-file trap in the OS. Entry 1 is reserved for +; future use. The first available allocation unit is assigned entry number +; two, and even though it is the first, is called cluster 2. Entries of 0FFFH +; are end of file marks; entries of zero are unallocated. Otherwise, the +; contents of a FAT entry is the number of the next cluster in the file. + + +; Field definition for Drive Parameter Block + +DEVNUM EQU 0 ;I/O driver number +SECSIZ EQU 1 ;Size of physical sector in records +CLUSMSK EQU 2 ;Records/cluster - 1 +CLUSSHFT EQU 3 ;Log2 of records/cluster +FIRFAT EQU 4 ;Starting record of FATs +FATSIZ EQU 6 ;Number of records occupied by FAT +FATCNT EQU 7 ;Number of FATs for this drive +FIRDIR EQU 8 ;Starting record of directory +DIRSIZ EQU 10 ;Number of records occupied by directory +FIRREC EQU 11 ;First record of first cluster +MAXCLUS EQU 13 ;Number of clusters on drive + 1 +DIRTY EQU 15 ;Whether FAT is dirty +FAT EQU 16 ;Pointer to start of FAT + +DPBSIZ EQU 18 ;Size of the structure in bytes + + +; BOIS entry point definitions + +BIOSSEG EQU 40H + +BIOSINIT EQU 0 ;Reserve room for jump to init code +BIOSSTAT EQU 3 ;Console input status check +BIOSIN EQU 6 ;Get console character +BIOSOUT EQU 9 ;Output console character +BIOSPRINT EQU 12 ;Output to printer +BIOSAUXIN EQU 15 ;Get byte from auxilliary +BIOSAUXOUT EQU 18 ;Output byte to auxilliary +BIOSREAD EQU 21 ;Disk read +BIOSWRITE EQU 24 ;Disk write +BIOSFLUSH EQU 27 ;Disk buffer flush + +; Start of code + + ORG 0 + JMP DOSINIT + +ESCTAB: + DB "SC" ;Copy one character from template + DB "VN" ;Skip over one character in template + DB "TA" ;Copy up to specified character + DB "WB" ;Skip up to specified character + DB "UH" ;Copy rest of template + DB "HH" ;Kill line with no change in template (Ctrl-X) + DB "RM" ;Cancel line and update template + DB "DD" ;Backspace (same as Ctrl-H) + DB "P@" ;Enter Insert mode + DB "QL" ;Exit Insert mode + DB 1BH,1BH ;Escape sequence to represent escape character + DB ESCCH,ESCCH + +ESCTABLEN EQU $-ESCTAB +HEADER DB 13,10,"86-DOS version 0.11" + DB 13,10 + DB "Copyright 1980 Seattle Computer Products, Inc.",13,10,"$" + +DOSINIT: + CLI + CLD + MOV AX,CS + MOV ES,AX + LODB ;Get no. of drives & no. of I/O drivers + CBW + MOV CX,AX + SEG CS + MOV [NUMIO],AL + MOV DI,AX + SHL DI + MOV AH,DPBSIZ ;Size of DPB + MUL AX,AH + MOV BX,DRVTAB + ADD DI,BX ;Point to first DPB + ADD AX,DI + MOV BP,AX ;Point to first FAT + SEG CS + MOV [FATBASE],AX +PERDEV: + SEG CS + MOV [BX],DI ;Store DPB pointer to table entry + INC BX + INC BX + MOV AL,CH + STOB ;DEVNUM + LODW ;Get pointer to DPT + PUSH SI ;Save INITTAB pointer + MOV SI,AX ;Load DPT + MOVB ;SECSIZ + LODB + DEC AL + STOB ;CLUSMSK + CBW +FIGSHFT: + INC AH + SAR AL + JNZ FIGSHFT + MOV AL,AH + STOB ;CLUSSHFT + LODW + STOW ;FIRFAT + MOV DX,AX + LODB + STOB ;FATSIZ + MOV AH,AL + PUSH AX + LODB + STOB ;FATCNT + MUL AX,AH + ADD AX,DX + STOW ;FIRDIR + MOV DX,AX + LODB + STOB ;DIRSIZ + CBW + ADD AX,DX + STOW ;FIRREC + POP DX + LODW + INC AX + STOW ;MAXCLUS + XOR AL,AL + STOB + POP SI + LODW ;Allocation table displacement + SEG CS + ADD AX,[FATBASE] + STOW ;FAT + MOV DL,0 + SHR DX ;FAT size in bytes + ADD AX,DX + CMP AX,BP + JBE SMFAT + MOV BP,AX +SMFAT: + INC CH ;Next I/O device number + DEC CL + JNZ PERDEV + ADD BP,15 ;True start of free space + MOV CL,4 + SHR BP,CL ;First free segment + XOR AX,AX + MOV DS,AX + MOV ES,AX + MOV DI,INTBASE + MOV AX,QUIT + STOW ;Set abort address--displacement + MOV AX,CS + MOV B,[ENTRYPOINT],LONGJUMP + MOV W,[ENTRYPOINT+1],ENTRY + MOV W,[ENTRYPOINT+3],CS + STOW + STOW + STOW + MOV W,[INTBASE+4],COMMAND + MOV DI,INTBASE+14H + MOV AX,BIOSREAD + STOW + MOV AX,BIOSSEG + STOW + STOW ;Add 2 to DI + STOW + MOV W,[INTBASE+18H],BIOSWRITE + MOV DX,CS + MOV DS,DX + ADD DX,BP ;Next free segment + MOV W,[DMAADD],128 + MOV W,[DMAADD+2],DX + MOV AX,[DRVTAB] + MOV [CURDRV],AX + MOV CX,DX ;Start scanning just after DOS + MOV BX,0FH +MEMSCAN: + INC CX + JZ SETEND + MOV DS,CX + MOV AL,[BX] + NOT AL + MOV [BX],AL + CMP AL,[BX] + NOT AL + MOV [BX],AL + JZ MEMSCAN + +SETEND: + SEG CS + MOV [ENDMEM],CX + XOR CX,CX + MOV DS,CX + MOV W,[EXIT],100H + MOV W,[EXIT+2],DX + MOV W,[INTBASE+0CH],100H + MOV W,[INTBASE+0EH],DX + CALL SETMEM + MOV SI,HEADER + CALL OUTMES + RET L + +QUIT: + MOV AH,0 + JP SAVREGS + +COMMAND: ;Interrupt call entry point + CMP AH,MAXCOM + JBE SAVREGS +BADCALL: + MOV AL,0 +IRET: IRET + +ENTRY: ;System call entry point and dispatcher + POP AX ;IP from the long call at 5 + POP AX ;Segment from the long call at 5 + SEG CS + POP [TEMP] ;IP from the CALL 5 + PUSHF ;Start re-ordering the stack + CLI + PUSH AX ;Save segment + SEG CS + PUSH [TEMP] ;Stack now ordered as if INT had been used + CMP CL,MAXCALL ;This entry point doesn't get as many calls + JA BADCALL + MOV AH,CL +SAVREGS: + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + INC SP + INC SP + SEG CS + POP [TEMP] + MOV SP,CS + MOV SS,SP + MOV SP,SSSAVE + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + MOV BL,AH + MOV BH,0 + SHL BX + CLD + SEG CS + CALL [BX+DISPATCH] + SEG CS + MOV [AXSAVE],AL + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + POP SS + SEG CS + MOV SP,[SPSAVE] + IRET +; Standard Functions +DISPATCH DW ABORT ;0 + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST ;5 + DW RAWIO + DW GETIO + DW SETIO + DW PRTBUF + DW BUFIN ;10 + DW CONSTAT + DW GETVER + DW DSKRESET + DW SELDSK + DW OPEN ;15 + DW CLOSE + DW SRCHFRST + DW SRCHNXT + DW DELETE + DW SEQRD ;20 + DW SEQWRT + DW CREATE + DW RENAME + DW INUSE + DW GETDRV ;25 + DW SETDMA + DW GETFATPT + DW GETFATPTDL + DW GETRDONLY + DW SETATTRIB ;30 + DW GETDSKPT + DW USERCODE + DW RNDRD + DW RNDWRT + DW FILESIZE ;35 + DW SETRNDREC +; Extended Functions + DW SETVECT + DW NEWBASE + DW BLKRD + DW BLKWRT ;40 + +GETIO: +SETIO: +GETVER: +GETFATPTDL: +GETRDONLY: +SETATTRIB: +USERCODE: + MOV AL,0 + RET + +READER: + CALL BIOSAUXIN,BIOSSEG + RET + +PUNCH: + MOV AL,DL + CALL BIOSAUXOUT,BIOSSEG + RET + + +UNPACK: + +; Inputs: +; DS = CS +; BX = Cluster number +; BP = Base of drive parameters +; SI = Pointer to drive FAT +; Outputs: +; DI = Contents of FAT for given cluster +; Zero set means DI=0 (free cluster) +; No other registers affected. Fatal error if cluster too big. + + CMP BX,[BP+MAXCLUS] + JA HURTFAT + LEA DI,[SI+BX] + SHR BX + MOV DI,[DI+BX] + JNC HAVCLUS + SHR DI + SHR DI + SHR DI + SHR DI + STC +HAVCLUS: + RCL BX + AND DI,0FFFH + RET +HURTFAT: + MOV SI,BADFAT + CALL OUTMES + JMP ERROR + + +PACK: + +; Inputs: +; DS = CS +; BX = Cluster number +; DX = Data +; SI = Pointer to drive FAT +; Outputs: +; The data is stored in the FAT at the given cluster. +; BX,DX,DI all destroyed +; No other registers affected + + MOV DI,BX + SHR BX + ADD BX,SI + ADD BX,DI + SHR DI + MOV DI,[BX] + JNC ALIGNED + SHL DX + SHL DX + SHL DX + SHL DX + AND DI,0FH + JP PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + MOV [BX],DI + RET + + +GETNAME: + +; Inputs: +; DS,DX point to FCB +; Function: +; Find file name in disk directory. First byte is +; drive number (0=current disk). "?" matches any +; character. +; Outputs: +; Carry set if file not found +; ELSE +; BP = Base of drive parameters +; DS = CS +; ES = CS +; AX = Directory record number +; BX = Pointer into directory buffer +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + + CALL MOVNAME + JC RET +FINDNAME: + MOV AX,CS + MOV DS,AX + MOV AL,0 +RDIRREC: + PUSH AX + CALL DIRREAD + POP AX + MOV BX,DIRBUF-16 +CONTSRCH: + CALL NEXTENT + JZ RET +NDIRREC: + INC AL ;Next directory record + CMP AL,[BP+DIRSIZ] + JB RDIRREC + STC + RET + +NEXTENT: + Add BX,16 + CMP BX,DIRBUF+127 + JA RET + CMP B,[BX],0E5H + JZ NEXTENT + MOV SI,BX + MOV DI,NAME1 + MOV CX,11 +WILDCRD: + REPE + CMPB + JZ RET + CMP B,[DI-1],"?" + JZ WILDCRD + JP NEXTENT + + +DELETE: ; System call 19 + CALL GETNAME + JC ERRET + PUSH AX + PUSH BX + CALL LOADFAT + POP BX +DELFILE: + MOV B,[BX],0E5H + PUSH BX + MOV BX,[BX+11] + MOV SI,[BP+FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP+MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + POP BX + CALL NEXTENT + JZ DELFILE + POP AX + PUSH AX + CALL DIRWRITE + POP AX + CALL NDIRREC + PUSH AX + JNC DELFILE + POP AX + CALL FATWRT + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + ADD SI,5 + MOV DI,NAME2 + CALL LODNAME + CALL FINDNAME + JC ERRET +SAVDREC: + MOV AH,AL +RENFIL: + MOV DI,BX + MOV SI,NAME2 + MOV CX,11 +NEWNAM: + LODB + CMP AL,"?" + JZ SKIPLET + MOV [DI],AL +SKIPLET: + INC DI + LOOP NEWNAM + CALL NEXTENT + JZ RENFIL + MOV AL,AH + PUSH AX + CALL DIRWRITE + POP AX + CALL NDIRREC + JNC SAVDREC ;New record read, save current number + XOR AL,AL + RET + +ERRET: + MOV AL,-1 + RET + + +MOVNAME: + +; Inputs: +; DS, DX point to FCB +; Outputs: +; ES = CS +; If file name OK: +; BP has base of driver parameters +; [NAME1] has name in upper case +; All registers except DX destroyed +; Carry set if bad file name or drive + + MOV AX,CS + MOV ES,AX + MOV DI,NAME1 + MOV SI,DX + LODB + SEG ES + CMP [NUMIO],AL + JC RET + CBW + XCHG AX,BP + SHL BP + MOV BP,[BP+CURDRV] +LODNAME: +; This entry point copies a file name from DS,SI +; to ES,DI converting to upper case. + MOV CX,11 +MOVCHK: + LODB + AND AL,7FH + CMP AL,"a"-1 + JLE STOLET + AND AL,5FH ;Convert to upper case +STOLET: + CMP AL," " + JB RET + STOB + LOOP MOVCHK + RET + +OPEN: ;System call 15 + PUSH DX + PUSH DS + CALL GETNAME +OPENNAM: + POP ES + POP DI + JC ERRET + MOV AH,[BP+DEVNUM] + INC AH + SEG ES + MOV [DI],AH + SEG ES + MOV [DI+EXTENT],0 + ADD DI,16 + MOV CX,BX + SUB CX,DIRBUF + MOV AH,CL + STOW ;ENTPOS + MOV AX,BP + STOW ;DRVBP + LEA SI,[BX+11] + LODW + STOW ;FIRCLUS + STOW ;LSTCLUS + LODB + SHL AL + LODW + RCL AX + STOW ;FILSIZ + XOR AX,AX + STOW ;CLUSPOS + STOW ;FLSFLG, SIZCHG + +LOADFAT: + TEST B,[BP+DIRTY],-1 + JNZ RET + CALL FIGFAT +READFAT: + PUSH DX + PUSH CX + PUSH BX + PUSH AX + CALL DREAD + OR AL,AL + POP AX + POP BX + POP CX + POP DX + JNZ FATERR + SUB AL,[BP+FATCNT] + JZ RET + NEG AL + JP FATWRT +FATERR: + ADD DX,CX + DEC AL + JNZ READFAT + POP BP + MOV SI,ALLBAD + CALL HARDERR + JP LOADFAT + +CLOSE: ;System call 16 + MOV DI,DX + TEST B,[DI+FLSFLG],-1 + JZ NOFLSH + PUSH DI + MOV BP,[DI+DRVBP] + MOV AL,[BP+DEVNUM] + CALL BIOSFLUSH,BIOSSEG + POP DI +NOFLSH: + TEST B,[DI+SIZCHG],-1 + JZ OKRET + MOV DX,DI + PUSH DX + PUSH DS + CALL GETNAME + POP ES + POP DI + JC BADCLOSE + MOV CX,BX + SUB CX,DIRBUF + MOV AH,CL + SEG ES + CMP AX,[DI+ENTPOS] + JNZ BADCLOSE + SEG ES + MOV CX,[DI+FIRCLUS] + MOV [BX+11],CX + SEG ES + MOV DX,[DI+FILSIZ] + SHR DX + MOV [BX+14],DX + MOV DL,0 + RCR DL + MOV [BX+13],DL + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty + TEST B,[BP+DIRTY],-1 + JZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty flag. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV B,[BP+DIRTY],0 + CALL FIGFAT +EACHFAT: + PUSH DX + PUSH CX + PUSH BX + PUSH AX + CALL DWRITE + POP AX + POP BX + POP CX + POP DX + ADD DX,CX + DEC AL + JNZ EACHFAT +OKRET: + MOV AL,0 + RET + +BADCLOSE: + MOV B,[BP+DIRTY],0 + MOV AL,-1 + RET + + +FIGFAT: +; Loads registers with values needed to read or +; write a FAT. + MOV AL,[BP+FATCNT] + MOV BX,[BP+FAT] + MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT + MOV CH,0 + MOV DX,[BP+FIRFAT] ;Record number of start of FATs + RET + + +DIRCOMP: +; Prepare registers for directory read or write + CBW + ADD AX,[BP+FIRDIR] + MOV DX,AX + MOV BX,DIRBUF + MOV CX,1 + RET + + +CREATE: ;System call 22 + CALL MOVNAME + JC ERRET3 + MOV DI,NAME1 + MOV CX,11 + MOV AL,"?" + REPNE + SCAB + JZ ERRET3 + PUSH DX + PUSH DS + MOV AX,CS + MOV DS,AX + XOR AX,AX +RDIRREC2: + PUSH AX + CALL DIRREAD + POP AX + MOV DI,DIRBUF-16 + MOV CX,8 +FNDFRE: + ADD DI,16 + CMP B,[DI],0E5H + LOOPNE FNDFRE + JZ FREESPOT + INC AL + CMP AL,[BP+DIRSIZ] + JC RDIRREC2 + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET +FREESPOT: + MOV BX,DI + MOV SI,NAME1 + MOV CX,5 + MOVB + REP + MOVW + XCHG AL,AH + MOV CL,5 + REP + STOB + XCHG AL,AH + PUSH AX + PUSH BX + CALL DIRWRITE + POP BX + POP AX + JMP OPENNAM + + +DIRREAD: + +; Inputs: +; DS = CS +; AL = Directory block number +; BP = Base of drive parameters +; Function: +; Read the directory block into DIRBUF. +; Outputs: +; AX,BP unchanged +; All other registers destroyed. + + CALL DIRCOMP + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of records +; DX = Absolute record number +; BP = Base of drive parameters +; Function: +; Calls BIOS to perform disk read. If BIOS reports +; errors, will call HARDERR for further action. +; BP preserved. All other registers destroyed. + + MOV AL,[BP+DEVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSREAD,BIOSSEG + POP DX + POP DI + POP BX + POP BP + JC DSKRDERR + XOR AL,AL + RET + +DSKRDERR: + MOV SI,RDERR + CALL HARDERR + JP DREAD + +DIRWRITE: + +; Inputs: +; DS = CS +; AL = Directory block number +; BP = Base of drive parameters +; Function: +; Write the directory block into DIRBUF. +; Outputs: +; BP unchanged +; All other registers destroyed. + + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of records +; DX = Absolute record number +; BP = Base of drive parameters +; Function: +; Calls BIOS to perform disk write. If BIOS reports +; errors, will call HARDERR for further action. +; BP preserved. All other registers destroyed. + + MOV AL,[BP+DEVNUM] + MOV AH,0 + CMP DX,[BP+FIRREC] + RCR AH + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSWRITE,BIOSSEG + POP DX + POP DI + POP BX + POP BP + JC DSKWRERR + XOR AL,AL + RET + +DSKWRERR: + MOV SI,WRERR + CALL HARDERR + JP DWRITE + +HARDERR: + SUB DI,CX + ADD DX,DI ;Next record to transfer + CALL RECTOBYT + ADD BX,DI ;Next location for transfer + CALL OUTMES +GETRESP: + CALL IN + OR AL,20H ;To lower-case + CMP AL,"a" + JZ ERROR + CMP AL,"r" + JZ RET + CMP AL,"i" + JZ IGNORE + CMP AL,"c" + JNZ GETRESP + POP AX + MOV AL,1 + RET +IGNORE: + POP AX + MOV AL,0 + RET + +ABORT: + SEG CS + MOV DS,[TEMP] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVW + MOVW + MOVW + MOVW +ERROR: + MOV SP,BPSAVE + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL NOBUF + XOR AX,AX + MOV DS,AX + MOV SI,EXIT + MOV DI,EXITHOLD + MOVW + MOVW + POP BP + POP ES + POP ES + POP DS + POP SS + MOV SP,[SPSAVE] + MOV DS,[DSSAVE] + SEG CS + JMP L,[EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + MOV CX,1 + CALL LOAD + JCXZ SETNREX + INC AX + JP SETNREX + +SEQWRT: ;System call 21 + CALL GETREC + MOV CX,1 + CALL STORE + JCXZ SETNREX + INC AX + JP SETNREX + +RNDRD: ;System call 33 + MOV CX,1 + MOV DI,DX + MOV AX,[DI+RR] + CALL LOAD + JP FINRND + +RNDWRT: ;System call 34 + MOV CX,1 + MOV DI,DX + MOV AX,[DI+RR] + CALL STORE + JP FINRND + +BLKRD: ;System call 39 + MOV DI,DX + MOV AX,[DI+RR] + CALL LOAD + JP FINBLK + +BLKWRT: ;System call 40 + MOV DI,DX + MOV AX,[DI+RR] + CALL STORE +FINBLK: + MOV [CXSAVE],CX + JCXZ FINRND + INC AX +FINRND: + SEG ES + MOV [DI+RR],AX +SETNREX: + MOV CX,AX + AND AL,7FH + SEG ES + MOV [DI+NR],AL + AND CL,80H + ROL CX + XCHG CL,CH + SEG ES + MOV [DI+EXTENT],CX + MOV AL,[DSKERR] + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; CX = No. of records to transfer +; BP = Base of drive parameters +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DX +; [NEXTADD] = Displacement of disk transfer within segment +; [DSKERR] = 0 (no errors yet) +; [NUMTRNS] = 0 (No transfers yet) +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + MOV BP,[DI+DRVBP] + MOV BX,DS + MOV ES,BX + MOV BX,CS + MOV DS,BX + MOV [RECPOS],AX + MOV [FCB],DX + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV B,[DSKERR],0 + MOV [NUMTRNS],0 + MOV SI,[BP+FAT] + ADD BX,7FH ;See if there is any space left + JC SEGEND + AND BL,80H + NEG BX ;Amount of room left in segment + ROL BX + XCHG BL,BH + JNZ CHKFIT + MOV BH,2 +CHKFIT: + CMP CX,BX ;See if it will fit in one segment + JBE OK + MOV CX,BX + MOV B,[DSKERR],2 ;Flag that trimming took place +OK: + MOV [RECCNT],CX ;Record count + RET +SEGEND: + MOV B,[DSKERR],2 + MOV CX,0 + POP BX ;Kill return address + RET + + +FNDCLUS: + +; Inputs: +; DS = CS +; CX = No. of clusters to skip +; BP = Base of drive parameters +; SI = FAT pointer +; ES:DI 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. + + SEG ES + MOV BX,[DI+LSTCLUS] + SEG ES + MOV DX,[DI+CLUSPOS] + OR BX,BX + JZ NOCLUS + SUB CX,DX + JNB FINDIT + ADD CX,DX + XOR DX,DX + SEG ES + MOV BX,[DI+FIRCLUS] +FINDIT: + JCXZ RET +SKPCLP: + CALL UNPACK + CMP DI,0FFFH + JZ RET + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +LOAD: + +; Inputs: +; DS:DI point to FCB +; AX = Position in file to read +; CX = No. of records to read +; Outputs: +; AX = Position of last record read +; CX = No. of records read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + SEG ES + MOV BX,[DI+FILSIZ] + SUB BX,AX + JBE WRTERRJ + CMP BX,CX + JNB ENUF + MOV B,[DSKERR],1 + MOV [RECCNT],BX +ENUF: + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + OR CX,CX + JNZ WRTERR + MOV DL,[RECPOS] + AND DL,[BP+CLUSMSK] + MOV CX,[RECCNT] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DREAD + POP DS + POP CX + POP BX + JCXZ SETFCB + MOV DL,0 + CMP BX,0FFFH + JNZ RDLP + MOV B,[DSKERR],1 + +SETFCB: + MOV AX,[CLUSNUM] + MOV DI,[FCB] + SEG ES + MOV [DI+LSTCLUS],AX + MOV AX,[RECPOS] + MOV BX,[NUMTRNS] + ADD AX,BX + SEG ES + CMP AX,[DI+FILSIZ] + JBE NOSZINC + SEG ES + MOV [DI+FILSIZ],AX + SEG ES + MOV B,[DI+SIZCHG],-1 +NOSZINC: + DEC AX + MOV DX,AX + MOV CL,[BP+CLUSSHFT] + SHR DX,CL + SEG ES + MOV [DI+CLUSPOS],DX + MOV CX,BX + RET +WRTERRJ: + JP WRTERR + +HAVSTART: + MOV CX,AX + PUSH BX + CALL FNDCLUS + JCXZ WRCLUS + CALL ALLOCATE + POP BX + JNC NOSKIP +WRTERR: + MOV B,[DSKERR],1 +ADDREC: + MOV AX,[RECPOS] + XOR CX,CX + MOV DI,[FCB] + RET +WRTEOF: + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + OR CX,CX + JNZ ADDREC + MOV DX,0FFFH + MOV B,[BP+DIRTY],-1 + MOV DI,[FCB] + MOV AX,[RECPOS] + SEG ES + MOV [DI+FILSIZ],AX + SEG ES + MOV B,[DI+SIZCHG],-1 + XOR CX,CX + RET + +STORE: + +; Inputs: +; DS:DI point to FCB +; AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + JCXZ WRTEOF + MOV BX,CX + ADD BX,AX + DEC BX + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + SHR BX,CL + MOV CX,AX + MOV AX,BX + CALL FNDCLUS + SUB AX,DX ;Last cluster minus current cluster + JCXZ HAVSTART ;See if no more data + PUSH CX ;No. of clusters of first + MOV CX,AX + CALL ALLOCATE + POP CX + JC WRTERR + DEC CX + JZ NOSKIP + CALL SKPCLP + PUSH BX +WRCLUS: + POP BX +NOSKIP: + MOV DL,[RECPOS] + AND DL,[BP+CLUSMSK] + MOV CX,[RECCNT] +WRTLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + MOV DL,0 + OR CX,CX + JNZ WRTLP + CALL SETFCB + SEG ES + MOV B,[DI+FLSFLG],-1 + RET + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = record within cluster +; 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 record address +; DI = Next cluster +; [CLUSNUM] = Last cluster accessed +; [NEXTADD] updated +; BP unchanged. Note that segment of transfer not set. + + PUSH DX + PUSH BX + MOV AL,[BP+CLUSMSK] + INC AL ;Number of records per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of records left in first cluster + MOV DX,CX + MOV SI,[BP+FAT] + MOV CX,0 +OPTCLUS: +;AL has number of records available in current cluster +;AH has number of records available in next cluster +;BX has current physical cluster +;CX has number of sequential records found so far +;DX has number of records left to transfer +;SI has FAT pointer + CALL 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 records still needed + MOV AX,DX + MOV BX,CX + XCHG BL,BH + ROR BX + MOV SI,[NEXTADD] + ADD BX,SI ;Adjust by size of transfer + MOV [NEXTADD],BX + ADD [NUMTRNS],CX + POP DX + POP BX + PUSH CX + MOV CL,[BP+CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP+FIRREC] + POP CX + MOV BX,SI + RET +BLKDON: + MOV CX,DX ;Make the total equal to the request + JP FINCLUS + + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; AX = Record number determined by EXTENT and NR fields +; DS:DI point to FCB +; No other registers affected. + + MOV DI,DX + MOV AL,[DI+NR] + MOV BX,[DI+EXTENT] + SHL AL + SHR BX + RCR AL + MOV AH,BL + RET + + +ALLOCATE: + +; Inputs: +; DS = CS +; ES = Segment of FCB +; BX = Last cluster of file (0 if null file) +; CX = No. of clusters to allocate +; DX = Position of cluster BX +; BP = Base of drive parameters +; SI = FAT pointer +; [FCB] = Displacement of FCB within segment +; 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 flag +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP+MAXCLUS] + JL TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + OR [SI],0FFFH + STC + RET + +TRYOUT: + CALL UNPACK + JZ HAVFRE +TRYIN: + DEC AX + JLE FINDFRE + XCHG AX,BX + CALL UNPACK + JZ HAVFRE + XCHG AX,BX + JP FINDFRE +HAVFRE: + XCHG BX,DX + MOV AX,DX + CALL PACK + MOV BX,AX + LOOP ALLOC + MOV DX,0FFFH + CALL PACK + MOV B,[BP+DIRTY],-1 + POP BX + CALL UNPACK + XCHG BX,DI + OR DI,DI + JNZ RET + MOV DI,[FCB] + SEG ES + MOV [DI+FIRCLUS],BX + OR [SI],0FFFH + RET + + +RELEASE: + +; Inputs: +; DS = CS +; BX = Cluster in file +; SI = FAT pointer +; BP = Base of drive parameters +; Function: +; Frees cluster chain starting with [BX] +; AX,BX,DX,DI all destroyed. Other registers unchanged. + + XOR DX,DX +RELBLKS: +; Enter here with DX=0FFFH to put an end-of-file mark +; in the first cluster and free the rest in the chain. + CALL UNPACK + JZ RET + MOV AX,DI + CALL PACK + CMP AX,0FFFH + MOV BX,AX + JNZ RELEASE + RET + + +GETEOF: + +; Inputs: +; BX = Cluster in a file +; SI = Base of drive FAT +; DS = CS +; Outputs: +; BX = Last cluster in the file +; DI destroyed. No other registers affected. + + CALL UNPACK + CMP DI,0FFFH + JZ RET + MOV BX,DI + JP GETEOF + + +SRCHFRST: ;System call 17 + CALL GETNAME +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + JC KILLSRCH + MOV [SRCHDON],AL + MOV [PDIR],BX + MOV [SRCHBP],BP +;Information in directory entry must be copied into the first +; 16 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,[DMAADD] + MOV CX,8 + REP + MOVW + MOV AL,0 + RET + +KILLSRCH: + MOV AL,-1 + MOV [SRCHDON],AL + RET + + +SRCHNXT: ;System call 18 + MOV AX,CS + MOV ES,AX + MOV DS,AX + MOV AL,[SRCHDON] + CMP AL,-1 + JZ RET + MOV BX,[PDIR] + MOV BP,[SRCHBP] + CALL CONTSRCH + JP SAVPLCE + + +FILESIZE: ;System call 35 + PUSH DI + PUSH DX + CALL GETNAME + POP DI + POP ES + MOV AL,-1 + JC RET + ADD DI,33 ;Write size in RR field + LEA SI,[BX+13] + LODB + SHL AL + LODW + RCL AX ;Round to nearest record + STOW + MOV AL,0 + RCL AL + STOB + RET + + +SETDMA: ;System call 26 + SEG CS + MOV [DMAADD],DX + SEG CS + MOV [DMAADD+2],DS + RET + +GETFATPT: ;System call 27 + MOV AX,CS + MOV DS,AX + MOV [DSSAVE],CS + MOV BP,[CURDRV] + CALL LOADFAT + MOV BX,[BP+FAT] + MOV AL,[BP+CLUSMSK] + INC AL + MOV DX,[BP+MAXCLUS] + DEC DX + MOV B,[BP+DIRTY],-1 + MOV [BXSAVE],BX + MOV [DXSAVE],DX + RET + + +GETDSKPT: ;System call 31 + SEG CS + MOV [DSSAVE],CS + SEG CS + MOV BX,[CURDRV] + SEG CS + MOV [BXSAVE],BX + RET + + +DSKRESET: ;System call 13 + SEG CS + MOV [DMAADD+2],DS + MOV AX,CS + MOV DS,AX + MOV [DMAADD],80H + MOV AX,[DRVTAB] + MOV [CURDRV],AX +NOBUF: + MOV CL,[NUMIO] + MOV CH,0 + MOV SI,DRVTAB +WRTFAT: + LODW + PUSH CX + PUSH SI + MOV BP,AX + CALL CHKFATWRT + POP SI + POP CX + LOOP WRTFAT + MOV AL,-1 + CALL BIOSFLUSH,BIOSSEG + RET + + +GETDRV: ;System call 25 + SEG CS + MOV BP,[CURDRV] + MOV AL,[BP+0] + RET + + +INUSE: ;System call 24 + MOV AX,CS + MOV DS,AX + MOV CL,[NUMIO] + MOV CH,0 + MOV SI,CX + SHL SI + ADD SI,CURDRV + MOV BX,0 + STD +CHKUSE: + LODW + MOV BP,AX + TEST B,[BP+DIRTY],-1 + JZ SETBIT + STC +SETBIT: + RCL BX + LOOP CHKUSE + MOV AL,BL + RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+RR],AX + MOV AL,0 + JZ BIGRR + INC AL +BIGRR: + MOV [DI+RR+2],AL + RET + + +SELDSK: ;System call 14 + MOV DH,0 + MOV BX,DX + PUSH CS + POP DS + CMP BL,[NUMIO] + JGE RET + SHL BX + MOV AX,[BX+DRVTAB] + MOV [CURDRV],AX + RET + +BUFIN: ;System call 10 + MOV AX,CS + MOV ES,AX + MOV SI,DX + MOV CH,0 + LODW + OR AL,AL + JZ RET + MOV BL,AH + MOV BH,CH + CMP AL,BL + JBE NOEDIT + CMP B,[BX+SI],0DH + JZ EDITON +NOEDIT: + MOV BL,CH +EDITON: + MOV DL,AL + DEC DX +NEWLIN: + SEG CS + MOV AL,[CARPOS] + SEG CS + MOV [STARTPOS],AL + PUSH SI + MOV DI,INBUF + MOV AH,CH + MOV BH,CH + MOV DH,CH +GETCH: + CALL IN + CMP AL,7FH + JZ BACKSP + CMP AL,8 + JZ BACKSP + CMP AL,13 + JZ ENDLIN + CMP AL,10 + JZ PHYCRLF + CMP AL,CANCEL + JZ KILNEW + CMP AL,27 + JZ ESC +SAVCH: + CMP DH,DL + JNB GETCH + STOB + INC DH + CALL OUT + OR AH,AH + JNZ GETCH + CMP BH,BL + JAE GETCH + INC SI + INC BH + JP GETCH + +ESC: + CALL IN + MOV CL,ESCTABLEN + PUSH DI + MOV DI,ESCTAB + REPNE + SCAB + POP DI + AND CL,0FEH + MOV BP,CX + JMP [BP+ESCFUNC] + +ENDLIN: + STOB + CALL OUT + POP DI + MOV [DI-1],DH + INC DH +COPYNEW: + MOV BP,ES + MOV BX,DS + MOV ES,BX + MOV DS,BP + MOV SI,INBUF + MOV CL,DH + REP + MOVB + RET +CRLF: + MOV AL,13 + CALL OUT + MOV AL,10 + JMP OUT + +PHYCRLF: + CALL CRLF + JP GETCH + +KILNEW: + MOV AL,"\" + CALL OUT + POP SI +PUTNEW: + CALL CRLF + JMP NEWLIN + +BACKSP: + OR DH,DH + JZ OLDBAK + CALL BACKUP + SEG ES + MOV AL,[DI] + CMP AL," " + JAE OLDBAK + CMP AL,9 + JZ BAKTAB + CALL BACKMES +OLDBAK: + OR AH,AH + JNZ GETCH1 + OR BH,BH + JZ GETCH1 + DEC BH + DEC SI +GETCH1: + JMP GETCH +BAKTAB: + PUSH DI + DEC DI + STD + MOV CL,DH + MOV AL," " + PUSH BX + MOV BL,7 + JCXZ FIGTAB +FNDPOS: + SCAB + JNA CHKCNT + SEG ES + CMP B,[DI+1],9 + JZ HAVTAB + DEC BL +CHKCNT: + LOOP FNDPOS +FIGTAB: + SEG CS + SUB BL,[STARTPOS] +HAVTAB: + SUB BL,DH + ADD CL,BL + AND CL,7 + CLD + POP BX + POP DI + JZ OLDBAK +TABBAK: + CALL BACKMES + LOOP TABBAK + JP OLDBAK +BACKUP: + DEC DH + DEC DI +BACKMES: + MOV AL,8 + CALL OUT + MOV AL," " + CALL OUTCH + MOV AL,8 + JMP OUTCH + +TWOESC: + MOV AL,ESCCH + JMP SAVCH + +COPYLIN: + MOV CL,BL + SUB CL,BH + JP COPYEACH + +COPYSTR: + CALL FINDOLD + JP COPYEACH + +COPYONE: + MOV CL,1 +COPYEACH: + CMP DH,DL + JZ GETCH2 + CMP BH,BL + JZ GETCH2 + LODB + STOB + CALL OUT + INC BH + INC DH + LOOP COPYEACH +GETCH2: + JMP GETCH + +SKIPONE: + CMP BH,BL + JZ GETCH2 + INC BH + INC SI + JMP GETCH + +SKIPSTR: + CALL FINDOLD + ADD SI,CX + ADD BH,CL + JMP GETCH + +FINDOLD: + CALL IN + MOV CL,BL + SUB CL,BH + JZ NOTFND + DEC CX + JZ NOTFND + PUSH ES + PUSH DS + POP ES + PUSH DI + MOV DI,SI + INC DI + REPNE + SCAB + POP DI + POP ES + JNZ NOTFND + NOT CL + ADD CL,BL + SUB CL,BH + RET +NOTFND: + POP BP + JMP GETCH + +REEDIT: + MOV AL,"@" + CALL OUT + POP DI + PUSH DI + PUSH ES + PUSH DS + CALL COPYNEW + POP DS + POP ES + POP SI + MOV BL,DH + JMP PUTNEW + +ENTERINS: + MOV AH,-1 + JMP GETCH + +EXITINS: + MOV AH,0 + JMP GETCH + +ESCFUNC DW GETCH + DW TWOESC + DW EXITINS + DW ENTERINS + DW BACKSP + DW REEDIT + DW KILNEW + DW COPYLIN + DW SKIPSTR + DW COPYSTR + DW SKIPONE + DW COPYONE + +CONOUT: ;System call 2 + MOV AL,DL +OUT: + CMP AL,20H + JB CTRLOUT + CMP AL,7FH + JZ OUTCH + SEG CS + INC B,[CARPOS] +OUTCH: + CALL BIOSOUT,BIOSSEG + SEG CS + TEST B,[PFLAG],-1 + JZ STATCHK + CALL BIOSPRINT,BIOSSEG + +STATCHK: + CALL BIOSSTAT,BIOSSEG + JZ RET +INCHK: + CALL BIOSIN,BIOSSEG + CMP AL,'S'-'@' + JNZ NOSTOP + CALL BIOSIN,BIOSSEG ;Eat Cntrl-S +NOSTOP: + CMP AL,'P'-'@' + JZ PRINTON + CMP AL,'N'-'@' + JZ PRINTOFF + CMP AL,'C'-'@' + JNZ RET + INT CONTC ;Execute user Ctrl-C handler + RET + +PRINTON: + SEG CS + MOV B,[PFLAG],1 + RET + +PRINTOFF: + SEG CS + MOV B,[PFLAG],0 + RET + +CTRLOUT: + CMP AL,10 + JZ OUTCH + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JZ TAB + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JP OUT + +ZERPOS: + SEG CS + MOV B,[CARPOS],0 + JP OUTCH + +BACKPOS: + SEG CS + DEC B,[CARPOS] + JP OUTCH + +TAB: + MOV AL,0 + SEG CS + XCHG AL,[CARPOS] + OR AL,0F8H + NEG AL + PUSH CX + MOV CL,AL + MOV CH,0 +TABLP: + MOV AL," " + CALL OUTCH + LOOP TABLP + POP CX + RET + + +CONSTAT: ;System call 11 + CALL BIOSSTAT,BIOSSEG + JZ RET + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL INCHK + PUSH AX + CALL OUT + POP AX + RET + + +IN: + CALL INCHK + JZ IN + RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + CALL BIOSSTAT,BIOSSEG + JZ RET + CALL BIOSIN,BIOSSEG + RET +RAWOUT: + CALL BIOSOUT,BIOSSEG + RET + +LIST: ;System call 5 + MOV AL,DL + CALL BIOSPRINT,BIOSSEG + RET + +PRTBUF: ;System call 9 + MOV SI,DX +OUTSTR: + LODB + CMP AL,"$" + JZ RET + CALL OUT + JP OUTSTR + +OUTMES: ;String output for internal messages + SEG CS + LODB + CMP AL,"$" + JZ RET + CALL OUT + JP OUTMES + + +SETVECT: ; Interrupt call 37 + XOR BX,BX + MOV ES,BX + MOV BL,AL + SHL BX + SHL BX + SEG ES + MOV [BX],DX + SEG ES + MOV [BX+2],DS + RET + + +NEWBASE: ; Interrupt call 38 + MOV ES,DX + SEG CS + MOV DS,[TEMP] + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP + MOVW + +SETMEM: + +; Inputs: +; AX = Size of memory in paragraphs +; DX = Segment +; Function: +; Completely prepares a program base at the +; specified segment. +; Outputs: +; DS = DX +; ES = DX +; [0] has INT 20H +; [2] = First unavailable segment ([ENDMEM]) +; [5] to [9] form a long call to the entry point +; [10] to [13] have exit address (from INT 22H) +; [14] to [17] have ctrl-C exit address (from INT 23H) +; DX,BP unchanged. All other registers destroyed. + + XOR CX,CX + MOV DS,CX + MOV ES,DX + MOV SI,EXIT + MOV DI,SAVEXIT + MOVW + MOVW + MOVW + MOVW + SEG CS + MOV CX,[ENDMEM] + SEG ES + MOV [2],CX + SUB CX,DX + CMP CX,0FFFH + JBE HAVDIF + MOV CX,0FFFH +HAVDIF: + MOV BX,ENTRYPOINTSEG + SUB BX,CX + SHL CX + SHL CX + SHL CX + SHL CX + MOV DS,DX + MOV [6],CX + MOV [8],BX + MOV [0],20CDH ;"INT INTTAB" + MOV B,[5],LONGCALL + RET + +RECTOBYT: + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + RET + + +;***** DATA AREA ***** +BADFAT DB 13,10,"Bad FAT",13,10,"$" +ALLBAD DB 13,10,"All FATs on disk are bad",13,10,"$" +RDERR DB 13,10,"Disk read error",13,10,"$" +WRERR DB 13,10,"Disk write error",13,10,"$" +CARPOS DB 0 +STARTPOS DB 0 +PFLAG DB 0 +SRCHDON DB -1 +PDIR DS 2 +SRCHBP DS 2 +EXITHOLD DS 4 +ENDMEM DS 2 +FATBASE DS 2 +INBUF DS 255 +DIRBUF DS 128 +NUMIO DS 1 ;Number of disk tables +NAME1 DS 11 ;File name buffer +NAME2 DS 11 ;File name buffer +DMAADD DS 4 ;User's disk transfer address (disp/seg) +TEMP DS 2 +DSKERR DS 1 +FCB DS 2 ;Address of user FCB +RECPOS DS 2 +NEXTADD DS 2 +RECCNT DS 2 +CLUSNUM DS 2 +NUMTRNS DS 2 + DS 50 +AXSAVE DS 2 +BXSAVE DS 2 +CXSAVE DS 2 +DXSAVE DS 2 +SISAVE DS 2 +DISAVE DS 2 +BPSAVE DS 2 +DSSAVE DS 2 +ESSAVE DS 2 +SSSAVE DS 2 +SPSAVE DS 2 +CURDRV DS 2 +DRVTAB: ;Address of start of DPBs + \ No newline at end of file diff --git a/HEX2BIN.ASM b/HEX2BIN.ASM index 0a324e6..205e586 100644 --- a/HEX2BIN.ASM +++ b/HEX2BIN.ASM @@ -127,7 +127,7 @@ DONE: MOV AH,SETDMA INT 21H MOV CX,BP - SUB CX,1F2H + SUB CX,START-7FH AND CL,80H JCXZ EXIT ROL CX @@ -152,4 +152,4 @@ ADDR: DB "Address out of range--conversion aborted$" DIRFUL: DB "Disk directory full$" START: - \ No newline at end of file + \ No newline at end of file