commit 8065d4d8be0962fa9f98f5a132c613b329bf38a7 Author: Yufeng Gao <85091235+TheBrokenPipe@users.noreply.github.com> Date: Wed Apr 22 01:04:31 2026 +1000 Initial commit Initial import of the transcribed source code from Tim Paterson's DOS listings. Co-authored-by: RichCini diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..16c6dd6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +* -text +LICENSE text=auto +*.md text=auto +*.txt text=auto diff --git a/1_transcription/bundle_1 b/1_transcription/bundle_1 new file mode 100644 index 0000000..997f202 --- /dev/null +++ b/1_transcription/bundle_1 @@ -0,0 +1,5012 @@ +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-1 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + TITLE MS-DOS version 1.25 by Tim Pate + rson March 3, 1982 + PAGE 60,132 + ; Use the following booleans to set the switches + = 0000 FALSE EQU 0 + = FFFF TRUE EQU NOT FALSE + + ; Use the switches below to produce the standard Microsoft version of the IBM + ; version of the operating system + = MSVER EQU TRUE + = IBM EQU FALSE + + ; Set this switch to cause DOS to move itself to the end of memory + = HIGHMEM EQU FALSE + + ; Turn on switch below to allow testing disk code with DEBUG. It sets + ; up a different stack for disk I/O (functions > 11) than that used for + ; character I/O which effectively makes the DOS re-entrant. + + = DSKTEST EQU FALSE + + C INCLUDE MSDOS.ASM + C ; 86-DOS High-performance operating system for the 8086 version 1.25 + C ; by Tim Paterson + C + C + C ; ****************** Revision History ************************* + C ; >> EVERY change must noted below!! << + C ; + C ; 0.34 12/29/80 General release, updating all past customers + C ; 0.42 02/25/81 32-byte directory entries added + C ; 0.56 03/23/81 Variable record and sector sizes + C ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack + C ; 0.74 04/15/81 Recognize I/O devices with file names + C ; 0.75 04/17/81 Improve and correct buffer handling + C ; 0.76 04/23/81 Correct directory size when not 2^N entries + C ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 + C ; 1.00 04/28/81 Renumber for general release + C ; 1.01 05/12/81 Fix bug in `STORE' + C ; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time, + C ; RENAME fix, general cleanup + C ; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE + C ; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't) + C ; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling + C ; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; + C ; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; + C ; Lots of smaller improvements + C ; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory + C ; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write + C ; 1.23 02/11/82 Add defaulting to parser; use variable escape character + C ; Don't zero extent field in IBM version (back to 1.01!) + C ; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28 + C ; 1.25 03/03/82 Put marker (00) at end of directory to speed searches + C ; + C ; ************************************************************* +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-2 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + C + C ; Interrupt Entry Points: + C + C ; INTBASE: ABORT + C ; INTBASE+4: COMMAND + C ; INTBASE+8: BASE EXIT ADDRESS + C ; INTBASE+C: CONTROL-C ABORT + C ; INTBASE+10H: FATAL ERROR ABORT + C ; INTBASE+14H: BIOS DISK READ + C ; INTBASE+18H: BIOS DISK WRITE + C ; INTBASE+40H: Long jump to CALL entry point + C + C ELSE + = 001B C ESCCH EQU 1BH + = 0018 C CANCEL EQU "X"-"@" ;Cancel with Ctrl-X + = C TOGLINS EQU FALSE ;Separate keys for insert mode on and off + = C TOGLPRN EQU FALSE ;Separate keys for printer echo on and off + = 0005 C NUMDEV EQU 5 ;Number of I/O device names + = C ZEROEXT EQU FALSE + C ENDIF + C + = 0024 C MAXCALL EQU 36 + = 002E C MAXCOM EQU 46 + = 0080 C INTBASE EQU 80H + = 0020 C INTTAB EQU 20H + = 000C C ENTRYPOINTSEG EQU 0CH + = 00C0 C ENTRYPOINT EQU INTBASE+40H + = 0023 C CONTC EQU INTTAB+3 + = 0088 C EXIT EQU INTBASE+8 + = 00EA C LONGJUMP EQU 0EAH + = 009A C LONGCALL EQU 9AH + = 0FFF C MAXDIF EQU 0FFFH + = 000A C SAVEXIT EQU 10 + C + C ; Field definition for FCBs + C + C FCBLOCK STRUC + 0000 0C [ C DB 12 DUP (?) ;Drive code and name + ?? C + ] C + C + 000C ???? C EXTENT DW ? + 000E ???? C RECSIZ DW ? ;Size of record (user settable) + 0010 ???? C FILSIZ DW ? ;Size of file in bytes + 0012 ???? C DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT + 0014 ???? C FDATE DW ? ;Date of last writing + 0016 ???? C FTIME DW ? ;Time of last writing + 0018 ?? C DEVID DB ? ;Device ID number, bits 0-5 + C ;bit 7=0 for file, bit 7=1 for I/O device + C ;If file, bit 6=0 if dirty + C ;If I/O device, bit 6=0 if EOF (input) + 0019 ???? C FIRCLUS DW ? ;First cluster of file + 001B ???? C LSTCLUS DW ? ;Last cluster accessed + 001D ???? C CLUSPOS DW ? ;Position of last cluster accessed +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-3 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 001F ?? C DB ? ;Forces NR to offset 32 + 0020 ?? C NR DB ? ;Next record + 0021 03 [ C RR DB 3 DUP (?) ;Random record + ?? C + ] C + C + 0024 C FCBLOCK ENDS + = 0010 C FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT + C + C ; Description of 32-byte directory entry (same as returned by SEARCH FIRST + C ; and SEARCH NEXT, functions 17 and 18). + C ; + C ; Location bytes Description + C ; + C ; 0 11 File name and extension ( 0E5H if empty) + C ; 11 1 Attributes. Bits 1 or 2 make file hidden + C ; 12 10 Zero field (for expansion) + C ; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour + C ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 + C ; 26 2 First allocation unit ( < 4080 ) + C ; 28 4 File size, in bytes (LSB first, 30 bits max.) + C ; + C ; The File Allocation Table uses a 12-bit entry for each allocation unit on + C ; the disk. These entries are packed, two for every three bytes. The contents + C ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result + C ; to the base address of the Allocation Table; 3) fetching the 16-bit word at + C ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the + C ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number + C ; zero is used as an end-of-file trap in the OS and as a flag for directory + C ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The + C ; first available allocation unit is assigned entry number two, and even + C ; though it is the first, is called cluster 2. Entries greater than 0FF8H are + C ; end of file marks; entries of zero are unallocated. Otherwise, the contents + C ; of a FAT entry is the number of the next cluster in the file. + C + C + C ; Field definition for Drive Parameter Block + C + C DPBLOCK STRUC + 0000 ?? C DEVNUM DB ? ;I/O driver number + 0001 ?? C DRVNUM DB ? ;Physical Unit number + 0002 ???? C SECSIZ DW ? ;Size of physical sector in bytes + 0004 ?? C CLUSMSK DB ? ;Sectors/cluster - 1 + 0005 ?? C CLUSSHFT DB ? ;Log2 of sectors/cluster + 0006 ???? C FIRFAT DW ? ;Starting record of FATs + 0008 ?? C FATCNT DB ? ;Number of FATs for this drive + 0009 ???? C MAXENT DW ? ;Number of directory entries + 000B ???? C FIRREC DW ? ;First sector of first cluster + 000D ???? C MAXCLUS DW ? ;Number of clusters on drive + 1 + 000F ?? C FATSIZ DB ? ;Number of records occupied by FAT + 0010 ???? C FIRDIR DW ? ;Starting record of directory + 0012 ???? C FAT DW ? ;Pointer to start of FAT + 0014 C DPBLOCK ENDS + C + = 0014 C DPBSIZ EQU 20 ;Size of the structure in bytes +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-4 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + = 000B C DIRSEC = FIRREC ;Number of dir. sectors (init temporary) + = 000D C DSKSIZ = MAXCLUS ;Size of disk (temp used during init only) + C + C ;The following are all of the segments used + C ;They are declared in the order that they should be placed in the executable + C + 0000 C CODE SEGMENT + 0000 C CODE ENDS + C + 0000 C CONSTANTS SEGMENT BYTE + 0000 C CONSTANTS ENDS + C + 0000 C DATA SEGMENT WORD + 0000 C DATA ENDS + C + C DOSGROUP GROUP CODE,CONSTANTS,DATA + C + 0000 C SEGBIOS SEGMENT + 0000 C SEGBIOS ENDS + C + C + C ; BOIS entry point definitions + C + C ENDIF + C IF NOT IBM + = 0040 C BIOSSEG EQU 40H + C ENDIF + C + 0000 C SEGBIOS SEGMENT AT BIOSSEG + 0000 C ORG 0 + 0000 03 [ C DB 3 DUP (?) ;Reserve room for jump to init code + ?? C + ] C + C + 0003 03 [ C BIOSSTAT DB 3 DUP (?) ;Console input status check + ?? C + ] C + C + 0006 03 [ C BIOSIN DB 3 DUP (?) ;Get console character + ?? C + ] C + C + 0009 03 [ C BIOSOUT DB 3 DUP (?) ;Output console character + ?? C + ] C + C + 000C 03 [ C BIOSPRINT DB 3 DUP (?) ;Output to printer + ?? C + ] C + C + 000F 03 [ C BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary + ?? C + ] C + C + 0012 03 [ C BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-5 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + ?? C + ] C + C + 0015 03 [ C BIOSREAD DB 3 DUP (?) ;Disk read + ?? C + ] C + C + 0018 03 [ C BIOSWRITE DB 3 DUP (?) ;Disk write + ?? C + ] C + C + 001B 03 [ C BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status + ?? C + ] C + C + 001E 03 [ C BIOSSETDATE DB 3 DUP (?) ;Set date + ?? C + ] C + C + 0021 03 [ C BIOSSETTIME DB 3 DUP (?) ;Set time + ?? C + ] C + C + 0024 03 [ C BIOSGETTIME DB 3 DUP (?) ;Get time and date + ?? C + ] C + C + 0027 03 [ C BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer + ?? C + ] C + C + 002A 03 [ C BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper + ?? C + ] C + C + C + 002D C SEGBIOS ENDS + C ; Location of user registers relative user stack pointer + C + C STKPTRS STRUC + 0000 ???? C AXSAVE DW ? + 0002 ???? C BXSAVE DW ? + 0004 ???? C CXSAVE DW ? + 0006 ???? C DXSAVE DW ? + 0008 ???? C SISAVE DW ? + 000A ???? C DISAVE DW ? + 000C ???? C BPSAVE DW ? + 000E ???? C DSSAVE DW ? + 0010 ???? C ESSAVE DW ? + 0012 ???? C IPSAVE DW ? + 0014 ???? C CSSAVE DW ? + 0016 ???? C FSAVE DW ? + 0018 C STKPTRS ENDS + C + C ; Start of code +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-6 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0000 C CODE SEGMENT + C ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP + C + 0000 C ORG 0 + = 0000 C CODSTRT EQU $ + 0000 E9 0024 R C JMP DOSINIT + C + 0003 1B C ESCCHAR DB ESCCH ;Lead-in character for escape sequences + 0004 C ESCTAB: + C IF NOT IBM + 0004 53 C DB "S" ;Copy one char + 0005 56 C DB "V" ;Skip one char + 0006 54 C DB "T" ;Copy to char + 0007 57 C DB "W" ;Skip to char + 0008 55 C DB "U" ;Copy line + 0009 45 C DB "E" ;Kill line (no change in template) + 000A 4A C DB "J" ;Reedit line (new template) + 000B 44 C DB "D" ;Backspace + 000C 50 C DB "P" ;Enter insert mode + 000D 51 C DB "Q" ;Exit insert mode + 000E 52 C DB "R" ;Escape character + 000F 52 C DB "R" ;End of table + C ENDIF + C ENDIF + C + = 000C C ESCTABLEN EQU $-ESCTAB + C IF NOT IBM + 0010 0D 0A 4D 53 2D 44 C HEADER DB 13,10,"MS-DOS version 1.25" + 4F 53 20 76 65 72 C + 73 69 6F 6E 20 31 C + 2E 32 35 C + C ENDIF + C ENDIF + C + 0025 0D 0A C DB 13,10 + 0027 43 6F 70 79 72 69 C DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$" + 67 68 74 20 31 39 C + 38 31 2C 38 32 20 C + 4D 69 63 72 6F 73 C + 6F 66 74 2C 20 49 C + 6E 63 2E 0D 0A 24 C + C ENDIF + C + 004B C QUIT: + 004B B4 00 C MOV AH,0 + 004D EB 1E C JMP SHORT SAVREGS + C + 004F C COMMAND: ;Interrupt call entry point + 004F 80 FC 2E C CMP AH,MAXCOM + 0052 76 19 C JBE SAVREGS + 0054 C BADCALL: + 0054 B0 00 C MOV AL,0 + 0056 CF C IRET: IRET + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-7 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0057 C ENTRY: ;System call entry point and dispatcher + 0057 58 C POP AX ;IP from the long call at 5 + 0058 58 C POP AX ;Segment from the long call at 5 + 0059 2E: 8F 06 0131 R C POP CS:[TEMP] ;IP from the CALL 5 + 005E 9C C PUSHF ;Start re-ordering the stack + 005F FA C CLI + 0060 50 C PUSH AX ;Save segment + 0061 2E: FF 36 0131 R C PUSH CS:[TEMP] ;Stack now ordered as if INT had been used + 0066 80 F9 24 C CMP CL,MAXCALL ;This entry point doesn't get as many calls + 0069 77 E9 C JA BADCALL + 006B 8A E1 C MOV AH,CL + 006D C SAVREGS: + 006D 06 C PUSH ES + 006E 1E C PUSH DS + 006F 55 C PUSH BP + 0070 57 C PUSH DI + 0071 56 C PUSH SI + 0072 52 C PUSH DX + 0073 51 C PUSH CX + 0074 53 C PUSH BX + 0075 50 C PUSH AX + C + C ENDIF + C + 0076 2E: 89 26 0131 R C MOV CS:[SPSAVE],SP + 007B 2E: 8C 16 0133 R C MOV CS:[SSSAVE],SS + 0080 8C CC C MOV SP,CS + 0082 8E D4 C MOV SS,SP + 0084 C REDISP: + 0084 BC 01DE R C MOV SP,OFFSET DOSGROUP:IOSTACK + 0087 FB C STI ;Stack OK now + 0088 8A DC C MOV BL,AH + 008A B7 00 C MOV BH,0 + 008C D1 E3 C SHL BX,1 + 008E FC C CLD + 008F 80 FC 0C C CMP AH,12 + 0092 7E 03 C JLE SAMSTK + 0094 BC 025E R C MOV SP,OFFSET DOSGROUP:DSKSTACK + 0097 C SAMSTK: + 0097 2E: FF 97 00B6 R C CALL CS:[BX+DISPATCH] + 009C C LEAVE: + 009C FA C CLI + 009D 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] + 00A2 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 00A7 8B EC C MOV BP,SP + 00A9 88 46 00 C MOV BYTE PTR [BP.AXSAVE],AL + C + C ENDIF + C + 00AC 58 C POP AX + 00AD 5B C POP BX + 00AE 59 C POP CX + 00AF 5A C POP DX + 00B0 5E C POP SI + 00B1 5F C POP DI +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-8 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 00B2 5D C POP BP + 00B3 1F C POP DS + 00B4 07 C POP ES + 00B5 CF C IRET + C ; Standard Functions + 00B6 06B1 R C DISPATCH DW ABORT ;0 + 00B8 1253 R C DW CONIN + 00BA 119D R C DW CONOUT + 00BC 0141 R C DW READER + 00BE 014A R C DW PUNCH + 00C0 128B R C DW LIST ;5 + 00C2 1262 R C DW RAWIO + 00C4 127F R C DW RAWINP + 00C6 125C R C DW IN + 00C8 1298 R C DW PRTBUF + 00CA 0FBD R C DW BUFIN ;10 + 00CC 1249 R C DW CONSTAT + 00CE 011E R C DW FLUSHKB + 00D0 0F64 R C DW DSKRESET + 00D2 0FAF R C DW SELDSK + 00D4 03CD R C DW OPEN ;15 + 00D6 04BB R C DW CLOSE + 00D8 0E50 R C DW SRCHFRST + 00DA 0EB3 R C DW SRCHNXT + 00DC 029B R C DW DELETE + 00DE 06F6 R C DW SEQRD ;20 + 00E0 06FE R C DW SEQWRT + 00E2 056D R C DW CREATE + 00E4 02F3 R C DW RENAME + 00E6 0114 R C DW INUSE + 00E8 0F97 R C DW GETDRV ;25 + 00EA 0F12 R C DW SETDMA + 00EC 0F20 R C DW GETFATPT + 00EE 0F22 R C DW GETFATPTDL + 00F0 0114 R C DW GETRDONLY + 00F2 0114 R C DW SETATTRIB ;30 + 00F4 0F4E R C DW GETDSKPT + 00F6 0114 R C DW USERCODE + 00F8 070E R C DW RNDRD + 00FA 0716 R C DW RNDWRT + 00FC 0ED2 R C DW FILESIZE ;35 + 00FE 0F9C R C DW SETRNDREC + C ; Extended Functions + 0100 1396 R C DW SETVECT + 0102 13A8 R C DW NEWBASE + 0104 071E R C DW BLKRD + 0106 0726 R C DW BLKWRT ;40 + 0108 12AF R C DW MAKEFCB + 010A 14A6 R C DW GETDATE + 010C 14C4 R C DW SETDATE + 010E 1546 R C DW GETTIME + 0110 1558 R C DW SETTIME ;45 + 0112 0117 R C DW VERIFY + C + 0114 C INUSE: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-9 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0114 C GETIO: + 0114 C SETIO: + 0114 C GETRDONLY: + 0114 C SETATTRIB: + 0114 C USERCODE: + 0114 B0 00 C MOV AL,0 + 0116 C3 C RET + C + 0117 C VERIFY: + 0117 24 01 C AND AL,1 + 0119 2E: A2 002E R C MOV CS:VERFLG,AL + 011D C3 C RET + C + 011E C FLUSHKB: + 011E 50 C PUSH AX + 011F 9A 0027 ---- R C CALL FAR PTR BIOSFLUSH + 0124 58 C POP AX + 0125 8A E0 C MOV AH,AL + 0127 3C 01 C CMP AL,1 + 0129 74 13 C JZ REDISPJ + 012B 3C 06 C CMP AL,6 + 012D 74 0F C JZ REDISPJ + 012F 3C 07 C CMP AL,7 + 0131 74 0B C JZ REDISPJ + 0133 3C 08 C CMP AL,8 + 0135 74 07 C JZ REDISPJ + 0137 3C 0A C CMP AL,10 + 0139 74 03 C JZ REDISPJ + 013B B0 00 C MOV AL,0 + 013D C3 C RET + C + 013E E9 0084 R C REDISPJ:JMP REDISP + C + 0141 C READER: + 0141 C AUXIN: + 0141 E8 11C4 R C CALL STATCHK + 0144 9A 000F ---- R C CALL FAR PTR BIOSAUXIN + 0149 C3 C RET + C + 014A C PUNCH: + 014A 8A C2 C MOV AL,DL + 014C C AUXOUT: + 014C 50 C PUSH AX + 014D E8 11C4 R C CALL STATCHK + 0150 58 C POP AX + 0151 9A 0012 ---- R C CALL FAR PTR BIOSAUXOUT + 0156 C3 C RET + C + C + 0157 C UNPACK: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster number + C ; BP = Base of drive parameters +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-10 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; SI = Pointer to drive FAT + C ; Outputs: + C ; DI = Contents of FAT for given cluster + C ; Zero set means DI=0 (free cluster) + C ; No other registers affected. Fatal error if cluster too big. + C + 0157 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 015A 77 18 C JA HURTFAT + 015C 8D 38 C LEA DI,[SI+BX] + 015E D1 EB C SHR BX,1 + 0160 8B 39 C MOV DI,[DI+BX] + 0162 73 09 C JNC HAVCLUS + 0164 D1 EF C SHR DI,1 + 0166 D1 EF C SHR DI,1 + 0168 D1 EF C SHR DI,1 + 016A D1 EF C SHR DI,1 + 016C F9 C STC + 016D C HAVCLUS: + 016D D1 D3 C RCL BX,1 + 016F 81 E7 0FFF C AND DI,0FFFH + 0173 C3 C RET + 0174 C HURTFAT: + 0174 50 C PUSH AX + 0175 B4 80 C MOV AH,80H ;Signal Bad FAT to INT 24H handler + 0177 BF 0FFF C MOV DI,0FFFH ;In case INT 24H returns (it shouldn't) + 017A E8 0639 R C CALL FATAL + 017D 58 C POP AX ;Try to ignore bad FAT + 017E C3 C RET + C + C + 017F C PACK: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster number + C ; DX = Data + C ; SI = Pointer to drive FAT + C ; Outputs: + C ; The data is stored in the FAT at the given cluster. + C ; BX,DX,DI all destroyed + C ; No other registers affected + C + 017F 8B FB C MOV DI,BX + 0181 D1 EB C SHR BX,1 + 0183 03 DE C ADD BX,SI + 0185 03 DF C ADD BX,DI + 0187 D1 EF C SHR DI,1 + 0189 8B 3F C MOV DI,[BX] + 018B 73 0E C JNC ALIGNED + 018D D1 E2 C SHL DX,1 + 018F D1 E2 C SHL DX,1 + 0191 D1 E2 C SHL DX,1 + 0193 D1 E2 C SHL DX,1 + 0195 81 E7 000F C AND DI,0FH + 0199 EB 04 C JMP SHORT PACKIN +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-11 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 019B C ALIGNED: + 019B 81 E7 F000 C AND DI,0F000H + 019F C PACKIN: + 019F 0B FA C OR DI,DX + 01A1 89 3F C MOV [BX],DI + 01A3 C3 C RET + C + 01A4 C DEVNAME: + 01A4 BE 0000 R C MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names + 01A7 B7 05 C MOV BH,NUMDEV ;BH = number of device names + 01A9 C LOOKIO: + 01A9 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 01AC B9 0004 C MOV CX,4 ;All devices are 4 letters + 01AF F3/ A6 C REPE CMPSB ;Check for name in list + 01B1 74 08 C JZ IOCHK ;If first 3 letters OK, check for the rest + 01B3 03 F1 C ADD SI,CX ;Point to next device name + 01B5 FE CF C DEC BH + 01B7 75 F0 C JNZ LOOKIO + 01B9 C CRET: + 01B9 F9 C STC ;Not found + 01BA C3 C RET + C + 01BB C IOCHK: + C ENDIF + 01BB F6 DF C NEG BH + 01BD B9 0002 C MOV CX,2 ;Check rest of name but not extension + 01C0 B8 2020 C MOV AX,2020H + 01C3 F3/ AF C REPE SCASW ;Make sure rest of name is blanks + 01C5 75 F2 C JNZ CRET + 01C7 C3 C RET1: RET ;Zero set so CREATE works + C + 01C8 C GETFILE: + C ; Same as GETNAME except ES:DI points to FCB on successful return + 01C8 E8 0372 R C CALL MOVNAME + 01CB 72 FA C JC RET1 + 01CD 52 C PUSH DX + 01CE 1E C PUSH DS + 01CF E8 01DA R C CALL FINDNAME + 01D2 07 C POP ES + 01D3 5F C POP DI + 01D4 C3 C RET2: RET + C + C + 01D5 C GETNAME: + C + C ; Inputs: + C ; DS,DX point to FCB + C ; Function: + C ; Find file name in disk directory. First byte is + C ; drive number (0=current disk). "?" matches any + C ; character. + C ; Outputs: + C ; Carry set if file not found + C ; ELSE + C ; Zero set if attributes match (always except when creating) +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-12 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; BP = Base of drive parameters + C ; DS = CS + C ; ES = CS + C ; BX = Pointer into directory buffer + C ; SI = Pointer to First Cluster field in directory entry + C ; [DIRBUF] has directory record with match + C ; [NAME1] has file name + C ; All other registers destroyed. + C + 01D5 E8 0372 R C CALL MOVNAME + 01D8 72 FA C JC RET2 ;Bad file name? + 01DA C FINDNAME: + 01DA 8C C8 C MOV AX,CS + 01DC 8E D8 C MOV DS,AX + 01DE E8 01A4 R C CALL DEVNAME + 01E1 73 F1 C JNC RET2 + 01E3 E8 0423 R C CALL STARTSRCH + 01E6 C CONTSRCH: + 01E6 E8 023E R C CALL GETENTRY + 01E9 72 E9 C JC RET2 + 01EB C SRCH: + 01EB 8A 27 C MOV AH,BYTE PTR [BX] + 01ED 0A E4 C OR AH,AH ;End of directory? + 01EF 74 1E C JZ FREE + 01F1 3A 26 0130 R C CMP AH,[DELALL] ;Free entry? + 01F5 74 18 C JZ FREE + 01F7 8B F3 C MOV SI,BX + 01F9 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 01FC B9 000B C MOV CX,11 + 01FF C WILDCRD: + 01FF F3/ A6 C REPE CMPSB + 0201 74 23 C JZ FOUND + 0203 80 7D FF 3F C CMP BYTE PTR [DI-1],"?" + 0207 74 F6 C JZ WILDCRD + 0209 C NEXTENT: + 0209 E8 0275 R C CALL NEXTENTRY + 020C 73 DD C JNC SRCH + 020E C3 C RET3: RET + C + 020F C FREE: + 020F 83 3E 015C R FF C CMP [ENTFREE],-1 ;Found a free entry before? + 0214 75 08 C JNZ TSTALL ;If so, ignore this one + 0216 8B 0E 0103 R C MOV CX,[LASTENT] + 021A 89 0E 015C R C MOV [ENTFREE],CX + 021E C TSTALL: + 021E 3A 26 0130 R C CMP AH,[DELALL] ;At end of directory? + 0222 74 E5 C JZ NEXTENT ;No - continue search + 0224 F9 C STC ;Report not found + 0225 C3 C RET + C + 0226 C FOUND: + C ;Check if attributes allow finding it + 0226 8A 26 0116 R C MOV AH,[ATTRIB] ;Attributes of search + 022A F6 D4 C NOT AH + 022C 22 24 C AND AH,[SI] ;Compare with attributes of file +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-13 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 022E 83 C6 0F C ADD SI,15 + 0231 80 E4 06 C AND AH,6 ;Only look at bits 1 and 2 + 0234 74 D8 C JZ RET3 + 0236 F6 06 012F R FF C TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating + 023B 74 CC C JZ NEXTENT ;Otherwise continue searching + 023D C3 C RET + C + C + 023E C GETENTRY: + C + C ; Inputs: + C ; [LASTENT] has previously searched directory entry + C ; Function: + C ; Locates next sequential directory entry in preparation for search + C ; Outputs: + C ; Carry set if none + C ; ELSE + C ; AL = Current directory block + C ; BX = Pointer to next directory entry in [DIRBUF] + C ; DX = Pointer to first byte after end of DIRBUF + C ; [LASTENT] = New directory entry number + C + 023E A1 0103 R C MOV AX,[LASTENT] + 0241 40 C INC AX ;Start with next entry + 0242 3B 46 09 C CMP AX,[BP.MAXENT] + 0245 73 4F C JAE NONE + 0247 C GETENT: + 0247 A3 0103 R C MOV [LASTENT],AX + 024A B1 04 C MOV CL,4 + 024C D3 E0 C SHL AX,CL + 024E 33 D2 C XOR DX,DX + 0250 D1 E0 C SHL AX,1 + 0252 D1 D2 C RCL DX,1 ;Account for overflow in last shift + 0254 8B 5E 02 C MOV BX,[BP.SECSIZ] + 0257 80 E3 E0 C AND BL,255-31 ;Must be multiple of 32 + 025A F7 F3 C DIV BX + 025C 8B DA C MOV BX,DX ;Position within sector + 025E 8A 66 00 C MOV AH,[BP.DEVNUM] ;AL=Directory sector no. + 0261 3B 06 0041 R C CMP AX,[DIRBUFID] + 0265 74 05 C JZ HAVDIRBUF + 0267 53 C PUSH BX + 0268 E8 05E8 R C CALL DIRREAD + 026B 5B C POP BX + 026C C HAVDIRBUF: + 026C BA 025E R C MOV DX,OFFSET DOSGROUP:DIRBUF + 026F 03 DA C ADD BX,DX + 0271 03 56 02 C ADD DX,[BP.SECSIZ] + 0274 C3 C RET + C + 0275 C NEXTENTRY: + C + C ; Inputs: + C ; Same as outputs of GETENTRY, above + C ; Function: + C ; Update AL, BX, and [LASTENT] for next directory entry. +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-14 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; Carry set if no more. + C + 0275 8B 3E 0103 R C MOV DI,[LASTENT] + 0279 47 C INC DI + 027A 3B 7E 09 C CMP DI,[BP.MAXENT] + 027D 73 17 C JAE NONE + 027F 89 3E 0103 R C MOV [LASTENT],DI + 0283 83 C3 20 C ADD BX,32 + 0286 3B DA C CMP BX,DX + 0288 72 0A C JB HAVIT + 028A FE C0 C INC AL ;Next directory sector + 028C 52 C PUSH DX ;Save limit + 028D E8 05E8 R C CALL DIRREAD + 0290 5A C POP DX + 0291 BB 025E R C MOV BX,OFFSET DOSGROUP:DIRBUF + 0294 C HAVIT: + 0294 F8 C CLC + 0295 C3 C RET + C + 0296 C NONE: + 0296 E8 067A R C CALL CHKDIRWRITE + 0299 F9 C STC + 029A C3 C RET4: RET + C + C + 029B C DELETE: ; System call 19 + 029B E8 0372 R C CALL MOVNAME + 029E B0 FF C MOV AL,-1 + 02A0 72 F8 C JC RET4 + 02A2 2E: A0 0116 R C MOV AL,CS:[ATTRIB] + 02A6 24 06 C AND AL,6 ;Look only at hidden bits + 02A8 3C 06 C CMP AL,6 ;Both must be set + 02AA 75 12 C JNZ NOTALL + 02AC B9 000B C MOV CX,11 + 02AF B0 3F C MOV AL,"?" + 02B1 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 02B4 F3/ AE C REPE SCASB ;See if name is *.* + 02B6 75 06 C JNZ NOTALL + 02B8 2E: C6 06 0130 R 00 C MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all + 02BE C NOTALL: + 02BE E8 01DA R C CALL FINDNAME + 02C1 B0 FF C MOV AL,-1 + 02C3 72 D5 C JC RET4 + 02C5 0A FF C OR BH,BH ;Check if device name + 02C7 78 D1 C JS RET4 ;Can't delete I/O devices + 02C9 C DELFILE: + 02C9 C6 06 002B R FF C MOV BYTE PTR [DIRTYDIR],-1 + 02CE 8A 26 0130 R C MOV AH,[DELALL] + 02D2 88 27 C MOV BYTE PTR [BX],AH + 02D4 8B 1C C MOV BX,[SI] + 02D6 8B 76 12 C MOV SI,[BP.FAT] + 02D9 0B DB C OR BX,BX + 02DB 74 08 C JZ DELNXT + 02DD 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 02E0 77 03 C JA DELNXT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-15 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 02E2 E8 0E2F R C CALL RELEASE + 02E5 C DELNXT: + 02E5 E8 01E6 R C CALL CONTSRCH + 02E8 73 DF C JNC DELFILE + 02EA E8 052C R C CALL FATWRT + 02ED E8 067A R C CALL CHKDIRWRITE + 02F0 32 C0 C XOR AL,AL + 02F2 C3 C RET + C + C + 02F3 C RENAME: ;System call 23 + 02F3 E8 0372 R C CALL MOVNAME + 02F6 72 77 C JC ERRET + 02F8 83 C6 05 C ADD SI,5 + 02FB BF 0117 R C MOV DI,OFFSET DOSGROUP:NAME2 + 02FE E8 039F R C CALL LODNAME + 0301 72 6C C JC ERRET ;Report error if second name invalid + 0303 E8 01DA R C CALL FINDNAME + 0306 72 67 C JC ERRET + 0308 0A FF C OR BH,BH ;Check if I/O device name + 030A 78 63 C JS ERRET ;If so, can't rename it + 030C BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 030F BF 0122 R C MOV DI,OFFSET DOSGROUP:NAME3 + 0312 B9 0006 C MOV CX,6 ;6 words (12 bytes)--include attribute byte + 0315 F3/ A5 C REP MOVSW ;Copy name to search for + 0317 C RENFIL: + 0317 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 031A BE 0117 R C MOV SI,OFFSET DOSGROUP:NAME2 + 031D B9 000B C MOV CX,11 + 0320 C NEWNAM: + 0320 AC C LODSB + 0321 3C 3F C CMP AL,"?" + 0323 75 02 C JNZ NOCHG + 0325 8A 07 C MOV AL,[BX] + 0327 C NOCHG: + 0327 AA C STOSB + 0328 43 C INC BX + 0329 E2 F5 C LOOP NEWNAM + 032B C6 05 06 C MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes + 032E E8 01A4 R C CALL DEVNAME ;Check if giving it a device name + 0331 73 39 C JNC RENERR + 0333 FF 36 0103 R C PUSH [LASTENT] ;Save position of match + 0337 C7 06 0103 R FFFF C MOV [LASTENT],-1 ;Search entire directory for duplicate + 033D E8 01E6 R C CALL CONTSRCH ;See if new name already exists + 0340 58 C POP AX + 0341 73 29 C JNC RENERR ;Error if found + 0343 E8 0247 R C CALL GETENT ;Re-read matching entry + 0346 8B FB C MOV DI,BX + 0348 BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 034B B9 0005 C MOV CX,5 + 034E A4 C MOVSB + 034F F3/ A5 C REP MOVSW ;Replace old name with new one + 0351 C6 06 002B R FF C MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory + 0356 BE 0122 R C MOV SI,OFFSET DOSGROUP:NAME3 + 0359 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-16 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 035C B9 0006 C MOV CX,6 ;Include attribute byte + 035F F3/ A5 C REP MOVSW ;Copy name back into search buffer + 0361 E8 01E6 R C CALL CONTSRCH + 0364 73 B1 C JNC RENFIL + 0366 E8 067A R C CALL CHKDIRWRITE + 0369 32 C0 C XOR AL,AL + 036B C3 C RET + C + 036C C RENERR: + 036C E8 067A R C CALL CHKDIRWRITE + 036F C ERRET: + 036F B0 FF C MOV AL,-1 + 0371 C3 C RET5: RET + C + C + 0372 C MOVNAME: + C + C ; Inputs: + C ; DS, DX point to FCB or extended FCB + C ; Outputs: + C ; DS:DX point to normal FCB + C ; ES = CS + C ; If file name OK: + C ; BP has base of driver parameters + C ; [NAME1] has name in upper case + C ; All registers except DX destroyed + C ; Carry set if bad file name or drive + C + 0372 2E: C7 06 012F R E500 C MOV CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.* + 0379 8C C8 C MOV AX,CS + 037B 8E C0 C MOV ES,AX + 037D BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 0380 8B F2 C MOV SI,DX + 0382 AC C LODSB + 0383 2E: A2 012E R C MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use + 0387 B4 00 C MOV AH,0 ;Set default attributes + 0389 3C FF C CMP AL,-1 ;Is it an extended FCB? + 038B 75 0A C JNZ HAVATTRB + 038D 83 C2 07 C ADD DX,7 ;Adjust to point to normal FCB + 0390 83 C6 06 C ADD SI,6 ;Point to drive select byte + 0393 8A 64 FF C MOV AH,[SI-1] ;Get attribute byte + 0396 AC C LODSB ;Get drive select byte + 0397 C HAVATTRB: + 0397 2E: 88 26 0116 R C MOV CS:[ATTRIB],AH ;Save attributes + 039C E8 03B9 R C CALL GETTHISDRV + 039F C LODNAME: + C ; This entry point copies a file name from DS,SI + C ; to ES,DI converting to upper case. + 039F 80 3C 20 C CMP BYTE PTR [SI]," " ;Don't allow blank as first letter + 03A2 F9 C STC ;In case of error + 03A3 74 CC C JZ RET5 + 03A5 B9 000B C MOV CX,11 + 03A8 C MOVCHK: + 03A8 E8 135A R C CALL GETLET + 03AB 72 C4 C JB RET5 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-17 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 03AD 75 05 C JNZ STOLET ;Is it a delimiter? + 03AF 3C 20 C CMP AL," " ;This is the only delimiter allowed + 03B1 F9 C STC ;In case of error + 03B2 75 BD C JNZ RET5 + 03B4 C STOLET: + 03B4 AA C STOSB + 03B5 E2 F1 C LOOP MOVCHK + 03B7 F8 C CLC ;Got through whole name - no error + 03B8 C3 C RET6: RET + C + 03B9 C GETTHISDRV: + 03B9 2E: 38 06 002C R C CMP CS:[NUMDRV],AL + 03BE 72 F8 C JC RET6 + 03C0 FE C8 C DEC AL + 03C2 79 04 C JNS PHYDRV + 03C4 2E: A0 004A R C MOV AL,CS:[CURDRV] + 03C8 C PHYDRV: + 03C8 2E: A2 013C R C MOV CS:[THISDRV],AL + 03CC C3 C RET + C + C + 03CD C OPEN: ;System call 15 + 03CD E8 01C8 R C CALL GETFILE + 03D0 C DOOPEN: + C ; Enter here to perform OPEN on file already found + C ; in directory. DS=CS, BX points to directory + C ; entry in DIRBUF, SI points to First Cluster field, and + C ; ES:DI point to the FCB to be opened. This entry point + C ; is used by CREATE. + 03D0 72 9D C JC ERRET + 03D2 0A FF C OR BH,BH ;Check if file is I/O device + 03D4 78 29 C JS OPENDEV ;Special handler if so + 03D6 A0 013C R C MOV AL,[THISDRV] + 03D9 40 C INC AX + 03DA AA C STOSB + 03DB 33 C0 C XOR AX,AX + C ENDIF + C IF NOT ZEROEXT + 03DD 83 C7 0C C ADD DI,12 ;Point to high half of CURRENT BLOCK field + 03E0 AA C STOSB ;Set it to zero (CP/M programs set low byte) + C ENDIF + 03E1 B0 80 C MOV AL,128 ;Default record size + 03E3 AB C STOSW ;Set record size + 03E4 AD C LODSW ;Get starting cluster + 03E5 8B D0 C MOV DX,AX ;Save it for the moment + 03E7 A5 C MOVSW ;Transfer size to FCB + 03E8 A5 C MOVSW + 03E9 8B 44 F8 C MOV AX,[SI-8] ;Get date + 03EC AB C STOSW ;Save date in FCB + 03ED 8B 44 F6 C MOV AX,[SI-10] ;Get time + 03F0 AB C STOSW ;Save it in FCB + 03F1 8A 46 00 C MOV AL,[BP.DEVNUM] + 03F4 0C 40 C OR AL,40H + 03F6 AA C STOSB + 03F7 8B C2 C MOV AX,DX ;Restore starting cluster +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-18 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 03F9 AB C STOSW ; first cluster + 03FA AB C STOSW ; last cluster accessed + 03FB 33 C0 C XOR AX,AX + 03FD AB C STOSW ; position of last cluster + 03FE C3 C RET + C + C + 03FF C OPENDEV: + 03FF 83 C7 0D C ADD DI,13 ;point to 2nd half of extent field + 0402 33 C0 C XOR AX,AX + 0404 AA C STOSB ;Set it to zero + 0405 B0 80 C MOV AL,128 + 0407 AB C STOSW ;Set record size to 128 + 0408 33 C0 C XOR AX,AX + 040A AB C STOSW + 040B AB C STOSW ;Set current size to zero + 040C E8 1400 R C CALL DATE16 + 040F AB C STOSW ;Date is todays + 0410 92 C XCHG AX,DX + 0411 AB C STOSW ;Use current time + 0412 8A C7 C MOV AL,BH ;Get device number + 0414 AA C STOSB + 0415 32 C0 C XOR AL,AL ;No error + 0417 C3 C RET + 0418 C FATERR: + 0418 97 C XCHG AX,DI ;Put error code in DI + 0419 B4 02 C MOV AH,2 ;While trying to read FAT + 041B A0 013C R C MOV AL,[THISDRV] ;Tell which drive + 041E E8 063C R C CALL FATAL1 + 0421 EB 09 C JMP SHORT FATREAD + 0423 C STARTSRCH: + 0423 B8 FFFF C MOV AX,-1 + 0426 A3 0103 R C MOV [LASTENT],AX + 0429 A3 015C R C MOV [ENTFREE],AX + 042C C FATREAD: + C + C ; Inputs: + C ; DS = CS + C ; Function: + C ; If disk may have been changed, FAT is read in and buffers are + C ; flagged invalid. If not, no action is taken. + C ; Outputs: + C ; BP = Base of drive parameters + C ; Carry set if invalid drive returned by MAPDEV + C ; All other registers destroyed + C + 042C A0 013C R C MOV AL,[THISDRV] + 042F 32 E4 C XOR AH,AH ;Set default response to zero & clear carry + 0431 9A 001B ---- R C CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say + 0436 72 E0 C JC FATERR + 0438 E8 0492 R C CALL GETBP + 043B A0 013C R C MOV AL,[THISDRV] ;Use physical unit number + 043E 8B 76 12 C MOV SI,[BP.FAT] + 0441 0A 64 FF C OR AH,[SI-1] ;Dirty byte for FAT + 0444 78 0A C JS NEWDSK ;If either say new disk, then it's so +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-19 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0446 75 47 C JNZ MAPDRV + 0448 B4 01 C MOV AH,1 + 044A 3B 06 003D R C CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive? + 044E 74 3F C JZ MAPDRV + 0450 C NEWDSK: + 0450 3A 06 003D R C CMP AL,[BUFDRVNO] ;See if buffer is for this drive + 0454 75 0C C JNZ BUFOK ;If not, don't touch it + 0456 C7 06 003B R 0000 C MOV [BUFSECNO],0 ;Flag buffers invalid + 045C C7 06 003D R 00FF C MOV WORD PTR [BUFDRVNO],00FFH + 0462 C BUFOK: + 0462 C7 06 0041 R FFFF C MOV [DIRBUFID],-1 + 0468 E8 0551 R C CALL FIGFAT + 046B C NEXTFAT: + 046B 50 C PUSH AX + 046C E8 0669 R C CALL DSKREAD + 046F 58 C POP AX + 0470 72 36 C JC BADFAT + 0472 2A 46 08 C SUB AL,[BP.FATCNT] + 0475 74 03 C JZ NEWFAT + 0477 E8 052C R C CALL FATWRT + 047A C NEWFAT: + 047A 8B 76 12 C MOV SI,[BP.FAT] + 047D 8A 46 00 C MOV AL,[BP.DEVNUM] + 0480 8A 24 C MOV AH,[SI] ;Get first byte of FAT + 0482 80 CC F8 C OR AH,0F8H ;Put in range + 0485 9A 002A ---- R C CALL FAR PTR BIOSMAPDEV + 048A B4 00 C MOV AH,0 + 048C 89 44 FE C MOV [SI-2],AX ;Set device no. and reset dirty bit + 048F C MAPDRV: + 048F 8A 44 FE C MOV AL,[SI-2] ;Get device number + 0492 C GETBP: + 0492 8B 2E 004B R C MOV BP,[DRVTAB] ;Just in case drive isn't valid + 0496 24 3F C AND AL,3FH ;Mask out dirty bit + 0498 3A 06 002D R C CMP AL,[NUMIO] + 049C F5 C CMC + 049D 72 08 C JC RET7 + 049F 50 C PUSH AX + 04A0 B4 14 C MOV AH,DPBSIZ + 04A2 F6 E4 C MUL AH + 04A4 03 E8 C ADD BP,AX + 04A6 58 C POP AX + 04A7 C3 C RET7: RET + C + 04A8 C BADFAT: + 04A8 8B CF C MOV CX,DI + 04AA 03 D1 C ADD DX,CX + 04AC FE C8 C DEC AL + 04AE 75 BB C JNZ NEXTFAT + 04B0 E8 0551 R C CALL FIGFAT ;Reset registers + 04B3 E8 05FC R C CALL DREAD ;Try first FAT once more + 04B6 EB C2 C JMP SHORT NEWFAT + C + 04B8 C OKRET1: + 04B8 B0 00 C MOV AL,0 + 04BA C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-20 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 04BB C CLOSE: ;System call 16 + 04BB 8B FA C MOV DI,DX + 04BD 80 3D FF C CMP BYTE PTR [DI],-1 ;Check for extended FCB + 04C0 75 03 C JNZ NORMFCB3 + 04C2 83 C7 07 C ADD DI,7 + 04C5 C NORMFCB3: + 04C5 F6 45 18 C0 C TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files + 04C9 75 ED C JNZ OKRET1 ;can't close if I/O device, or not writen + 04CB 8A 05 C MOV AL,[DI] ;Get physical unit number + 04CD FE C8 C DEC AL ;Make zero = drive A + 04CF B4 01 C MOV AH,1 ;Look for dirty buffer + 04D1 2E: 3B 06 003D R C CMP AX,CS:WORD PTR [BUFDRVNO] + 04D6 75 1D C JNZ FNDDIR + C ;Write back dirty buffer if on same drive + 04D8 52 C PUSH DX + 04D9 1E C PUSH DS + 04DA 0E C PUSH CS + 04DB 1F C POP DS + 04DC C6 06 003E R 00 C MOV BYTE PTR [DIRTYBUF],0 + 04E1 8B 1E 0039 R C MOV BX,[BUFFER] + 04E5 B9 0001 C MOV CX,1 + 04E8 8B 16 003B R C MOV DX,[BUFSECNO] + 04EC 8B 2E 003F R C MOV BP,[BUFDRVBP] + 04F0 E8 068C R C CALL DWRITE + 04F3 1F C POP DS + 04F4 5A C POP DX + 04F5 C FNDDIR: + 04F5 E8 01C8 R C CALL GETFILE + 04F8 C BADCLOSEJ: + 04F8 72 4D C JC BADCLOSE + 04FA 26: 8B 4D 19 C MOV CX,ES:[DI.FIRCLUS] + 04FE 89 0C C MOV [SI],CX + 0500 26: 8B 55 10 C MOV DX,ES:WORD PTR [DI.FILSIZ] + 0504 89 54 02 C MOV [SI+2],DX + 0507 26: 8B 55 12 C MOV DX,ES:WORD PTR [DI.FILSIZ+2] + 050B 89 54 04 C MOV [SI+4],DX + 050E 26: 8B 55 14 C MOV DX,ES:[DI.FDATE] + 0512 89 54 FE C MOV [SI-2],DX + 0515 26: 8B 55 16 C MOV DX,ES:[DI.FTIME] + 0519 89 54 FC C MOV [SI-4],DX + 051C E8 0681 R C CALL DIRWRITE + C + 051F C CHKFATWRT: + C ; Do FATWRT only if FAT is dirty and uses same I/O driver + 051F 8B 76 12 C MOV SI,[BP.FAT] + 0522 8A 46 00 C MOV AL,[BP.DEVNUM] + 0525 B4 01 C MOV AH,1 + 0527 39 44 FE C CMP [SI-2],AX ;See if FAT dirty and uses same driver + 052A 75 18 C JNZ OKRET + C + 052C C FATWRT: + C + C ; Inputs: + C ; DS = CS +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-21 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; BP = Base of drive parameter table + C ; Function: + C ; Write the FAT back to disk and reset FAT + C ; dirty bit. + C ; Outputs: + C ; AL = 0 + C ; BP unchanged + C ; All other registers destroyed + C + 052C E8 0551 R C CALL FIGFAT + 052F C6 47 FF 00 C MOV BYTE PTR [BX-1],0 + 0533 C EACHFAT: + 0533 52 C PUSH DX + 0534 51 C PUSH CX + 0535 53 C PUSH BX + 0536 50 C PUSH AX + 0537 E8 068C R C CALL DWRITE + 053A 58 C POP AX + 053B 5B C POP BX + 053C 59 C POP CX + 053D 5A C POP DX + 053E 03 D1 C ADD DX,CX + 0540 FE C8 C DEC AL + 0542 75 EF C JNZ EACHFAT + 0544 C OKRET: + 0544 B0 00 C MOV AL,0 + 0546 C3 C RET + C + 0547 C BADCLOSE: + 0547 8B 76 12 C MOV SI,[BP.FAT] + 054A C6 44 FF 00 C MOV BYTE PTR [SI-1],0 + 054E B0 FF C MOV AL,-1 + 0550 C3 C RET + C + C + 0551 C FIGFAT: + C ; Loads registers with values needed to read or + C ; write a FAT. + 0551 8A 46 08 C MOV AL,[BP.FATCNT] + 0554 8B 5E 12 C MOV BX,[BP.FAT] + 0557 8A 4E 0F C MOV CL,[BP.FATSIZ] ;No. of records occupied by FAT + 055A B5 00 C MOV CH,0 + 055C 8B 56 06 C MOV DX,[BP.FIRFAT] ;Record number of start of FATs + 055F C3 C RET + C + C + 0560 C DIRCOMP: + C ; Prepare registers for directory read or write + 0560 98 C CBW + 0561 03 46 10 C ADD AX,[BP.FIRDIR] + 0564 8B D0 C MOV DX,AX + 0566 BB 025E R C MOV BX,OFFSET DOSGROUP:DIRBUF + 0569 B9 0001 C MOV CX,1 + 056C C3 C RET + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-22 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 056D C CREATE: ;System call 22 + 056D E8 0372 R C CALL MOVNAME + 0570 72 28 C JC ERRET3 + 0572 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 0575 B9 000B C MOV CX,11 + 0578 B0 3F C MOV AL,"?" + 057A F2/ AE C REPNE SCASB + 057C 74 1C C JZ ERRET3 + 057E 2E: C6 06 012F R FF C MOV CS:BYTE PTR [CREATING],-1 + 0584 52 C PUSH DX + 0585 1E C PUSH DS + 0586 E8 01DA R C CALL FINDNAME + 0589 73 12 C JNC EXISTENT + 058B A1 015C R C MOV AX,[ENTFREE] ;First free entry found in FINDNAME + 058E 3D FFFF C CMP AX,-1 + 0591 74 05 C JZ ERRPOP + 0593 E8 0247 R C CALL GETENT ;Point at that free entry + 0596 EB 21 C JMP SHORT FREESPOT + 0598 C ERRPOP: + 0598 1F C POP DS + 0599 5A C POP DX + 059A C ERRET3: + 059A B0 FF C MOV AL,-1 + 059C C3 C RET + C + 059D C EXISTENT: + 059D 75 F9 C JNZ ERRPOP ;Error if attributes don't match + 059F 0A FF C OR BH,BH ;Check if file is I/O device + 05A1 78 3F C JS OPENJMP ;If so, no action + 05A3 8B 0C C MOV CX,[SI] ;Get pointer to clusters + 05A5 E3 12 C JCXZ FREESPOT + 05A7 3B 4E 0D C CMP CX,[BP.MAXCLUS] + 05AA 77 0D C JA FREESPOT + 05AC 53 C PUSH BX + 05AD 8B D9 C MOV BX,CX + 05AF 8B 76 12 C MOV SI,[BP.FAT] + 05B2 E8 0E2F R C CALL RELEASE ;Free any data already allocated + 05B5 E8 052C R C CALL FATWRT + 05B8 5B C POP BX + 05B9 C FREESPOT: + 05B9 8B FB C MOV DI,BX + 05BB BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 05BE B9 0005 C MOV CX,5 + 05C1 A4 C MOVSB + 05C2 F3/ A5 C REP MOVSW + 05C4 A0 0116 R C MOV AL,[ATTRIB] + 05C7 AA C STOSB + 05C8 33 C0 C XOR AX,AX + 05CA B1 05 C MOV CL,5 + 05CC F3/ AB C REP STOSW + 05CE E8 1400 R C CALL DATE16 + 05D1 92 C XCHG AX,DX + 05D2 AB C STOSW + 05D3 92 C XCHG AX,DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-23 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 05D4 AB C STOSW + 05D5 33 C0 C XOR AX,AX + 05D7 57 C PUSH DI + 05D8 B1 06 C MOV CL,6 + 05DA C SMALLENT: + 05DA F3/ AA C REP STOSB + 05DC 53 C PUSH BX + 05DD E8 0681 R C CALL DIRWRITE + 05E0 5B C POP BX + 05E1 5E C POP SI + 05E2 C OPENJMP: + 05E2 F8 C CLC ;Clear carry so OPEN won't fail + 05E3 07 C POP ES + 05E4 5F C POP DI + 05E5 E9 03D0 R C JMP DOOPEN + C + C + 05E8 C DIRREAD: + C + C ; Inputs: + C ; DS = CS + C ; AL = Directory block number + C ; BP = Base of drive parameters + C ; Function: + C ; Read the directory block into DIRBUF. + C ; Outputs: + C ; AX,BP unchanged + C ; All other registers destroyed. + C + 05E8 50 C PUSH AX + 05E9 E8 067A R C CALL CHKDIRWRITE + 05EC 58 C POP AX + 05ED 50 C PUSH AX + 05EE 8A 66 00 C MOV AH,[BP.DEVNUM] + 05F1 A3 0041 R C MOV [DIRBUFID],AX + 05F4 E8 0560 R C CALL DIRCOMP + 05F7 E8 05FC R C CALL DREAD + 05FA 58 C POP AX + 05FB C3 C RET8: RET + C + C + 05FC C DREAD: + C + C ; Inputs: + C ; BX,DS = Transfer address + C ; CX = Number of sectors + C ; DX = Absolute record number + C ; BP = Base of drive parameters + C ; Function: + C ; Calls BIOS to perform disk read. If BIOS reports + C ; errors, will call HARDERR for further action. + C ; BP preserved. All other registers destroyed. + C + 05FC E8 0669 R C CALL DSKREAD + 05FF 73 FA C JNC RET8 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-24 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0601 2E: C6 06 013B R 00 C MOV CS:BYTE PTR [READOP],0 + 0607 E8 060F R C CALL HARDERR + 060A 3C 01 C CMP AL,1 ;Check for retry + 060C 74 EE C JZ DREAD + 060E C3 C RET ;Ignore otherwise + C + C + 060F C HARDERR: + C + C ;Hard disk error handler. Entry conditions: + C ; DS:BX = Original disk transfer address + C ; DX = Original logical sector number + C ; CX = Number of sectors to go (first one gave the error) + C ; AX = Hardware error code + C ; DI = Original sector transfer count + C ; BP = Base of drive parameters + C ; [READOP] = 0 for read, 1 for write + C + 060F 97 C XCHG AX,DI ;Error code in DI, count in AX + 0610 2B C1 C SUB AX,CX ;Number of sectors successfully transferred + 0612 03 D0 C ADD DX,AX ;First sector number to retry + 0614 52 C PUSH DX + 0615 F7 66 02 C MUL [BP.SECSIZ] ;Number of bytes transferred + 0618 5A C POP DX + 0619 03 D8 C ADD BX,AX ;First address for retry + 061B B4 00 C MOV AH,0 ;Flag disk section in error + 061D 3B 56 06 C CMP DX,[BP.FIRFAT] ;In reserved area? + 0620 72 10 C JB ERRINT + 0622 FE C4 C INC AH ;Flag for FAT + 0624 3B 56 10 C CMP DX,[BP.FIRDIR] ;In FAT? + 0627 72 09 C JB ERRINT + 0629 FE C4 C INC AH + 062B 3B 56 0B C CMP DX,[BP.FIRREC] ;In directory? + 062E 72 02 C JB ERRINT + 0630 FE C4 C INC AH ;Must be in data area + 0632 C ERRINT: + 0632 D0 E4 C SHL AH,1 ;Make room for read/write bit + 0634 2E: 0A 26 013B R C OR AH,CS:[READOP] + 0639 C FATAL: + 0639 8A 46 01 C MOV AL,[BP.DRVNUM] ;Get drive number + 063C C FATAL1: + 063C 55 C PUSH BP ;The only thing we preserve + 063D 2E: 89 26 0135 R C MOV CS:[CONTSTK],SP + 0642 FA C CLI ;Prepare to play with stack + 0643 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 0648 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] ;User stack pointer restored + 064D CD 24 C INT 24H ;Fatal error interrupt vector + 064F 2E: 89 26 0131 R C MOV CS:[SPSAVE],SP + 0654 2E: 8C 16 0133 R C MOV CS:[SSSAVE],SS + 0659 8C CC C MOV SP,CS + 065B 8E D4 C MOV SS,SP + 065D 2E: 8B 26 0135 R C MOV SP,CS:[CONTSTK] + 0662 FB C STI + 0663 5D C POP BP + 0664 3C 02 C CMP AL,2 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-25 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0666 74 61 C JZ ERROR + 0668 C3 C RET + C + 0669 C DSKREAD: + 0669 8A 46 00 C MOV AL,[BP.DEVNUM] + 066C 55 C PUSH BP + 066D 53 C PUSH BX + 066E 51 C PUSH CX + 066F 52 C PUSH DX + 0670 9A 0015 ---- R C CALL FAR PTR BIOSREAD + 0675 5A C POP DX + 0676 5F C POP DI + 0677 5B C POP BX + 0678 5D C POP BP + 0679 C3 C RET9: RET + C + C + 067A C CHKDIRWRITE: + 067A F6 06 002B R FF C TEST BYTE PTR [DIRTYDIR],-1 + 067F 74 F8 C JZ RET9 + C + 0681 C DIRWRITE: + C + C ; Inputs: + C ; DS = CS + C ; AL = Directory block number + C ; BP = Base of drive parameters + C ; Function: + C ; Write the directory block into DIRBUF. + C ; Outputs: + C ; BP unchanged + C ; All other registers destroyed. + C + 0681 C6 06 002B R 00 C MOV BYTE PTR [DIRTYDIR],0 + 0686 A0 0041 R C MOV AL,BYTE PTR [DIRBUFID] + 0689 E8 0560 R C CALL DIRCOMP + C + C + 068C C DWRITE: + C + C ; Inputs: + C ; BX,DS = Transfer address + C ; CX = Number of sectors + C ; DX = Absolute record number + C ; BP = Base of drive parameters + C ; Function: + C ; Calls BIOS to perform disk write. If BIOS reports + C ; errors, will call HARDERR for further action. + C ; BP preserved. All other registers destroyed. + C + 068C 8A 46 00 C MOV AL,[BP.DEVNUM] + 068F 2E: 8A 26 002E R C MOV AH,CS:VERFLG + 0694 55 C PUSH BP + 0695 53 C PUSH BX + 0696 51 C PUSH CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-26 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0697 52 C PUSH DX + 0698 9A 0018 ---- R C CALL FAR PTR BIOSWRITE + 069D 5A C POP DX + 069E 5F C POP DI + 069F 5B C POP BX + 06A0 5D C POP BP + 06A1 73 D6 C JNC RET9 + 06A3 2E: C6 06 013B R 01 C MOV CS:BYTE PTR [READOP],1 + 06A9 E8 060F R C CALL HARDERR + 06AC 3C 01 C CMP AL,1 ;Check for retry + 06AE 74 DC C JZ DWRITE + 06B0 C3 C RET + C + C + 06B1 C ABORT: + 06B1 2E: C5 36 0131 R C LDS SI,CS:DWORD PTR [SPSAVE] + 06B6 8E 5C 14 C MOV DS,[SI.CSSAVE] + 06B9 33 C0 C XOR AX,AX + 06BB 8E C0 C MOV ES,AX + 06BD BE 000A C MOV SI,SAVEXIT + 06C0 BF 0088 C MOV DI,EXIT + 06C3 A5 C MOVSW + 06C4 A5 C MOVSW + 06C5 A5 C MOVSW + 06C6 A5 C MOVSW + 06C7 A5 C MOVSW + 06C8 A5 C MOVSW + 06C9 C ERROR: + 06C9 8C C8 C MOV AX,CS + 06CB 8E D8 C MOV DS,AX + 06CD 8E C0 C MOV ES,AX + 06CF E8 0F66 R C CALL WRTFATS + 06D2 33 C0 C XOR AX,AX + 06D4 FA C CLI + 06D5 8E 16 0133 R C MOV SS,[SSSAVE] + 06D9 8B 26 0131 R C MOV SP,[SPSAVE] + 06DD 8E D8 C MOV DS,AX + 06DF BE 0088 C MOV SI,EXIT + 06E2 BF 0105 R C MOV DI,OFFSET DOSGROUP:EXITHOLD + 06E5 A5 C MOVSW + 06E6 A5 C MOVSW + 06E7 58 C POP AX + 06E8 5B C POP BX + 06E9 59 C POP CX + 06EA 5A C POP DX + 06EB 5E C POP SI + 06EC 5F C POP DI + 06ED 5D C POP BP + 06EE 1F C POP DS + 06EF 07 C POP ES + 06F0 FB C STI ;Stack OK now + 06F1 2E: FF 2E 0105 R C JMP CS:DWORD PTR [EXITHOLD] + C + C + 06F6 C SEQRD: ;System call 20 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-27 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 06F6 E8 0D9A R C CALL GETREC + 06F9 E8 0A1E R C CALL LOAD + 06FC EB 06 C JMP SHORT FINSEQ + C + 06FE C SEQWRT: ;System call 21 + 06FE E8 0D9A R C CALL GETREC + 0701 E8 0BA9 R C CALL STORE + 0704 C FINSEQ: + 0704 E3 45 C JCXZ SETNREX + 0706 05 0001 C ADD AX,1 + 0709 83 D2 00 C ADC DX,0 + 070C EB 3D C JMP SHORT SETNREX + C + 070E C RNDRD: ;System call 33 + 070E E8 0767 R C CALL GETRRPOS1 + 0711 E8 0A1E R C CALL LOAD + 0714 EB 25 C JMP SHORT FINRND + C + 0716 C RNDWRT: ;System call 34 + 0716 E8 0767 R C CALL GETRRPOS1 + 0719 E8 0BA9 R C CALL STORE + 071C EB 1D C JMP SHORT FINRND + C + 071E C BLKRD: ;System call 39 + 071E E8 076A R C CALL GETRRPOS + 0721 E8 0A1E R C CALL LOAD + 0724 EB 06 C JMP SHORT FINBLK + C + 0726 C BLKWRT: ;System call 40 + 0726 E8 076A R C CALL GETRRPOS + 0729 E8 0BA9 R C CALL STORE + 072C C FINBLK: + 072C C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0730 89 4C 04 C MOV [SI.CXSAVE],CX + 0733 E3 06 C JCXZ FINRND + 0735 05 0001 C ADD AX,1 + 0738 83 D2 00 C ADC DX,0 + 073B C FINRND: + 073B 26: 89 45 21 C MOV ES:WORD PTR [DI.RR],AX + 073F 26: 88 55 23 C MOV ES:[DI.RR+2],DL + 0743 0A F6 C OR DH,DH + 0745 74 04 C JZ SETNREX + 0747 26: 88 75 24 C MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant + 074B C SETNREX: + 074B 8B C8 C MOV CX,AX + 074D 24 7F C AND AL,7FH + 074F 26: 88 45 20 C MOV ES:[DI.NR],AL + 0753 80 E1 80 C AND CL,80H + 0756 D1 E1 C SHL CX,1 + 0758 D1 D2 C RCL DX,1 + 075A 8A C5 C MOV AL,CH + 075C 8A E2 C MOV AH,DL + 075E 26: 89 45 0C C MOV ES:[DI.EXTENT],AX + 0762 2E: A0 0138 R C MOV AL,CS:[DSKERR] + 0766 C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-28 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0767 C GETRRPOS1: + 0767 B9 0001 C MOV CX,1 + 076A C GETRRPOS: + 076A 8B FA C MOV DI,DX + 076C 80 3D FF C CMP BYTE PTR [DI],-1 + 076F 75 03 C JNZ NORMFCB1 + 0771 83 C7 07 C ADD DI,7 + 0774 C NORMFCB1: + 0774 8B 45 21 C MOV AX,WORD PTR [DI.RR] + 0777 8B 55 23 C MOV DX,WORD PTR [DI.RR+2] + 077A C3 C RET + C + 077B C NOFILERR: + 077B 33 C9 C XOR CX,CX + 077D C6 06 0138 R 04 C MOV BYTE PTR [DSKERR],4 + 0782 5B C POP BX + 0783 C3 C RET + C + 0784 C SETUP: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Record position in file of disk transfer + C ; CX = Record count + C ; Outputs: + C ; DS = CS + C ; ES:DI point to FCB + C ; BL = DEVID from FCB + C ; CX = No. of bytes to transfer + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; [RECCNT] = Record count + C ; [RECPOS] = Record position in file + C ; [FCB] = DI + C ; [NEXTADD] = Displacement of disk transfer within segment + C ; [SECPOS] = Position of first sector + C ; [BYTPOS] = Byte position in file + C ; [BYTSECPOS] = Byte position in first sector + C ; [CLUSNUM] = First cluster + C ; [SECCLUSPOS] = Sector within first cluster + C ; [DSKERR] = 0 (no errors yet) + C ; [TRANS] = 0 (No transfers yet) + C ; [THISDRV] = Physical drive unit number + C ; If SETUP detects no records will be transfered, it returns 1 level up + C ; with CX = 0. + C + 0784 50 C PUSH AX + 0785 8A 05 C MOV AL,[DI] + 0787 FE C8 C DEC AL + 0789 2E: A2 013C R C MOV CS:[THISDRV],AL + 078D 8A 45 18 C MOV AL,[DI.DEVID] + 0790 8B 75 0E C MOV SI,[DI.RECSIZ] + 0793 0B F6 C OR SI,SI + 0795 75 06 C JNZ HAVRECSIZ +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-29 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0797 BE 0080 C MOV SI,128 + 079A 89 75 0E C MOV [DI.RECSIZ],SI + 079D C HAVRECSIZ: + 079D 1E C PUSH DS + 079E 07 C POP ES ;Set ES to DS + 079F 0E C PUSH CS + 07A0 1F C POP DS ;Set DS to CS + 07A1 0A C0 C OR AL,AL ;Is it a device? + 07A3 79 02 C JNS NOTDEVICE + 07A5 B0 00 C MOV AL,0 ;Fake in drive 0 so we can get SP + 07A7 C NOTDEVICE: + 07A7 E8 0492 R C CALL GETBP + 07AA 58 C POP AX + 07AB 72 CE C JC NOFILERR + 07AD 83 FE 40 C CMP SI,64 ;Check if highest byte of RECPOS is significant + 07B0 72 02 C JB SMALREC + 07B2 B6 00 C MOV DH,0 ;Ignore MSB if record >= 64 bytes + 07B4 C SMALREC: + 07B4 89 0E 0146 R C MOV [RECCNT],CX + 07B8 A3 0142 R C MOV WORD PTR [RECPOS],AX + 07BB 89 16 0144 R C MOV WORD PTR [RECPOS+2],DX + 07BF 89 3E 013E R C MOV [FCB],DI + 07C3 8B 1E 0031 R C MOV BX,[DMAADD] + 07C7 89 1E 0140 R C MOV [NEXTADD],BX + 07CB C6 06 0138 R 00 C MOV BYTE PTR [DSKERR],0 + 07D0 C6 06 0139 R 00 C MOV BYTE PTR [TRANS],0 + 07D5 8B DA C MOV BX,DX + 07D7 F7 E6 C MUL SI + 07D9 A3 0152 R C MOV WORD PTR [BYTPOS],AX + 07DC 52 C PUSH DX + 07DD 8B C3 C MOV AX,BX + 07DF F7 E6 C MUL SI + 07E1 5B C POP BX + 07E2 03 C3 C ADD AX,BX + 07E4 83 D2 00 C ADC DX,0 ;Ripple carry + 07E7 75 5A C JNZ EOFERR + 07E9 A3 0154 R C MOV WORD PTR [BYTPOS+2],AX + 07EC 8B D0 C MOV DX,AX + 07EE A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 07F1 8B 5E 02 C MOV BX,[BP.SECSIZ] + 07F4 3B D3 C CMP DX,BX ;See if divide will overflow + 07F6 73 4B C JNC EOFERR + 07F8 F7 F3 C DIV BX + 07FA A3 014C R C MOV [SECPOS],AX + 07FD 89 16 0150 R C MOV [BYTSECPOS],DX + 0801 8B D0 C MOV DX,AX + 0803 22 46 04 C AND AL,[BP.CLUSMSK] + 0806 A2 0137 R C MOV [SECCLUSPOS],AL + 0809 8B C1 C MOV AX,CX ;Record count + 080B 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 080E D3 EA C SHR DX,CL + 0810 89 16 014A R C MOV [CLUSNUM],DX + 0814 F7 E6 C MUL SI ;Multiply by bytes per record + 0816 8B C8 C MOV CX,AX + 0818 03 06 0031 R C ADD AX,[DMAADD] ;See if it will fit in one segment +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-30 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 081C 83 D2 00 C ADC DX,0 + 081F 74 1A C JZ OK ;Must be less than 64K + 0821 A1 0031 R C MOV AX,[DMAADD] + 0824 F7 D8 C NEG AX ;Amount of room left in segment + 0826 75 01 C JNZ PARTSEG ;All 64K available? + 0828 48 C DEC AX ;If so, reduce by one + 0829 C PARTSEG: + 0829 33 D2 C XOR DX,DX + 082B F7 F6 C DIV SI ;How many records will fit? + 082D A3 0146 R C MOV [RECCNT],AX + 0830 F7 E6 C MUL SI ;Translate that back into bytes + 0832 C6 06 0138 R 02 C MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place + 0837 8B C8 C MOV CX,AX + 0839 E3 0F C JCXZ NOROOM + 083B C OK: + 083B 26: 8A 5D 18 C MOV BL,ES:[DI.DEVID] + 083F 8B 76 12 C MOV SI,[BP.FAT] + 0842 C3 C RET + C + 0843 C EOFERR: + 0843 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0848 33 C9 C XOR CX,CX + 084A C NOROOM: + 084A 5B C POP BX ;Kill return address + 084B C3 C RET + C + 084C C BREAKDOWN: + C + C ;Inputs: + C ; DS = CS + C ; CX = Length of disk transfer in bytes + C ; BP = Base of drive parameters + C ; [BYTSECPOS] = Byte position witin first sector + C ;Outputs: + C ; [BYTCNT1] = Bytes to transfer in first sector + C ; [SECCNT] = No. of whole sectors to transfer + C ; [BYTCNT2] = Bytes to transfer in last sector + C ;AX, BX, DX destroyed. No other registers affected. + C + 084C A1 0150 R C MOV AX,[BYTSECPOS] + 084F 8B D9 C MOV BX,CX + 0851 0B C0 C OR AX,AX + 0853 74 0D C JZ SAVFIR ;Partial first sector? + 0855 2B 46 02 C SUB AX,[BP.SECSIZ] + 0858 F7 D8 C NEG AX ;Max number of bytes left in first sector + 085A 2B D8 C SUB BX,AX ;Subtract from total length + 085C 73 04 C JAE SAVFIR + 085E 03 C3 C ADD AX,BX ;Don't use all of the rest of the sector + 0860 33 DB C XOR BX,BX ;And no bytes are left + 0862 C SAVFIR: + 0862 A3 0156 R C MOV [BYTCNT1],AX + 0865 8B C3 C MOV AX,BX + 0867 33 D2 C XOR DX,DX + 0869 F7 76 02 C DIV [BP.SECSIZ] ;How many whole sectors? + 086C A3 015A R C MOV [SECCNT],AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-31 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 086F 89 16 0158 R C MOV [BYTCNT2],DX ;Bytes remaining for last sector + 0873 C3 C RET10: RET + C + C + 0874 C FNDCLUS: + C + C ; Inputs: + C ; DS = CS + C ; CX = No. of clusters to skip + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; ES:DI point to FCB + C ; Outputs: + C ; BX = Last cluster skipped to + C ; CX = No. of clusters remaining (0 unless EOF) + C ; DX = Position of last cluster + C ; DI destroyed. No other registers affected. + C + 0874 26: 8B 5D 1B C MOV BX,ES:[DI.LSTCLUS] + 0878 26: 8B 55 1D C MOV DX,ES:[DI.CLUSPOS] + 087C 0B DB C OR BX,BX + 087E 74 1D C JZ NOCLUS + 0880 2B CA C SUB CX,DX + 0882 73 08 C JNB FINDIT + 0884 03 CA C ADD CX,DX + 0886 33 D2 C XOR DX,DX + 0888 26: 8B 5D 19 C MOV BX,ES:[DI.FIRCLUS] + 088C C FINDIT: + 088C E3 E5 C JCXZ RET10 + 088E C SKPCLP: + 088E E8 0157 R C CALL UNPACK + 0891 81 FF 0FF8 C CMP DI,0FF8H + 0895 73 DC C JAE RET10 + 0897 87 DF C XCHG BX,DI + 0899 42 C INC DX + 089A E2 F2 C LOOP SKPCLP + 089C C3 C RET + 089D C NOCLUS: + 089D 41 C INC CX + 089E 4A C DEC DX + 089F C3 C RET + C + C + 08A0 C BUFSEC: + C ; Inputs: + C ; AL = 0 if buffer must be read, 1 if no pre-read needed + C ; BP = Base of drive parameters + C ; [CLUSNUM] = Physical cluster number + C ; [SECCLUSPOS] = Sector position of transfer within cluster + C ; [BYTCNT1] = Size of transfer + C ; Function: + C ; Insure specified sector is in buffer, flushing buffer before + C ; read if necessary. + C ; Outputs: + C ; SI = Pointer to buffer +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-32 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; DI = Pointer to transfer address + C ; CX = Number of bytes + C ; [NEXTADD] updated + C ; [TRANS] set to indicate a transfer will occur + C + 08A0 8B 16 014A R C MOV DX,[CLUSNUM] + 08A4 8A 1E 0137 R C MOV BL,[SECCLUSPOS] + 08A8 E8 0D8B R C CALL FIGREC + 08AB A2 013A R C MOV [PREREAD],AL + 08AE 3B 16 003B R C CMP DX,[BUFSECNO] + 08B2 75 09 C JNZ GETSEC + 08B4 A0 003D R C MOV AL,[BUFDRVNO] + 08B7 3A 06 013C R C CMP AL,[THISDRV] + 08BB 74 4A C JZ FINBUF ;Already have it? + 08BD C GETSEC: + 08BD 32 C0 C XOR AL,AL + 08BF 86 06 003E R C XCHG [DIRTYBUF],AL ;Read dirty flag and reset it + 08C3 0A C0 C OR AL,AL + 08C5 74 16 C JZ RDSEC + 08C7 52 C PUSH DX + 08C8 55 C PUSH BP + 08C9 8B 2E 003F R C MOV BP,[BUFDRVBP] + 08CD 8B 1E 0039 R C MOV BX,[BUFFER] + 08D1 B9 0001 C MOV CX,1 + 08D4 8B 16 003B R C MOV DX,[BUFSECNO] + 08D8 E8 068C R C CALL DWRITE + 08DB 5D C POP BP + 08DC 5A C POP DX + 08DD C RDSEC: + 08DD F6 06 013A R FF C TEST BYTE PTR [PREREAD],-1 + 08E2 75 15 C JNZ SETBUF + 08E4 33 C0 C XOR AX,AX + 08E6 A3 003B R C MOV [BUFSECNO],AX ;Set buffer valid in case of disk error + 08E9 48 C DEC AX + 08EA A2 003D R C MOV [BUFDRVNO],AL + 08ED 8B 1E 0039 R C MOV BX,[BUFFER] + 08F1 B9 0001 C MOV CX,1 + 08F4 52 C PUSH DX + 08F5 E8 05FC R C CALL DREAD + 08F8 5A C POP DX + 08F9 C SETBUF: + 08F9 89 16 003B R C MOV [BUFSECNO],DX + 08FD A0 013C R C MOV AL,[THISDRV] + 0900 A2 003D R C MOV [BUFDRVNO],AL + 0903 89 2E 003F R C MOV [BUFDRVBP],BP + 0907 C FINBUF: + 0907 C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 090C 8B 3E 0140 R C MOV DI,[NEXTADD] + 0910 8B F7 C MOV SI,DI + 0912 8B 0E 0156 R C MOV CX,[BYTCNT1] + 0916 03 F1 C ADD SI,CX + 0918 89 36 0140 R C MOV [NEXTADD],SI + 091C 8B 36 0039 R C MOV SI,[BUFFER] + 0920 03 36 0150 R C ADD SI,[BYTSECPOS] + 0924 C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-33 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0925 C BUFRD: + 0925 32 C0 C XOR AL,AL ;Pre-read necessary + 0927 E8 08A0 R C CALL BUFSEC + 092A 06 C PUSH ES + 092B 8E 06 0033 R C MOV ES,[DMAADD+2] + 092F D1 E9 C SHR CX,1 + 0931 73 01 C JNC EVENRD + 0933 A4 C MOVSB + 0934 C EVENRD: + 0934 F3/ A5 C REP MOVSW + 0936 07 C POP ES + 0937 C3 C RET + C + 0938 C BUFWRT: + 0938 A1 014C R C MOV AX,[SECPOS] + 093B 40 C INC AX ;Set for next sector + 093C A3 014C R C MOV [SECPOS],AX + 093F 3B 06 014E R C CMP AX,[VALSEC] ;Has sector been written before? + 0943 B0 01 C MOV AL,1 + 0945 77 02 C JA NOREAD ;Skip preread if SECPOS>VALSEC + 0947 B0 00 C MOV AL,0 + 0949 C NOREAD: + 0949 E8 08A0 R C CALL BUFSEC + 094C 87 FE C XCHG DI,SI + 094E 1E C PUSH DS + 094F 06 C PUSH ES + 0950 0E C PUSH CS + 0951 07 C POP ES + 0952 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0956 D1 E9 C SHR CX,1 + 0958 73 01 C JNC EVENWRT + 095A A4 C MOVSB + 095B C EVENWRT: + 095B F3/ A5 C REP MOVSW + 095D 07 C POP ES + 095E 1F C POP DS + 095F C6 06 003E R 01 C MOV BYTE PTR [DIRTYBUF],1 + 0964 C3 C RET + C + 0965 C NEXTSEC: + 0965 F6 06 0139 R FF C TEST BYTE PTR [TRANS],-1 + 096A 74 27 C JZ CLRET + 096C A0 0137 R C MOV AL,[SECCLUSPOS] + 096F FE C0 C INC AL + 0971 3A 46 04 C CMP AL,[BP.CLUSMSK] + 0974 76 1A C JBE SAVPOS + 0976 8B 1E 014A R C MOV BX,[CLUSNUM] + 097A 81 FB 0FF8 C CMP BX,0FF8H + 097E 73 15 C JAE NONEXT + 0980 8B 76 12 C MOV SI,[BP.FAT] + 0983 E8 0157 R C CALL UNPACK + 0986 89 3E 014A R C MOV [CLUSNUM],DI + 098A FF 06 0148 R C INC [LASTPOS] + 098E B0 00 C MOV AL,0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-34 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0990 C SAVPOS: + 0990 A2 0137 R C MOV [SECCLUSPOS],AL + 0993 C CLRET: + 0993 F8 C CLC + 0994 C3 C RET + 0995 C NONEXT: + 0995 F9 C STC + 0996 C3 C RET + C + 0997 C TRANBUF: + 0997 AC C LODSB + 0998 AA C STOSB + 0999 3C 0D C CMP AL,13 ;Check for carriage return + 099B 75 03 C JNZ NORMCH + 099D C6 04 0A C MOV BYTE PTR [SI],10 + 09A0 C NORMCH: + 09A0 3C 0A C CMP AL,10 + 09A2 E0 F3 C LOOPNZ TRANBUF + 09A4 75 0B C JNZ ENDRDCON + 09A6 E8 119F R C CALL OUT ;Transmit linefeed + 09A9 33 F6 C XOR SI,SI + 09AB 0B C9 C OR CX,CX + 09AD 75 47 C JNZ GETBUF + 09AF 0C 01 C OR AL,1 ;Clear zero flag--not end of file + 09B1 C ENDRDCON: + 09B1 89 36 002F R C MOV [CONTPOS],SI + 09B5 C ENDRDDEV: + 09B5 89 3E 0140 R C MOV [NEXTADD],DI + 09B9 07 C POP ES + 09BA 75 09 C JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + 09BC 8B 3E 013E R C MOV DI,[FCB] + 09C0 26: 80 65 18 BF C AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available + 09C5 C SETFCBJ: + 09C5 E9 0ACD R C JMP SETFCB + C + 09C8 C READDEV: + 09C8 06 C PUSH ES + 09C9 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 09CD FE C3 C INC BL + 09CF 74 0E C JZ READCON + 09D1 FE C3 C INC BL + 09D3 75 E0 C JNZ ENDRDDEV + 09D5 C READAUX: + 09D5 E8 0141 R C CALL AUXIN + 09D8 AA C STOSB + 09D9 3C 1A C CMP AL,1AH + 09DB E0 F8 C LOOPNZ READAUX + 09DD EB D6 C JMP SHORT ENDRDDEV + C + 09DF C READCON: + 09DF 0E C PUSH CS + 09E0 1F C POP DS + 09E1 8B 36 002F R C MOV SI,[CONTPOS] + 09E5 0B F6 C OR SI,SI + 09E7 75 AE C JNZ TRANBUF +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-35 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 09E9 80 3E 0080 R 80 C CMP BYTE PTR [CONBUF],128 + 09EE 74 06 C JZ GETBUF + 09F0 C7 06 0080 R FF80 C MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template + 09F6 C GETBUF: + 09F6 51 C PUSH CX + 09F7 06 C PUSH ES + 09F8 57 C PUSH DI + 09F9 BA 0080 R C MOV DX,OFFSET DOSGROUP:CONBUF + 09FC E8 0FBD R C CALL BUFIN ;Get input buffer + 09FF 5F C POP DI + 0A00 07 C POP ES + 0A01 59 C POP CX + 0A02 BE 0082 R C MOV SI,2 + OFFSET DOSGROUP:CONBUF + 0A05 80 3C 1A C CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character + 0A08 75 8D C JNZ TRANBUF + 0A0A B0 1A C MOV AL,1AH + 0A0C AA C STOSB + 0A0D B0 0A C MOV AL,10 + 0A0F E8 119F R C CALL OUT ;Send linefeed + 0A12 33 F6 C XOR SI,SI + 0A14 EB 9B C JMP SHORT ENDRDCON + C + 0A16 C RDERR: + 0A16 33 C9 C XOR CX,CX + 0A18 E9 0B92 R C JMP WRTERR + C + 0A1B E9 0B2D R C RDLASTJ:JMP RDLAST + C + 0A1E C LOAD: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Position in file to read + C ; CX = No. of records to read + C ; Outputs: + C ; DX:AX = Position of last record read + C ; CX = No. of bytes read + C ; ES:DI point to FCB + C ; LSTCLUS, CLUSPOS fields in FCB set + C + 0A1E E8 0784 R C CALL SETUP + 0A21 0A DB C OR BL,BL ;Check for named device I/O + 0A23 78 A3 C JS READDEV + 0A25 26: 8B 45 10 C MOV AX,ES:WORD PTR [DI.FILSIZ] + 0A29 26: 8B 5D 12 C MOV BX,ES:WORD PTR [DI.FILSIZ+2] + 0A2D 2B 06 0152 R C SUB AX,WORD PTR [BYTPOS] + 0A31 1B 1E 0154 R C SBB BX,WORD PTR [BYTPOS+2] + 0A35 72 DF C JB RDERR + 0A37 75 0A C JNZ ENUF + 0A39 0B C0 C OR AX,AX + 0A3B 74 D9 C JZ RDERR + 0A3D 3B C1 C CMP AX,CX + 0A3F 73 02 C JAE ENUF + 0A41 8B C8 C MOV CX,AX + 0A43 C ENUF: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-36 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0A43 E8 084C R C CALL BREAKDOWN + 0A46 8B 0E 014A R C MOV CX,[CLUSNUM] + 0A4A E8 0874 R C CALL FNDCLUS + 0A4D 0B C9 C OR CX,CX + 0A4F 75 C5 C JNZ RDERR + 0A51 89 16 0148 R C MOV [LASTPOS],DX + 0A55 89 1E 014A R C MOV [CLUSNUM],BX + 0A59 83 3E 0156 R 00 C CMP [BYTCNT1],0 + 0A5E 74 03 C JZ RDMID + 0A60 E8 0925 R C CALL BUFRD + 0A63 C RDMID: + 0A63 83 3E 015A R 00 C CMP [SECCNT],0 + 0A68 74 B1 C JZ RDLASTJ + 0A6A E8 0965 R C CALL NEXTSEC + 0A6D 72 5E C JC SETFCB + 0A6F C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 0A74 C ONSEC: + 0A74 8A 16 0137 R C MOV DL,[SECCLUSPOS] + 0A78 8B 0E 015A R C MOV CX,[SECCNT] + 0A7C 8B 1E 014A R C MOV BX,[CLUSNUM] + 0A80 C RDLP: + 0A80 E8 0D15 R C CALL OPTIMIZE + 0A83 57 C PUSH DI + 0A84 50 C PUSH AX + 0A85 1E C PUSH DS + 0A86 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0A8A 52 C PUSH DX + 0A8B 53 C PUSH BX + 0A8C 9C C PUSHF ;Save carry flag + 0A8D E8 05FC R C CALL DREAD + 0A90 9D C POPF ;Restore carry flag + 0A91 5F C POP DI ;Initial transfer address + 0A92 58 C POP AX ;First sector transfered + 0A93 1F C POP DS + 0A94 72 25 C JC NOTBUFFED ;Was one of those sectors in the buffer? + 0A96 80 3E 003E R 00 C CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty? + 0A9B 74 1E C JZ NOTBUFFED ;If not no problem + C ;We have transfered in a sector from disk when a dirty copy of it is in the buffer. + C ;We must transfer the sector from the buffer to correct memory address + 0A9D 2B 06 003B R C SUB AX,[BUFSECNO] ;How many sectors into the transfer? + 0AA1 F7 D8 C NEG AX + 0AA3 8B 4E 02 C MOV CX,[BP.SECSIZ] + 0AA6 F7 E1 C MUL CX ;How many bytes into the transfer? + 0AA8 03 F8 C ADD DI,AX + 0AAA 8B 36 0039 R C MOV SI,[BUFFER] + 0AAE 06 C PUSH ES + 0AAF 8E 06 0033 R C MOV ES,[DMAADD+2] ;Get disk transfer segment + 0AB3 D1 E9 C SHR CX,1 + 0AB5 F3/ A5 C REP MOVSW + 0AB7 73 01 C JNC EVENMOV + 0AB9 A4 C MOVSB + 0ABA C EVENMOV: + 0ABA 07 C POP ES + 0ABB C NOTBUFFED: + 0ABB 59 C POP CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-37 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0ABC 5B C POP BX + 0ABD E3 6E C JCXZ RDLAST + 0ABF 81 FB 0FF8 C CMP BX,0FF8H + 0AC3 73 08 C JAE SETFCB + 0AC5 B2 00 C MOV DL,0 + 0AC7 FF 06 0148 R C INC [LASTPOS] ;We'll be using next cluster + 0ACB EB B3 C JMP SHORT RDLP + C + 0ACD C SETFCB: + 0ACD 8B 36 013E R C MOV SI,[FCB] + 0AD1 A1 0140 R C MOV AX,[NEXTADD] + 0AD4 8B F8 C MOV DI,AX + 0AD6 2B 06 0031 R C SUB AX,[DMAADD] ;Number of bytes transfered + 0ADA 33 D2 C XOR DX,DX + 0ADC 26: 8B 4C 0E C MOV CX,ES:[SI.RECSIZ] + 0AE0 F7 F1 C DIV CX ;Number of records + 0AE2 3B 06 0146 R C CMP AX,[RECCNT] ;Check if all records transferred + 0AE6 74 22 C JZ FULLREC + 0AE8 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0AED 0B D2 C OR DX,DX + 0AEF 74 19 C JZ FULLREC ;If remainder 0, then full record transfered + 0AF1 C6 06 0138 R 03 C MOV BYTE PTR [DSKERR],3 ;Flag partial last record + 0AF6 2B CA C SUB CX,DX ;Bytes left in last record + 0AF8 06 C PUSH ES + 0AF9 8E 06 0033 R C MOV ES,[DMAADD+2] + 0AFD 93 C XCHG AX,BX ;Save the record count temporarily + 0AFE 33 C0 C XOR AX,AX ;Fill with zeros + 0B00 D1 E9 C SHR CX,1 + 0B02 73 01 C JNC EVENFIL + 0B04 AA C STOSB + 0B05 C EVENFIL: + 0B05 F3/ AB C REP STOSW + 0B07 93 C XCHG AX,BX ;Restore record count to AX + 0B08 07 C POP ES + 0B09 40 C INC AX ;Add last (partial) record to total + 0B0A C FULLREC: + 0B0A 8B C8 C MOV CX,AX + 0B0C 8B FE C MOV DI,SI ;ES:DI point to FCB + 0B0E C SETCLUS: + 0B0E A1 014A R C MOV AX,[CLUSNUM] + 0B11 26: 89 45 1B C MOV ES:[DI.LSTCLUS],AX + 0B15 A1 0148 R C MOV AX,[LASTPOS] + 0B18 26: 89 45 1D C MOV ES:[DI.CLUSPOS],AX + 0B1C C ADDREC: + 0B1C A1 0142 R C MOV AX,WORD PTR [RECPOS] + 0B1F 8B 16 0144 R C MOV DX,WORD PTR [RECPOS+2] + 0B23 E3 07 C JCXZ RET28 ;If no records read, don't change position + 0B25 49 C DEC CX + 0B26 03 C1 C ADD AX,CX ;Update current record position + 0B28 83 D2 00 C ADC DX,0 + 0B2B 41 C INC CX + 0B2C C3 C RET28: RET + C + 0B2D C RDLAST: + 0B2D A1 0158 R C MOV AX,[BYTCNT2] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-38 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0B30 0B C0 C OR AX,AX + 0B32 74 99 C JZ SETFCB + 0B34 A3 0156 R C MOV [BYTCNT1],AX + 0B37 E8 0965 R C CALL NEXTSEC + 0B3A 72 91 C JC SETFCB + 0B3C C7 06 0150 R 0000 C MOV [BYTSECPOS],0 + 0B42 E8 0925 R C CALL BUFRD + 0B45 EB 86 C JMP SHORT SETFCB + C + 0B47 C WRTDEV: + 0B47 1E C PUSH DS + 0B48 C5 36 0031 R C LDS SI,DWORD PTR [DMAADD] + 0B4C 80 CB 40 C OR BL,40H + 0B4F FE C3 C INC BL + 0B51 74 1E C JZ WRTCON + 0B53 FE C3 C INC BL + 0B55 74 10 C JZ WRTAUX + 0B57 FE C3 C INC BL + 0B59 74 20 C JZ ENDWRDEV ;Done if device is NUL + 0B5B C WRTLST: + 0B5B AC C LODSB + 0B5C 3C 1A C CMP AL,1AH + 0B5E 74 1B C JZ ENDWRDEV + 0B60 E8 128D R C CALL LISTOUT + 0B63 E2 F6 C LOOP WRTLST + 0B65 EB 14 C JMP SHORT ENDWRDEV + C + 0B67 C WRTAUX: + 0B67 AC C LODSB + 0B68 E8 014C R C CALL AUXOUT + 0B6B 3C 1A C CMP AL,1AH + 0B6D E0 F8 C LOOPNZ WRTAUX + 0B6F EB 0A C JMP SHORT ENDWRDEV + C + 0B71 C WRTCON: + 0B71 AC C LODSB + 0B72 3C 1A C CMP AL,1AH + 0B74 74 05 C JZ ENDWRDEV + 0B76 E8 119F R C CALL OUT + 0B79 E2 F6 C LOOP WRTCON + 0B7B C ENDWRDEV: + 0B7B 1F C POP DS + 0B7C 8B 0E 0146 R C MOV CX,[RECCNT] + 0B80 8B 3E 013E R C MOV DI,[FCB] + 0B84 EB 96 C JMP SHORT ADDREC + C + 0B86 C HAVSTART: + 0B86 8B C8 C MOV CX,AX + 0B88 E8 088E R C CALL SKPCLP + 0B8B E3 16 C JCXZ DOWRTJ + 0B8D E8 0DBA R C CALL ALLOCATE + 0B90 73 11 C JNC DOWRTJ + 0B92 C WRTERR: + 0B92 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0B97 C LVDSK: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-39 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0B97 A1 0142 R C MOV AX,WORD PTR [RECPOS] + 0B9A 8B 16 0144 R C MOV DX,WORD PTR [RECPOS+2] + 0B9E 8B 3E 013E R C MOV DI,[FCB] + 0BA2 C3 C RET + C + 0BA3 EB 7F 90 C DOWRTJ: JMP DOWRT + C + 0BA6 C WRTEOFJ: + 0BA6 E9 0CC3 R C JMP WRTEOF + C + 0BA9 C STORE: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Position in file of disk transfer + C ; CX = Record count + C ; Outputs: + C ; DX:AX = Position of last record written + C ; CX = No. of records written + C ; ES:DI point to FCB + C ; LSTCLUS, CLUSPOS fields in FCB set + C + 0BA9 E8 0784 R C CALL SETUP + 0BAC E8 1400 R C CALL DATE16 + 0BAF 26: 89 45 14 C MOV ES:[DI.FDATE],AX + 0BB3 26: 89 55 16 C MOV ES:[DI.FTIME],DX + 0BB7 0A DB C OR BL,BL + 0BB9 78 8C C JS WRTDEV + 0BBB 80 E3 3F C AND BL,3FH ;Mark file as dirty + 0BBE 26: 88 5D 18 C MOV ES:[DI.DEVID],BL + 0BC2 E8 084C R C CALL BREAKDOWN + 0BC5 A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 0BC8 8B 16 0154 R C MOV DX,WORD PTR [BYTPOS+2] + 0BCC E3 D8 C JCXZ WRTEOFJ + 0BCE 49 C DEC CX + 0BCF 03 C1 C ADD AX,CX + 0BD1 83 D2 00 C ADC DX,0 ;AX:DX=last byte accessed + 0BD4 F7 76 02 C DIV [BP.SECSIZ] ;AX=last sector accessed + 0BD7 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0BDA D3 E8 C SHR AX,CL ;Last cluster to be accessed + 0BDC 50 C PUSH AX + 0BDD 26: 8B 45 10 C MOV AX,ES:WORD PTR [DI.FILSIZ] + 0BE1 26: 8B 55 12 C MOV DX,ES:WORD PTR [DI.FILSIZ+2] + 0BE5 F7 76 02 C DIV [BP.SECSIZ] + 0BE8 0B D2 C OR DX,DX + 0BEA 74 01 C JZ NORNDUP + 0BEC 40 C INC AX ;Round up if any remainder + 0BED C NORNDUP: + 0BED A3 014E R C MOV [VALSEC],AX ;Number of sectors that have been written + 0BF0 58 C POP AX + 0BF1 8B 0E 014A R C MOV CX,[CLUSNUM] ;First cluster accessed + 0BF5 E8 0874 R C CALL FNDCLUS + 0BF8 89 1E 014A R C MOV [CLUSNUM],BX + 0BFC 89 16 0148 R C MOV [LASTPOS],DX + 0C00 2B C2 C SUB AX,DX ;Last cluster minus current cluster +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-40 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0C02 74 20 C JZ DOWRT ;If we have last clus, we must have first + 0C04 E3 80 C JCXZ HAVSTART ;See if no more data + 0C06 51 C PUSH CX ;No. of clusters short of first + 0C07 8B C8 C MOV CX,AX + 0C09 E8 0DBA R C CALL ALLOCATE + 0C0C 58 C POP AX + 0C0D 72 83 C JC WRTERR + 0C0F 8B C8 C MOV CX,AX + 0C11 8B 16 0148 R C MOV DX,[LASTPOS] + 0C15 42 C INC DX + 0C16 49 C DEC CX + 0C17 74 03 C JZ NOSKIP + 0C19 E8 088E R C CALL SKPCLP + 0C1C C NOSKIP: + 0C1C 89 1E 014A R C MOV [CLUSNUM],BX + 0C20 89 16 0148 R C MOV [LASTPOS],DX + 0C24 C DOWRT: + 0C24 83 3E 0156 R 00 C CMP [BYTCNT1],0 + 0C29 74 07 C JZ WRTMID + 0C2B 8B 1E 014A R C MOV BX,[CLUSNUM] + 0C2F E8 0938 R C CALL BUFWRT + 0C32 C WRTMID: + 0C32 A1 015A R C MOV AX,[SECCNT] + 0C35 0B C0 C OR AX,AX + 0C37 74 40 C JZ WRTLAST + 0C39 01 06 014C R C ADD [SECPOS],AX + 0C3D E8 0965 R C CALL NEXTSEC + 0C40 C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 0C45 8A 16 0137 R C MOV DL,[SECCLUSPOS] + 0C49 8B 1E 014A R C MOV BX,[CLUSNUM] + 0C4D 8B 0E 015A R C MOV CX,[SECCNT] + 0C51 C WRTLP: + 0C51 E8 0D15 R C CALL OPTIMIZE + 0C54 72 0C C JC NOTINBUF ;Is one of the sectors buffered? + 0C56 C7 06 003B R 0000 C MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're + 0C5C C7 06 003D R 00FF C MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it + 0C62 C NOTINBUF: + 0C62 57 C PUSH DI + 0C63 50 C PUSH AX + 0C64 1E C PUSH DS + 0C65 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0C69 E8 068C R C CALL DWRITE + 0C6C 1F C POP DS + 0C6D 59 C POP CX + 0C6E 5B C POP BX + 0C6F E3 08 C JCXZ WRTLAST + 0C71 B2 00 C MOV DL,0 + 0C73 FF 06 0148 R C INC [LASTPOS] ;We'll be using next cluster + 0C77 EB D8 C JMP SHORT WRTLP + 0C79 C WRTLAST: + 0C79 A1 0158 R C MOV AX,[BYTCNT2] + 0C7C 0B C0 C OR AX,AX + 0C7E 74 0F C JZ FINWRT + 0C80 A3 0156 R C MOV [BYTCNT1],AX + 0C83 E8 0965 R C CALL NEXTSEC +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-41 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0C86 C7 06 0150 R 0000 C MOV [BYTSECPOS],0 + 0C8C E8 0938 R C CALL BUFWRT + 0C8F C FINWRT: + 0C8F A1 0140 R C MOV AX,[NEXTADD] + 0C92 2B 06 0031 R C SUB AX,[DMAADD] + 0C96 03 06 0152 R C ADD AX,WORD PTR [BYTPOS] + 0C9A 8B 16 0154 R C MOV DX,WORD PTR [BYTPOS+2] + 0C9E 83 D2 00 C ADC DX,0 + 0CA1 8B CA C MOV CX,DX + 0CA3 8B 3E 013E R C MOV DI,[FCB] + 0CA7 26: 3B 45 10 C CMP AX,ES:WORD PTR [DI.FILSIZ] + 0CAB 26: 1B 4D 12 C SBB CX,ES:WORD PTR [DI.FILSIZ+2] + 0CAF 72 08 C JB SAMSIZ + 0CB1 26: 89 45 10 C MOV ES:WORD PTR [DI.FILSIZ],AX + 0CB5 26: 89 55 12 C MOV ES:WORD PTR [DI.FILSIZ+2],DX + 0CB9 C SAMSIZ: + 0CB9 8B 0E 0146 R C MOV CX,[RECCNT] + 0CBD E9 0B0E R C JMP SETCLUS + C + C + 0CC0 E9 0B92 R C WRTERRJ:JMP WRTERR + C + 0CC3 C WRTEOF: + 0CC3 8B C8 C MOV CX,AX + 0CC5 0B CA C OR CX,DX + 0CC7 74 3D C JZ KILLFIL + 0CC9 2D 0001 C SUB AX,1 + 0CCC 83 DA 00 C SBB DX,0 + 0CCF F7 76 02 C DIV [BP.SECSIZ] + 0CD2 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0CD5 D3 E8 C SHR AX,CL + 0CD7 8B C8 C MOV CX,AX + 0CD9 E8 0874 R C CALL FNDCLUS + 0CDC E3 1C C JCXZ RELFILE + 0CDE E8 0DBA R C CALL ALLOCATE + 0CE1 72 DD C JC WRTERRJ + 0CE3 C UPDATE: + 0CE3 8B 3E 013E R C MOV DI,[FCB] + 0CE7 A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 0CEA 26: 89 45 10 C MOV ES:WORD PTR [DI.FILSIZ],AX + 0CEE A1 0154 R C MOV AX,WORD PTR [BYTPOS+2] + 0CF1 26: 89 45 12 C MOV ES:WORD PTR [DI.FILSIZ+2],AX + 0CF5 33 C9 C XOR CX,CX + 0CF7 E9 0B1C R C JMP ADDREC + C + 0CFA C RELFILE: + 0CFA BA 0FFF C MOV DX,0FFFH + 0CFD E8 0E31 R C CALL RELBLKS + 0D00 C SETDIRT: + 0D00 C6 44 FF 01 C MOV BYTE PTR [SI-1],1 + 0D04 EB DD C JMP SHORT UPDATE + C + 0D06 C KILLFIL: + 0D06 33 DB C XOR BX,BX + 0D08 26: 87 5D 19 C XCHG BX,ES:[DI.FIRCLUS] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-42 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D0C 0B DB C OR BX,BX + 0D0E 74 D3 C JZ UPDATE + 0D10 E8 0E2F R C CALL RELEASE + 0D13 EB EB C JMP SHORT SETDIRT + C + C + 0D15 C OPTIMIZE: + C + C ; Inputs: + C ; DS = CS + C ; BX = Physical cluster + C ; CX = No. of records + C ; DL = sector within cluster + C ; BP = Base of drives parameters + C ; [NEXTADD] = transfer address + C ; Outputs: + C ; AX = No. of records remaining + C ; BX = Transfer address + C ; CX = No. or records to be transferred + C ; DX = Physical sector address + C ; DI = Next cluster + C ; Carry clear if a sector to transfer is in the buffer + C ; Carry set otherwise + C ; [CLUSNUM] = Last cluster accessed + C ; [NEXTADD] updated + C ; BP unchanged. Note that segment of transfer not set. + C + 0D15 52 C PUSH DX + 0D16 53 C PUSH BX + 0D17 8A 46 04 C MOV AL,[BP.CLUSMSK] + 0D1A FE C0 C INC AL ;Number of sectors per cluster + 0D1C 8A E0 C MOV AH,AL + 0D1E 2A C2 C SUB AL,DL ;AL = Number of sectors left in first cluster + 0D20 8B D1 C MOV DX,CX + 0D22 8B 76 12 C MOV SI,[BP.FAT] + 0D25 B9 0000 C MOV CX,0 + 0D28 C OPTCLUS: + C ;AL has number of sectors available in current cluster + C ;AH has number of sectors available in next cluster + C ;BX has current physical cluster + C ;CX has number of sequential sectors found so far + C ;DX has number of sectors left to transfer + C ;SI has FAT pointer + 0D28 E8 0157 R C CALL UNPACK + 0D2B 02 C8 C ADD CL,AL + 0D2D 80 D5 00 C ADC CH,0 + 0D30 3B CA C CMP CX,DX + 0D32 73 49 C JAE BLKDON + 0D34 8A C4 C MOV AL,AH + 0D36 43 C INC BX + 0D37 3B FB C CMP DI,BX + 0D39 74 ED C JZ OPTCLUS + 0D3B 4B C DEC BX + 0D3C C FINCLUS: + 0D3C 89 1E 014A R C MOV [CLUSNUM],BX ;Last cluster accessed +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-43 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D40 2B D1 C SUB DX,CX ;Number of sectors still needed + 0D42 52 C PUSH DX + 0D43 8B C1 C MOV AX,CX + 0D45 F7 66 02 C MUL [BP.SECSIZ] ;Number of sectors times sector size + 0D48 8B 36 0140 R C MOV SI,[NEXTADD] + 0D4C 03 C6 C ADD AX,SI ;Adjust by size of transfer + 0D4E A3 0140 R C MOV [NEXTADD],AX + 0D51 58 C POP AX ;Number of sectors still needed + 0D52 5A C POP DX ;Starting cluster + 0D53 2B DA C SUB BX,DX ;Number of new clusters accessed + 0D55 01 1E 0148 R C ADD [LASTPOS],BX + 0D59 5B C POP BX ;BL = sector postion within cluster + 0D5A E8 0D8B R C CALL FIGREC + 0D5D 8B DE C MOV BX,SI + C ;Now let's see if any of these sectors are already in the buffer + 0D5F 39 16 003B R C CMP [BUFSECNO],DX + 0D63 72 17 C JC RET100 ;If DX > [BUFSECNO] then not in buffer + 0D65 8B F2 C MOV SI,DX + 0D67 03 F1 C ADD SI,CX ;Last sector + 1 + 0D69 39 36 003B R C CMP [BUFSECNO],SI + 0D6D F5 C CMC + 0D6E 72 0C C JC RET100 ;If SI <= [BUFSECNO] then not in buffer + 0D70 50 C PUSH AX + 0D71 8A 46 00 C MOV AL,[BP.DEVNUM] + 0D74 3A 06 003D R C CMP AL,[BUFDRVNO] ;Is buffer for this drive? + 0D78 58 C POP AX + 0D79 74 01 C JZ RET100 ;If so, then we match + 0D7B F9 C STC ;No match + 0D7C C3 C RET100: RET + 0D7D C BLKDON: + 0D7D 2B CA C SUB CX,DX ;Number of sectors in cluster we don't want + 0D7F 2A E1 C SUB AH,CL ;Number of sectors in cluster we accepted + 0D81 FE CC C DEC AH ;Adjust to mean position within cluster + 0D83 88 26 0137 R C MOV [SECCLUSPOS],AH + 0D87 8B CA C MOV CX,DX ;Anyway, make the total equal to the request + 0D89 EB B1 C JMP SHORT FINCLUS + C + C + 0D8B C FIGREC: + C + C ;Inputs: + C ; DX = Physical cluster number + C ; BL = Sector postion within cluster + C ; BP = Base of drive parameters + C ;Outputs: + C ; DX = physical sector number + C ;No other registers affected. + C + 0D8B 51 C PUSH CX + 0D8C 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0D8F 4A C DEC DX + 0D90 4A C DEC DX + 0D91 D3 E2 C SHL DX,CL + 0D93 0A D3 C OR DL,BL + 0D95 03 56 0B C ADD DX,[BP.FIRREC] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-44 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D98 59 C POP CX + 0D99 C3 C RET + C + 0D9A C GETREC: + C + C ; Inputs: + C ; DS:DX point to FCB + C ; Outputs: + C ; CX = 1 + C ; DX:AX = Record number determined by EXTENT and NR fields + C ; DS:DI point to FCB + C ; No other registers affected. + C + 0D9A 8B FA C MOV DI,DX + 0D9C 80 3D FF C CMP BYTE PTR [DI],-1 ;Check for extended FCB + 0D9F 75 03 C JNZ NORMFCB2 + 0DA1 83 C7 07 C ADD DI,7 + 0DA4 C NORMFCB2: + 0DA4 B9 0001 C MOV CX,1 + 0DA7 8A 45 20 C MOV AL,[DI.NR] + 0DAA 8B 55 0C C MOV DX,[DI.EXTENT] + 0DAD D0 E0 C SHL AL,1 + 0DAF D1 EA C SHR DX,1 + 0DB1 D0 D8 C RCR AL,1 + 0DB3 8A E2 C MOV AH,DL + 0DB5 8A D6 C MOV DL,DH + 0DB7 B6 00 C MOV DH,0 + 0DB9 C3 C RET + C + C + 0DBA C ALLOCATE: + C + C ; Inputs: + C ; DS = CS + C ; ES = Segment of FCB + C ; BX = Last cluster of file (0 if null file) + C ; CX = No. of clusters to allocate + C ; DX = Position of cluster BX + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; [FCB] = Displacement of FCB within segment + C ; Outputs: + C ; IF insufficient space + C ; THEN + C ; Carry set + C ; CX = max. no. of records that could be added to file + C ; ELSE + C ; Carry clear + C ; BX = First cluster allocated + C ; FAT is fully updated including dirty bit + C ; FIRCLUS field of FCB set if file was null + C ; SI,BP unchanged. All other registers destroyed. + C + 0DBA FF 34 C PUSH [SI] + 0DBC 52 C PUSH DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-45 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0DBD 51 C PUSH CX + 0DBE 53 C PUSH BX + 0DBF 8B C3 C MOV AX,BX + 0DC1 C ALLOC: + 0DC1 8B D3 C MOV DX,BX + 0DC3 C FINDFRE: + 0DC3 43 C INC BX + 0DC4 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 0DC7 7E 29 C JLE TRYOUT + 0DC9 3D 0001 C CMP AX,1 + 0DCC 7F 29 C JG TRYIN + 0DCE 5B C POP BX + 0DCF BA 0FFF C MOV DX,0FFFH + 0DD2 E8 0E31 R C CALL RELBLKS + 0DD5 58 C POP AX ;No. of clusters requested + 0DD6 2B C1 C SUB AX,CX ;AX=No. of clusters allocated + 0DD8 5A C POP DX + 0DD9 8F 04 C POP [SI] + 0DDB 42 C INC DX ;Position of first cluster allocated + 0DDC 03 C2 C ADD AX,DX ;AX=max no. of cluster in file + 0DDE 8A 56 04 C MOV DL,[BP.CLUSMSK] + 0DE1 B6 00 C MOV DH,0 + 0DE3 42 C INC DX ;DX=records/cluster + 0DE4 F7 E2 C MUL DX ;AX=max no. of records in file + 0DE6 8B C8 C MOV CX,AX + 0DE8 2B 0E 0142 R C SUB CX,WORD PTR [RECPOS] ;CX=max no. of records that could be written + 0DEC 77 02 C JA MAXREC + 0DEE 33 C9 C XOR CX,CX ;If CX was negative, zero it + 0DF0 C MAXREC: + 0DF0 F9 C STC + 0DF1 C3 C RET11: RET + C + 0DF2 C TRYOUT: + 0DF2 E8 0157 R C CALL UNPACK + 0DF5 74 0C C JZ HAVFRE + 0DF7 C TRYIN: + 0DF7 48 C DEC AX + 0DF8 7E C9 C JLE FINDFRE + 0DFA 93 C XCHG AX,BX + 0DFB E8 0157 R C CALL UNPACK + 0DFE 74 03 C JZ HAVFRE + 0E00 93 C XCHG AX,BX + 0E01 EB C0 C JMP SHORT FINDFRE + 0E03 C HAVFRE: + 0E03 87 DA C XCHG BX,DX + 0E05 8B C2 C MOV AX,DX + 0E07 E8 017F R C CALL PACK + 0E0A 8B D8 C MOV BX,AX + 0E0C E2 B3 C LOOP ALLOC + 0E0E BA 0FFF C MOV DX,0FFFH + 0E11 E8 017F R C CALL PACK + 0E14 C6 44 FF 01 C MOV BYTE PTR [SI-1],1 + 0E18 5B C POP BX + 0E19 59 C POP CX ;Don't need this stuff since we're successful + 0E1A 5A C POP DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-46 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0E1B E8 0157 R C CALL UNPACK + 0E1E 8F 04 C POP [SI] + 0E20 87 DF C XCHG BX,DI + 0E22 0B FF C OR DI,DI + 0E24 75 CB C JNZ RET11 + 0E26 8B 3E 013E R C MOV DI,[FCB] + 0E2A 26: 89 5D 19 C MOV ES:[DI.FIRCLUS],BX + 0E2E C3 C RET12: RET + C + C + 0E2F C RELEASE: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster in file + C ; SI = FAT pointer + C ; BP = Base of drive parameters + C ; Function: + C ; Frees cluster chain starting with [BX] + C ; AX,BX,DX,DI all destroyed. Other registers unchanged. + C + 0E2F 33 D2 C XOR DX,DX + 0E31 C RELBLKS: + C ; Enter here with DX=0FFFH to put an end-of-file mark + C ; in the first cluster and free the rest in the chain. + 0E31 E8 0157 R C CALL UNPACK + 0E34 74 F8 C JZ RET12 + 0E36 8B C7 C MOV AX,DI + 0E38 E8 017F R C CALL PACK + 0E3B 3D 0FF8 C CMP AX,0FF8H + 0E3E 8B D8 C MOV BX,AX + 0E40 72 ED C JB RELEASE + 0E42 C3 C RET13: RET + C + C + 0E43 C GETEOF: + C + C ; Inputs: + C ; BX = Cluster in a file + C ; SI = Base of drive FAT + C ; DS = CS + C ; Outputs: + C ; BX = Last cluster in the file + C ; DI destroyed. No other registers affected. + C + 0E43 E8 0157 R C CALL UNPACK + 0E46 81 FF 0FF8 C CMP DI,0FF8H + 0E4A 73 F6 C JAE RET13 + 0E4C 8B DF C MOV BX,DI + 0E4E EB F3 C JMP SHORT GETEOF + C + C + 0E50 C SRCHFRST: ;System call 17 + 0E50 E8 01C8 R C CALL GETFILE + 0E53 C SAVPLCE: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-47 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; Search-for-next enters here to save place and report + C ; findings. + 0E53 72 35 C JC KILLSRCH + 0E55 0A FF C OR BH,BH + 0E57 78 3A C JS SRCHDEV + 0E59 A1 0103 R C MOV AX,[LASTENT] + 0E5C 26: 89 45 10 C MOV ES:[DI.FILDIRENT],AX + 0E60 26: 89 6D 12 C MOV ES:[DI.DRVBP],BP + C ;Information in directory entry must be copied into the first + C ; 33 bytes starting at the disk transfer address. + 0E64 8B F3 C MOV SI,BX + 0E66 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 0E6A B8 00FF C MOV AX,00FFH + 0E6D 3A 06 012E R C CMP AL,[EXTFCB] + 0E71 75 09 C JNZ NORMFCB + 0E73 AB C STOSW + 0E74 FE C0 C INC AL + 0E76 AB C STOSW + 0E77 AB C STOSW + 0E78 A0 0116 R C MOV AL,[ATTRIB] + 0E7B AA C STOSB + 0E7C C NORMFCB: + 0E7C A0 013C R C MOV AL,[THISDRV] + 0E7F FE C0 C INC AL + 0E81 AA C STOSB ;Set drive number + 0E82 B9 0010 C MOV CX,16 + 0E85 F3/ A5 C REP MOVSW ;Copy remaining 10 characters of name + 0E87 32 C0 C XOR AL,AL + 0E89 C3 C RET + C + 0E8A C KILLSRCH: + = 0E8B C KILLSRCH1 EQU KILLSRCH+1 + C ;The purpose of the KILLSRCH1 label is to provide a jump label to the following + C ; instruction which leaves out the segment override. + 0E8A 26: C7 45 10 FFFF C MOV WORD PTR ES:[DI.FILDIRENT],-1 + 0E90 B0 FF C MOV AL,-1 + 0E92 C3 C RET + C + 0E93 C SRCHDEV: + 0E93 26: 89 5D 10 C MOV ES:[DI.FILDIRENT],BX + 0E97 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 0E9B 33 C0 C XOR AX,AX + 0E9D AA C STOSB ;Zero drive byte + 0E9E 83 EE 04 C SUB SI,4 ;Point to device name + 0EA1 A5 C MOVSW + 0EA2 A5 C MOVSW + 0EA3 B8 2020 C MOV AX,2020H + 0EA6 AA C STOSB + 0EA7 AB C STOSW + 0EA8 AB C STOSW + 0EA9 AB C STOSW ;Fill with 8 blanks + 0EAA 33 C0 C XOR AX,AX + 0EAC B9 000A C MOV CX,10 + 0EAF F3/ AB C REP STOSW + 0EB1 AA C STOSB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-48 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0EB2 C3 C RET14: RET + C + 0EB3 C SRCHNXT: ;System call 18 + 0EB3 E8 0372 R C CALL MOVNAME + 0EB6 8B FA C MOV DI,DX + 0EB8 72 D1 C JC NEAR PTR KILLSRCH1 + 0EBA 8B 6D 12 C MOV BP,[DI.DRVBP] + 0EBD 8B 45 10 C MOV AX,[DI.FILDIRENT] + 0EC0 0B C0 C OR AX,AX + 0EC2 78 C7 C JS NEAR PTR KILLSRCH1 + 0EC4 52 C PUSH DX + 0EC5 1E C PUSH DS + 0EC6 0E C PUSH CS + 0EC7 1F C POP DS + 0EC8 A3 0103 R C MOV [LASTENT],AX + 0ECB E8 01E6 R C CALL CONTSRCH + 0ECE 07 C POP ES + 0ECF 5F C POP DI + 0ED0 EB 81 C JMP SAVPLCE + C + C + 0ED2 C FILESIZE: ;System call 35 + 0ED2 E8 01C8 R C CALL GETFILE + 0ED5 B0 FF C MOV AL,-1 + 0ED7 72 D9 C JC RET14 + 0ED9 83 C7 21 C ADD DI,33 ;Write size in RR field + 0EDC 26: 8B 4D ED C MOV CX,ES:[DI.RECSIZ-33] + 0EE0 0B C9 C OR CX,CX + 0EE2 75 03 C JNZ RECOK + 0EE4 B9 0080 C MOV CX,128 + 0EE7 C RECOK: + 0EE7 33 C0 C XOR AX,AX + 0EE9 33 D2 C XOR DX,DX ;Intialize size to zero + 0EEB 0A FF C OR BH,BH ;Check for named I/O device + 0EED 78 14 C JS DEVSIZ + 0EEF 46 C INC SI + 0EF0 46 C INC SI ;Point to length field + 0EF1 8B 44 02 C MOV AX,[SI+2] ;Get high word of size + 0EF4 F7 F1 C DIV CX + 0EF6 50 C PUSH AX ;Save high part of result + 0EF7 AD C LODSW ;Get low word of size + 0EF8 F7 F1 C DIV CX + 0EFA 0B D2 C OR DX,DX ;Check for zero remainder + 0EFC 5A C POP DX + 0EFD 74 04 C JZ DEVSIZ + 0EFF 40 C INC AX ;Round up for partial record + 0F00 75 01 C JNZ DEVSIZ ;Propagate carry? + 0F02 42 C INC DX + 0F03 C DEVSIZ: + 0F03 AB C STOSW + 0F04 8B C2 C MOV AX,DX + 0F06 AA C STOSB + 0F07 B0 00 C MOV AL,0 + 0F09 83 F9 40 C CMP CX,64 + 0F0C 73 A4 C JAE RET14 ;Only 3-byte field if RECSIZ >= 64 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-49 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0F0E 26: 88 25 C MOV ES:[DI],AH + 0F11 C3 C RET + C + C + 0F12 C SETDMA: ;System call 26 + 0F12 2E: 89 16 0031 R C MOV CS:[DMAADD],DX + 0F17 2E: 8C 1E 0033 R C MOV CS:[DMAADD+2],DS + 0F1C C3 C RET + C + 0F1D C NOSUCHDRV: + 0F1D B0 FF C MOV AL,-1 + 0F1F C3 C RET + C + 0F20 C GETFATPT: ;System call 27 + 0F20 B2 00 C MOV DL,0 ;Use default drive + C + 0F22 C GETFATPTDL: ;System call 28 + 0F22 0E C PUSH CS + 0F23 1F C POP DS + 0F24 8A C2 C MOV AL,DL + 0F26 E8 03B9 R C CALL GETTHISDRV + 0F29 72 F2 C JC NOSUCHDRV + 0F2B E8 042C R C CALL FATREAD + 0F2E 8B 5E 12 C MOV BX,[BP.FAT] + 0F31 8A 46 04 C MOV AL,[BP.CLUSMSK] + 0F34 FE C0 C INC AL + 0F36 8B 56 0D C MOV DX,[BP.MAXCLUS] + 0F39 4A C DEC DX + 0F3A 8B 4E 02 C MOV CX,[BP.SECSIZ] + 0F3D C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0F41 89 5C 02 C MOV [SI.BXSAVE],BX + 0F44 89 54 06 C MOV [SI.DXSAVE],DX + 0F47 89 4C 04 C MOV [SI.CXSAVE],CX + 0F4A 8C 4C 0E C MOV [SI.DSSAVE],CS + 0F4D C3 C RET + C + C + 0F4E C GETDSKPT: ;System call 31 + 0F4E 0E C PUSH CS + 0F4F 1F C POP DS + 0F50 A0 004A R C MOV AL,[CURDRV] + 0F53 A2 013C R C MOV [THISDRV],AL + 0F56 E8 042C R C CALL FATREAD + 0F59 C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0F5D 89 6C 02 C MOV [SI.BXSAVE],BP + 0F60 8C 4C 0E C MOV [SI.DSSAVE],CS + 0F63 C3 C RET + C + C + 0F64 C DSKRESET: ;System call 13 + 0F64 0E C PUSH CS + 0F65 1F C POP DS + 0F66 C WRTFATS: + C ; DS=CS. Writes back all dirty FATs. All registers destroyed. + 0F66 32 C0 C XOR AL,AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-50 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0F68 86 06 003E R C XCHG AL,[DIRTYBUF] + 0F6C 0A C0 C OR AL,AL + 0F6E 74 12 C JZ NOBUF + 0F70 8B 2E 003F R C MOV BP,[BUFDRVBP] + 0F74 8B 16 003B R C MOV DX,[BUFSECNO] + 0F78 8B 1E 0039 R C MOV BX,[BUFFER] + 0F7C B9 0001 C MOV CX,1 + 0F7F E8 068C R C CALL DWRITE + 0F82 C NOBUF: + 0F82 8A 0E 002D R C MOV CL,[NUMIO] + 0F86 B5 00 C MOV CH,0 + 0F88 8B 2E 004B R C MOV BP,[DRVTAB] + 0F8C C WRTFAT: + 0F8C 51 C PUSH CX + 0F8D E8 051F R C CALL CHKFATWRT + 0F90 59 C POP CX + 0F91 83 C5 14 C ADD BP,DPBSIZ + 0F94 E2 F6 C LOOP WRTFAT + 0F96 C3 C RET + C + C + 0F97 C GETDRV: ;System call 25 + 0F97 2E: A0 004A R C MOV AL,CS:[CURDRV] + 0F9B C3 C RET15: RET + C + C + 0F9C C SETRNDREC: ;System call 36 + 0F9C E8 0D9A R C CALL GETREC + 0F9F 89 45 21 C MOV [DI+33],AX + 0FA2 88 55 23 C MOV [DI+35],DL + 0FA5 83 7D 0E 40 C CMP [DI.RECSIZ],64 + 0FA9 73 F0 C JAE RET15 + 0FAB 88 75 24 C MOV [DI+36],DH ;Set 4th byte only if record size < 64 + 0FAE C3 C RET16: RET + C + C + 0FAF C SELDSK: ;System call 14 + 0FAF 2E: A0 002C R C MOV AL,CS:[NUMDRV] + 0FB3 3A D0 C CMP DL,AL + 0FB5 73 05 C JNB RET17 + 0FB7 2E: 88 16 004A R C MOV CS:[CURDRV],DL + 0FBC C3 C RET17: RET + C + 0FBD C BUFIN: ;System call 10 + 0FBD 8C C8 C MOV AX,CS + 0FBF 8E C0 C MOV ES,AX + 0FC1 8B F2 C MOV SI,DX + 0FC3 B5 00 C MOV CH,0 + 0FC5 AD C LODSW + 0FC6 0A C0 C OR AL,AL + 0FC8 74 F2 C JZ RET17 + 0FCA 8A DC C MOV BL,AH + 0FCC 8A FD C MOV BH,CH + 0FCE 3A C3 C CMP AL,BL + 0FD0 76 05 C JBE NOEDIT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-51 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0FD2 80 38 0D C CMP BYTE PTR [BX+SI],0DH + 0FD5 74 02 C JZ EDITON + 0FD7 C NOEDIT: + 0FD7 8A DD C MOV BL,CH + 0FD9 C EDITON: + 0FD9 8A D0 C MOV DL,AL + 0FDB 4A C DEC DX + 0FDC C NEWLIN: + 0FDC 2E: A0 0028 R C MOV AL,CS:[CARPOS] + 0FE0 2E: A2 0029 R C MOV CS:[STARTPOS],AL + 0FE4 56 C PUSH SI + 0FE5 BF 0000 R C MOV DI,OFFSET DOSGROUP:INBUF + 0FE8 8A E5 C MOV AH,CH + 0FEA 8A FD C MOV BH,CH + 0FEC 8A F5 C MOV DH,CH + 0FEE C GETCH: + 0FEE E8 125C R C CALL IN + 0FF1 3C 06 C CMP AL,"F"-"@" ;Ignore ^F + 0FF3 74 F9 C JZ GETCH + 0FF5 2E: 3A 06 0003 R C CMP AL,CS:ESCCHAR + 0FFA 74 32 C JZ ESC + 0FFC 3C 7F C CMP AL,7FH + 0FFE 74 7E C JZ BACKSP + 1000 3C 08 C CMP AL,8 + 1002 74 7A C JZ BACKSP + 1004 3C 0D C CMP AL,13 + 1006 74 3A C JZ ENDLIN + 1008 3C 0A C CMP AL,10 + 100A 74 5A C JZ PHYCRLF + 100C 3C 18 C CMP AL,CANCEL + 100E 74 5B C JZ KILNEW + 1010 C SAVCH: + 1010 3A F2 C CMP DH,DL + 1012 73 13 C JAE BUFFUL + 1014 AA C STOSB + 1015 FE C6 C INC DH + 1017 E8 117D R C CALL BUFOUT + 101A 0A E4 C OR AH,AH + 101C 75 D0 C JNZ GETCH + 101E 3A FB C CMP BH,BL + 1020 73 CC C JAE GETCH + 1022 46 C INC SI + 1023 FE C7 C INC BH + 1025 EB C7 C JMP SHORT GETCH + C + 1027 C BUFFUL: + 1027 B0 07 C MOV AL,7 + 1029 E8 119F R C CALL OUT + 102C EB C0 C JMP SHORT GETCH + C + 102E C ESC: + 102E E8 125C R C CALL IN + 1031 B1 0C C MOV CL,ESCTABLEN + 1033 57 C PUSH DI + 1034 BF 0004 R C MOV DI,OFFSET DOSGROUP:ESCTAB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-52 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1037 F2/ AE C REPNE SCASB + 1039 5F C POP DI + 103A D1 E1 C SHL CX,1 + 103C 8B E9 C MOV BP,CX + 103E FF A6 1165 R C JMP [BP+OFFSET DOSGROUP:ESCFUNC] + C + 1042 C ENDLIN: + 1042 AA C STOSB + 1043 E8 119F R C CALL OUT + 1046 5F C POP DI + 1047 88 75 FF C MOV [DI-1],DH + 104A FE C6 C INC DH + 104C C COPYNEW: + 104C 8C C5 C MOV BP,ES + 104E 8C DB C MOV BX,DS + 1050 8E C3 C MOV ES,BX + 1052 8E DD C MOV DS,BP + 1054 BE 0000 R C MOV SI,OFFSET DOSGROUP:INBUF + 1057 8A CE C MOV CL,DH + 1059 F3/ A4 C REP MOVSB + 105B C3 C RET + 105C C CRLF: + 105C B0 0D C MOV AL,13 + 105E E8 119F R C CALL OUT + 1061 B0 0A C MOV AL,10 + 1063 E9 119F R C JMP OUT + C + 1066 C PHYCRLF: + 1066 E8 105C R C CALL CRLF + 1069 EB 83 C JMP SHORT GETCH + C + 106B C KILNEW: + 106B B0 5C C MOV AL,"\" + 106D E8 119F R C CALL OUT + 1070 5E C POP SI + 1071 C PUTNEW: + 1071 E8 105C R C CALL CRLF + 1074 2E: A0 0029 R C MOV AL,CS:[STARTPOS] + 1078 E8 1228 R C CALL TAB + 107B E9 0FDC R C JMP NEWLIN + C + 107E C BACKSP: + 107E 0A F6 C OR DH,DH + 1080 74 11 C JZ OLDBAK + 1082 E8 10D3 R C CALL BACKUP + 1085 26: 8A 05 C MOV AL,ES:[DI] + 1088 3C 20 C CMP AL," " + 108A 73 07 C JAE OLDBAK + 108C 3C 09 C CMP AL,9 + 108E 74 11 C JZ BAKTAB + 1090 E8 10D6 R C CALL BACKMES + 1093 C OLDBAK: + 1093 0A E4 C OR AH,AH + 1095 75 07 C JNZ GETCH1 + 1097 0A FF C OR BH,BH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-53 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1099 74 03 C JZ GETCH1 + 109B FE CF C DEC BH + 109D 4E C DEC SI + 109E C GETCH1: + 109E E9 0FEE R C JMP GETCH + 10A1 C BAKTAB: + 10A1 57 C PUSH DI + 10A2 4F C DEC DI + 10A3 FD C STD + 10A4 8A CE C MOV CL,DH + 10A6 B0 20 C MOV AL," " + 10A8 53 C PUSH BX + 10A9 B3 07 C MOV BL,7 + 10AB E3 0E C JCXZ FIGTAB + 10AD C FNDPOS: + 10AD AE C SCASB + 10AE 76 09 C JNA CHKCNT + 10B0 26: 80 7D 01 09 C CMP ES:BYTE PTR [DI+1],9 + 10B5 74 09 C JZ HAVTAB + 10B7 FE CB C DEC BL + 10B9 C CHKCNT: + 10B9 E2 F2 C LOOP FNDPOS + 10BB C FIGTAB: + 10BB 2E: 2A 1E 0029 R C SUB BL,CS:[STARTPOS] + 10C0 C HAVTAB: + 10C0 2A DE C SUB BL,DH + 10C2 02 CB C ADD CL,BL + 10C4 80 E1 07 C AND CL,7 + 10C7 FC C CLD + 10C8 5B C POP BX + 10C9 5F C POP DI + 10CA 74 C7 C JZ OLDBAK + 10CC C TABBAK: + 10CC E8 10D6 R C CALL BACKMES + 10CF E2 FB C LOOP TABBAK + 10D1 EB C0 C JMP SHORT OLDBAK + 10D3 C BACKUP: + 10D3 FE CE C DEC DH + 10D5 4F C DEC DI + 10D6 C BACKMES: + 10D6 B0 08 C MOV AL,8 + 10D8 E8 119F R C CALL OUT + 10DB B0 20 C MOV AL," " + 10DD E8 119F R C CALL OUT + 10E0 B0 08 C MOV AL,8 + 10E2 E9 119F R C JMP OUT + C + 10E5 C TWOESC: + 10E5 B0 1B C MOV AL,ESCCH + 10E7 E9 1010 R C JMP SAVCH + C + 10EA C COPYLIN: + 10EA 8A CB C MOV CL,BL + 10EC 2A CF C SUB CL,BH + 10EE EB 07 C JMP SHORT COPYEACH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-54 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 10F0 C COPYSTR: + 10F0 E8 1123 R C CALL FINDOLD + 10F3 EB 02 C JMP SHORT COPYEACH + C + 10F5 C COPYONE: + 10F5 B1 01 C MOV CL,1 + 10F7 C COPYEACH: + 10F7 B4 00 C MOV AH,0 + 10F9 3A F2 C CMP DH,DL + 10FB 74 0F C JZ GETCH2 + 10FD 3A FB C CMP BH,BL + 10FF 74 0B C JZ GETCH2 + 1101 AC C LODSB + 1102 AA C STOSB + 1103 E8 117D R C CALL BUFOUT + 1106 FE C7 C INC BH + 1108 FE C6 C INC DH + 110A E2 EB C LOOP COPYEACH + 110C C GETCH2: + 110C E9 0FEE R C JMP GETCH + C + 110F C SKIPONE: + 110F 3A FB C CMP BH,BL + 1111 74 F9 C JZ GETCH2 + 1113 FE C7 C INC BH + 1115 46 C INC SI + 1116 E9 0FEE R C JMP GETCH + C + 1119 C SKIPSTR: + 1119 E8 1123 R C CALL FINDOLD + 111C 03 F1 C ADD SI,CX + 111E 02 F9 C ADD BH,CL + 1120 E9 0FEE R C JMP GETCH + C + 1123 C FINDOLD: + 1123 E8 125C R C CALL IN + 1126 8A CB C MOV CL,BL + 1128 2A CF C SUB CL,BH + 112A 74 17 C JZ NOTFND + 112C 49 C DEC CX + 112D 74 14 C JZ NOTFND + 112F 06 C PUSH ES + 1130 1E C PUSH DS + 1131 07 C POP ES + 1132 57 C PUSH DI + 1133 8B FE C MOV DI,SI + 1135 47 C INC DI + 1136 F2/ AE C REPNE SCASB + 1138 5F C POP DI + 1139 07 C POP ES + 113A 75 07 C JNZ NOTFND + 113C F6 D1 C NOT CL + 113E 02 CB C ADD CL,BL + 1140 2A CF C SUB CL,BH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-55 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1142 C3 C RET30: RET + 1143 C NOTFND: + 1143 5D C POP BP + 1144 E9 0FEE R C JMP GETCH + C + 1147 C REEDIT: + 1147 B0 40 C MOV AL,"@" + 1149 E8 119F R C CALL OUT + 114C 5F C POP DI + 114D 57 C PUSH DI + 114E 06 C PUSH ES + 114F 1E C PUSH DS + 1150 E8 104C R C CALL COPYNEW + 1153 1F C POP DS + 1154 07 C POP ES + 1155 5E C POP SI + 1156 8A DE C MOV BL,DH + 1158 E9 1071 R C JMP PUTNEW + C + 115B C ENTERINS: + C ENDIF + C IF NOT TOGLINS + 115B B4 FF C MOV AH,-1 + 115D E9 0FEE R C JMP GETCH + C + 1160 C EXITINS: + 1160 B4 00 C MOV AH,0 + 1162 E9 0FEE R C JMP GETCH + C ENDIF + C + 1165 0FEE R C ESCFUNC DW GETCH + 1167 10E5 R C DW TWOESC + C IF NOT TOGLINS + 1169 1160 R C DW EXITINS + C ENDIF + 116B 115B R C DW ENTERINS + 116D 107E R C DW BACKSP + 116F 1147 R C DW REEDIT + 1171 106B R C DW KILNEW + 1173 10EA R C DW COPYLIN + 1175 1119 R C DW SKIPSTR + 1177 10F0 R C DW COPYSTR + 1179 110F R C DW SKIPONE + 117B 10F5 R C DW COPYONE + C + C ENDIF + 117D C BUFOUT: + 117D 3C 20 C CMP AL," " + 117F 73 1E C JAE OUT + 1181 3C 09 C CMP AL,9 + 1183 74 1A C JZ OUT + 1185 50 C PUSH AX + 1186 B0 5E C MOV AL,"^" + 1188 E8 119F R C CALL OUT + 118B 58 C POP AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-56 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 118C 0C 40 C OR AL,40H + 118E EB 0F C JMP SHORT OUT + C + 1190 C NOSTOP: + 1190 3C 10 C CMP AL,"P"-"@" + 1192 74 40 C JZ INCHK + C IF NOT TOGLPRN + 1194 3C 0E C CMP AL,"N"-"@" + 1196 74 3C C JZ INCHK + C ENDIF + 1198 3C 03 C CMP AL,"C"-"@" + 119A 74 38 C JZ INCHK + 119C C3 C RET + C + 119D C CONOUT: ;System call 2 + 119D 8A C2 C MOV AL,DL + 119F C OUT: + 119F 3C 20 C CMP AL,20H + 11A1 72 71 C JB CTRLOUT + 11A3 3C 7F C CMP AL,7FH + 11A5 74 05 C JZ OUTCH + 11A7 2E: FE 06 0028 R C INC CS:BYTE PTR [CARPOS] + 11AC C OUTCH: + 11AC 50 C PUSH AX + 11AD E8 11C4 R C CALL STATCHK + 11B0 58 C POP AX + 11B1 9A 0009 ---- R C CALL FAR PTR BIOSOUT + 11B6 2E: F6 06 002A R FF C TEST CS:BYTE PTR [PFLAG],-1 + 11BC 74 05 C JZ RET18 + 11BE 9A 000C ---- R C CALL FAR PTR BIOSPRINT + 11C3 C3 C RET18: RET + C + 11C4 C STATCHK: + 11C4 9A 0003 ---- R C CALL FAR PTR BIOSSTAT + 11C9 74 F8 C JZ RET18 + 11CB 3C 13 C CMP AL,'S'-'@' + 11CD 75 C1 C JNZ NOSTOP + 11CF 9A 0006 ---- R C CALL FAR PTR BIOSIN ;Eat Cntrl-S + 11D4 C INCHK: + 11D4 9A 0006 ---- R C CALL FAR PTR BIOSIN + 11D9 3C 10 C CMP AL,'P'-'@' + 11DB 74 29 C JZ PRINTON + C IF NOT TOGLPRN + 11DD 3C 0E C CMP AL,'N'-'@' + 11DF 74 2C C JZ PRINTOFF + C ENDIF + 11E1 3C 03 C CMP AL,'C'-'@' + 11E3 75 DE C JNZ RET18 + C ; Ctrl-C handler. + C ; "^C" and CR/LF is printed. Then the user registers are restored and the + C ; user CTRL-C handler is executed. At this point the top of the stack has + C ; 1) the interrupt return address should the user CTRL-C handler wish to + C ; allow processing to continue; 2) the original interrupt return address + C ; to the code that performed the function call in the first place. If the + C ; user CTRL-C handler wishes to continue, it must leave all registers +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-57 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; unchanged and IRET. The function that was interrupted will simply be + C ; repeated. + 11E5 B0 03 C MOV AL,3 ;Display "^C" + 11E7 E8 117D R C CALL BUFOUT + 11EA E8 105C R C CALL CRLF + 11ED FA C CLI ;Prepare to play with stack + 11EE 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 11F3 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] ;User stack now restored + 11F8 58 C POP AX + 11F9 5B C POP BX + 11FA 59 C POP CX + 11FB 5A C POP DX + 11FC 5E C POP SI + 11FD 5F C POP DI + 11FE 5D C POP BP + 11FF 1F C POP DS + 1200 07 C POP ES ;User registers now restored + 1201 CD 23 C INT CONTC ;Execute user Ctrl-C handler + 1203 E9 004F R C JMP COMMAND ;Repeat command otherwise + C + 1206 C PRINTON: + C ENDIF + C IF NOT TOGLPRN + 1206 2E: C6 06 002A R 01 C MOV CS:BYTE PTR [PFLAG],1 + 120C C3 C RET + C + 120D C PRINTOFF: + 120D 2E: C6 06 002A R 00 C MOV CS:BYTE PTR [PFLAG],0 + 1213 C3 C RET + C ENDIF + C + 1214 C CTRLOUT: + 1214 3C 0D C CMP AL,13 + 1216 74 20 C JZ ZERPOS + 1218 3C 08 C CMP AL,8 + 121A 74 25 C JZ BACKPOS + 121C 3C 09 C CMP AL,9 + 121E 75 1E C JNZ OUTCHJ + 1220 2E: A0 0028 R C MOV AL,CS:[CARPOS] + 1224 0C F8 C OR AL,0F8H + 1226 F6 D8 C NEG AL + 1228 C TAB: + 1228 51 C PUSH CX + 1229 8A C8 C MOV CL,AL + 122B B5 00 C MOV CH,0 + 122D E3 07 C JCXZ POPTAB + 122F C TABLP: + 122F B0 20 C MOV AL," " + 1231 E8 119F R C CALL OUT + 1234 E2 F9 C LOOP TABLP + 1236 C POPTAB: + 1236 59 C POP CX + 1237 C3 C RET19: RET + C + 1238 C ZERPOS: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-58 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1238 2E: C6 06 0028 R 00 C MOV CS:BYTE PTR [CARPOS],0 + 123E E9 11AC R C OUTCHJ: JMP OUTCH + C + 1241 C BACKPOS: + 1241 2E: FE 0E 0028 R C DEC CS:BYTE PTR [CARPOS] + 1246 E9 11AC R C JMP OUTCH + C + C + 1249 C CONSTAT: ;System call 11 + 1249 E8 11C4 R C CALL STATCHK + 124C B0 00 C MOV AL,0 + 124E 74 E7 C JZ RET19 + 1250 0C FF C OR AL,-1 + 1252 C3 C RET + C + C + 1253 C CONIN: ;System call 1 + 1253 E8 125C R C CALL IN + 1256 50 C PUSH AX + 1257 E8 119F R C CALL OUT + 125A 58 C POP AX + 125B C3 C RET + C + C + 125C C IN: ;System call 8 + 125C E8 11D4 R C CALL INCHK + 125F 74 FB C JZ IN + 1261 C3 C RET29: RET + C + 1262 C RAWIO: ;System call 6 + 1262 8A C2 C MOV AL,DL + 1264 3C FF C CMP AL,-1 + 1266 75 1D C JNZ RAWOUT + 1268 2E: C5 36 0131 R C LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area + 126D 9A 0003 ---- R C CALL FAR PTR BIOSSTAT + 1272 75 07 C JNZ RESFLG + 1274 80 4C 16 40 C OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag + 1278 32 C0 C XOR AL,AL + 127A C3 C RET + C + 127B C RESFLG: + 127B 80 64 16 BF C AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag + 127F C RAWINP: ;System call 7 + 127F 9A 0006 ---- R C CALL FAR PTR BIOSIN + 1284 C3 C RET + 1285 C RAWOUT: + 1285 9A 0009 ---- R C CALL FAR PTR BIOSOUT + 128A C3 C RET + C + 128B C LIST: ;System call 5 + 128B 8A C2 C MOV AL,DL + 128D C LISTOUT: + 128D 50 C PUSH AX + 128E E8 11C4 R C CALL STATCHK + 1291 58 C POP AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-59 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1292 9A 000C ---- R C CALL FAR PTR BIOSPRINT + 1297 C3 C RET20: RET + C + 1298 C PRTBUF: ;System call 9 + 1298 8B F2 C MOV SI,DX + 129A C OUTSTR: + 129A AC C LODSB + 129B 3C 24 C CMP AL,"$" + 129D 74 F8 C JZ RET20 + 129F E8 119F R C CALL OUT + 12A2 EB F6 C JMP SHORT OUTSTR + C + 12A4 C OUTMES: ;String output for internal messages + 12A4 2E: AC C LODS CS:BYTE PTR [SI] + 12A6 3C 24 C CMP AL,"$" + 12A8 74 ED C JZ RET20 + 12AA E8 119F R C CALL OUT + 12AD EB F5 C JMP SHORT OUTMES + C + C + 12AF C MAKEFCB: ;Interrupt call 41 + = 0002 C DRVBIT EQU 2 + = 0004 C NAMBIT EQU 4 + = 0008 C EXTBIT EQU 8 + 12AF B2 00 C MOV DL,0 ;Flag--not ambiguous file name + 12B1 A8 02 C TEST AL,DRVBIT ;Use current drive field if default? + 12B3 75 04 C JNZ DEFDRV + 12B5 26: C6 05 00 C MOV BYTE PTR ES:[DI],0 ;No - use default drive + 12B9 C DEFDRV: + 12B9 47 C INC DI + 12BA B9 0008 C MOV CX,8 + 12BD A8 04 C TEST AL,NAMBIT ;Use current name fiels as defualt? + 12BF 93 C XCHG AX,BX ;Save bits in BX + 12C0 B0 20 C MOV AL," " + 12C2 74 04 C JZ FILLB ;If not, go fill with blanks + 12C4 03 F9 C ADD DI,CX + 12C6 33 C9 C XOR CX,CX ;Don't fill any + 12C8 C FILLB: + 12C8 F3/ AA C REP STOSB + 12CA B1 03 C MOV CL,3 + 12CC F6 C3 08 C TEST BL,EXTBIT ;Use current extension as default + 12CF 74 04 C JZ FILLB2 + 12D1 03 F9 C ADD DI,CX + 12D3 33 C9 C XOR CX,CX + 12D5 C FILLB2: + 12D5 F3/ AA C REP STOSB + 12D7 91 C XCHG AX,CX ;Put zero in AX + 12D8 AB C STOSW + 12D9 AB C STOSW ;Initialize two words after to zero + 12DA 83 EF 10 C SUB DI,16 ;Point back at start + 12DD F6 C3 01 C TEST BL,1 ;Scan off separators if not zero + 12E0 74 09 C JZ SKPSPC + 12E2 E8 1352 R C CALL SCANB ;Peel off blanks and tabs + 12E5 E8 137F R C CALL DELIM ;Is it a one-time-only delimiter? + 12E8 75 04 C JNZ NOSCAN +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-60 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 12EA 46 C INC SI ;Skip over the delimiter + 12EB C SKPSPC: + 12EB E8 1352 R C CALL SCANB ;Always kill preceding blanks and tabs + 12EE C NOSCAN: + 12EE E8 135A R C CALL GETLET + 12F1 76 16 C JBE NODRV ;Quit if termination character + 12F3 80 3C 3A C CMP BYTE PTR[SI],":" ;Check for potential drive specifier + 12F6 75 11 C JNZ NODRV + 12F8 46 C INC SI ;Skip over colon + 12F9 2C 40 C SUB AL,"@" ;Convert drive letter to binary drive number + 12FB 76 07 C JBE BADDRV ;Valid drive numbers are 1-15 + 12FD 2E: 3A 06 002C R C CMP AL,CS:[NUMDRV] + 1302 76 02 C JBE HAVDRV + 1304 C BADDRV: + 1304 B2 FF C MOV DL,-1 + 1306 C HAVDRV: + 1306 AA C STOSB ;Put drive specifier in first byte + 1307 46 C INC SI + 1308 4F C DEC DI ;Counteract next two instructions + 1309 C NODRV: + 1309 4E C DEC SI ;Back up + 130A 47 C INC DI ;Skip drive byte + 130B B9 0008 C MOV CX,8 + 130E E8 132C R C CALL GETWORD ;Get 8-letter file name + 1311 80 3C 2E C CMP BYTE PTR [SI],"." + 1314 75 07 C JNZ NODOT + 1316 46 C INC SI ;Skip over dot if present + 1317 B9 0003 C MOV CX,3 ;Get 3-letter extension + 131A E8 1332 R C CALL MUSTGETWORD + 131D C NODOT: + 131D 2E: C5 1E 0131 R C LDS BX,CS:DWORD PTR [SPSAVE] + 1322 89 77 08 C MOV [BX.SISAVE],SI + 1325 8A C2 C MOV AL,DL + 1327 C3 C RET + C + 1328 C NONAM: + 1328 03 F9 C ADD DI,CX + 132A 4E C DEC SI + 132B C3 C RET + C + 132C C GETWORD: + 132C E8 135A R C CALL GETLET + 132F 76 F7 C JBE NONAM ;Exit if invalid character + 1331 4E C DEC SI + 1332 C MUSTGETWORD: + 1332 E8 135A R C CALL GETLET + 1335 76 15 C JBE FILLNAM + 1337 E3 F9 C JCXZ MUSTGETWORD + 1339 49 C DEC CX + 133A 3C 2A C CMP AL,"*" ;Check for ambiguous file specifier + 133C 75 04 C JNZ NOSTAR + 133E B0 3F C MOV AL,"?" + 1340 F3/ AA C REP STOSB + 1342 C NOSTAR: + 1342 AA C STOSB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-61 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1343 3C 3F C CMP AL,"?" + 1345 75 EB C JNZ MUSTGETWORD + 1347 80 CA 01 C OR DL,1 ;Flag ambiguous file name + 134A EB E6 C JMP MUSTGETWORD + 134C C FILLNAM: + 134C B0 20 C MOV AL," " + 134E F3/ AA C REP STOSB + 1350 4E C DEC SI + 1351 C3 C RET21: RET + C + 1352 C SCANB: + 1352 AC C LODSB + 1353 E8 138F R C CALL SPCHK + 1356 74 FA C JZ SCANB + 1358 4E C DEC SI + 1359 C3 C RET + C + 135A C GETLET: + C ;Get a byte from [SI], convert it to upper case, and compare for delimiter. + C ;ZF set if a delimiter, CY set if a control character (other than TAB). + 135A AC C LODSB + 135B 24 7F C AND AL,7FH + 135D 3C 61 C CMP AL,"a" + 135F 72 06 C JB CHK + 1361 3C 7A C CMP AL,"z" + 1363 77 02 C JA CHK + 1365 2C 20 C SUB AL,20H ;Convert to upper case + 1367 C CHK: + 1367 3C 2E C CMP AL,"." + 1369 74 E6 C JZ RET21 + 136B 3C 22 C CMP AL,'"' + 136D 74 E2 C JZ RET21 + 136F 3C 2F C CMP AL,"/" + 1371 74 DE C JZ RET21 + 1373 3C 5B C CMP AL,"[" + 1375 74 DA C JZ RET21 + 1377 3C 5D C CMP AL,"]" + 1379 74 D6 C JZ RET21 + C + C ENDIF + 137B 3C 3A C CMP AL,":" ;Allow ":" as separator in IBM version + 137D 74 D2 C JZ RET21 + C IF NOT IBM + 137F C DELIM: + C ENDIF + C + 137F 3C 2B C CMP AL,"+" + 1381 74 12 C JZ RET101 + 1383 3C 3D C CMP AL,"=" + 1385 74 0E C JZ RET101 + 1387 3C 3B C CMP AL,";" + 1389 74 0A C JZ RET101 + 138B 3C 2C C CMP AL,"," + 138D 74 06 C JZ RET101 + 138F C SPCHK: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-62 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 138F 3C 09 C CMP AL,9 ;Filter out tabs too + 1391 74 02 C JZ RET101 + C ;WARNING! " " MUST be the last compare + 1393 3C 20 C CMP AL," " + 1395 C3 C RET101: RET + C + 1396 C SETVECT: ; Interrupt call 37 + 1396 33 DB C XOR BX,BX + 1398 8E C3 C MOV ES,BX + 139A 8A D8 C MOV BL,AL + 139C D1 E3 C SHL BX,1 + 139E D1 E3 C SHL BX,1 + 13A0 26: 89 17 C MOV ES:[BX],DX + 13A3 26: 8C 5F 02 C MOV ES:[BX+2],DS + 13A7 C3 C RET + C + C + 13A8 C NEWBASE: ; Interrupt call 38 + 13A8 8E C2 C MOV ES,DX + 13AA 2E: C5 36 0131 R C LDS SI,CS:DWORD PTR [SPSAVE] + 13AF 8E 5C 14 C MOV DS,[SI.CSSAVE] + 13B2 33 F6 C XOR SI,SI + 13B4 8B FE C MOV DI,SI + 13B6 A1 0002 C MOV AX,DS:[2] + 13B9 B9 0080 C MOV CX,80H + 13BC F3/ A5 C REP MOVSW + C + 13BE C SETMEM: + C + C ; Inputs: + C ; AX = Size of memory in paragraphs + C ; DX = Segment + C ; Function: + C ; Completely prepares a program base at the + C ; specified segment. + C ; Outputs: + C ; DS = DX + C ; ES = DX + C ; [0] has INT 20H + C ; [2] = First unavailable segment ([ENDMEM]) + C ; [5] to [9] form a long call to the entry point + C ; [10] to [13] have exit address (from INT 22H) + C ; [14] to [17] have ctrl-C exit address (from INT 23H) + C ; [18] to [21] have fatal error address (from INT 24H) + C ; DX,BP unchanged. All other registers destroyed. + C + 13BE 33 C9 C XOR CX,CX + 13C0 8E D9 C MOV DS,CX + 13C2 8E C2 C MOV ES,DX + 13C4 BE 0088 C MOV SI,EXIT + 13C7 BF 000A C MOV DI,SAVEXIT + 13CA A5 C MOVSW + 13CB A5 C MOVSW + 13CC A5 C MOVSW + 13CD A5 C MOVSW +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-63 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 13CE A5 C MOVSW + 13CF A5 C MOVSW + 13D0 26: A3 0002 C MOV ES:[2],AX + 13D4 2B C2 C SUB AX,DX + 13D6 3D 0FFF C CMP AX,MAXDIF + 13D9 76 03 C JBE HAVDIF + 13DB B8 0FFF C MOV AX,MAXDIF + 13DE C HAVDIF: + 13DE BB 000C C MOV BX,ENTRYPOINTSEG + 13E1 2B D8 C SUB BX,AX + 13E3 D1 E0 C SHL AX,1 + 13E5 D1 E0 C SHL AX,1 + 13E7 D1 E0 C SHL AX,1 + 13E9 D1 E0 C SHL AX,1 + 13EB 8E DA C MOV DS,DX + 13ED A3 0006 C MOV DS:[6],AX + 13F0 89 1E 0008 C MOV DS:[8],BX + 13F4 C7 06 0000 20CD C MOV DS:[0],20CDH ;"INT INTTAB" + 13FA C6 06 0005 9A C MOV DS:(BYTE PTR [5]),LONGCALL + 13FF C3 C RET + C + 1400 C DATE16: + 1400 51 C PUSH CX + 1401 E8 1427 R C CALL READTIME + 1404 D0 E1 C SHL CL,1 ;Minutes to left part of byte + 1406 D0 E1 C SHL CL,1 + 1408 D1 E1 C SHL CX,1 ;Push hours and minutes to left end + 140A D1 E1 C SHL CX,1 + 140C D1 E1 C SHL CX,1 + 140E D0 EE C SHR DH,1 ;Count every two seconds + 1410 0A CE C OR CL,DH ;Combine seconds with hours and minutes + 1412 8B D1 C MOV DX,CX + 1414 59 C POP CX + 1415 A1 0044 R C MOV AX,WORD PTR [MONTH] ;Fetch month and year + 1418 D0 E0 C SHL AL,1 ;Push month to left to make room for day + 141A D0 E0 C SHL AL,1 + 141C D0 E0 C SHL AL,1 + 141E D0 E0 C SHL AL,1 + 1420 D1 E0 C SHL AX,1 + 1422 0A 06 0043 R C OR AL,[DAY] + 1426 C3 C RET22: RET + C + = 05B5 C FOURYEARS EQU 3*365+366 + C + 1427 C READTIME: + C ;Gets time in CX:DX. Figures new date if it has changed. + C ;Uses AX, CX, DX. + 1427 9A 0024 ---- R C CALL FAR PTR BIOSGETTIME + 142C 3B 06 0047 R C CMP AX,[DAYCNT] ;See if day count is the same + 1430 74 F4 C JZ RET22 + 1432 3D AB36 C CMP AX,FOURYEARS*30 ;Number of days in 120 years + 1435 73 EF C JAE RET22 ;Ignore if too large + 1437 A3 0047 R C MOV [DAYCNT],AX + 143A 56 C PUSH SI + 143B 51 C PUSH CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-64 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 143C 52 C PUSH DX ;Save time + 143D 33 D2 C XOR DX,DX + 143F B9 05B5 C MOV CX,FOURYEARS ;Number of days in 4 years + 1442 F7 F1 C DIV CX ;Compute number of 4-year units + 1444 D1 E0 C SHL AX,1 + 1446 D1 E0 C SHL AX,1 + 1448 D1 E0 C SHL AX,1 ;Multiply by 8 (no. of half-years) + 144A 8B C8 C MOV CX,AX ;<240 implies AH=0 + 144C BE 1492 R C MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year + 144F E8 1475 R C CALL DSLIDE ;Find out which of four years we're in + 1452 D1 E9 C SHR CX,1 ;Convert half-years to whole years + 1454 73 04 C JNC SK ;Extra half-year? + 1456 81 C2 00C8 C ADD DX,200 + 145A C SK: + 145A E8 1481 R C CALL SETYEAR + 145D B1 01 C MOV CL,1 ;At least at first month in year + 145F BE 149A R C MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + 1462 E8 1475 R C CALL DSLIDE ;Find out which month we're in + 1465 88 0E 0044 R C MOV [MONTH],CL + 1469 42 C INC DX ;Remainder is day of month (start with one) + 146A 88 16 0043 R C MOV [DAY],DL + 146E E8 1529 R C CALL WKDAY ;Set day of week + 1471 5A C POP DX + 1472 59 C POP CX + 1473 5E C POP SI + 1474 C3 C RET23: RET + C + 1475 C DSLIDE: + 1475 B4 00 C MOV AH,0 + 1477 C DSLIDE1: + 1477 AC C LODSB ;Get count of days + 1478 3B D0 C CMP DX,AX ;See if it will fit + 147A 72 F8 C JB RET23 ;If not, done + 147C 2B D0 C SUB DX,AX + 147E 41 C INC CX ;Count one more month/year + 147F EB F6 C JMP SHORT DSLIDE1 + C + 1481 C SETYEAR: + C ;Set year with value in CX. Adjust length of February for this year. + 1481 88 0E 0045 R C MOV BYTE PTR [YEAR],CL + 1485 C CHKYR: + 1485 F6 C1 03 C TEST CL,3 ;Check for leap year + 1488 B0 1C C MOV AL,28 + 148A 75 02 C JNZ SAVFEB ;28 days if no leap year + 148C FE C0 C INC AL ;Add leap day + 148E C SAVFEB: + 148E A2 149B R C MOV [MONTAB+1],AL ;Store for February + 1491 C3 C RET + C + C ;Days in year + 1492 C8 A6 C YRTAB DB 200,166 ;Leap year + 1494 C8 A5 C DB 200,165 + 1496 C8 A5 C DB 200,165 + 1498 C8 A5 C DB 200,165 + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-65 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ;Days of each month + 149A 1F C MONTAB DB 31 ;January + 149B 1C C DB 28 ;February--reset each time year changes + 149C 1F C DB 31 ;March + 149D 1E C DB 30 ;April + 149E 1F C DB 31 ;May + 149F 1E C DB 30 ;June + 14A0 1F C DB 31 ;July + 14A1 1F C DB 31 ;August + 14A2 1E C DB 30 ;September + 14A3 1F C DB 31 ;October + 14A4 1E C DB 30 ;November + 14A5 1F C DB 31 ;December + C + 14A6 C GETDATE: ;Function call 42 + 14A6 0E C PUSH CS + 14A7 1F C POP DS + 14A8 E8 1427 R C CALL READTIME ;Check for rollover to next day + 14AB A1 0045 R C MOV AX,[YEAR] + 14AE 8B 1E 0043 R C MOV BX,WORD PTR [DAY] + 14B2 C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + 14B6 89 5C 06 C MOV [SI.DXSAVE],BX ;DH=month, DL=day + 14B9 05 07BC C ADD AX,1980 ;Put bias back + 14BC 89 44 04 C MOV [SI.CXSAVE],AX ;CX=year + 14BF 2E: A0 0049 R C MOV AL,CS:[WEEKDAY] + 14C3 C3 C RET24: RET + C + 14C4 C SETDATE: ;Function call 43 + 14C4 B0 FF C MOV AL,-1 ;Be ready to flag error + 14C6 81 E9 07BC C SUB CX,1980 ;Fix bias in year + 14CA 72 F7 C JC RET24 ;Error if not big enough + 14CC 83 F9 77 C CMP CX,119 ;Year must be less than 2100 + 14CF 77 F2 C JA RET24 + 14D1 0A F6 C OR DH,DH + 14D3 74 EE C JZ RET24 + 14D5 0A D2 C OR DL,DL + 14D7 74 EA C JZ RET24 ;Error if either month or day is 0 + 14D9 80 FE 0C C CMP DH,12 ;Check against max. month + 14DC 77 E5 C JA RET24 + 14DE 0E C PUSH CS + 14DF 1F C POP DS + 14E0 E8 1485 R C CALL CHKYR ;Set Feb. up for new year + 14E3 8A C6 C MOV AL,DH + 14E5 BB 1499 R C MOV BX,OFFSET DOSGROUP:MONTAB-1 + 14E8 D7 C XLAT ;Look up days in month + 14E9 3A C2 C CMP AL,DL + 14EB B0 FF C MOV AL,-1 ;Restore error flag, just in case + 14ED 72 D4 C JB RET24 ;Error if too many days + 14EF E8 1481 R C CALL SETYEAR + 14F2 89 16 0043 R C MOV WORD PTR [DAY],DX ;Set both day and month + 14F6 D1 E9 C SHR CX,1 + 14F8 D1 E9 C SHR CX,1 + 14FA B8 05B5 C MOV AX,FOURYEARS + 14FD 8B DA C MOV BX,DX + 14FF F7 E1 C MUL CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-66 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1501 8A 0E 0045 R C MOV CL,BYTE PTR [YEAR] + 1505 80 E1 03 C AND CL,3 + 1508 BE 1492 R C MOV SI,OFFSET DOSGROUP:YRTAB + 150B 8B D0 C MOV DX,AX + 150D D1 E1 C SHL CX,1 ;Two entries per year, so double count + 150F E8 153C R C CALL DSUM ;Add up the days in each year + 1512 8A CF C MOV CL,BH ;Month of year + 1514 BE 149A R C MOV SI,OFFSET DOSGROUP:MONTAB + 1517 49 C DEC CX ;Account for months starting with one + 1518 E8 153C R C CALL DSUM ;Add up days in each month + 151B 8A CB C MOV CL,BL ;Day of month + 151D 49 C DEC CX ;Account for days starting with one + 151E 03 D1 C ADD DX,CX ;Add in to day total + 1520 92 C XCHG AX,DX ;Get day count in AX + 1521 A3 0047 R C MOV [DAYCNT],AX + 1524 9A 001E ---- R C CALL FAR PTR BIOSSETDATE + 1529 C WKDAY: + 1529 A1 0047 R C MOV AX,[DAYCNT] + 152C 33 D2 C XOR DX,DX + 152E B9 0007 C MOV CX,7 + 1531 40 C INC AX + 1532 40 C INC AX ;First day was Tuesday + 1533 F7 F1 C DIV CX ;Compute day of week + 1535 88 16 0049 R C MOV [WEEKDAY],DL + 1539 32 C0 C XOR AL,AL ;Flag OK + 153B C3 C RET25: RET + C + 153C C DSUM: + 153C B4 00 C MOV AH,0 + 153E E3 FB C JCXZ RET25 + 1540 C DSUM1: + 1540 AC C LODSB + 1541 03 D0 C ADD DX,AX + 1543 E2 FB C LOOP DSUM1 + 1545 C3 C RET + C + 1546 C GETTIME: ;Function call 44 + 1546 0E C PUSH CS + 1547 1F C POP DS + 1548 E8 1427 R C CALL READTIME + 154B C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + 154F 89 54 06 C MOV [SI.DXSAVE],DX + 1552 89 4C 04 C MOV [SI.CXSAVE],CX + 1555 32 C0 C XOR AL,AL + 1557 C3 C RET26: RET + C + 1558 C SETTIME: ;Function call 45 + C ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec. + 1558 B0 FF C MOV AL,-1 ;Flag in case of error + 155A 80 FD 18 C CMP CH,24 ;Check hours + 155D 73 F8 C JAE RET26 + 155F 80 F9 3C C CMP CL,60 ;Check minutes + 1562 73 F3 C JAE RET26 + 1564 80 FE 3C C CMP DH,60 ;Check seconds + 1567 73 EE C JAE RET26 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-67 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1569 80 FA 64 C CMP DL,100 ;Check 1/100's + 156C 73 E9 C JAE RET26 + 156E 9A 0021 ---- R C CALL FAR PTR BIOSSETTIME + 1573 32 C0 C XOR AL,AL + 1575 C3 C RET + C + C + C ; Default handler for division overflow trap + 1576 C DIVOV: + 1576 56 C PUSH SI + 1577 50 C PUSH AX + 1578 BE 0014 R C MOV SI,OFFSET DOSGROUP:DIVMES + 157B E8 12A4 R C CALL OUTMES + 157E 58 C POP AX + 157F 5E C POP SI + 1580 CD 23 C INT 23H ;Use Ctrl-C abort on divide overflow + 1582 CF C IRET + C + = 1583 C CODSIZ EQU $-CODSTRT ;Size of code segment + 1583 C CODE ENDS + C + C + C ;***** DATA AREA ***** + 0000 C CONSTANTS SEGMENT BYTE + 0000 C ORG 0 + = 0000 C CONSTRT EQU $ ;Start of constants segment + C + 0000 C IONAME: + C IF NOT IBM + 0000 50 52 4E 20 4C 53 C DB "PRN ","LST ","NUL ","AUX ","CON " + 54 20 4E 55 4C 20 C + 41 55 58 20 43 4F C + 4E 20 C + C ENDIF + C ENDIF + 0014 0D 0A 44 69 76 69 C DIVMES DB 13,10,"Divide overflow",13,10,"$" + 64 65 20 6F 76 65 C + 72 66 6C 6F 77 0D C + 0A 24 C + 0028 00 C CARPOS DB 0 + 0029 00 C STARTPOS DB 0 + 002A 00 C PFLAG DB 0 + 002B 00 C DIRTYDIR DB 0 ;Dirty buffer flag + 002C 00 C NUMDRV DB 0 ;Number of drives + 002D ?? C NUMIO DB ? ;Number of disk tables + 002E 00 C VERFLG DB 0 ;Initialize with verify off + 002F 0000 C CONTPOS DW 0 + 0031 0080 C DMAADD DW 80H ;User's disk transfer address (disp/seg) + 0033 ???? C DW ? + 0035 ???? C ENDMEM DW ? + 0037 0000 C MAXSEC DW 0 + 0039 ???? C BUFFER DW ? + 003B 0000 C BUFSECNO DW 0 + 003D FF C BUFDRVNO DB -1 + 003E 00 C DIRTYBUF DB 0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-68 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 003F ???? C BUFDRVBP DW ? + 0041 FFFF C DIRBUFID DW -1 + 0043 00 C DAY DB 0 + 0044 00 C MONTH DB 0 + 0045 0000 C YEAR DW 0 + 0047 FFFF C DAYCNT DW -1 + 0049 00 C WEEKDAY DB 0 + 004A 00 C CURDRV DB 0 ;Default to drive A + 004B 0000 C DRVTAB DW 0 ;Address of start of DPBs + = 15D0 C DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments + 004D C CONSTANTS ENDS + C + 0000 C DATA SEGMENT WORD + C ; Init code overlaps with data area below + C + 0000 C ORG 0 + 0000 80 [ C INBUF DB 128 DUP (?) + ?? C + ] C + C + 0080 83 [ C CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer + ?? C + ] C + C + 0103 ???? C LASTENT DW ? + 0105 04 [ C EXITHOLD DB 4 DUP (?) + ?? C + ] C + C + 0109 ???? C FATBASE DW ? + 010B 0B [ C NAME1 DB 11 DUP (?) ;File name buffer + ?? C + ] C + C + 0116 ?? C ATTRIB DB ? + 0117 0B [ C NAME2 DB 11 DUP (?) + ?? C + ] C + C + 0122 0C [ C NAME3 DB 12 DUP (?) + ?? C + ] C + C + 012E ?? C EXTFCB DB ? + C ;WARNING - the following two items are accessed as a word + 012F ?? C CREATING DB ? + 0130 ?? C DELALL DB ? + 0131 C TEMP LABEL WORD + 0131 ???? C SPSAVE DW ? + 0133 ???? C SSSAVE DW ? + 0135 ???? C CONTSTK DW ? + 0137 ?? C SECCLUSPOS DB ? ;Position of first sector within cluster + 0138 ?? C DSKERR DB ? + 0139 ?? C TRANS DB ? + 013A ?? C PREREAD DB ? ;0 means preread; 1 means optional +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-69 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 013B ?? C READOP DB ? + 013C ?? C THISDRV DB ? + C + 013D 90 C EVEN + 013E ???? C FCB DW ? ;Address of user FCB + 0140 ???? C NEXTADD DW ? + 0142 04 [ C RECPOS DB 4 DUP (?) + ?? C + ] C + C + 0146 ???? C RECCNT DW ? + 0148 ???? C LASTPOS DW ? + 014A ???? C CLUSNUM DW ? + 014C ???? C SECPOS DW ? ;Position of first sector accessed + 014E ???? C VALSEC DW ? ;Number of valid (previously written) sectors + 0150 ???? C BYTSECPOS DW ? ;Position of first byte within sector + 0152 04 [ C BYTPOS DB 4 DUP (?) ;Byte position in file of access + ?? C + ] C + C + 0156 ???? C BYTCNT1 DW ? ;No. of bytes in first sector + 0158 ???? C BYTCNT2 DW ? ;No. of bytes in last sector + 015A ???? C SECCNT DW ? ;No. of whole sectors + 015C ???? C ENTFREE DW ? + C + 015E 80 [ C DB 80H DUP (?) ;Stack space + ?? C + ] C + C + 01DE C IOSTACK LABEL BYTE + 01DE 80 [ C DB 80H DUP (?) + ?? C + ] C + C + 025E C DSKSTACK LABEL BYTE + C + C ENDIF + C + 025E C DIRBUF LABEL WORD + C + C ;Init code below overlaps with data area above + C + 0000 C ORG 0 + C + 0000 C MOVFAT: + C ;This section of code is safe from being overwritten by block move + 0000 F3/ A4 C REP MOVS BYTE PTR [DI],[SI] + 0002 FC C CLD + 0003 26: 89 16 0033 R C MOV ES:[DMAADD+2],DX + 0008 8B 36 004B R C MOV SI,[DRVTAB] ;Address of first DPB + 000C B0 FF C MOV AL,-1 + 000E 8A 0E 002D R C MOV CL,[NUMIO] ;Number of DPBs + 0012 C FLGFAT: + 0012 26: 8B 7C 12 C MOV DI,ES:[SI.FAT] ;get pointer to FAT + 0016 4F C DEC DI ;Point to dirty byte +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-70 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0017 AA C STOSB ;Flag as unused + 0018 83 C6 14 C ADD SI,DPBSIZ ;Point to next DPB + 001B E2 F5 C LOOP FLGFAT + 001D A1 0035 R C MOV AX,[ENDMEM] + 0020 E8 13BE R C CALL SETMEM ;Set up segment + C + 0023 C XXX PROC FAR + 0023 CB C RET + 0024 C XXX ENDP + C + 0024 C DOSINIT: + 0024 FA C CLI + 0025 FC C CLD + 0026 0E C PUSH CS + 0027 07 C POP ES + 0028 26: 89 16 0035 R C MOV ES:[ENDMEM],DX + 002D AC C LODSB ;Get no. of drives & no. of I/O drivers + 002E 26: A2 002D R C MOV ES:[NUMIO],AL + 0032 BF 0247 R C MOV DI,OFFSET DOSGROUP:MEMSTRT + 0035 C PERDRV: + 0035 8B EF C MOV BP,DI + 0037 26: A0 0246 R C MOV AL,ES:[DRVCNT] + 003B AA C STOSB ;DEVNUM + 003C AC C LODSB ;Physical unit no. + 003D AA C STOSB ;DRVNUM + 003E 3C 0F C CMP AL,15 + 0040 77 5C C JA BADINIT + 0042 98 C CBW ;Index into FAT size table + 0043 D1 E0 C SHL AX,1 + 0045 05 0226 R C ADD AX,OFFSET DOSGROUP:FATSIZTAB + 0048 93 C XCHG BX,AX + 0049 AD C LODSW ;Pointer to DPT + 004A 56 C PUSH SI + 004B 8B F0 C MOV SI,AX + 004D AD C LODSW + 004E AB C STOSW ;SECSIZ + 004F 8B D0 C MOV DX,AX + 0051 26: 3B 06 0037 R C CMP AX,ES:[MAXSEC] + 0056 76 04 C JBE NOTMAX + 0058 26: A3 0037 R C MOV ES:[MAXSEC],AX + 005C C NOTMAX: + 005C AC C LODSB + 005D FE C8 C DEC AL + 005F AA C STOSB ;CLUSMSK + 0060 74 09 C JZ HAVSHFT + 0062 98 C CBW + 0063 C FIGSHFT: + 0063 FE C4 C INC AH + 0065 D0 F8 C SAR AL,1 + 0067 75 FA C JNZ FIGSHFT + 0069 8A C4 C MOV AL,AH + 006B C HAVSHFT: + 006B AA C STOSB ;CLUSSHFT + 006C A5 C MOVSW ;FIRFAT (= number of reserved sectors) + 006D A4 C MOVSB ;FATCNT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-71 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 006E A5 C MOVSW ;MAXENT + 006F 8B C2 C MOV AX,DX ;SECSIZ again + 0071 B1 05 C MOV CL,5 + 0073 D3 E8 C SHR AX,CL + 0075 8B C8 C MOV CX,AX ;Directory entries per sector + 0077 48 C DEC AX + 0078 26: 03 46 09 C ADD AX,ES:[BP.MAXENT] + 007C 33 D2 C XOR DX,DX + 007E F7 F1 C DIV CX + 0080 AB C STOSW ;DIRSEC (temporarily) + 0081 A5 C MOVSW ;DSKSIZ (temporarily) + 0082 C FNDFATSIZ: + 0082 B0 01 C MOV AL,1 + 0084 BA 0001 C MOV DX,1 + 0087 C GETFATSIZ: + 0087 52 C PUSH DX + 0088 E8 01E5 R C CALL FIGFATSIZ + 008B 5A C POP DX + 008C 3A C2 C CMP AL,DL ;Compare newly computed FAT size with trial + 008E 74 16 C JZ HAVFATSIZ ;Has sequence converged? + 0090 3A C6 C CMP AL,DH ;Compare with previous trial + 0092 8A F2 C MOV DH,DL + 0094 8A D0 C MOV DL,AL ;Shuffle trials + 0096 75 EF C JNZ GETFATSIZ ;Continue iterations if not oscillating + 0098 26: FF 4E 0D C DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations + 009C EB E4 C JMP SHORT FNDFATSIZ ;Try again + C + 009E C BADINIT: + 009E BE 0213 R C MOV SI,OFFSET DOSGROUP:BADMES + 00A1 E8 12A4 R C CALL OUTMES + 00A4 FB C STI + 00A5 F4 C HLT + C + 00A6 C HAVFATSIZ: + 00A6 AA C STOSB ;FATSIZ + 00A7 26: F6 66 08 C MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs + 00AB 26: 03 46 06 C ADD AX,ES:[BP.FIRFAT] + 00AF AB C STOSW ;FIRDIR + 00B0 26: 03 46 0B C ADD AX,ES:[BP.DIRSEC] + 00B4 26: 89 46 0B C MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC + 00B8 E8 01F1 R C CALL FIGMAX + 00BB 26: 89 4E 0D C MOV ES:[BP.MAXCLUS],CX + 00BF 8B C3 C MOV AX,BX ;Pointer into FAT size table + 00C1 AB C STOSW ;Allocate space for FAT pointer + 00C2 26: 8A 46 0F C MOV AL,ES:[BP.FATSIZ] + 00C6 32 E4 C XOR AH,AH + 00C8 26: F7 66 02 C MUL ES:[BP.SECSIZ] + 00CC 26: 3B 07 C CMP AX,ES:[BX] ;Bigger than already allocated + 00CF 76 03 C JBE SMFAT + 00D1 26: 89 07 C MOV ES:[BX],AX + 00D4 C SMFAT: + 00D4 5E C POP SI ;Restore pointer to init. table + 00D5 26: A0 0246 R C MOV AL,ES:[DRVCNT] + 00D9 FE C0 C INC AL + 00DB 26: A2 0246 R C MOV ES:[DRVCNT],AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-72 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 00DF 26: 3A 06 002D R C CMP AL,ES:[NUMIO] + 00E4 73 05 C JAE CONTINIT + 00E6 E9 0035 R C JMP PERDRV + C + 00E9 C BADINITJ: + 00E9 EB B3 C JMP BADINIT + C + 00EB C CONTINIT: + 00EB 0E C PUSH CS + 00EC 1F C POP DS + C ;Calculate true address of buffers, FATs, free space + 00ED 8B 2E 0037 R C MOV BP,[MAXSEC] + 00F1 B8 025E R C MOV AX,OFFSET DOSGROUP:DIRBUF + 00F4 03 C5 C ADD AX,BP + 00F6 A3 0039 R C MOV [BUFFER],AX ;Start of buffer + 00F9 03 C5 C ADD AX,BP + 00FB A3 004B R C MOV [DRVTAB],AX ;Start of DPBs + 00FE D1 E5 C SHL BP,1 ;Two sectors - directory and buffer + 0100 03 EF C ADD BP,DI ;Allocate buffer space + 0102 81 C5 0017 C ADD BP,ADJFAC ;True address of FATs + 0106 55 C PUSH BP + 0107 BE 0226 R C MOV SI,OFFSET DOSGROUP:FATSIZTAB + 010A 8B FE C MOV DI,SI + 010C B9 0010 C MOV CX,16 + 010F C TOTFATSIZ: + 010F 45 C INC BP ;Add one for Dirty byte + 0110 45 C INC BP ;Add one for I/O device number + 0111 AD C LODSW ;Get size of this FAT + 0112 95 C XCHG AX,BP + 0113 AB C STOSW ;Save address of this FAT + 0114 03 E8 C ADD BP,AX ;Compute size of next FAT + 0116 3B C5 C CMP AX,BP ;If size was zero done + 0118 E0 F5 C LOOPNZ TOTFATSIZ + 011A B0 0F C MOV AL,15 + 011C 2A C1 C SUB AL,CL ;Compute number of FATs used + 011E A2 002C R C MOV [NUMDRV],AL + 0121 33 C0 C XOR AX,AX ;Set zero flag + 0123 F3/ AF C REPZ SCASW ;Make sure all other entries are zero + 0125 75 C2 C JNZ BADINITJ + 0127 83 C5 0F C ADD BP,15 ;True start of free space + 012A B1 04 C MOV CL,4 + 012C D3 ED C SHR BP,CL ;First free segment + 012E 8C CA C MOV DX,CS + 0130 03 D5 C ADD DX,BP + 0132 BB 000F C MOV BX,0FH + 0135 8B 0E 0035 R C MOV CX,[ENDMEM] + 0139 83 F9 01 C CMP CX,1 ;Use memory scan? + 013C 75 15 C JNZ SETEND + 013E 8B CA C MOV CX,DX ;Start scanning just after DOS + 0140 C MEMSCAN: + 0140 41 C INC CX + 0141 74 10 C JZ SETEND + 0143 8E D9 C MOV DS,CX + 0145 8A 07 C MOV AL,[BX] + 0147 F6 D0 C NOT AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-73 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0149 88 07 C MOV [BX],AL + 014B 3A 07 C CMP AL,[BX] + 014D F6 D0 C NOT AL + 014F 88 07 C MOV [BX],AL + 0151 74 ED C JZ MEMSCAN + 0153 C SETEND: + C ENDIF + C IF NOT HIGHMEM + 0153 8C CD C MOV BP,CS + C ENDIF + C ; BP has segment of DOS (whether to load high or run in place) + C ; DX has program segment (whether after DOS or overlaying DOS) + C ; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) + 0155 2E: 89 0E 0035 R C MOV CS:[ENDMEM],CX + C ENDIF + 015A 33 C0 C XOR AX,AX + 015C 8E D8 C MOV DS,AX + 015E 8E C0 C MOV ES,AX + 0160 BF 0080 C MOV DI,INTBASE + 0163 B8 004B R C MOV AX,OFFSET DOSGROUP:QUIT + 0166 AB C STOSW ;Set abort address--displacement + 0167 8B C5 C MOV AX,BP + 0169 C6 06 00C0 EA C MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP + 016E C7 06 00C1 0057 R C MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY + 0174 A3 00C3 C MOV WORD PTR DS:[ENTRYPOINT+3],AX + 0177 C7 06 0000 1576 R C MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address + 017D A3 0002 C MOV DS:[2],AX + 0180 B9 0009 C MOV CX,9 + 0183 F3/ AB C REP STOSW ;Set 5 segments (skip 2 between each) + 0185 C7 06 0084 004F R C MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND + 018B C7 06 008C 0056 R C MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit + 0191 C7 06 0090 0056 R C MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit + 0197 B8 0015 R C MOV AX,OFFSET BIOSREAD + 019A AB C STOSW + 019B B8 0040 C MOV AX,BIOSSEG + 019E AB C STOSW + 019F AB C STOSW ;Add 2 to DI + 01A0 AB C STOSW + 01A1 C7 06 0098 0018 R C MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE + 01A7 C7 06 0088 0100 C MOV WORD PTR DS:[EXIT],100H + 01AD 89 16 008A C MOV WORD PTR DS:[EXIT+2],DX + C IF NOT IBM + 01B1 BE 0010 R C MOV SI,OFFSET DOSGROUP:HEADER + 01B4 E8 12A4 R C CALL OUTMES + C ENDIF + 01B7 0E C PUSH CS + 01B8 1F C POP DS + 01B9 0E C PUSH CS + 01BA 07 C POP ES + C ;Move the FATs into position + 01BB A0 002D R C MOV AL,[NUMIO] + 01BE 98 C CBW + 01BF 91 C XCHG AX,CX + 01C0 BF 0259 R C MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT + 01C3 C FATPOINT: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-74 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 01C3 8B 35 C MOV SI,WORD PTR [DI] ;Get address within FAT address table + 01C5 A5 C MOVSW ;Set address of this FAT + 01C6 83 C7 12 C ADD DI,DPBSIZ-2 ;Point to next DPB + 01C9 E2 F8 C LOOP FATPOINT + 01CB 59 C POP CX ;True address of first FAT + 01CC BE 0247 R C MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from + 01CF 8B 3E 004B R C MOV DI,[DRVTAB] ;Place to move DPBs to + 01D3 2B CF C SUB CX,DI ;Total length of DPBs + 01D5 3B FE C CMP DI,SI + 01D7 76 07 C JBE MOVJMP ;Are we moving to higher or lower memory? + 01D9 49 C DEC CX ;Move backwards to higher memory + 01DA 03 F9 C ADD DI,CX + 01DC 03 F1 C ADD SI,CX + 01DE 41 C INC CX + 01DF FD C STD + 01E0 C MOVJMP: + 01E0 8E C5 C MOV ES,BP + 01E2 E9 0000 R C JMP MOVFAT + C + 01E5 C FIGFATSIZ: + 01E5 26: F6 66 08 C MUL ES:BYTE PTR[BP.FATCNT] + 01E9 26: 03 46 06 C ADD AX,ES:[BP.FIRFAT] + 01ED 26: 03 46 0B C ADD AX,ES:[BP.DIRSEC] + 01F1 C FIGMAX: + C ;AX has equivalent of FIRREC + 01F1 26: 2B 46 0D C SUB AX,ES:[BP.DSKSIZ] + 01F5 F7 D8 C NEG AX + 01F7 26: 8A 4E 05 C MOV CL,ES:[BP.CLUSSHFT] + 01FB D3 E8 C SHR AX,CL + 01FD 40 C INC AX + 01FE 8B C8 C MOV CX,AX ;MAXCLUS + 0200 40 C INC AX + 0201 8B D0 C MOV DX,AX + 0203 D1 EA C SHR DX,1 + 0205 13 C2 C ADC AX,DX ;Size of FAT in bytes + 0207 26: 8B 76 02 C MOV SI,ES:[BP.SECSIZ] + 020B 03 C6 C ADD AX,SI + 020D 48 C DEC AX + 020E 33 D2 C XOR DX,DX + 0210 F7 F6 C DIV SI + 0212 C3 C RET + C + 0213 C BADMES: + 0213 0D 0A 49 4E 49 54 C DB 13,10,"INIT TABLE BAD",13,10,"$" + 20 54 41 42 4C 45 C + 20 42 41 44 0D 0A C + 24 C + C + 0226 C FATSIZTAB: + 0226 0000 0000 0000 0000 C DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0000 0000 0000 0000 C + 0000 0000 0000 0000 C + 0000 0000 0000 0000 C + C + 0246 00 C DRVCNT DB 0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-75 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0247 C MEMSTRT LABEL WORD + = 0017 C ADJFAC EQU DIRBUF-MEMSTRT + 0247 C DATA ENDS + C END + +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-1 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +Structures and records: + + N a m e Width # fields + Shift Width Mask Initial + +DPBLOCK. . . . . . . . . . . . . 0014 000D + DEVNUM . . . . . . . . . . . . . 0000 + DRVNUM . . . . . . . . . . . . . 0001 + SECSIZ . . . . . . . . . . . . . 0002 + CLUSMSK. . . . . . . . . . . . . 0004 + CLUSSHFT . . . . . . . . . . . . 0005 + FIRFAT . . . . . . . . . . . . . 0006 + FATCNT . . . . . . . . . . . . . 0008 + MAXENT . . . . . . . . . . . . . 0009 + FIRREC . . . . . . . . . . . . . 000B + MAXCLUS. . . . . . . . . . . . . 000D + FATSIZ . . . . . . . . . . . . . 000F + FIRDIR . . . . . . . . . . . . . 0010 + FAT. . . . . . . . . . . . . . . 0012 +FCBLOCK. . . . . . . . . . . . . 0024 000E + EXTENT . . . . . . . . . . . . . 000C + RECSIZ . . . . . . . . . . . . . 000E + FILSIZ . . . . . . . . . . . . . 0010 + DRVBP. . . . . . . . . . . . . . 0012 + FDATE. . . . . . . . . . . . . . 0014 + FTIME. . . . . . . . . . . . . . 0016 + DEVID. . . . . . . . . . . . . . 0018 + FIRCLUS. . . . . . . . . . . . . 0019 + LSTCLUS. . . . . . . . . . . . . 001B + CLUSPOS. . . . . . . . . . . . . 001D + NR . . . . . . . . . . . . . . . 0020 + RR . . . . . . . . . . . . . . . 0021 +STKPTRS. . . . . . . . . . . . . 0018 000C + AXSAVE . . . . . . . . . . . . . 0000 + BXSAVE . . . . . . . . . . . . . 0002 + CXSAVE . . . . . . . . . . . . . 0004 + DXSAVE . . . . . . . . . . . . . 0006 + SISAVE . . . . . . . . . . . . . 0008 + DISAVE . . . . . . . . . . . . . 000A + BPSAVE . . . . . . . . . . . . . 000C + DSSAVE . . . . . . . . . . . . . 000E + ESSAVE . . . . . . . . . . . . . 0010 + IPSAVE . . . . . . . . . . . . . 0012 + CSSAVE . . . . . . . . . . . . . 0014 + FSAVE. . . . . . . . . . . . . . 0016 + +Segments and groups: + + N a m e Size align combine class + +DOSGROUP . . . . . . . . . . . . GROUP + CODE . . . . . . . . . . . . . . 1583 PARA NONE + CONSTANTS. . . . . . . . . . . . 004D BYTE NONE + DATA . . . . . . . . . . . . . . 025E WORD NONE +SEGBIOS. . . . . . . . . . . . . 002D AT 0040 + +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-2 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +Symbols: + + N a m e Type Value Attr + +ABORT. . . . . . . . . . . . . . L NEAR 06B1 CODE +ADDREC . . . . . . . . . . . . . L NEAR 0B1C CODE +ADJFAC . . . . . . . . . . . . . Number 0017 +ALIGNED. . . . . . . . . . . . . L NEAR 019B CODE +ALLOC. . . . . . . . . . . . . . L NEAR 0DC1 CODE +ALLOCATE . . . . . . . . . . . . L NEAR 0DBA CODE +ATTRIB . . . . . . . . . . . . . L BYTE 0116 DATA +AUXIN. . . . . . . . . . . . . . L NEAR 0141 CODE +AUXOUT . . . . . . . . . . . . . L NEAR 014C CODE +BACKMES. . . . . . . . . . . . . L NEAR 10D6 CODE +BACKPOS. . . . . . . . . . . . . L NEAR 1241 CODE +BACKSP . . . . . . . . . . . . . L NEAR 107E CODE +BACKUP . . . . . . . . . . . . . L NEAR 10D3 CODE +BADCALL. . . . . . . . . . . . . L NEAR 0054 CODE +BADCLOSE . . . . . . . . . . . . L NEAR 0547 CODE +BADCLOSEJ. . . . . . . . . . . . L NEAR 04F8 CODE +BADDRV . . . . . . . . . . . . . L NEAR 1304 CODE +BADFAT . . . . . . . . . . . . . L NEAR 04A8 CODE +BADINIT. . . . . . . . . . . . . L NEAR 009E DATA +BADINITJ . . . . . . . . . . . . L NEAR 00E9 DATA +BADMES . . . . . . . . . . . . . L NEAR 0213 DATA +BAKTAB . . . . . . . . . . . . . L NEAR 10A1 CODE +BIOSAUXIN. . . . . . . . . . . . L BYTE 000F SEGBIOS Length =0003 +BIOSAUXOUT . . . . . . . . . . . L BYTE 0012 SEGBIOS Length =0003 +BIOSDSKCHG . . . . . . . . . . . L BYTE 001B SEGBIOS Length =0003 +BIOSFLUSH. . . . . . . . . . . . L BYTE 0027 SEGBIOS Length =0003 +BIOSGETTIME. . . . . . . . . . . L BYTE 0024 SEGBIOS Length =0003 +BIOSIN . . . . . . . . . . . . . L BYTE 0006 SEGBIOS Length =0003 +BIOSMAPDEV . . . . . . . . . . . L BYTE 002A SEGBIOS Length =0003 +BIOSOUT. . . . . . . . . . . . . L BYTE 0009 SEGBIOS Length =0003 +BIOSPRINT. . . . . . . . . . . . L BYTE 000C SEGBIOS Length =0003 +BIOSREAD . . . . . . . . . . . . L BYTE 0015 SEGBIOS Length =0003 +BIOSSEG. . . . . . . . . . . . . Number 0040 +BIOSSETDATE. . . . . . . . . . . L BYTE 001E SEGBIOS Length =0003 +BIOSSETTIME. . . . . . . . . . . L BYTE 0021 SEGBIOS Length =0003 +BIOSSTAT . . . . . . . . . . . . L BYTE 0003 SEGBIOS Length =0003 +BIOSWRITE. . . . . . . . . . . . L BYTE 0018 SEGBIOS Length =0003 +BLKDON . . . . . . . . . . . . . L NEAR 0D7D CODE +BLKRD. . . . . . . . . . . . . . L NEAR 071E CODE +BLKWRT . . . . . . . . . . . . . L NEAR 0726 CODE +BREAKDOWN. . . . . . . . . . . . L NEAR 084C CODE +BUFDRVBP . . . . . . . . . . . . L WORD 003F CONSTANTS +BUFDRVNO . . . . . . . . . . . . L BYTE 003D CONSTANTS +BUFFER . . . . . . . . . . . . . L WORD 0039 CONSTANTS +BUFFUL . . . . . . . . . . . . . L NEAR 1027 CODE +BUFIN. . . . . . . . . . . . . . L NEAR 0FBD CODE +BUFOK. . . . . . . . . . . . . . L NEAR 0462 CODE +BUFOUT . . . . . . . . . . . . . L NEAR 117D CODE +BUFRD. . . . . . . . . . . . . . L NEAR 0925 CODE +BUFSEC . . . . . . . . . . . . . L NEAR 08A0 CODE +BUFSECNO . . . . . . . . . . . . L WORD 003B CONSTANTS +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-3 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +BUFWRT . . . . . . . . . . . . . L NEAR 0938 CODE +BYTCNT1. . . . . . . . . . . . . L WORD 0156 DATA +BYTCNT2. . . . . . . . . . . . . L WORD 0158 DATA +BYTPOS . . . . . . . . . . . . . L BYTE 0152 DATA Length =0004 +BYTSECPOS. . . . . . . . . . . . L WORD 0150 DATA +CANCEL . . . . . . . . . . . . . Number 0018 +CARPOS . . . . . . . . . . . . . L BYTE 0028 CONSTANTS +CHK. . . . . . . . . . . . . . . L NEAR 1367 CODE +CHKCNT . . . . . . . . . . . . . L NEAR 10B9 CODE +CHKDIRWRITE. . . . . . . . . . . L NEAR 067A CODE +CHKFATWRT. . . . . . . . . . . . L NEAR 051F CODE +CHKYR. . . . . . . . . . . . . . L NEAR 1485 CODE +CLOSE. . . . . . . . . . . . . . L NEAR 04BB CODE +CLRET. . . . . . . . . . . . . . L NEAR 0993 CODE +CLUSNUM. . . . . . . . . . . . . L WORD 014A DATA +CODSIZ . . . . . . . . . . . . . Number 1583 +CODSTRT. . . . . . . . . . . . . Number 0000 CODE +COMMAND. . . . . . . . . . . . . L NEAR 004F CODE +CONBUF . . . . . . . . . . . . . L BYTE 0080 DATA Length =0083 +CONIN. . . . . . . . . . . . . . L NEAR 1253 CODE +CONOUT . . . . . . . . . . . . . L NEAR 119D CODE +CONSTAT. . . . . . . . . . . . . L NEAR 1249 CODE +CONSTRT. . . . . . . . . . . . . Number 0000 CONSTANTS +CONTC. . . . . . . . . . . . . . Number 0023 +CONTINIT . . . . . . . . . . . . L NEAR 00EB DATA +CONTPOS. . . . . . . . . . . . . L WORD 002F CONSTANTS +CONTSRCH . . . . . . . . . . . . L NEAR 01E6 CODE +CONTSTK. . . . . . . . . . . . . L WORD 0135 DATA +COPYEACH . . . . . . . . . . . . L NEAR 10F7 CODE +COPYLIN. . . . . . . . . . . . . L NEAR 10EA CODE +COPYNEW. . . . . . . . . . . . . L NEAR 104C CODE +COPYONE. . . . . . . . . . . . . L NEAR 10F5 CODE +COPYSTR. . . . . . . . . . . . . L NEAR 10F0 CODE +CREATE . . . . . . . . . . . . . L NEAR 056D CODE +CREATING . . . . . . . . . . . . L BYTE 012F DATA +CRET . . . . . . . . . . . . . . L NEAR 01B9 CODE +CRLF . . . . . . . . . . . . . . L NEAR 105C CODE +CTRLOUT. . . . . . . . . . . . . L NEAR 1214 CODE +CURDRV . . . . . . . . . . . . . L BYTE 004A CONSTANTS +DATE16 . . . . . . . . . . . . . L NEAR 1400 CODE +DAY. . . . . . . . . . . . . . . L BYTE 0043 CONSTANTS +DAYCNT . . . . . . . . . . . . . L WORD 0047 CONSTANTS +DEFDRV . . . . . . . . . . . . . L NEAR 12B9 CODE +DELALL . . . . . . . . . . . . . L BYTE 0130 DATA +DELETE . . . . . . . . . . . . . L NEAR 029B CODE +DELFILE. . . . . . . . . . . . . L NEAR 02C9 CODE +DELIM. . . . . . . . . . . . . . L NEAR 137F CODE +DELNXT . . . . . . . . . . . . . L NEAR 02E5 CODE +DEVNAME. . . . . . . . . . . . . L NEAR 01A4 CODE +DEVSIZ . . . . . . . . . . . . . L NEAR 0F03 CODE +DIRBUF . . . . . . . . . . . . . L WORD 025E DATA +DIRBUFID . . . . . . . . . . . . L WORD 0041 CONSTANTS +DIRCOMP. . . . . . . . . . . . . L NEAR 0560 CODE +DIRREAD. . . . . . . . . . . . . L NEAR 05E8 CODE +DIRSEC . . . . . . . . . . . . . Number 000B +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-4 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +DIRTYBUF . . . . . . . . . . . . L BYTE 003E CONSTANTS +DIRTYDIR . . . . . . . . . . . . L BYTE 002B CONSTANTS +DIRWRITE . . . . . . . . . . . . L NEAR 0681 CODE +DISPATCH . . . . . . . . . . . . L WORD 00B6 CODE +DIVMES . . . . . . . . . . . . . L BYTE 0014 CONSTANTS +DIVOV. . . . . . . . . . . . . . L NEAR 1576 CODE +DMAADD . . . . . . . . . . . . . L WORD 0031 CONSTANTS +DOOPEN . . . . . . . . . . . . . L NEAR 03D0 CODE +DOSINIT. . . . . . . . . . . . . L NEAR 0024 DATA +DOSLEN . . . . . . . . . . . . . Number 15D0 +DOWRT. . . . . . . . . . . . . . L NEAR 0C24 CODE +DOWRTJ . . . . . . . . . . . . . L NEAR 0BA3 CODE +DPBSIZ . . . . . . . . . . . . . Number 0014 +DREAD. . . . . . . . . . . . . . L NEAR 05FC CODE +DRVBIT . . . . . . . . . . . . . Number 0002 +DRVCNT . . . . . . . . . . . . . L BYTE 0246 DATA +DRVTAB . . . . . . . . . . . . . L WORD 004B CONSTANTS +DSKERR . . . . . . . . . . . . . L BYTE 0138 DATA +DSKREAD. . . . . . . . . . . . . L NEAR 0669 CODE +DSKRESET . . . . . . . . . . . . L NEAR 0F64 CODE +DSKSIZ . . . . . . . . . . . . . Number 000D +DSKSTACK . . . . . . . . . . . . L BYTE 025E DATA +DSKTEST. . . . . . . . . . . . . Alias FALSE +DSLIDE . . . . . . . . . . . . . L NEAR 1475 CODE +DSLIDE1. . . . . . . . . . . . . L NEAR 1477 CODE +DSUM . . . . . . . . . . . . . . L NEAR 153C CODE +DSUM1. . . . . . . . . . . . . . L NEAR 1540 CODE +DWRITE . . . . . . . . . . . . . L NEAR 068C CODE +EACHFAT. . . . . . . . . . . . . L NEAR 0533 CODE +EDITON . . . . . . . . . . . . . L NEAR 0FD9 CODE +ENDLIN . . . . . . . . . . . . . L NEAR 1042 CODE +ENDMEM . . . . . . . . . . . . . L WORD 0035 CONSTANTS +ENDRDCON . . . . . . . . . . . . L NEAR 09B1 CODE +ENDRDDEV . . . . . . . . . . . . L NEAR 09B5 CODE +ENDWRDEV . . . . . . . . . . . . L NEAR 0B7B CODE +ENTERINS . . . . . . . . . . . . L NEAR 115B CODE +ENTFREE. . . . . . . . . . . . . L WORD 015C DATA +ENTRY. . . . . . . . . . . . . . L NEAR 0057 CODE +ENTRYPOINT . . . . . . . . . . . Number 00C0 +ENTRYPOINTSEG. . . . . . . . . . Number 000C +ENUF . . . . . . . . . . . . . . L NEAR 0A43 CODE +EOFERR . . . . . . . . . . . . . L NEAR 0843 CODE +ERRET. . . . . . . . . . . . . . L NEAR 036F CODE +ERRET3 . . . . . . . . . . . . . L NEAR 059A CODE +ERRINT . . . . . . . . . . . . . L NEAR 0632 CODE +ERROR. . . . . . . . . . . . . . L NEAR 06C9 CODE +ERRPOP . . . . . . . . . . . . . L NEAR 0598 CODE +ESC. . . . . . . . . . . . . . . L NEAR 102E CODE +ESCCH. . . . . . . . . . . . . . Number 001B +ESCCHAR. . . . . . . . . . . . . L BYTE 0003 CODE +ESCFUNC. . . . . . . . . . . . . L WORD 1165 CODE +ESCTAB . . . . . . . . . . . . . L NEAR 0004 CODE +ESCTABLEN. . . . . . . . . . . . Number 000C +EVENFIL. . . . . . . . . . . . . L NEAR 0B05 CODE +EVENMOV. . . . . . . . . . . . . L NEAR 0ABA CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-5 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +EVENRD . . . . . . . . . . . . . L NEAR 0934 CODE +EVENWRT. . . . . . . . . . . . . L NEAR 095B CODE +EXISTENT . . . . . . . . . . . . L NEAR 059D CODE +EXIT . . . . . . . . . . . . . . Number 0088 +EXITHOLD . . . . . . . . . . . . L BYTE 0105 DATA Length =0004 +EXITINS. . . . . . . . . . . . . L NEAR 1160 CODE +EXTBIT . . . . . . . . . . . . . Number 0008 +EXTFCB . . . . . . . . . . . . . L BYTE 012E DATA +FALSE. . . . . . . . . . . . . . Number 0000 +FATAL. . . . . . . . . . . . . . L NEAR 0639 CODE +FATAL1 . . . . . . . . . . . . . L NEAR 063C CODE +FATBASE. . . . . . . . . . . . . L WORD 0109 DATA +FATERR . . . . . . . . . . . . . L NEAR 0418 CODE +FATPOINT . . . . . . . . . . . . L NEAR 01C3 DATA +FATREAD. . . . . . . . . . . . . L NEAR 042C CODE +FATSIZTAB. . . . . . . . . . . . L NEAR 0226 DATA +FATWRT . . . . . . . . . . . . . L NEAR 052C CODE +FCB. . . . . . . . . . . . . . . L WORD 013E DATA +FIGFAT . . . . . . . . . . . . . L NEAR 0551 CODE +FIGFATSIZ. . . . . . . . . . . . L NEAR 01E5 DATA +FIGMAX . . . . . . . . . . . . . L NEAR 01F1 DATA +FIGREC . . . . . . . . . . . . . L NEAR 0D8B CODE +FIGSHFT. . . . . . . . . . . . . L NEAR 0063 DATA +FIGTAB . . . . . . . . . . . . . L NEAR 10BB CODE +FILDIRENT. . . . . . . . . . . . Number 0010 +FILESIZE . . . . . . . . . . . . L NEAR 0ED2 CODE +FILLB. . . . . . . . . . . . . . L NEAR 12C8 CODE +FILLB2 . . . . . . . . . . . . . L NEAR 12D5 CODE +FILLNAM. . . . . . . . . . . . . L NEAR 134C CODE +FINBLK . . . . . . . . . . . . . L NEAR 072C CODE +FINBUF . . . . . . . . . . . . . L NEAR 0907 CODE +FINCLUS. . . . . . . . . . . . . L NEAR 0D3C CODE +FINDFRE. . . . . . . . . . . . . L NEAR 0DC3 CODE +FINDIT . . . . . . . . . . . . . L NEAR 088C CODE +FINDNAME . . . . . . . . . . . . L NEAR 01DA CODE +FINDOLD. . . . . . . . . . . . . L NEAR 1123 CODE +FINRND . . . . . . . . . . . . . L NEAR 073B CODE +FINSEQ . . . . . . . . . . . . . L NEAR 0704 CODE +FINWRT . . . . . . . . . . . . . L NEAR 0C8F CODE +FLGFAT . . . . . . . . . . . . . L NEAR 0012 DATA +FLUSHKB. . . . . . . . . . . . . L NEAR 011E CODE +FNDCLUS. . . . . . . . . . . . . L NEAR 0874 CODE +FNDDIR . . . . . . . . . . . . . L NEAR 04F5 CODE +FNDFATSIZ. . . . . . . . . . . . L NEAR 0082 DATA +FNDPOS . . . . . . . . . . . . . L NEAR 10AD CODE +FOUND. . . . . . . . . . . . . . L NEAR 0226 CODE +FOURYEARS. . . . . . . . . . . . Number 05B5 +FREE . . . . . . . . . . . . . . L NEAR 020F CODE +FREESPOT . . . . . . . . . . . . L NEAR 05B9 CODE +FULLREC. . . . . . . . . . . . . L NEAR 0B0A CODE +GETBP. . . . . . . . . . . . . . L NEAR 0492 CODE +GETBUF . . . . . . . . . . . . . L NEAR 09F6 CODE +GETCH. . . . . . . . . . . . . . L NEAR 0FEE CODE +GETCH1 . . . . . . . . . . . . . L NEAR 109E CODE +GETCH2 . . . . . . . . . . . . . L NEAR 110C CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-6 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +GETDATE. . . . . . . . . . . . . L NEAR 14A6 CODE +GETDRV . . . . . . . . . . . . . L NEAR 0F97 CODE +GETDSKPT . . . . . . . . . . . . L NEAR 0F4E CODE +GETENT . . . . . . . . . . . . . L NEAR 0247 CODE +GETENTRY . . . . . . . . . . . . L NEAR 023E CODE +GETEOF . . . . . . . . . . . . . L NEAR 0E43 CODE +GETFATPT . . . . . . . . . . . . L NEAR 0F20 CODE +GETFATPTDL . . . . . . . . . . . L NEAR 0F22 CODE +GETFATSIZ. . . . . . . . . . . . L NEAR 0087 DATA +GETFILE. . . . . . . . . . . . . L NEAR 01C8 CODE +GETIO. . . . . . . . . . . . . . L NEAR 0114 CODE +GETLET . . . . . . . . . . . . . L NEAR 135A CODE +GETNAME. . . . . . . . . . . . . L NEAR 01D5 CODE +GETRDONLY. . . . . . . . . . . . L NEAR 0114 CODE +GETREC . . . . . . . . . . . . . L NEAR 0D9A CODE +GETRRPOS . . . . . . . . . . . . L NEAR 076A CODE +GETRRPOS1. . . . . . . . . . . . L NEAR 0767 CODE +GETSEC . . . . . . . . . . . . . L NEAR 08BD CODE +GETTHISDRV . . . . . . . . . . . L NEAR 03B9 CODE +GETTIME. . . . . . . . . . . . . L NEAR 1546 CODE +GETWORD. . . . . . . . . . . . . L NEAR 132C CODE +HARDERR. . . . . . . . . . . . . L NEAR 060F CODE +HAVATTRB . . . . . . . . . . . . L NEAR 0397 CODE +HAVCLUS. . . . . . . . . . . . . L NEAR 016D CODE +HAVDIF . . . . . . . . . . . . . L NEAR 13DE CODE +HAVDIRBUF. . . . . . . . . . . . L NEAR 026C CODE +HAVDRV . . . . . . . . . . . . . L NEAR 1306 CODE +HAVFATSIZ. . . . . . . . . . . . L NEAR 00A6 DATA +HAVFRE . . . . . . . . . . . . . L NEAR 0E03 CODE +HAVIT. . . . . . . . . . . . . . L NEAR 0294 CODE +HAVRECSIZ. . . . . . . . . . . . L NEAR 079D CODE +HAVSHFT. . . . . . . . . . . . . L NEAR 006B DATA +HAVSTART . . . . . . . . . . . . L NEAR 0B86 CODE +HAVTAB . . . . . . . . . . . . . L NEAR 10C0 CODE +HEADER . . . . . . . . . . . . . L BYTE 0010 CODE +HIGHMEM. . . . . . . . . . . . . Alias FALSE +HURTFAT. . . . . . . . . . . . . L NEAR 0174 CODE +IBM. . . . . . . . . . . . . . . Alias FALSE +IN . . . . . . . . . . . . . . . L NEAR 125C CODE +INBUF. . . . . . . . . . . . . . L BYTE 0000 DATA Length =0080 +INCHK. . . . . . . . . . . . . . L NEAR 11D4 CODE +INTBASE. . . . . . . . . . . . . Number 0080 +INTTAB . . . . . . . . . . . . . Number 0020 +INUSE. . . . . . . . . . . . . . L NEAR 0114 CODE +IOCHK. . . . . . . . . . . . . . L NEAR 01BB CODE +IONAME . . . . . . . . . . . . . L NEAR 0000 CONSTANTS +IOSTACK. . . . . . . . . . . . . L BYTE 01DE DATA +IRET . . . . . . . . . . . . . . L NEAR 0056 CODE +KILLFIL. . . . . . . . . . . . . L NEAR 0D06 CODE +KILLSRCH . . . . . . . . . . . . L NEAR 0E8A CODE +KILLSRCH1. . . . . . . . . . . . E NEAR 0E8B CODE +KILNEW . . . . . . . . . . . . . L NEAR 106B CODE +LASTENT. . . . . . . . . . . . . L WORD 0103 DATA +LASTPOS. . . . . . . . . . . . . L WORD 0148 DATA +LEAVE. . . . . . . . . . . . . . L NEAR 009C CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-7 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +LIST . . . . . . . . . . . . . . L NEAR 128B CODE +LISTOUT. . . . . . . . . . . . . L NEAR 128D CODE +LOAD . . . . . . . . . . . . . . L NEAR 0A1E CODE +LODNAME. . . . . . . . . . . . . L NEAR 039F CODE +LONGCALL . . . . . . . . . . . . Number 009A +LONGJUMP . . . . . . . . . . . . Number 00EA +LOOKIO . . . . . . . . . . . . . L NEAR 01A9 CODE +LVDSK. . . . . . . . . . . . . . L NEAR 0B97 CODE +MAKEFCB. . . . . . . . . . . . . L NEAR 12AF CODE +MAPDRV . . . . . . . . . . . . . L NEAR 048F CODE +MAXCALL. . . . . . . . . . . . . Number 0024 +MAXCOM . . . . . . . . . . . . . Number 002E +MAXDIF . . . . . . . . . . . . . Number 0FFF +MAXREC . . . . . . . . . . . . . L NEAR 0DF0 CODE +MAXSEC . . . . . . . . . . . . . L WORD 0037 CONSTANTS +MEMSCAN. . . . . . . . . . . . . L NEAR 0140 DATA +MEMSTRT. . . . . . . . . . . . . L WORD 0247 DATA +MONTAB . . . . . . . . . . . . . L BYTE 149A CODE +MONTH. . . . . . . . . . . . . . L BYTE 0044 CONSTANTS +MOVCHK . . . . . . . . . . . . . L NEAR 03A8 CODE +MOVFAT . . . . . . . . . . . . . L NEAR 0000 DATA +MOVJMP . . . . . . . . . . . . . L NEAR 01E0 DATA +MOVNAME. . . . . . . . . . . . . L NEAR 0372 CODE +MSVER. . . . . . . . . . . . . . Alias TRUE +MUSTGETWORD. . . . . . . . . . . L NEAR 1332 CODE +NAMBIT . . . . . . . . . . . . . Number 0004 +NAME1. . . . . . . . . . . . . . L BYTE 010B DATA Length =000B +NAME2. . . . . . . . . . . . . . L BYTE 0117 DATA Length =000B +NAME3. . . . . . . . . . . . . . L BYTE 0122 DATA Length =000C +NEWBASE. . . . . . . . . . . . . L NEAR 13A8 CODE +NEWDSK . . . . . . . . . . . . . L NEAR 0450 CODE +NEWFAT . . . . . . . . . . . . . L NEAR 047A CODE +NEWLIN . . . . . . . . . . . . . L NEAR 0FDC CODE +NEWNAM . . . . . . . . . . . . . L NEAR 0320 CODE +NEXTADD. . . . . . . . . . . . . L WORD 0140 DATA +NEXTENT. . . . . . . . . . . . . L NEAR 0209 CODE +NEXTENTRY. . . . . . . . . . . . L NEAR 0275 CODE +NEXTFAT. . . . . . . . . . . . . L NEAR 046B CODE +NEXTSEC. . . . . . . . . . . . . L NEAR 0965 CODE +NOBUF. . . . . . . . . . . . . . L NEAR 0F82 CODE +NOCHG. . . . . . . . . . . . . . L NEAR 0327 CODE +NOCLUS . . . . . . . . . . . . . L NEAR 089D CODE +NODOT. . . . . . . . . . . . . . L NEAR 131D CODE +NODRV. . . . . . . . . . . . . . L NEAR 1309 CODE +NOEDIT . . . . . . . . . . . . . L NEAR 0FD7 CODE +NOFILERR . . . . . . . . . . . . L NEAR 077B CODE +NONAM. . . . . . . . . . . . . . L NEAR 1328 CODE +NONE . . . . . . . . . . . . . . L NEAR 0296 CODE +NONEXT . . . . . . . . . . . . . L NEAR 0995 CODE +NOREAD . . . . . . . . . . . . . L NEAR 0949 CODE +NORMCH . . . . . . . . . . . . . L NEAR 09A0 CODE +NORMFCB. . . . . . . . . . . . . L NEAR 0E7C CODE +NORMFCB1 . . . . . . . . . . . . L NEAR 0774 CODE +NORMFCB2 . . . . . . . . . . . . L NEAR 0DA4 CODE +NORMFCB3 . . . . . . . . . . . . L NEAR 04C5 CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-8 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +NORNDUP. . . . . . . . . . . . . L NEAR 0BED CODE +NOROOM . . . . . . . . . . . . . L NEAR 084A CODE +NOSCAN . . . . . . . . . . . . . L NEAR 12EE CODE +NOSKIP . . . . . . . . . . . . . L NEAR 0C1C CODE +NOSTAR . . . . . . . . . . . . . L NEAR 1342 CODE +NOSTOP . . . . . . . . . . . . . L NEAR 1190 CODE +NOSUCHDRV. . . . . . . . . . . . L NEAR 0F1D CODE +NOTALL . . . . . . . . . . . . . L NEAR 02BE CODE +NOTBUFFED. . . . . . . . . . . . L NEAR 0ABB CODE +NOTDEVICE. . . . . . . . . . . . L NEAR 07A7 CODE +NOTFND . . . . . . . . . . . . . L NEAR 1143 CODE +NOTINBUF . . . . . . . . . . . . L NEAR 0C62 CODE +NOTMAX . . . . . . . . . . . . . L NEAR 005C DATA +NUMDEV . . . . . . . . . . . . . Number 0005 +NUMDRV . . . . . . . . . . . . . L BYTE 002C CONSTANTS +NUMIO. . . . . . . . . . . . . . L BYTE 002D CONSTANTS +OK . . . . . . . . . . . . . . . L NEAR 083B CODE +OKRET. . . . . . . . . . . . . . L NEAR 0544 CODE +OKRET1 . . . . . . . . . . . . . L NEAR 04B8 CODE +OLDBAK . . . . . . . . . . . . . L NEAR 1093 CODE +ONSEC. . . . . . . . . . . . . . L NEAR 0A74 CODE +OPEN . . . . . . . . . . . . . . L NEAR 03CD CODE +OPENDEV. . . . . . . . . . . . . L NEAR 03FF CODE +OPENJMP. . . . . . . . . . . . . L NEAR 05E2 CODE +OPTCLUS. . . . . . . . . . . . . L NEAR 0D28 CODE +OPTIMIZE . . . . . . . . . . . . L NEAR 0D15 CODE +OUT. . . . . . . . . . . . . . . L NEAR 119F CODE +OUTCH. . . . . . . . . . . . . . L NEAR 11AC CODE +OUTCHJ . . . . . . . . . . . . . L NEAR 123E CODE +OUTMES . . . . . . . . . . . . . L NEAR 12A4 CODE +OUTSTR . . . . . . . . . . . . . L NEAR 129A CODE +PACK . . . . . . . . . . . . . . L NEAR 017F CODE +PACKIN . . . . . . . . . . . . . L NEAR 019F CODE +PARTSEG. . . . . . . . . . . . . L NEAR 0829 CODE +PERDRV . . . . . . . . . . . . . L NEAR 0035 DATA +PFLAG. . . . . . . . . . . . . . L BYTE 002A CONSTANTS +PHYCRLF. . . . . . . . . . . . . L NEAR 1066 CODE +PHYDRV . . . . . . . . . . . . . L NEAR 03C8 CODE +POPTAB . . . . . . . . . . . . . L NEAR 1236 CODE +PREREAD. . . . . . . . . . . . . L BYTE 013A DATA +PRINTOFF . . . . . . . . . . . . L NEAR 120D CODE +PRINTON. . . . . . . . . . . . . L NEAR 1206 CODE +PRTBUF . . . . . . . . . . . . . L NEAR 1298 CODE +PUNCH. . . . . . . . . . . . . . L NEAR 014A CODE +PUTNEW . . . . . . . . . . . . . L NEAR 1071 CODE +QUIT . . . . . . . . . . . . . . L NEAR 004B CODE +RAWINP . . . . . . . . . . . . . L NEAR 127F CODE +RAWIO. . . . . . . . . . . . . . L NEAR 1262 CODE +RAWOUT . . . . . . . . . . . . . L NEAR 1285 CODE +RDERR. . . . . . . . . . . . . . L NEAR 0A16 CODE +RDLAST . . . . . . . . . . . . . L NEAR 0B2D CODE +RDLASTJ. . . . . . . . . . . . . L NEAR 0A1B CODE +RDLP . . . . . . . . . . . . . . L NEAR 0A80 CODE +RDMID. . . . . . . . . . . . . . L NEAR 0A63 CODE +RDSEC. . . . . . . . . . . . . . L NEAR 08DD CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-9 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +READAUX. . . . . . . . . . . . . L NEAR 09D5 CODE +READCON. . . . . . . . . . . . . L NEAR 09DF CODE +READDEV. . . . . . . . . . . . . L NEAR 09C8 CODE +READER . . . . . . . . . . . . . L NEAR 0141 CODE +READOP . . . . . . . . . . . . . L BYTE 013B DATA +READTIME . . . . . . . . . . . . L NEAR 1427 CODE +RECCNT . . . . . . . . . . . . . L WORD 0146 DATA +RECOK. . . . . . . . . . . . . . L NEAR 0EE7 CODE +RECPOS . . . . . . . . . . . . . L BYTE 0142 DATA Length =0004 +REDISP . . . . . . . . . . . . . L NEAR 0084 CODE +REDISPJ. . . . . . . . . . . . . L NEAR 013E CODE +REEDIT . . . . . . . . . . . . . L NEAR 1147 CODE +RELBLKS. . . . . . . . . . . . . L NEAR 0E31 CODE +RELEASE. . . . . . . . . . . . . L NEAR 0E2F CODE +RELFILE. . . . . . . . . . . . . L NEAR 0CFA CODE +RENAME . . . . . . . . . . . . . L NEAR 02F3 CODE +RENERR . . . . . . . . . . . . . L NEAR 036C CODE +RENFIL . . . . . . . . . . . . . L NEAR 0317 CODE +RESFLG . . . . . . . . . . . . . L NEAR 127B CODE +RET1 . . . . . . . . . . . . . . L NEAR 01C7 CODE +RET10. . . . . . . . . . . . . . L NEAR 0873 CODE +RET100 . . . . . . . . . . . . . L NEAR 0D7C CODE +RET101 . . . . . . . . . . . . . L NEAR 1395 CODE +RET11. . . . . . . . . . . . . . L NEAR 0DF1 CODE +RET12. . . . . . . . . . . . . . L NEAR 0E2E CODE +RET13. . . . . . . . . . . . . . L NEAR 0E42 CODE +RET14. . . . . . . . . . . . . . L NEAR 0EB2 CODE +RET15. . . . . . . . . . . . . . L NEAR 0F9B CODE +RET16. . . . . . . . . . . . . . L NEAR 0FAE CODE +RET17. . . . . . . . . . . . . . L NEAR 0FBC CODE +RET18. . . . . . . . . . . . . . L NEAR 11C3 CODE +RET19. . . . . . . . . . . . . . L NEAR 1237 CODE +RET2 . . . . . . . . . . . . . . L NEAR 01D4 CODE +RET20. . . . . . . . . . . . . . L NEAR 1297 CODE +RET21. . . . . . . . . . . . . . L NEAR 1351 CODE +RET22. . . . . . . . . . . . . . L NEAR 1426 CODE +RET23. . . . . . . . . . . . . . L NEAR 1474 CODE +RET24. . . . . . . . . . . . . . L NEAR 14C3 CODE +RET25. . . . . . . . . . . . . . L NEAR 153B CODE +RET26. . . . . . . . . . . . . . L NEAR 1557 CODE +RET28. . . . . . . . . . . . . . L NEAR 0B2C CODE +RET29. . . . . . . . . . . . . . L NEAR 1261 CODE +RET3 . . . . . . . . . . . . . . L NEAR 020E CODE +RET30. . . . . . . . . . . . . . L NEAR 1142 CODE +RET4 . . . . . . . . . . . . . . L NEAR 029A CODE +RET5 . . . . . . . . . . . . . . L NEAR 0371 CODE +RET6 . . . . . . . . . . . . . . L NEAR 03B8 CODE +RET7 . . . . . . . . . . . . . . L NEAR 04A7 CODE +RET8 . . . . . . . . . . . . . . L NEAR 05FB CODE +RET9 . . . . . . . . . . . . . . L NEAR 0679 CODE +RNDRD. . . . . . . . . . . . . . L NEAR 070E CODE +RNDWRT . . . . . . . . . . . . . L NEAR 0716 CODE +SAMSIZ . . . . . . . . . . . . . L NEAR 0CB9 CODE +SAMSTK . . . . . . . . . . . . . L NEAR 0097 CODE +SAVCH. . . . . . . . . . . . . . L NEAR 1010 CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-10 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +SAVEXIT. . . . . . . . . . . . . Number 000A +SAVFEB . . . . . . . . . . . . . L NEAR 148E CODE +SAVFIR . . . . . . . . . . . . . L NEAR 0862 CODE +SAVPLCE. . . . . . . . . . . . . L NEAR 0E53 CODE +SAVPOS . . . . . . . . . . . . . L NEAR 0990 CODE +SAVREGS. . . . . . . . . . . . . L NEAR 006D CODE +SCANB. . . . . . . . . . . . . . L NEAR 1352 CODE +SECCLUSPOS . . . . . . . . . . . L BYTE 0137 DATA +SECCNT . . . . . . . . . . . . . L WORD 015A DATA +SECPOS . . . . . . . . . . . . . L WORD 014C DATA +SELDSK . . . . . . . . . . . . . L NEAR 0FAF CODE +SEQRD. . . . . . . . . . . . . . L NEAR 06F6 CODE +SEQWRT . . . . . . . . . . . . . L NEAR 06FE CODE +SETATTRIB. . . . . . . . . . . . L NEAR 0114 CODE +SETBUF . . . . . . . . . . . . . L NEAR 08F9 CODE +SETCLUS. . . . . . . . . . . . . L NEAR 0B0E CODE +SETDATE. . . . . . . . . . . . . L NEAR 14C4 CODE +SETDIRT. . . . . . . . . . . . . L NEAR 0D00 CODE +SETDMA . . . . . . . . . . . . . L NEAR 0F12 CODE +SETEND . . . . . . . . . . . . . L NEAR 0153 DATA +SETFCB . . . . . . . . . . . . . L NEAR 0ACD CODE +SETFCBJ. . . . . . . . . . . . . L NEAR 09C5 CODE +SETIO. . . . . . . . . . . . . . L NEAR 0114 CODE +SETMEM . . . . . . . . . . . . . L NEAR 13BE CODE +SETNREX. . . . . . . . . . . . . L NEAR 074B CODE +SETRNDREC. . . . . . . . . . . . L NEAR 0F9C CODE +SETTIME. . . . . . . . . . . . . L NEAR 1558 CODE +SETUP. . . . . . . . . . . . . . L NEAR 0784 CODE +SETVECT. . . . . . . . . . . . . L NEAR 1396 CODE +SETYEAR. . . . . . . . . . . . . L NEAR 1481 CODE +SK . . . . . . . . . . . . . . . L NEAR 145A CODE +SKIPONE. . . . . . . . . . . . . L NEAR 110F CODE +SKIPSTR. . . . . . . . . . . . . L NEAR 1119 CODE +SKPCLP . . . . . . . . . . . . . L NEAR 088E CODE +SKPSPC . . . . . . . . . . . . . L NEAR 12EB CODE +SMALLENT . . . . . . . . . . . . L NEAR 05DA CODE +SMALREC. . . . . . . . . . . . . L NEAR 07B4 CODE +SMFAT. . . . . . . . . . . . . . L NEAR 00D4 DATA +SPCHK. . . . . . . . . . . . . . L NEAR 138F CODE +SPSAVE . . . . . . . . . . . . . L WORD 0131 DATA +SRCH . . . . . . . . . . . . . . L NEAR 01EB CODE +SRCHDEV. . . . . . . . . . . . . L NEAR 0E93 CODE +SRCHFRST . . . . . . . . . . . . L NEAR 0E50 CODE +SRCHNXT. . . . . . . . . . . . . L NEAR 0EB3 CODE +SSSAVE . . . . . . . . . . . . . L WORD 0133 DATA +STARTPOS . . . . . . . . . . . . L BYTE 0029 CONSTANTS +STARTSRCH. . . . . . . . . . . . L NEAR 0423 CODE +STATCHK. . . . . . . . . . . . . L NEAR 11C4 CODE +STOLET . . . . . . . . . . . . . L NEAR 03B4 CODE +STORE. . . . . . . . . . . . . . L NEAR 0BA9 CODE +TAB. . . . . . . . . . . . . . . L NEAR 1228 CODE +TABBAK . . . . . . . . . . . . . L NEAR 10CC CODE +TABLP. . . . . . . . . . . . . . L NEAR 122F CODE +TEMP . . . . . . . . . . . . . . L WORD 0131 DATA +THISDRV. . . . . . . . . . . . . L BYTE 013C DATA +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-11 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +TOGLINS. . . . . . . . . . . . . Alias FALSE +TOGLPRN. . . . . . . . . . . . . Alias FALSE +TOTFATSIZ. . . . . . . . . . . . L NEAR 010F DATA +TRANBUF. . . . . . . . . . . . . L NEAR 0997 CODE +TRANS. . . . . . . . . . . . . . L BYTE 0139 DATA +TRUE . . . . . . . . . . . . . . Number FFFF +TRYIN. . . . . . . . . . . . . . L NEAR 0DF7 CODE +TRYOUT . . . . . . . . . . . . . L NEAR 0DF2 CODE +TSTALL . . . . . . . . . . . . . L NEAR 021E CODE +TWOESC . . . . . . . . . . . . . L NEAR 10E5 CODE +UNPACK . . . . . . . . . . . . . L NEAR 0157 CODE +UPDATE . . . . . . . . . . . . . L NEAR 0CE3 CODE +USERCODE . . . . . . . . . . . . L NEAR 0114 CODE +VALSEC . . . . . . . . . . . . . L WORD 014E DATA +VERFLG . . . . . . . . . . . . . L BYTE 002E CONSTANTS +VERIFY . . . . . . . . . . . . . L NEAR 0117 CODE +WEEKDAY. . . . . . . . . . . . . L BYTE 0049 CONSTANTS +WILDCRD. . . . . . . . . . . . . L NEAR 01FF CODE +WKDAY. . . . . . . . . . . . . . L NEAR 1529 CODE +WRTAUX . . . . . . . . . . . . . L NEAR 0B67 CODE +WRTCON . . . . . . . . . . . . . L NEAR 0B71 CODE +WRTDEV . . . . . . . . . . . . . L NEAR 0B47 CODE +WRTEOF . . . . . . . . . . . . . L NEAR 0CC3 CODE +WRTEOFJ. . . . . . . . . . . . . L NEAR 0BA6 CODE +WRTERR . . . . . . . . . . . . . L NEAR 0B92 CODE +WRTERRJ. . . . . . . . . . . . . L NEAR 0CC0 CODE +WRTFAT . . . . . . . . . . . . . L NEAR 0F8C CODE +WRTFATS. . . . . . . . . . . . . L NEAR 0F66 CODE +WRTLAST. . . . . . . . . . . . . L NEAR 0C79 CODE +WRTLP. . . . . . . . . . . . . . L NEAR 0C51 CODE +WRTLST . . . . . . . . . . . . . L NEAR 0B5B CODE +WRTMID . . . . . . . . . . . . . L NEAR 0C32 CODE +XXX. . . . . . . . . . . . . . . F PROC 0023 DATA Length =0001 +YEAR . . . . . . . . . . . . . . L WORD 0045 CONSTANTS +YRTAB. . . . . . . . . . . . . . L BYTE 1492 CODE +ZEROEXT. . . . . . . . . . . . . Alias FALSE +ZERPOS . . . . . . . . . . . . . L NEAR 1238 CODE + +Warning Severe +Errors Errors +0 0 diff --git a/1_transcription/bundle_2 b/1_transcription/bundle_2 new file mode 100644 index 0000000..6c7ee34 --- /dev/null +++ b/1_transcription/bundle_2 @@ -0,0 +1,4018 @@ + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + + + + + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 + + + + + *START* User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:49:36 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:86DOS.A86<055>[500,500] Created: 07-Jul-81 17:06:59 Printed: 08-Jul-81 13:49:52 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:129 /FORMS:NORMAL + 00010 +00020 ; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +00030 ; by Tim Paterson +00040 +00050 ; ****************** Revision History ************************* +00060 ; >> EVERY change must noted below!! << +00070 ; +00080 ; 0.34 12/29/80 General release, updating all past customers +00090 ; 0.42 02/25/81 32-byte directory entries added +00100 ; 0.56 03/23/81 Variable record and sector sizes +00110 ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +00120 ; 0.74 04/15/81 Recognize I/O devices with file names +00130 ; 0.75 04/17/81 Improve and correct buffer handling +00140 ; 0.76 04/23/81 Correct directory size when not 2^N entries +00150 ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +00160 ; 1.00 04/28/81 Renumber for general release +00170 ; +00180 ; ************************************************************* +00190 +00192 EXCESS: EQU 511 ;Make 86-DOS artificially larger +00194 +00200 ; Use the switch below to generate code to accept the old 16-byte +00210 ; directory entry as well as the new 32-byte entry. +00220 +00230 SMALLDIR: EQU 0 ;1 to enable, 0 to disable +00240 +00250 +00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +00270 ; up a different stack for disk I/O (functions > 11) than that used for +00280 ; character I/O which effectively makes the DOS re-entrant. +00290 +00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +00310 +00320 +00330 ; Interrupt Entry Points: +00340 +00350 ; INTBASE: ABORT +00360 ; INTBASE+4: COMMAND +00370 ; INTBASE+8: BASE EXIT ADDRESS +00380 ; INTBASE+C: CONTROL-C ABORT +00390 ; INTBASE+10H: FATAL ERROR ABORT +00400 ; INTBASE+14H: BIOS DISK READ +00410 ; INTBASE+18H: BIOS DISK WRITE +00420 ; INTBASE+40H: Long jump to CALL entry point +00430 +00440 +00450 MAXCALL:EQU 36 +00460 MAXCOM: EQU 45 +00470 ESCCH: EQU 0 +00480 INTBASE:EQU 80H +00490 INTTAB: EQU 20H +00500 ENTRYPOINTSEG: EQU 0CH +00510 ENTRYPOINT: EQU INTBASE+40H +00520 CONTC: EQU INTTAB+3 +00530 EXIT: EQU INTBASE+8 +00540 LONGJUMP:EQU 0EAH +00550 LONGCALL:EQU 9AH +00560 MAXDIF: EQU 0FFFH +00570 SAVEXIT:EQU 10 +00580 ;Date format +00590 ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 +00600 ; y y y y y y y m m m m d d d d d +00610 ; +00620 ;where y=year,m=month,d=day +00630 +00640 ; Field definition for FCBs +00650 +00660 ORG 0 +00670 DS 12 ;Drive code and name +00680 EXTENT: DS 2 +00690 RECSIZ: DS 2 ;Size of record (user settable) +00700 FILSIZ: DS 4 ;Size of file in bytes +00710 FDATE: DS 2 ;Date of last writing +00720 FILDIRBLK:DS 2 ;Location in directory +00730 FIRCLUS:DS 2 ;First cluster of file +00740 LSTCLUS:DS 2 ;Last cluster accessed +00750 CLUSPOS:DS 2 ;Position of last cluster accessed +00760 DIRTYFIL:DS 1 ;File has been written to if <>0 +00770 ORG 32 +00780 NR: DS 1 ;Next record +00790 RR: DS 3 ;Random record +00800 +00810 +00820 ; Description of 32-byte directory entry (same as returned by SEARCH FIRST +00830 ; and SEARCH NEXT, functions 17 and 18). +00840 +00850 ; Location bytes Description +00860 +00870 ; 0 11 File name and extension ( 0E5H if empty) +00880 ; 11 1 Attributes. Bits 1 or 2 make file hidden +00890 ; 12 12 Zero field (for expansion) +00900 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +00910 ; 26 2 First allocation unit ( < 4080 ) +00920 ; 28 4 File size, in bytes (LSB first, 30 bits max.) +00930 +00940 +00950 ; Field definition for Drive Parameter Block +00960 +00970 ORG 0 +00980 DRVNUM: DS 1 ;Drive number +00990 SECSIZ: DS 2 ;Size of physical sector in bytes +01000 CLUSMSK:DS 1 ;Sectors/cluster - 1 +01010 CLUSSHFT:DS 1 ;Log2 of sectors/cluster +01020 FIRFAT: DS 2 ;Starting record of FATs +01030 FATCNT: DS 1 ;Number of FATs for this drive +01040 MAXENT: DS 2 ;Number of directory entries +01050 DIRSEC: ;Number of dir. sectors (init temporary) +01060 FIRREC: DS 2 ;First sector of first cluster +01070 DSKSIZ: ;Size of disk (temp used during init only) +01080 MAXCLUS:DS 2 ;Number of clusters on drive + 1 +01090 FATSIZ: DS 1 ;Number of records occupied by FAT +01100 FIRDIR: DS 2 ;Starting record of directory +01110 +01120 IF SMALLDIR +01130 FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +01140 MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +01150 FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +01160 MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries +01170 ENDIF +01180 +01190 DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +01200 FAT: ;Start of FAT +01210 DIRSIZ: ;-1=small dir. entry, else large +01220 +01230 +01240 ; BIOS entry point defintions +01250 +01260 BIOSSEG: EQU 60H +01270 ORG 0 +01280 DS 3 +01290 BIOSSTAT: DS 3 +01300 BIOSIN: DS 3 +01310 BIOSOUT: DS 3 +01320 BIOSPRINT: DS 3 +01330 BIOSAUXIN: DS 3 +01340 BIOSAUXOUT: DS 3 +01350 BIOSREAD: DS 3 +01360 BIOSWRITE: DS 3 +01370 BIOSDSKCHG: DS 3 +01380 +01390 +01400 ; Location of user registers relative user stack pointer +01410 +01420 ORG 0 +01430 AXSAVE: DS 2 +01440 BXSAVE: DS 2 +01450 CXSAVE: DS 2 +01460 DXSAVE: DS 2 +01470 SISAVE: DS 2 +01480 DISAVE: DS 2 +01490 BPSAVE: DS 2 +01500 DSSAVE: DS 2 +01510 ESSAVE: DS 2 +01520 IPSAVE: DS 2 +01530 CSSAVE: DS 2 +01540 FSAVE: DS 2 +01550 +01560 +01570 ; Start of code +01580 +01590 ORG 0 +01600 PUT 100H +01610 +01620 JMP DOSINIT +01630 ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +01640 ESCTAB: +01650 DB 77 ;Copy one char--RIGHT ARROW +01660 DB 59 ;Copy one char--F1 +01670 DB 83 ;Skip one char--DELETE +01680 DB 60 ;Copy to char--F2 +01690 DB 62 ;Skip to char--F4 +01700 DB 61 ;Copy line--F3 +01710 DB 64 ;Ctrl-Z--F6 +01720 DB 63 ;Reedit line (new template)--F5 +01730 DB 75 ;Backspace--LEFT ARROW +01740 DB 82 ;Toggle insert mode--INSERT +01750 DB 65 ;Escape character--F7 +01760 DB 65 ;End of table +01770 +01780 ESCTABLEN:EQU $-ESCTAB +01790 +01800 +01810 QUIT: +01820 MOV AH,0 +01830 JP SAVREGS +01840 +01850 COMMAND: ;Interrupt call entry point +01860 CMP AH,MAXCOM +01870 JBE SAVREGS +01880 BADCALL: +01890 MOV AL,0 +01900 IRET: IRET +01910 +01920 ENTRY: ;System call entry point and dispatcher +01930 POP AX ;IP from the long call at 5 +01940 POP AX ;Segment from the long call at 5 +01950 SEG CS +01960 POP [TEMP] ;IP from the CALL 5 +01970 PUSHF ;Start re-ordering the stack +01980 DI +01990 PUSH AX ;Save segment +02000 SEG CS +02010 PUSH [TEMP] ;Stack now ordered as if INT had been used +02020 CMP CL,MAXCALL ;This entry point doesn't get as many calls +02030 JA BADCALL +02040 MOV AH,CL +02050 SAVREGS: +02060 PUSH ES +02070 PUSH DS +02080 PUSH BP +02090 PUSH DI +02100 PUSH SI +02110 PUSH DX +02120 PUSH CX +02130 PUSH BX +02140 PUSH AX +02150 +02160 IF DSKTEST +02170 SEG CS +02180 MOV AX,[SPSAVE] +02190 SEG CS +02200 MOV [NSP],AX +02210 SEG CS +02220 MOV AX,[SSSAVE] +02230 SEG CS +02240 MOV [NSS],AX +02250 POP AX +02260 PUSH AX +02270 ENDIF +02280 +02290 SEG CS +02300 MOV [SPSAVE],SP +02310 SEG CS +02320 MOV [SSSAVE],SS +02330 MOV SP,CS +02340 MOV SS,SP +02350 REDISP: +02360 MOV SP,IOSTACK +02370 EI ;Stack OK now +02380 SEG CS +02390 MOV [FUNC],AH +02400 MOV BL,AH +02410 MOV BH,0 +02420 SHL BX +02430 UP +02440 CMP AH,12 +02450 JLE SAMSTK +02460 MOV SP,DSKSTACK +02470 SAMSTK: +02480 SEG CS +02490 CALL [BX+DISPATCH] +02500 LEAVE: +02510 DI +02520 SEG CS +02530 MOV SP,[SPSAVE] +02540 SEG CS +02550 MOV SS,[SSSAVE] +02560 MOV BP,SP +02570 MOV [BP+AXSAVE],AL +02580 +02590 IF DSKTEST +02600 SEG CS +02610 MOV AX,[NSP] +02620 SEG CS +02630 MOV [SPSAVE],AX +02640 SEG CS +02650 MOV AX,[NSS] +02660 SEG CS +02670 MOV [SSSAVE],AX +02680 ENDIF +02690 +02700 POP AX +02710 POP BX +02720 POP CX +02730 POP DX +02740 POP SI +02750 POP DI +02760 POP BP +02770 POP DS +02780 POP ES +02790 IRET +02800 +02810 DISPATCH: +02820 ; Standard Functions +02830 DW ABORT +02840 DW CONIN +02850 DW CONOUT +02860 DW READER +02870 DW PUNCH +02880 DW LIST +02890 DW RAWIO +02900 DW RAWINP +02910 DW IN +02920 DW PRTBUF +02930 DW BUFIN +02940 DW CONSTAT +02950 DW FLUSHKB +02960 DW DSKRESET +02970 DW SELDSK +02980 DW OPEN +02990 DW CLOSE +03000 DW SRCHFRST +03010 DW SRCHNXT +03020 DW DELETE +03030 DW SEQRD +03040 DW SEQWRT +03050 DW CREATE +03060 DW RENAME +03070 DW INUSE +03080 DW CURDRV +03090 DW SETDMA +03100 DW GETFATPT +03110 DW WRTPROT +03120 DW GETRDONLY +03130 DW SETATTRIB +03140 DW GETDSKPT +03150 DW USERCODE +03160 DW RNDRD +03170 DW RNDWRT +03180 DW FILESIZE +03190 DW SETRNDREC +03200 ; Extended Functions +03210 DW SETVECT +03220 DW NEWBASE +03230 DW BLKRD +03240 DW BLKWRT ;40 +03250 DW MAKEFCB +03260 DW GETDATE +03270 DW SETDATE +03280 DW GETTIME +03290 DW SETTIME ;45 +03300 +03310 GETIO: +03320 SETIO: +03330 WRTPROT: +03340 GETRDONLY: +03350 SETATTRIB: +03360 USERCODE: +03370 INUSE: +03380 GETDSKPT: +03390 MOV AL,0 +03400 RET +03410 +03420 FLUSHKB: +03430 XOR BX,BX +03440 MOV ES,BX ;Select segment 0 +03450 SEG ES +03460 MOV B,[41AH],1EH ;Reset KB queue head pointer +03470 SEG ES +03480 MOV B,[41CH],1EH ;Reset tail pointer +03490 MOV AH,AL +03500 CMP AL,1 +03510 JZ REDISPJ +03512 CMP AL,6 +03514 JZ REDISPJ +03520 CMP AL,7 +03530 JZ REDISPJ +03540 CMP AL,8 +03550 JZ REDISPJ +03560 CMP AL,10 +03570 JZ REDISPJ +03575 MOV AL,0 +03580 RET +03590 +03600 REDISPJ:JMP REDISP +03610 +03620 READER: +03630 AUXIN: +03640 CALL STATCHK +03650 CALL BIOSAUXIN,BIOSSEG +03660 RET +03670 +03680 PUNCH: +03690 MOV AL,DL +03700 AUXOUT: +03710 PUSH AX +03720 CALL STATCHK +03730 POP AX +03740 CALL BIOSAUXOUT,BIOSSEG +03750 RET +03760 +03770 +03780 UNPACK: +03790 +03800 ; Inputs: +03810 ; DS = CS +03820 ; BX = Cluster number +03830 ; BP = Base of drive parameters +03840 ; SI = Pointer to drive FAT +03850 ; Outputs: +03860 ; DI = Contents of FAT for given cluster +03870 ; Zero set means DI=0 (free cluster) +03880 ; No other registers affected. Fatal error if cluster too big. +03890 +03900 CMP BX,[BP+MAXCLUS] +03910 JA HURTFAT +03920 LEA DI,[SI+BX] +03930 SHR BX +03940 MOV DI,[DI+BX] +03950 JNC HAVCLUS +03960 SHR DI +03970 SHR DI +03980 SHR DI +03990 SHR DI +04000 STC +04010 HAVCLUS: +04020 RCL BX +04030 AND DI,0FFFH +04040 RET +04050 +04060 HURTFAT: +04070 PUSH AX +04080 MOV AH,80H +04090 MOV DI,0FFFH +04100 CALL FATAL +04110 POP AX +04120 RET +04130 +04140 +04150 PACK: +04160 +04170 ; Inputs: +04180 ; DS = CS +04190 ; BX = Cluster number +04200 ; DX = Data +04210 ; SI = Pointer to drive FAT +04220 ; Outputs: +04230 ; The data is stored in the FAT at the given cluster. +04240 ; BX,DX,DI all destroyed +04250 ; No other registers affected +04260 +04270 MOV DI,BX +04280 SHR BX +04290 ADD BX,SI +04300 ADD BX,DI +04310 SHR DI +04320 MOV DI,[BX] +04330 JNC ALIGNED +04340 SHL DX +04350 SHL DX +04360 SHL DX +04370 SHL DX +04380 AND DI,0FH +04390 JP PACKIN +04400 ALIGNED: +04410 AND DI,0F000H +04420 PACKIN: +04430 OR DI,DX +04440 MOV [BX],DI +04450 RET +04452 +04454 DEVNAME: +04455 MOV SI,IONAME ;List of I/O devices with file names +04456 MOV BL,6 ;BL = number of device names +04457 LOOKIO: +04458 MOV DI,NAME1 +04459 MOV CX,4 ;All device names are 4 letters +04460 REPE +04461 CMPB ;Check for name in list +04462 JZ IOCHK ;If first 4 letters OK, check the rest +04463 ADD SI,CX ;Point to next device name +04464 DEC BL +04465 JNZ LOOKIO +04466 CRET: +04467 STC +04468 RET +04470 IOCHK: +04480 MOV CX,4 ;Check rest of name but not extension +04490 MOV AL," " +04500 REPE +04510 SCAB ;Make sure rest of name is blanks +04520 JNZ CRET +04530 MOV AL,BL +04540 MOV BX,IONUM-1 +04550 XLAT ;Translate to internal device number +04560 MOV BL,AL +04570 MOV BH,-1 +04580 RET +04590 +04600 GETFILE: +04610 ; Same as GETNAME except ES:DI points to FCB on successful return +04620 CALL MOVNAME +04630 JC RET +04640 PUSH DX +04650 PUSH DS +04660 CALL FINDNAME +04670 POP ES +04680 POP DI +04690 RET +04700 +04710 GETNAME: +04720 +04730 ; Inputs: +04740 ; DS,DX point to FCB +04750 ; Function: +04760 ; Find file name in disk directory. First byte is +04770 ; drive number (0=current disk). "?" matches any +04780 ; character. +04790 ; Outputs: +04800 ; Carry set if file not found +04810 ; ELSE +04820 ; Zero set if attributes match (always except when creating) +04830 ; BP = Base of drive parameters +04840 ; DS = CS +04850 ; ES = CS +04860 ; BX = Pointer into directory buffer +04870 ; SI = Pointer to First Cluster field in directory entry +04880 ; [DIRBUF] has directory record with match +04890 ; [NAME1] has file name +04900 ; All other registers destroyed. +04910 +04920 CALL MOVNAME +04930 JC RET ;Bad file name? +04940 FINDNAME: +04950 MOV AX,CS +04960 MOV DS,AX +04961 CALL DEVNAME +04962 JNC RET +05090 CALL STARTSRCH +05100 CONTSRCH: +05110 CALL GETENTRY +05120 JC RET +05130 SRCH: +05140 CMP B,[BX],0E5H +05150 JZ NEXTENT +05160 MOV SI,BX +05170 MOV DI,NAME1 +05180 MOV CX,11 +05190 WILDCRD: +05200 REPE +05210 CMPB +05220 JZ FOUND +05230 CMP B,[DI-1],"?" +05240 JZ WILDCRD +05250 NEXTENT: +05260 CALL NEXTENTRY +05270 JNC SRCH +05280 RET +05290 +05300 FOUND: +05310 +05320 IF SMALLDIR +05330 CMP B,[BP+DIRSIZ],-1 +05340 JZ RET +05350 ENDIF +05360 +05370 ;Check if attributes allow finding it +05380 MOV AH,[ATTRIB] ;Attributes of search +05390 NOT AH +05400 AND AH,[SI] ;Compare with attributes of file +05410 ADD SI,15 +05420 AND AH,6 ;Only look at bits 1 and 2 +05430 JZ RET +05440 TEST B,[CREATING],-1 +05450 JZ NEXTENT +05460 RET +05470 +05480 +05490 GETENTRY: +05500 +05510 ; Inputs: +05520 ; [LASTENT] has previously searched directory entry +05530 ; Function: +05540 ; Locates next sequential directory entry in preparation for search +05550 ; Outputs: +05560 ; Carry set if none +05570 ; ELSE +05580 ; AL = Current directory block +05590 ; BX = Pointer to next directory entry in [DIRBUF] +05600 ; DX = Pointer to first byte after end of DIRBUF +05610 ; [LASTENT] = New directory entry number +05620 +05630 MOV AX,[LASTENT] +05640 INC AX ;Start with next entry +05650 CMP AX,[BP+MAXENT] +05660 JAE NONE +05670 GETENT: +05680 MOV [LASTENT],AX +05690 MOV CL,4 +05700 SHL AX,CL +05710 XOR DX,DX +05720 +05730 IF SMALLDIR +05740 CMP B,[BP+DIRSIZ],-1 +05750 JZ SMALENT1 +05760 ENDIF +05770 +05780 SHL AX +05790 RCL DX ;Account for overflow in last shift +05800 SMALENT1: +05810 MOV BX,[BP+SECSIZ] +05820 AND BL,255-31 ;Must be multiple of 32 +05830 DIV AX,BX +05840 MOV BX,DX ;Position within sector +05850 MOV AH,[BP+DRVNUM] ;AL=Directory sector no. +05860 CMP AX,[DIRBUFID] +05870 JZ HAVDIRBUF +05880 PUSH BX +05890 CALL DIRREAD +05900 POP BX +05910 HAVDIRBUF: +05920 MOV DX,DIRBUF +05930 ADD BX,DX +05940 ADD DX,[BP+SECSIZ] +05950 RET +05960 +05970 NEXTENTRY: +05980 +05990 ; Inputs: +06000 ; Same as outputs of GETENTRY, above +06010 ; Function: +06020 ; Update AL, BX, and [LASTENT] for next directory entry. +06030 ; Carry set if no more. +06040 +06050 MOV DI,[LASTENT] +06060 INC DI +06070 CMP DI,[BP+MAXENT] +06080 JAE NONE +06090 MOV [LASTENT],DI +06100 ADD BX,32 +06110 +06120 IF SMALLDIR +06130 CMP B,[BP+DIRSIZ],-1 +06140 JNZ BIGENT3 +06150 SUB BX,16 +06160 BIGENT3: +06170 ENDIF +06180 +06190 CMP BX,DX +06200 JB HAVIT +06210 INC AL ;Next directory sector +06220 PUSH DX ;Save limit +06230 CALL DIRREAD +06240 POP DX +06250 MOV BX,DIRBUF +06260 HAVIT: +06270 CLC +06280 RET +06290 +06300 NONE: +06310 CALL CHKDIRWRITE +06320 STC +06330 RET +06340 +06350 +06360 DELETE: ; System call 19 +06370 CALL GETNAME +06375 MOV AL,-1 +06380 JC RET +06390 CMP BH,AL ;Check if device name +06400 JZ RET ;Can't delete I/O devices +06410 DELFILE: +06420 MOV B,[DIRTYDIR],-1 +06430 MOV B,[BX],0E5H +06440 MOV BX,[SI] +06450 LEA SI,[BP+FAT] +06460 OR BX,BX +06470 JZ DELNXT +06480 CMP BX,[BP+MAXCLUS] +06490 JA DELNXT +06500 CALL RELEASE +06510 DELNXT: +06520 CALL CONTSRCH +06530 JNC DELFILE +06540 CALL FATWRT +06550 CALL CHKDIRWRITE +06560 XOR AL,AL +06570 RET +06580 +06590 +06600 RENAME: ;System call 23 +06610 CALL MOVNAME +06620 JC ERRET +06650 ADD SI,5 +06660 MOV DI,NAME2 +06670 CALL LODNAME +06675 JC ERRET +06680 CALL FINDNAME +06690 JC ERRET +06692 CMP BH,-1 ;Check if I/O device name +06694 JZ ERRET ;If so, can't rename it +06700 MOV SI,NAME1 +06710 MOV DI,NAME3 +06720 MOV CX,6 ;Include attribute byte +06730 REP +06740 MOVW ;Copy name to search for +06750 RENFIL: +06760 MOV DI,NAME1 +06770 MOV SI,NAME2 +06780 MOV CX,11 +06790 NEWNAM: +06800 LODB +06810 CMP AL,"?" +06820 JNZ NOCHG +06830 MOV AL,[BX] +06840 NOCHG: +06850 STOB +06860 INC BX +06870 LOOP NEWNAM +06871 MOV B,[DI],6 ;Stop duplicates with any attributes +06872 CALL DEVNAME ;Check if giving it a device name +06874 JNC RENERR +06890 PUSH [LASTENT] ;Save position of match +06895 MOV [LASTENT],-1 ;Search entire dirctory for duplicate +06900 CALL CONTSRCH ;See if new name already exists +06910 POP AX +06920 JNC RENERR ;Error if found +06930 CALL GETENT ;Re-read matching entry +06940 MOV DI,BX +06950 MOV SI,NAME1 +06960 MOV CX,11 +06970 REP +06980 MOVB ;Replace old name with new +06990 MOV B,[DIRTYDIR],-1 ;Flag change in directory +07000 MOV SI,NAME3 +07010 MOV DI,NAME1 +07020 MOV CX,6 ;Include attribute byte +07030 REP +07040 MOVW ;Copy name back into search buffer +07050 CALL CONTSRCH +07060 JNC RENFIL +07070 CALL CHKDIRWRITE +07080 XOR AL,AL +07090 RET +07100 +07102 RENERR: +07104 CALL CHKDIRWRITE +07110 ERRET: +07120 MOV AL,-1 +07130 RET +07140 +07150 +07160 MOVNAME: +07170 +07180 ; Inputs: +07190 ; DS, DX point to FCB or extended FCB +07200 ; Outputs: +07210 ; DS:DX point to normal FCB +07220 ; ES = CS +07230 ; If file name OK: +07240 ; BP has base of driver parameters +07250 ; [NAME1] has name in upper case +07260 ; All registers except DX destroyed +07270 ; Carry set if bad file name or drive +07280 +07290 SEG CS +07300 MOV B,[CREATING],0 +07310 MOV AX,CS +07320 MOV ES,AX +07330 MOV DI,NAME1 +07340 MOV SI,DX +07350 LODB +07360 SEG CS +07370 MOV [EXTFCB],AL +07380 MOV AH,0 +07390 CMP AL,-1 +07400 JNZ HAVATTRB +07410 ADD DX,7 +07420 ADD SI,6 +07430 MOV AH,[SI-1] +07440 LODB +07450 HAVATTRB: +07460 SEG CS +07470 MOV [ATTRIB],AH +07480 CALL GETBP +07490 JB RET +07500 LODNAME: +07510 ; This entry point copies a file name from DS,SI +07520 ; to ES,DI converting to upper case. +07522 CMP B,[SI]," " ;First letter may not be blank +07524 STC ;Ready to indicate error +07526 JZ RET +07530 MOV CX,11 +07540 MOVCHK: +07550 CALL GETLET +07560 JNZ CTRLCHK ;Is it a delimiter? +07570 CMP AL," " ;This is the only delimiter allowed +07580 STC ;In case of error +07590 JNZ RET +07600 CTRLCHK: +07610 CMP AL,20H +07620 JC RET +07630 STOB +07640 LOOP MOVCHK +07650 RET +07660 +07670 GETBP: +07680 SEG CS +07690 CMP [NUMDRV],AL +07700 JC RET +07710 CBW +07720 XCHG BP,AX +07730 SHL BP +07740 MOV BP,[BP+CURDRVPT] +07750 RET +07760 +07770 +07780 OPEN: ;System call 15 +07790 CALL GETFILE +07800 DOOPEN: +07810 ; Enter here to perform OPEN on file already found +07820 ; in directory. DS=CS, BX points to directory +07830 ; entry in DIRBUF, SI points to First Cluster field, and +07840 ; ES:DI point to the FCB to be opened. This entry point +07850 ; is used by CREATE. +07860 JC ERRET +07870 CMP BH,-1 ;Check if file is I/O device +07880 JZ OPENDEV ;Special handler if so +07890 MOV AL,[BP+DRVNUM] +07900 INC AL +07910 STOB +07920 ADD DI,11 ;Point to extent field +07930 XOR AX,AX +07940 STOW ;Set extent field to 0 +07950 MOV AX,128 ;Default record size +07960 STOW ;Set record size +07970 LODW ;Get starting cluster +07980 MOV DX,AX ;Save it for the moment +07990 MOVW ;Transfer size to FCB +08000 MOVW +08010 MOV AX,[SI-8] ;Get date +08020 +08030 IF SMALLDIR +08040 CMP B,[BP+DIRSIZ],-1 +08050 JNZ BIGENT10 +08060 SEG ES +08070 MOV [DI-1],0 +08080 XOR AX,AX ;Date not available in small entry +08090 BIGENT10: +08100 ENDIF +08110 +08120 STOW ;Save date in FCB +08130 MOV AX,[LASTENT] +08140 STOW ;directory location +08150 MOV AX,DX ;Restore starting cluster +08160 STOW ; first cluster +08170 STOW ; last cluster accessed +08180 XOR AX,AX +08190 STOW ; position of last cluster +08200 STOB ; dirty flag +08210 RET +08220 +08230 OPENDEV: +08240 SEG ES +08250 MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag +08260 XOR AL,AL +08270 RET +08280 +08290 +08300 STARTSRCH: +08310 MOV [LASTENT],-1 +08320 FATREAD: +08330 +08340 ; Inputs: +08350 ; DS = CS +08360 ; BP = Base of drive parameters +08370 ; Function: +08380 ; If disk may have been changed, FAT is read in and buffers are +08390 ; flagged invalid. If not, no action is taken. +08400 ; Outputs: +08410 ; AL = 0 +08420 ; BP unchanged +08430 ; All other registers destroyed +08440 +08450 MOV AL,[BP+DRVNUM] +08460 CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say +08470 MOV AL,[BP+DRVNUM] +08480 OR AH,[BP+DIRTYFAT] +08490 JS NEWDSK ;If either say new disk, then it's so +08500 DEC AH ;Check for AH=1 (disk not changed) +08510 JZ RET +08520 MOV AH,1 +08530 CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? +08540 JZ RET ;If so, disk has not been changed +08550 NEWDSK: +08560 CMP AL,[BUFDRVNO] ;See if buffer is for this drive +08570 JNZ BUFOK ;If not, don't touch it +08580 MOV [BUFSECNO],0 ;Flag buffers invalid +08590 MOV [BUFDRVNO],00FFH +08600 BUFOK: +08610 MOV [DIRBUFID],-1 +08620 CALL FIGFAT +08630 NEXTFAT: +08640 PUSH AX +08650 CALL DSKREAD +08660 POP AX +08670 JC BADFAT +08680 +08690 IF SMALLDIR +08700 MOV DL,AL +08710 LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries +08720 CMP B,[BP+DIRSIZ],-1 +08730 JZ SETSIZ +08740 ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +08750 SETSIZ: +08760 LODW +08770 MOV [BP+FIRREC],AX +08780 LODW +08790 MOV [BP+MAXCLUS],AX +08800 MOV AL,DL +08810 ENDIF +08820 +08830 SUB AL,[BP+FATCNT] +08840 JZ RET +08850 NEG AL +08860 ;{Insert error code here. AL=number of bad fats. +08870 ;Since one good FAT was read, should include option +08880 ;to rewrite all FATs.} +08890 JMP FATWRT +08900 +08910 BADFAT: +08920 MOV CX,DI +08930 ADD DX,CX +08940 DEC AL +08950 JNZ NEXTFAT +08960 CALL FIGFAT ;Reset registers +08970 JMP DREAD ;Try first FAT once more +08980 +08990 OKRET1: +09000 MOV AL,0 +09010 RET +09020 +09030 CLOSE: ;System call 16 +09040 MOV DI,DX +09050 CMP B,[DI],-1 +09060 JNZ NORMFCB3 +09070 ADD DI,7 +09080 NORMFCB3: +09090 CMP B,[DI+FILDIRBLK+1],-1 ;Check for I/O device +09100 JZ OKRET1 ;Can't close I/O device +09110 TEST B,[DI+DIRTYFIL],-1 +09120 JZ OKRET1 ;If not written to, do nothing +09130 MOV AL,[DI] ;Get drive number +09140 CALL GETBP ;Get base of drive parameters +09150 JC BADCLOSEJ +09160 MOV AL,[BP+DRVNUM] +09170 MOV AH,1 ;Look for dirty buffer +09180 SEG CS +09190 CMP AX,[BUFDRVNO] +09200 JNZ FNDDIR +09210 ;Write back dirty buffer if on same drive +09220 PUSH DX +09230 PUSH DS +09240 PUSH CS +09250 POP DS +09260 MOV B,[DIRTYBUF],0 +09270 MOV BX,[BUFFER] +09280 MOV CX,1 +09290 MOV DX,[BUFSECNO] +09300 CALL DWRITE +09310 POP DS +09320 POP DX +09330 FNDDIR: +09340 CALL GETFILE +09350 BADCLOSEJ: +09360 JC BADCLOSE +09370 MOV AX,[LASTENT] +09380 SEG ES +09390 CMP AX,[DI+FILDIRBLK] +09400 JNZ BADCLOSE +09410 SEG ES +09420 MOV CX,[DI+FIRCLUS] +09430 MOV [SI],CX +09440 SEG ES +09450 MOV DX,[DI+FILSIZ] +09460 MOV [SI+2],DX +09470 SEG ES +09480 MOV DX,[DI+FILSIZ+2] +09490 +09500 IF SMALLDIR +09510 CMP B,[BP+DIRSIZ],-1 +09520 JNZ BIGENT11 +09530 MOV [SI+4],DL +09540 JP SMALLENT2 +09550 BIGENT11: +09560 ENDIF +09570 +09580 MOV [SI+4],DX +09590 SEG ES +09600 MOV DX,[DI+FDATE] +09610 MOV [SI-2],DX +09620 SMALLENT2: +09630 CALL DIRWRITE +09640 +09650 CHKFATWRT: +09660 ; Do FATWRT only if FAT is dirty +09670 +09680 CMP B,[BP+DIRTYFAT],1 +09690 JNZ OKRET +09700 +09710 FATWRT: +09720 +09730 ; Inputs: +09740 ; DS = CS +09750 ; BP = Base of drive parameter table +09760 ; Function: +09770 ; Write the FAT back to disk and reset FAT +09780 ; dirty bit. +09790 ; Outputs: +09800 ; AL = 0 +09810 ; BP unchanged +09820 ; All other registers destroyed +09830 +09840 MOV B,[BP+DIRTYFAT],0 +09850 CALL FIGFAT +09860 EACHFAT: +09870 PUSH DX +09880 PUSH CX +09890 PUSH BX +09900 PUSH AX +09910 CALL DWRITE +09920 POP AX +09930 POP BX +09940 POP CX +09950 POP DX +09960 ADD DX,CX +09970 DEC AL +09980 JNZ EACHFAT +09990 OKRET: +10000 MOV AL,0 +10010 RET +10020 +10030 BADCLOSE: +10040 MOV B,[BP+DIRTYFAT],0 +10050 MOV AL,-1 +10060 RET +10070 +10080 +10090 FIGFAT: +10100 ; Loads registers with values needed to read or +10110 ; write a FAT. +10120 MOV AL,[BP+FATCNT] +10130 LEA BX,[BP+FAT] +10140 MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT +10150 MOV CH,0 +10160 MOV DX,[BP+FIRFAT] ;Record number of start of FATs +10170 RET +10180 +10190 +10200 DIRCOMP: +10210 ; Prepare registers for directory read or write +10220 CBW +10230 ADD AX,[BP+FIRDIR] +10240 MOV DX,AX +10250 MOV BX,DIRBUF +10260 MOV CX,1 +10270 RET +10280 +10290 +10300 CREATE: ;System call 22 +10310 CALL MOVNAME +10320 JC ERRET3 +10330 MOV DI,NAME1 +10340 MOV CX,11 +10350 MOV AL,"?" +10360 REPNE +10370 SCAB +10380 JZ ERRET3 +10390 SEG CS +10400 MOV B,[CREATING],1 +10410 PUSH DX +10420 PUSH DS +10430 CALL FINDNAME +10440 JNC EXISTENT +10450 CALL STARTSRCH +10460 CALL GETENTRY +10470 LOOKFRE: +10480 CMP B,[BX],0E5H +10490 JZ FREESPOT +10500 CALL NEXTENTRY +10510 JNC LOOKFRE +10520 ERRPOP: +10530 POP DS +10540 POP DX +10550 ERRET3: +10560 MOV AL,-1 +10570 RET +10580 +10590 EXISTENT: +10600 JNZ ERRPOP ;Error if attributes don't match +10610 CMP BH,-1 ;Check if file is I/O device +10620 JZ OPENJMP ;If so, no action +10630 MOV CX,[SI] ;Get pointer to clusters +10640 JCXZ FREESPOT +10650 CMP CX,[BP+MAXCLUS] +10660 JA FREESPOT +10670 PUSH BX +10680 MOV BX,CX +10690 LEA SI,[BP+FAT] +10700 CALL RELEASE ;Free any data already allocated +10710 CALL FATWRT +10720 POP BX +10730 FREESPOT: +10740 MOV DI,BX +10750 MOV SI,NAME1 +10760 MOV CX,5 +10770 MOVB +10780 REP +10790 MOVW +10800 +10810 IF SMALLDIR +10820 CMP B,[BP+DIRSIZ],-1 +10830 JNZ BIGENT4 +10840 PUSH DI +10850 MOV CL,5 +10860 XOR AX,AX +10870 JP SMALLENT +10880 BIGENT4: +10890 ENDIF +10900 +10910 MOV AL,[ATTRIB] +10920 STOB +10930 XOR AX,AX +10940 MOV CL,6 +10950 REP +10960 STOW +10970 CALL DATE16 +10980 STOW +10990 XOR AX,AX +11000 PUSH DI +11010 MOV CL,6 +11020 SMALLENT: +11030 REP +11040 STOB +11050 PUSH BX +11060 CALL DIRWRITE +11070 POP BX +11080 POP SI +11090 OPENJMP: +11100 CLC ;Clear carry so OPEN won't fail +11110 POP ES +11120 POP DI +11130 JMP DOOPEN +11140 +11150 +11160 DIRREAD: +11170 +11180 ; Inputs: +11190 ; DS = CS +11200 ; AL = Directory block number +11210 ; BP = Base of drive parameters +11220 ; Function: +11230 ; Read the directory block into DIRBUF. +11240 ; Outputs: +11250 ; AX,BP unchanged +11260 ; All other registers destroyed. +11270 +11280 PUSH AX +11290 CALL CHKDIRWRITE +11300 POP AX +11310 PUSH AX +11320 MOV AH,[BP+DRVNUM] +11330 MOV [DIRBUFID],AX +11340 CALL DIRCOMP +11350 CALL DREAD +11360 POP AX +11370 RET +11380 +11390 +11400 DREAD: +11410 +11420 ; Inputs: +11430 ; BX,DS = Transfer address +11440 ; CX = Number of sectors +11450 ; DX = Absolute record number +11460 ; BP = Base of drive parameters +11470 ; Function: +11480 ; Calls BIOS to perform disk read. If BIOS reports +11490 ; errors, will call HARDERR for further action. +11500 ; BP preserved. All other registers destroyed. +11510 +11520 CALL DSKREAD +11530 JNC RET +11540 SEG CS +11550 MOV B,[READOP],0 +11560 CALL HARDERR +11570 CMP AL,1 ;Check for retry +11580 JZ DREAD +11590 RET ;Ignore otherwise +11600 +11610 HARDERR: +11620 ;Hard disk error handler. Entry conditions: +11630 ; DS:BX = Original disk transfer address +11640 ; DX = Original logical sector number +11650 ; CX = Number of sectors to go (first one gave the error) +11660 ; AX = Hardware error code +11670 ; DI = Original sector transfer count +11680 ; BP = Base of drive parameters +11690 ; [READOP] = 0 for read, 1 for write +11700 +11710 XCHG AX,DI ;Error code in DI, count in AX +11720 SUB AX,CX ;Number of sectors successfully transferred +11730 ADD DX,AX ;First sector number to retry +11740 PUSH DX +11750 MUL AX,[BP+SECSIZ] ;Number of bytes transferred +11760 POP DX +11770 ADD BX,AX ;First address for retry +11780 MOV AH,0 ;Flag disk section in error +11790 CMP DX,[BP+FIRFAT] ;In reserved area? +11800 JB ERRINT +11810 INC AH ;Flag for FAT +11820 CMP DX,[FIRDIR] ;In FAT? +11830 JB ERRINT +11840 INC AH +11850 CMP DX,[FIRREC] ;In directory? +11860 JB ERRINT +11870 INC AH ;Must be in data area +11880 ERRINT: +11890 SHL AH ;Make room for read/write bit +11900 SEG CS +11910 OR AH,[READOP] +11920 FATAL: +11930 MOV AL,[BP+DRVNUM] ;Get drive number +11940 PUSH BP ;The only thing we preserve +11950 SEG CS +11960 MOV [CONTSTK],SP +11970 DI ;Prepare to play with stack +11980 SEG CS +11990 MOV SS,[SSSAVE] +12000 SEG CS +12010 MOV SP,[SPSAVE] ;User stack pointer restored +12020 INT 24H ;Fatal error interrupt vector +12030 SEG CS +12040 MOV [SPSAVE],SP +12050 SEG CS +12060 MOV [SSSAVE],SS +12070 MOV SP,CS +12080 MOV SS,SP +12090 SEG CS +12100 MOV SP,[CONTSTK] +12110 EI +12120 POP BP +12130 CMP AL,2 +12140 JZ ERROR +12150 RET +12160 +12170 DSKREAD: +12180 MOV AL,[BP+DRVNUM] +12190 PUSH BP +12200 PUSH BX +12210 PUSH CX +12220 PUSH DX +12230 CALL BIOSREAD,BIOSSEG +12240 POP DX +12250 POP DI +12260 POP BX +12270 POP BP +12280 RET +12290 +12300 +12310 CHKDIRWRITE: +12320 TEST B,[DIRTYDIR],-1 +12330 JZ RET +12340 +12350 DIRWRITE: +12360 +12370 ; Inputs: +12380 ; DS = CS +12390 ; AL = Directory block number +12400 ; BP = Base of drive parameters +12410 ; Function: +12420 ; Write the directory block into DIRBUF. +12430 ; Outputs: +12440 ; BP unchanged +12450 ; All other registers destroyed. +12460 +12470 MOV B,[DIRTYDIR],0 +12480 MOV AL,[DIRBUFID] +12490 CALL DIRCOMP +12500 +12510 +12520 DWRITE: +12530 +12540 ; Inputs: +12550 ; BX,DS = Transfer address +12560 ; CX = Number of sectors +12570 ; DX = Absolute record number +12580 ; BP = Base of drive parameters +12590 ; Function: +12600 ; Calls BIOS to perform disk write. If BIOS reports +12610 ; errors, will call HARDERR for further action. +12620 ; BP preserved. All other registers destroyed. +12630 +12640 MOV AL,[BP+DRVNUM] +12650 PUSH BP +12660 PUSH BX +12670 PUSH CX +12680 PUSH DX +12690 CALL BIOSWRITE,BIOSSEG +12700 POP DX +12710 POP DI +12720 POP BX +12730 POP BP +12740 JNC RET +12750 SEG CS +12760 MOV B,[READOP],1 +12770 CALL HARDERR +12780 CMP AL,1 ;Check for retry +12790 JZ DWRITE +12800 RET +12810 +12820 ABORT: +12830 SEG CS +12840 LDS SI,[SPSAVE] +12850 MOV DS,[SI+CSSAVE] +12860 XOR AX,AX +12870 MOV ES,AX +12880 MOV SI,SAVEXIT +12890 MOV DI,EXIT +12900 MOVW +12910 MOVW +12920 MOVW +12930 MOVW +12940 ERROR: +12950 MOV AX,CS +12960 MOV DS,AX +12970 MOV ES,AX +12980 CALL WRTFATS +12990 XOR AX,AX +13000 DI +13010 MOV SS,[SSSAVE] +13020 MOV SP,[SPSAVE] +13030 MOV DS,AX +13040 MOV SI,EXIT +13050 MOV DI,EXITHOLD +13060 MOVW +13070 MOVW +13080 POP AX +13090 POP BX +13100 POP CX +13110 POP DX +13120 POP SI +13130 POP DI +13140 POP BP +13150 POP DS +13160 POP ES +13170 EI ;Stack OK now +13180 SEG CS +13190 JMP L,[EXITHOLD] +13200 +13210 +13220 SEQRD: ;System call 20 +13230 CALL GETREC +13240 CALL LOAD +13250 JP FINSEQ +13260 +13270 SEQWRT: ;System call 21 +13280 CALL GETREC +13290 CALL STORE +13300 FINSEQ: +13310 JCXZ SETNREX +13320 ADD AX,1 +13330 ADC DX,0 +13340 JP SETNREX +13350 +13360 RNDRD: ;System call 33 +13370 CALL GETRRPOS1 +13380 CALL LOAD +13390 JP FINRND +13400 +13410 RNDWRT: ;System call 34 +13420 CALL GETRRPOS1 +13430 CALL STORE +13440 JP FINRND +13450 +13460 BLKRD: ;System call 39 +13470 CALL GETRRPOS +13480 CALL LOAD +13490 JP FINBLK +13500 +13510 BLKWRT: ;System call 40 +13520 CALL GETRRPOS +13530 CALL STORE +13540 FINBLK: +13550 LDS SI,[SPSAVE] +13560 MOV [SI+CXSAVE],CX +13570 JCXZ FINRND +13580 ADD AX,1 +13590 ADC DX,0 +13600 FINRND: +13610 SEG ES +13620 MOV [DI+RR],AX +13630 SEG ES +13640 MOV [DI+RR+2],DL +13650 OR DH,DH +13660 JZ SETNREX +13670 SEG ES +13680 MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +13690 SETNREX: +13700 MOV CX,AX +13710 AND AL,7FH +13720 SEG ES +13730 MOV [DI+NR],AL +13740 AND CL,80H +13750 SHL CX +13760 RCL DX +13770 MOV AL,CH +13780 MOV AH,DL +13790 SEG ES +13800 MOV [DI+EXTENT],AX +13810 SEG CS +13820 MOV AL,[DSKERR] +13830 RET +13840 +13850 GETRRPOS1: +13860 MOV CX,1 +13870 GETRRPOS: +13880 MOV DI,DX +13890 CMP B,[DI],-1 +13900 JNZ NORMFCB1 +13910 ADD DI,7 +13920 NORMFCB1: +13930 MOV AX,[DI+RR] +13940 MOV DX,[DI+RR+2] +13950 RET +13960 +13970 NOFILERR: +13980 XOR CX,CX +13990 MOV B,[DSKERR],4 +14000 POP BX +14010 RET +14020 +14030 SETUP: +14040 +14050 ; Inputs: +14060 ; DS:DI point to FCB +14070 ; DX:AX = Record position in file of disk transfer +14080 ; CX = Record count +14090 ; Outputs: +14100 ; DS = CS +14110 ; ES:DI point to FCB +14120 ; CX = No. of bytes to transfer +14130 ; BP = Base of drive parameters +14140 ; SI = FAT pointer +14150 ; [RECCNT] = Record count +14160 ; [RECPOS] = Record position in file +14170 ; [FCB] = DI +14180 ; [NEXTADD] = Displacement of disk transfer within segment +14190 ; [SECPOS] = Position of first sector +14200 ; [BYTPOS] = Byte position in file +14210 ; [BYTSECPOS] = Byte position in first sector +14220 ; [CLUSNUM] = First cluster +14230 ; [SECCLUSPOS] = Sector within first cluster +14240 ; [DSKERR] = 0 (no errors yet) +14250 ; [TRANS] = 0 (No transfers yet) +14260 ; If SETUP detects no records will be transfered, it returns 1 level up +14270 ; with CX = 0. +14280 +14290 PUSH AX +14300 MOV AL,[DI] +14310 MOV SI,[DI+RECSIZ] +14320 OR SI,SI +14330 JNZ HAVRECSIZ +14340 MOV SI,128 +14350 MOV [DI+RECSIZ],SI +14360 HAVRECSIZ: +14370 MOV BX,DS +14380 MOV ES,BX +14390 MOV BX,CS +14400 MOV DS,BX +14410 CALL GETBP +14420 POP AX +14430 JC NOFILERR +14440 CMP SI,64 ;Check if highest byte of RECPOS is significant +14450 JB SMALREC +14460 MOV DH,0 ;Ignore MSB if record >= 64 bytes +14470 SMALREC: +14480 MOV [RECCNT],CX +14490 MOV [RECPOS],AX +14500 MOV [RECPOS+2],DX +14510 MOV [FCB],DI +14520 MOV BX,[DMAADD] +14530 MOV [NEXTADD],BX +14540 MOV B,[DSKERR],0 +14550 MOV B,[TRANS],0 +14560 MOV BX,DX +14570 MUL AX,SI +14580 MOV [BYTPOS],AX +14590 PUSH DX +14600 MOV AX,BX +14610 MUL AX,SI +14620 POP BX +14630 ADD AX,BX +14640 ADC DX,0 ;Ripple carry +14650 JNZ EOFERR +14660 MOV [BYTPOS+2],AX +14670 MOV DX,AX +14680 MOV AX,[BYTPOS] +14690 MOV BX,[BP+SECSIZ] +14700 CMP DX,BX ;See if divide will overflow +14710 JNC EOFERR +14720 DIV AX,BX +14730 MOV [SECPOS],AX +14740 MOV [BYTSECPOS],DX +14750 MOV DX,AX +14760 AND AL,[BP+CLUSMSK] +14770 MOV [SECCLUSPOS],AL +14780 MOV AX,CX ;Record count +14790 MOV CL,[BP+CLUSSHFT] +14800 SHR DX,CL +14810 MOV [CLUSNUM],DX +14820 MUL AX,SI ;Multiply by bytes per record +14830 MOV CX,AX +14840 ADD AX,[DMAADD] ;See if it will fit in one segment +14850 ADC DX,0 +14860 JZ OK ;Must be less than 64K +14870 MOV AX,[DMAADD] +14880 NEG AX ;Amount of room left in segment +14890 JNZ PARTSEG ;All 64K available? +14900 DEC AX ;If so, reduce it by one +14910 PARTSEG: +14920 XOR DX,DX +14930 DIV AX,SI ;How many records will fit? +14940 MOV [RECCNT],AX +14950 MUL AX,SI ;Translate that back into bytes +14960 MOV B,[DSKERR],2 ;Flag that trimming took place +14970 MOV CX,AX +14980 JCXZ NOROOM +14990 OK: +15000 LEA SI,[BP+FAT] +15010 RET +15020 +15030 EOFERR: +15040 MOV B,[DSKERR],1 +15050 XOR CX,CX +15060 NOROOM: +15070 POP BX ;Kill return address +15080 RET +15090 +15100 BREAKDOWN: +15110 +15120 ;Inputs: +15130 ; DS = CS +15140 ; CX = Length of disk transfer in bytes +15150 ; BP = Base of drive parameters +15160 ; [BYTSECPOS] = Byte position witin first sector +15170 ;Outputs: +15180 ; [BYTCNT1] = Bytes to transfer in first sector +15190 ; [SECCNT] = No. of whole sectors to transfer +15200 ; [BYTCNT2] = Bytes to transfer in last sector +15210 ;AX, BX, DX destroyed. No other registers affected. +15220 +15230 MOV AX,[BYTSECPOS] +15240 MOV BX,CX +15250 OR AX,AX +15260 JZ SAVFIR ;Partial first sector? +15270 SUB AX,[BP+SECSIZ] +15280 NEG AX ;Max number of bytes left in first sector +15290 SUB BX,AX ;Subtract from total length +15300 JAE SAVFIR +15310 ADD AX,BX ;Don't use all of the rest of the sector +15320 XOR BX,BX ;And no bytes are left +15330 SAVFIR: +15340 MOV [BYTCNT1],AX +15350 MOV AX,BX +15360 XOR DX,DX +15370 DIV AX,[BP+SECSIZ] ;How many whole sectors? +15380 MOV [SECCNT],AX +15390 MOV [BYTCNT2],DX ;Bytes remaining for last sector +15400 RET +15410 +15420 +15430 FNDCLUS: +15440 +15450 ; Inputs: +15460 ; DS = CS +15470 ; CX = No. of clusters to skip +15480 ; BP = Base of drive parameters +15490 ; SI = FAT pointer +15500 ; ES:DI point to FCB +15510 ; Outputs: +15520 ; BX = Last cluster skipped to +15530 ; CX = No. of clusters remaining (0 unless EOF) +15540 ; DX = Position of last cluster +15550 ; DI destroyed. No other registers affected. +15560 +15570 SEG ES +15580 MOV BX,[DI+LSTCLUS] +15590 SEG ES +15600 MOV DX,[DI+CLUSPOS] +15610 OR BX,BX +15620 JZ NOCLUS +15630 SUB CX,DX +15640 JNB FINDIT +15650 ADD CX,DX +15660 XOR DX,DX +15670 SEG ES +15680 MOV BX,[DI+FIRCLUS] +15690 FINDIT: +15700 JCXZ RET +15710 SKPCLP: +15720 CALL UNPACK +15730 CMP DI,0FF8H +15740 JAE RET +15750 XCHG BX,DI +15760 INC DX +15770 LOOP SKPCLP +15780 RET +15790 NOCLUS: +15800 INC CX +15810 DEC DX +15820 RET +15830 +15840 +15850 BUFSEC: +15860 ; Inputs: +15870 ; AL = 0 if buffer must be read, 1 if no pre-read needed +15880 ; BP = Base of drive parameters +15890 ; [CLUSNUM] = Physical cluster number +15900 ; [SECCLUSPOS] = Sector position of transfer within cluster +15910 ; [BYTCNT1] = Size of transfer +15920 ; Function: +15930 ; Insure specified sector is in buffer, flushing buffer before +15940 ; read if necessary. +15950 ; Outputs: +15960 ; SI = Pointer to buffer +15970 ; DI = Pointer to transfer address +15980 ; CX = Number of bytes +15990 ; [NEXTADD] updated +16000 ; [TRANS] set to indicate a transfer will occur +16010 +16020 MOV DX,[CLUSNUM] +16030 MOV BL,[SECCLUSPOS] +16040 CALL FIGREC +16050 MOV [PREREAD],AL +16060 CMP DX,[BUFSECNO] +16070 JNZ GETSEC +16080 MOV AL,[BUFDRVNO] +16090 CMP AL,[BP+DRVNUM] +16100 JZ FINBUF ;Already have it? +16110 GETSEC: +16120 TEST B,[DIRTYBUF],-1 +16130 JZ RDSEC +16140 PUSH DX +16150 PUSH BP +16160 MOV BP,[BUFDRVBP] +16170 MOV BX,[BUFFER] +16180 MOV CX,1 +16190 MOV DX,[BUFSECNO] +16200 CALL DWRITE +16210 POP BP +16220 POP DX +16230 RDSEC: +16240 TEST B,[PREREAD],-1 +16250 JNZ SETBUF +16260 MOV BX,[BUFFER] +16270 MOV CX,1 +16280 PUSH DX +16290 CALL DREAD +16300 POP DX +16310 SETBUF: +16320 MOV [BUFSECNO],DX +16330 MOV AL,[BP+DRVNUM] +16340 MOV AH,0 +16350 MOV [BUFDRVNO],AX +16360 MOV [BUFDRVBP],BP +16370 FINBUF: +16380 MOV B,[TRANS],1 ;A transfer is taking place +16390 MOV DI,[NEXTADD] +16400 MOV SI,DI +16410 MOV CX,[BYTCNT1] +16420 ADD SI,CX +16430 MOV [NEXTADD],SI +16440 MOV SI,[BUFFER] +16450 ADD SI,[BYTSECPOS] +16460 RET +16470 +16480 BUFRD: +16490 XOR AL,AL ;Pre-read necessary +16500 CALL BUFSEC +16510 PUSH ES +16520 MOV ES,[DMAADD+2] +16530 SHR CX +16540 JNC EVENRD +16550 MOVB +16560 EVENRD: +16570 REP +16580 MOVW +16590 POP ES +16600 RET +16610 +16620 BUFWRT: +16630 MOV AX,[SECPOS] +16640 INC AX ;Set for next sector +16650 MOV [SECPOS],AX +16660 CMP AX,[VALSEC] ;Has sector been written before? +16670 MOV AL,1 +16680 JA NOREAD ;Skip preread if SECPOS>VALSEC +16690 MOV AL,0 +16700 NOREAD: +16710 CALL BUFSEC +16720 XCHG DI,SI +16730 PUSH DS +16740 PUSH ES +16750 PUSH CS +16760 POP ES +16770 MOV DS,[DMAADD+2] +16780 SHR CX +16790 JNC EVENWRT +16800 MOVB +16810 EVENWRT: +16820 REP +16830 MOVW +16840 POP ES +16850 POP DS +16860 MOV B,[DIRTYBUF],1 +16870 RET +16880 +16890 NEXTSEC: +16900 TEST B,[TRANS],-1 +16910 JZ CLRET +16920 MOV AL,[SECCLUSPOS] +16930 INC AL +16940 CMP AL,[BP+CLUSMSK] +16950 JBE SAVPOS +16960 MOV BX,[CLUSNUM] +16970 CMP BX,0FF8H +16980 JAE NONEXT +16990 LEA SI,[BP+FAT] +17000 CALL UNPACK +17010 MOV [CLUSNUM],DI +17020 INC [LASTPOS] +17030 MOV AL,0 +17040 SAVPOS: +17050 MOV [SECCLUSPOS],AL +17060 CLRET: +17070 CLC +17080 RET +17090 NONEXT: +17100 STC +17110 RET +17120 +17130 TRANBUF: +17140 LODB +17150 STOB +17160 CMP AL,13 ;Check for carriage return +17170 JNZ NORMCH +17180 MOV B,[SI],10 +17190 NORMCH: +17200 CMP AL,10 +17210 LOOPNZ TRANBUF +17220 JNZ ENDRDCON +17230 CALL OUT ;Transmit linefeed +17240 XOR SI,SI +17250 OR CX,CX +17260 JNZ GETBUF +17270 OR AL,1 ;Clear zero flag--not end of file +17280 ENDRDCON: +17290 MOV [CONTPOS],SI +17300 ENDRDDEV: +17310 MOV [NEXTADD],DI +17320 POP ES +17330 JNZ SETFCBJ ;Zero set if Ctrl-Z found in input +17340 MOV DI,[FCB] +17350 SEG ES +17360 OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +17370 SETFCBJ: +17380 JMP SETFCB +17390 +17400 READDEV: +17410 PUSH ES +17420 LES DI,[DMAADD] +17430 OR BL,BL +17440 JZ READCON +17450 DEC BL +17460 JNZ ENDRDDEV +17470 READAUX: +17480 CALL AUXIN +17490 STOB +17500 CMP AL,1AH +17510 LOOPNZ READAUX +17520 JP ENDRDDEV +17530 +17540 READCON: +17550 PUSH CS +17560 POP DS +17570 MOV SI,[CONTPOS] +17580 OR SI,SI +17590 JNZ TRANBUF +17600 CMP B,[CONBUF],128 +17610 JZ GETBUF +17620 MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +17630 GETBUF: +17640 PUSH CX +17650 PUSH ES +17660 PUSH DI +17670 MOV DX,CONBUF +17680 CALL BUFIN ;Get input buffer +17690 POP DI +17700 POP ES +17710 POP CX +17720 MOV SI,CONBUF+2 +17730 CMP B,[SI],1AH ;Check for Ctrl-Z in first character +17740 JNZ TRANBUF +17750 MOV AL,1AH +17760 STOB +17770 MOV AL,10 +17780 CALL OUT ;Send linefeed +17790 XOR SI,SI +17800 JP ENDRDCON +17810 +17820 RDERR: +17830 XOR CX,CX +17840 JMP WRTERR +17850 +17860 RDLASTJ:JMP RDLAST +17870 +17880 LOAD: +17890 +17900 ; Inputs: +17910 ; DS:DI point to FCB +17920 ; DX:AX = Position in file to read +17930 ; CX = No. of records to read +17940 ; Outputs: +17950 ; DX:AX = Position of last record read +17960 ; CX = No. of bytes read +17970 ; ES:DI point to FCB +17980 ; LSTCLUS, CLUSPOS fields in FCB set +17990 +18000 CALL SETUP +18010 SEG ES +18020 MOV BX,[DI+FILDIRBLK] +18030 CMP BH,-1 ;Check for named device I/O +18040 JZ READDEV +18050 SEG ES +18060 MOV AX,[DI+FILSIZ] +18070 SEG ES +18080 MOV BX,[DI+FILSIZ+2] +18090 SUB AX,[BYTPOS] +18100 SBC BX,[BYTPOS+2] +18110 JB RDERR +18120 JNZ ENUF +18130 OR AX,AX +18140 JZ RDERR +18150 CMP AX,CX +18160 JAE ENUF +18170 MOV CX,AX +18180 ENUF: +18190 CALL BREAKDOWN +18200 MOV CX,[CLUSNUM] +18210 CALL FNDCLUS +18220 OR CX,CX +18230 JNZ RDERR +18240 MOV [LASTPOS],DX +18250 MOV [CLUSNUM],BX +18260 CMP [BYTCNT1],0 +18270 JZ RDMID +18280 CALL BUFRD +18290 RDMID: +18300 CMP [SECCNT],0 +18310 JZ RDLASTJ +18320 CALL NEXTSEC +18330 JC SETFCB +18340 MOV B,[TRANS],1 ;A transfer is taking place +18350 ONSEC: +18360 MOV DL,[SECCLUSPOS] +18370 MOV CX,[SECCNT] +18380 MOV BX,[CLUSNUM] +18390 RDLP: +18400 CALL OPTIMIZE +18410 PUSH DI +18420 PUSH AX +18430 PUSH DS +18440 MOV DS,[DMAADD+2] +18450 CALL DREAD +18460 POP DS +18470 POP CX +18480 POP BX +18490 JCXZ RDLAST +18500 CMP BX,0FF8H +18510 JAE SETFCB +18520 MOV DL,0 +18530 INC [LASTPOS] ;We'll be using next cluster +18540 JP RDLP +18550 +18560 SETFCB: +18570 MOV SI,[FCB] +18580 MOV AX,[NEXTADD] +18590 MOV DI,AX +18600 SUB AX,[DMAADD] ;Number of bytes transfered +18610 XOR DX,DX +18620 SEG ES +18630 MOV CX,[SI+RECSIZ] +18640 DIV AX,CX ;Number of records +18650 CMP AX,[RECCNT] ;Check if all records transferred +18660 JZ FULLREC +18670 MOV B,[DSKERR],1 +18680 OR DX,DX +18690 JZ FULLREC ;If remainder 0, then full record transfered +18700 MOV B,[DSKERR],3 ;Flag partial last record +18710 SUB CX,DX ;Bytes left in last record +18720 PUSH ES +18730 MOV ES,[DMAADD+2] +18740 XCHG AX,BX ;Save the record count temporarily +18750 XOR AX,AX ;Fill with zeros +18760 SHR CX +18770 JNC EVENFIL +18780 STOB +18790 EVENFIL: +18800 REP +18810 STOW +18820 XCHG AX,BX ;Restore record count to AX +18830 POP ES +18840 INC AX ;Add last (partial) record to total +18850 FULLREC: +18860 MOV CX,AX +18870 MOV DI,SI ;ES:DI point to FCB +18880 SETCLUS: +18890 MOV AX,[CLUSNUM] +18900 SEG ES +18910 MOV [DI+LSTCLUS],AX +18920 MOV AX,[LASTPOS] +18930 SEG ES +18940 MOV [DI+CLUSPOS],AX +18950 ADDREC: +18960 MOV AX,[RECPOS] +18970 MOV DX,[RECPOS+2] +18975 JCXZ RET ;If no records read, don't change pos. +18980 DEC CX +18990 ADD AX,CX ;Update current record position +19000 ADC DX,0 +19010 INC CX +19020 RET +19030 +19040 RDLAST: +19050 MOV AX,[BYTCNT2] +19060 OR AX,AX +19070 JZ SETFCB +19080 MOV [BYTCNT1],AX +19090 CALL NEXTSEC +19100 JC SETFCB +19110 MOV [BYTSECPOS],0 +19120 CALL BUFRD +19130 JP SETFCB +19140 +19150 WRTDEV: +19160 PUSH DS +19170 LDS SI,[DMAADD] +19180 AND BL,7FH +19190 OR BL,BL +19200 JZ WRTCON +19210 DEC BL +19220 JZ WRTAUX +19230 DEC BL +19240 JNZ ENDWRDEV ;Done if device is NUL +19250 WRTLST: +19260 LODB +19270 CMP AL,1AH +19280 JZ ENDWRDEV +19290 CALL LISTOUT +19300 LOOP WRTLST +19310 JP ENDWRDEV +19320 +19330 WRTAUX: +19340 LODB +19350 CALL AUXOUT +19360 CMP AL,1AH +19370 LOOPNZ WRTAUX +19380 JP ENDWRDEV +19390 +19400 WRTCON: +19410 LODB +19420 CMP AL,1AH +19430 JZ ENDWRDEV +19440 CALL OUT +19450 LOOP WRTCON +19460 ENDWRDEV: +19470 POP DS +19480 MOV CX,[RECCNT] +19490 MOV DI,[FCB] +19500 JP ADDREC +19510 +19520 HAVSTART: +19530 MOV CX,AX +19540 CALL SKPCLP +19550 JCXZ DOWRTJ +19560 CALL ALLOCATE +19570 JNC DOWRTJ +19580 WRTERR: +19590 MOV B,[DSKERR],1 +19600 LVDSK: +19610 MOV AX,[RECPOS] +19620 MOV DX,[RECPOS+2] +19630 MOV DI,[FCB] +19640 RET +19650 +19660 DOWRTJ: JMP DOWRT +19670 +19680 WRTEOFJ: +19690 JMP WRTEOF +19700 +19710 STORE: +19720 +19730 ; Inputs: +19740 ; DS:DI point to FCB +19750 ; DX:AX = Position in file of disk transfer +19760 ; CX = Record count +19770 ; Outputs: +19780 ; DX:AX = Position of last record written +19790 ; CX = No. of records written +19800 ; ES:DI point to FCB +19810 ; LSTCLUS, CLUSPOS fields in FCB set +19820 +19830 MOV B,[DI+DIRTYFIL],1 +19840 CALL SETUP +19850 CALL DATE16 +19860 SEG ES +19870 MOV [DI+FDATE],AX +19880 SEG ES +19890 MOV BX,[DI+FILDIRBLK] +19900 CMP BH,-1 +19910 JZ WRTDEV +19920 CALL BREAKDOWN +19930 MOV AX,[BYTPOS] +19940 MOV DX,[BYTPOS+2] +19950 JCXZ WRTEOFJ +19960 DEC CX +19970 ADD AX,CX +19980 ADC DX,0 ;AX:DX=last byte accessed +19990 DIV AX,[BP+SECSIZ] ;AX=last sector accessed +20000 MOV CL,[BP+CLUSSHFT] +20010 SHR AX,CL ;Last cluster to be accessed +20020 PUSH AX +20030 SEG ES +20040 MOV AX,[DI+FILSIZ] +20050 SEG ES +20060 MOV DX,[DI+FILSIZ+2] +20070 DIV AX,[BP+SECSIZ] +20080 OR DX,DX +20090 JZ NORNDUP +20100 INC AX ;Round up if any remainder +20110 NORNDUP: +20120 MOV [VALSEC],AX ;Number of sectors that have been written +20130 POP AX +20140 MOV CX,[CLUSNUM] ;First cluster accessed +20150 CALL FNDCLUS +20160 MOV [CLUSNUM],BX +20170 MOV [LASTPOS],DX +20180 SUB AX,DX ;Last cluster minus current cluster +20190 JZ DOWRT ;If we have last clus, we must have first +20200 JCXZ HAVSTART ;See if no more data +20210 PUSH CX ;No. of clusters short of first +20220 MOV CX,AX +20230 CALL ALLOCATE +20240 POP AX +20250 JC WRTERR +20260 MOV CX,AX +20270 MOV DX,[LASTPOS] +20280 INC DX +20290 DEC CX +20300 JZ NOSKIP +20310 CALL SKPCLP +20320 NOSKIP: +20330 MOV [CLUSNUM],BX +20340 MOV [LASTPOS],DX +20350 DOWRT: +20360 CMP [BYTCNT1],0 +20370 JZ WRTMID +20380 MOV BX,[CLUSNUM] +20390 CALL BUFWRT +20400 WRTMID: +20410 MOV AX,[SECCNT] +20420 OR AX,AX +20430 JZ WRTLAST +20440 ADD [SECPOS],AX +20450 CALL NEXTSEC +20460 MOV B,[TRANS],1 ;A transfer is taking place +20470 MOV DL,[SECCLUSPOS] +20480 MOV BX,[CLUSNUM] +20490 MOV CX,[SECCNT] +20500 WRTLP: +20510 CALL OPTIMIZE +20520 PUSH DI +20530 PUSH AX +20540 PUSH DS +20550 MOV DS,[DMAADD+2] +20560 CALL DWRITE +20570 POP DS +20580 POP CX +20590 POP BX +20600 JCXZ WRTLAST +20610 MOV DL,0 +20620 INC [LASTPOS] ;We'll be using next cluster +20630 JP WRTLP +20640 WRTLAST: +20650 MOV AX,[BYTCNT2] +20660 OR AX,AX +20670 JZ FINWRT +20680 MOV [BYTCNT1],AX +20690 CALL NEXTSEC +20700 MOV [BYTSECPOS],0 +20710 CALL BUFWRT +20720 FINWRT: +20730 MOV AX,[NEXTADD] +20740 SUB AX,[DMAADD] +20750 ADD AX,[BYTPOS] +20760 MOV DX,[BYTPOS+2] +20770 ADC DX,0 +20780 MOV CX,DX +20790 MOV DI,[FCB] +20800 SEG ES +20810 CMP AX,[DI+FILSIZ] +20820 SEG ES +20830 SBB CX,[DI+FILSIZ+2] +20840 JB SAMSIZ +20850 SEG ES +20860 MOV [DI+FILSIZ],AX +20870 SEG ES +20880 MOV [DI+FILSIZ+2],DX +20890 SAMSIZ: +20900 MOV CX,[RECCNT] +20910 JMP SETCLUS +20920 +20930 +20940 WRTERRJ:JMP WRTERR +20950 +20960 WRTEOF: +20970 MOV CX,AX +20980 OR CX,DX +20990 JZ KILLFIL +21000 SUB AX,1 +21010 SBC DX,0 +21020 DIV AX,[BP+SECSIZ] +21030 MOV CL,[BP+CLUSSHFT] +21040 SHR AX,CL +21050 MOV CX,AX +21060 CALL FNDCLUS +21070 JCXZ RELFILE +21080 CALL ALLOCATE +21090 JC WRTERRJ +21100 UPDATE: +21110 MOV DI,[FCB] +21120 MOV AX,[BYTPOS] +21130 SEG ES +21140 MOV [DI+FILSIZ],AX +21150 MOV AX,[BYTPOS+2] +21160 SEG ES +21170 MOV [DI+FILSIZ+2],AX +21180 XOR CX,CX +21190 RET +21200 +21210 RELFILE: +21220 MOV DX,0FFFH +21230 CALL RELBLKS +21240 SETDIRT: +21250 MOV B,[BP+DIRTYFAT],1 +21260 JP UPDATE +21270 +21280 KILLFIL: +21290 XOR BX,BX +21300 SEG ES +21310 XCHG BX,[DI+FIRCLUS] +21320 OR BX,BX +21330 JZ UPDATE +21340 CALL RELEASE +21350 JP SETDIRT +21360 +21370 +21380 OPTIMIZE: +21390 +21400 ; Inputs: +21410 ; DS = CS +21420 ; BX = Physical cluster +21430 ; CX = No. of records +21440 ; DL = sector within cluster +21450 ; BP = Base of drives parameters +21460 ; [NEXTADD] = transfer address +21470 ; Outputs: +21480 ; AX = No. of records remaining +21490 ; BX = Transfer address +21500 ; CX = No. or records to be transferred +21510 ; DX = Physical sector address +21520 ; DI = Next cluster +21530 ; [CLUSNUM] = Last cluster accessed +21540 ; [NEXTADD] updated +21550 ; BP unchanged. Note that segment of transfer not set. +21560 +21570 PUSH DX +21580 PUSH BX +21590 MOV AL,[BP+CLUSMSK] +21600 INC AL ;Number of sectors per cluster +21610 MOV AH,AL +21620 SUB AL,DL ;AL = Number of sectors left in first cluster +21630 MOV DX,CX +21640 LEA SI,[BP+FAT] +21650 MOV CX,0 +21660 OPTCLUS: +21670 ;AL has number of sectors available in current cluster +21680 ;AH has number of sectors available in next cluster +21690 ;BX has current physical cluster +21700 ;CX has number of sequential sectors found so far +21710 ;DX has number of sectors left to transfer +21720 ;SI has FAT pointer +21730 CALL UNPACK +21740 ADD CL,AL +21750 ADC CH,0 +21760 CMP CX,DX +21770 JAE BLKDON +21780 MOV AL,AH +21790 INC BX +21800 CMP DI,BX +21810 JZ OPTCLUS +21820 DEC BX +21830 FINCLUS: +21840 MOV [CLUSNUM],BX ;Last cluster accessed +21850 SUB DX,CX ;Number of sectors still needed +21860 PUSH DX +21870 MOV AX,CX +21880 MUL AX,[BP+SECSIZ] ;Number of sectors times sector size +21890 MOV SI,[NEXTADD] +21900 ADD AX,SI ;Adjust by size of transfer +21910 MOV [NEXTADD],AX +21920 POP AX ;Number of sectors still needed +21930 POP DX ;Starting cluster +21940 SUB BX,DX ;Number of new clusters accessed +21950 ADD [LASTPOS],BX +21960 POP BX ;BL = sector postion within cluster +21970 CALL FIGREC +21980 MOV BX,SI +21990 RET +22000 BLKDON: +22010 SUB CX,DX ;Number of sectors in cluster we don't want +22020 SUB AH,CL ;Number of sectors in cluster we accepted +22030 DEC AH ;Adjust to mean position within cluster +22040 MOV [SECCLUSPOS],AH +22050 MOV CX,DX ;Anyway, make the total equal to the request +22060 JP FINCLUS +22070 +22080 +22090 FIGREC: +22100 +22110 ;Inputs: +22120 ; DX = Physical cluster number +22130 ; BL = Sector postion within cluster +22140 ; BP = Base of drive parameters +22150 ;Outputs: +22160 ; DX = physical sector number +22170 ;No other registers affected. +22180 +22190 PUSH CX +22200 MOV CL,[BP+CLUSSHFT] +22210 DEC DX +22220 DEC DX +22230 SHL DX,CL +22240 OR DL,BL +22250 ADD DX,[BP+FIRREC] +22260 POP CX +22270 RET +22280 +22290 GETREC: +22300 +22310 ; Inputs: +22320 ; DS:DX point to FCB +22330 ; Outputs: +22340 ; CX = 1 +22350 ; DX:AX = Record number determined by EXTENT and NR fields +22360 ; DS:DI point to FCB +22370 ; No other registers affected. +22380 +22390 MOV DI,DX +22400 CMP B,[DI],-1 +22410 JNZ NORMFCB2 +22420 ADD DI,7 +22430 NORMFCB2: +22440 MOV CX,1 +22450 MOV AL,[DI+NR] +22460 MOV DX,[DI+EXTENT] +22470 SHL AL +22480 SHR DX +22490 RCR AL +22500 MOV AH,DL +22510 MOV DL,DH +22520 MOV DH,0 +22530 RET +22540 +22550 +22560 ALLOCATE: +22570 +22580 ; Inputs: +22590 ; DS = CS +22600 ; ES = Segment of FCB +22610 ; BX = Last cluster of file (0 if null file) +22620 ; CX = No. of clusters to allocate +22630 ; DX = Position of cluster BX +22640 ; BP = Base of drive parameters +22650 ; SI = FAT pointer +22660 ; [FCB] = Displacement of FCB within segment +22670 ; Outputs: +22680 ; IF insufficient space +22690 ; THEN +22700 ; Carry set +22710 ; CX = max. no. of records that could be added to file +22720 ; ELSE +22730 ; Carry clear +22740 ; BX = First cluster allocated +22750 ; FAT is fully updated including dirty bit +22760 ; FIRCLUS field of FCB set if file was null +22770 ; SI,BP unchanged. All other registers destroyed. +22780 +22790 PUSH [SI] +22800 PUSH DX +22810 PUSH CX +22820 PUSH BX +22830 MOV AX,BX +22840 ALLOC: +22850 MOV DX,BX +22860 FINDFRE: +22870 INC BX +22880 CMP BX,[BP+MAXCLUS] +22890 JLE TRYOUT +22900 CMP AX,1 +22910 JG TRYIN +22920 POP BX +22930 MOV DX,0FFFH +22940 CALL RELBLKS +22950 POP AX ;No. of clusters requested +22960 SUB AX,CX ;AX=No. of clusters allocated +22970 POP DX +22980 POP [SI] +22990 INC DX ;Position of first cluster allocated +23000 ADD AX,DX ;AX=max no. of cluster in file +23010 MOV DL,[BP+CLUSMSK] +23020 MOV DH,0 +23030 INC DX ;DX=records/cluster +23040 MUL AX,DX ;AX=max no. of records in file +23050 MOV CX,AX +23060 SUB CX,[RECPOS] ;CX=max no. of records that could be written +23070 JA MAXREC +23080 XOR CX,CX ;If CX was negative, zero it +23090 MAXREC: +23100 STC +23110 RET +23120 +23130 TRYOUT: +23140 CALL UNPACK +23150 JZ HAVFRE +23160 TRYIN: +23170 DEC AX +23180 JLE FINDFRE +23190 XCHG AX,BX +23200 CALL UNPACK +23210 JZ HAVFRE +23220 XCHG AX,BX +23230 JP FINDFRE +23240 HAVFRE: +23250 XCHG BX,DX +23260 MOV AX,DX +23270 CALL PACK +23280 MOV BX,AX +23290 LOOP ALLOC +23300 MOV DX,0FFFH +23310 CALL PACK +23320 MOV B,[BP+DIRTYFAT],1 +23330 POP BX +23340 POP CX ;Don't need this stuff since we're successful +23350 POP DX +23360 CALL UNPACK +23370 POP [SI] +23380 XCHG BX,DI +23390 OR DI,DI +23400 JNZ RET +23410 MOV DI,[FCB] +23420 SEG ES +23430 MOV [DI+FIRCLUS],BX +23440 RET +23450 +23460 +23470 RELEASE: +23480 +23490 ; Inputs: +23500 ; DS = CS +23510 ; BX = Cluster in file +23520 ; SI = FAT pointer +23530 ; BP = Base of drive parameters +23540 ; Function: +23550 ; Frees cluster chain starting with [BX] +23560 ; AX,BX,DX,DI all destroyed. Other registers unchanged. +23570 +23580 XOR DX,DX +23590 RELBLKS: +23600 ; Enter here with DX=0FFFH to put an end-of-file mark +23610 ; in the first cluster and free the rest in the chain. +23620 CALL UNPACK +23630 JZ RET +23640 MOV AX,DI +23650 CALL PACK +23660 CMP AX,0FF8H +23670 MOV BX,AX +23680 JB RELEASE +23690 RET +23700 +23710 +23720 GETEOF: +23730 +23740 ; Inputs: +23750 ; BX = Cluster in a file +23760 ; SI = Base of drive FAT +23770 ; DS = CS +23780 ; Outputs: +23790 ; BX = Last cluster in the file +23800 ; DI destroyed. No other registers affected. +23810 +23820 CALL UNPACK +23830 CMP DI,0FF8H +23840 JAE RET +23850 MOV BX,DI +23860 JP GETEOF +23870 +23880 +23890 SRCHFRST: ;System call 17 +23900 CALL GETFILE +23910 SAVPLCE: +23920 ; Search-for-next enters here to save place and report +23930 ; findings. +23940 JC KILLSRCH +23950 CMP BH,-1 +23960 JZ SRCHDEV +23970 MOV AX,[LASTENT] +23980 SEG ES +23990 MOV [DI+FILDIRBLK],AX +24000 ;Information in directory entry must be copied into the first +24010 ; 33 bytes starting at the disk transfer address. +24020 MOV SI,BX +24030 LES DI,[DMAADD] +24040 MOV AX,00FFH +24050 CMP AL,[EXTFCB] +24060 JNZ NORMFCB +24070 STOW +24080 INC AL +24090 STOW +24100 STOW +24110 MOV AL,[ATTRIB] +24120 STOB +24130 NORMFCB: +24140 MOV AL,[BP+DRVNUM] +24150 INC AL +24160 STOB ;Set drive number +24170 MOVB ;Copy first character of name +24180 MOV CX,5 +24190 REP +24200 MOVW ;Copy remaining 10 characters of name +24210 XOR AX,AX +24220 +24230 IF SMALLDIR +24240 CMP B,[BP+DIRSIZ],-1 +24250 JNZ BIGENT5 +24260 STOB ;Zero out unused portion +24270 MOV CX,7 +24280 REP +24290 STOW ;Zero a total of 15 bytes +24300 MOVW ;Copy first cluster pointer +24310 MOVW ;Copy low word of length +24320 MOVB ;Copy 3rd byte of length +24330 STOB ;4th byte of length must be zero +24340 RET +24350 BIGENT5: +24360 ENDIF +24370 +24380 MOV CX,10 +24390 REP +24400 MOVW +24410 MOVB +24420 RET +24430 +24440 KILLSRCH: +24450 SEG ES +24460 KILLSRCH1: +24470 MOV [DI+FILDIRBLK],-2 +24480 MOV AL,-1 +24490 RET +24500 +24510 SRCHDEV: +24520 SEG ES +24530 MOV [DI+FILDIRBLK],BX +24540 LES DI,[DMAADD] +24550 XOR AX,AX +24560 STOB ;Zero drive byte +24570 SUB SI,4 ;Point to device name +24580 MOVW +24590 MOVW +24600 MOV AX,2020H +24610 MOV CX,3 +24620 REP +24630 STOW ;Fill with 6 blanks +24640 STOB ;And a 7th +24650 XOR AX,AX +24660 MOV CX,10 +24670 REP +24680 STOW +24690 STOB +24700 RET +24710 +24720 SRCHNXT: ;System call 18 +24730 CALL MOVNAME +24740 MOV DI,DX +24750 JC KILLSRCH1 +24760 PUSH DX +24770 PUSH DS +24780 MOV AX,[DI+FILDIRBLK] +24790 PUSH CS +24800 POP DS +24810 MOV [LASTENT],AX +24820 CALL CONTSRCH +24830 POP ES +24840 POP DI +24850 JMP SAVPLCE +24860 +24870 +24880 FILESIZE: ;System call 35 +24890 CALL GETFILE +24900 MOV AL,-1 +24910 JC RET +24920 ADD DI,33 ;Write size in RR field +24930 SEG ES +24940 MOV CX,[DI-33+RECSIZ] +24950 OR CX,CX +24960 JNZ RECOK +24970 MOV CX,128 +24980 RECOK: +24990 XOR AX,AX +25000 XOR DX,DX ;Intialize size to zero +25010 CMP BH,-1 ;Check for named I/O device +25020 JZ DEVSIZ +25030 INC SI +25040 INC SI ;Point to length field +25050 MOV AX,[SI+2] ;Get high word of size +25060 +25070 IF SMALLDIR +25080 CMP B,[BP+DIRSIZ],-1 +25090 JNZ BIGSIZ +25100 MOV AH,0 +25110 BIGSIZ: +25120 ENDIF +25130 +25140 DIV AX,CX +25150 PUSH AX ;Save high part of result +25160 LODW ;Get low word of size +25170 DIV AX,CX +25180 OR DX,DX ;Check for zero remainder +25190 POP DX +25200 JZ DEVSIZ +25210 INC AX ;Round up for partial record +25220 JNZ DEVSIZ ;Propagate carry? +25230 INC DX +25240 DEVSIZ: +25250 STOW +25260 MOV AX,DX +25270 STOB +25280 MOV AL,0 +25290 CMP CX,64 +25300 JAE RET ;Only 3-byte field if RECSIZ >= 64 +25310 SEG ES +25320 MOV [DI],AH +25330 RET +25340 +25350 +25360 SETDMA: ;System call 26 +25370 SEG CS +25380 MOV [DMAADD],DX +25390 SEG CS +25400 MOV [DMAADD+2],DS +25410 RET +25420 +25430 +25440 GETFATPT: ;System call 27 +25450 MOV AX,CS +25460 MOV DS,AX +25470 MOV BP,[CURDRVPT] +25480 CALL FATREAD +25490 LEA BX,[BP+FAT] +25500 MOV AL,[BP+CLUSMSK] +25510 INC AL +25520 MOV DX,[BP+MAXCLUS] +25530 DEC DX +25540 MOV B,[BP+DIRTYFAT],1 +25550 MOV CX,[BP+SECSIZ] +25560 LDS SI,[SPSAVE] +25570 MOV [SI+BXSAVE],BX +25580 MOV [SI+DXSAVE],DX +25590 MOV [SI+CXSAVE],CX +25600 MOV [SI+DSSAVE],CS +25610 RET +25620 +25630 +25640 DSKRESET: ;System call 13 +25650 SEG CS +25660 MOV [DMAADD+2],DS +25670 MOV AX,CS +25680 MOV DS,AX +25690 MOV [DMAADD],80H +25700 MOV AX,[CURDRVPT+2] +25710 MOV [CURDRVPT],AX +25720 WRTFATS: +25730 ; DS=CS. Writes back all dirty FATs. All registers destroyed. +25740 MOV AX,[BUFDRVNO] +25750 OR AH,AH +25760 JZ NOBUF +25770 CBW +25780 MOV BX,AX +25790 SHL BX +25800 MOV BP,[BX+DRVTAB] +25810 MOV B,[DIRTYBUF],0 +25820 MOV DX,[BUFSECNO] +25830 MOV BX,BUFFER +25840 MOV CX,1 +25850 CALL DWRITE +25860 NOBUF: +25870 MOV CL,[NUMDRV] +25880 MOV CH,0 +25890 MOV SI,CURDRVPT+2 +25900 WRTFAT: +25910 LODW +25920 PUSH CX +25930 PUSH SI +25940 MOV BP,AX +25950 CALL CHKFATWRT +25960 POP SI +25970 POP CX +25980 LOOP WRTFAT +25990 RET +26000 +26010 +26020 CURDRV: ;System call 25 +26030 SEG CS +26040 MOV BP,[CURDRVPT] +26050 MOV AL,[BP+DRVNUM] +26060 RET +26070 +26080 +26090 SETRNDREC: ;System call 36 +26100 CALL GETREC +26110 MOV [DI+33],AX +26120 MOV [DI+35],DL +26130 CMP [DI+RECSIZ],64 +26140 JAE RET +26150 MOV [DI+36],DH ;Set 4th byte only if record size < 64 +26160 RET +26170 +26180 +26190 SELDSK: ;System call 14 +26200 MOV DH,0 +26210 MOV BX,DX +26220 PUSH CS +26230 POP DS +26240 MOV AL,[NUMDRV] +26250 CMP BL,AL +26260 JNB RET +26270 SHL BX +26280 MOV DX,[BX+CURDRVPT+2] +26290 MOV [CURDRVPT],DX +26300 RET +26310 +26320 +26330 BUFIN: ;System call 10 +26340 MOV AX,CS +26350 MOV ES,AX +26360 MOV SI,DX +26370 MOV CH,0 +26380 LODW +26390 OR AL,AL +26400 JZ RET +26410 MOV BL,AH +26420 MOV BH,CH +26430 CMP AL,BL +26440 JBE NOEDIT +26450 CMP B,[BX+SI],0DH +26460 JZ EDITON +26470 NOEDIT: +26480 MOV BL,CH +26490 EDITON: +26500 MOV DL,AL +26510 DEC DX +26520 NEWLIN: +26530 SEG CS +26540 MOV AL,[CARPOS] +26550 SEG CS +26560 MOV [STARTPOS],AL +26570 PUSH SI +26580 MOV DI,INBUF +26590 MOV AH,CH +26600 MOV BH,CH +26610 MOV DH,CH +26620 GETCH: +26630 CALL IN +26640 CMP AL,7FH +26650 JZ BACKSPJ +26660 CMP AL,8 +26670 JZ BACKSPJ +26680 CMP AL,13 +26690 JZ ENDLIN +26700 CMP AL,10 +26710 JZ PHYCRLF +26720 CMP AL,"X"-"@" +26730 JZ KILNEW +26740 CMP AL,1BH +26750 JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X +26760 CMP AL,ESCCH +26770 JZ ESC +26780 SAVCH: +26790 CMP DH,DL +26800 JAE BELL +26810 STOB +26820 INC DH +26830 CALL BUFOUT +26840 OR AH,AH +26850 JNZ GETCH +26860 CMP BH,BL +26870 JAE GETCH +26880 INC SI +26890 INC BH +26900 JP GETCH +26910 +26920 BELL: +26930 MOV AL,7 +26940 CALL OUTCH +26950 JP GETCH +26960 +26970 BACKSPJ:JP BACKSP +26980 +26990 ESC: +27000 CALL IN +27010 PUSH DI +27020 MOV CL,ESCTABLEN +27030 MOV DI,ESCTAB +27040 REPNE +27050 SCAB +27060 POP DI +27070 MOV BP,CX +27080 SHL BP +27090 SEG CS ;To work in init +27100 JMP [BP+ESCFUNC] +27110 +27120 ENDLIN: +27130 STOB +27140 CALL OUT +27150 POP DI +27160 MOV [DI-1],DH +27170 INC DH +27180 COPYNEW: +27190 MOV BP,ES +27200 MOV BX,DS +27210 MOV ES,BX +27220 MOV DS,BP +27230 MOV SI,INBUF +27240 MOV CL,DH +27250 REP +27260 MOVB +27270 RET +27280 CRLF: +27290 MOV AL,13 +27300 CALL OUT +27310 MOV AL,10 +27320 JMP OUT +27330 +27340 PHYCRLF: +27350 CALL CRLF +27360 JP GETCH +27370 +27380 KILNEW: +27390 MOV AL,"\" +27400 CALL OUT +27410 POP SI +27420 PUTNEW: +27430 CALL CRLF +27440 SEG CS +27450 MOV AL,[STARTPOS] +27460 CALL TAB +27470 JMP NEWLIN +27480 +27490 BACKSP: +27500 OR DH,DH +27510 JZ OLDBAK +27520 CALL BACKUP +27530 SEG ES +27540 MOV AL,[DI] +27550 CMP AL," " +27560 JAE OLDBAK +27570 CMP AL,9 +27580 JZ BAKTAB +27590 CALL BACKMES +27600 OLDBAK: +27610 OR AH,AH +27620 JNZ GETCH1 +27630 OR BH,BH +27640 JZ GETCH1 +27650 DEC BH +27660 DEC SI +27670 GETCH1: +27680 JMP GETCH +27690 BAKTAB: +27700 PUSH DI +27710 DEC DI +27720 DOWN +27730 MOV CL,DH +27740 MOV AL," " +27750 PUSH BX +27760 MOV BL,7 +27770 JCXZ FIGTAB +27780 FNDPOS: +27790 SCAB +27800 JNA CHKCNT +27810 SEG ES +27820 CMP B,[DI+1],9 +27830 JZ HAVTAB +27840 DEC BL +27850 CHKCNT: +27860 LOOP FNDPOS +27870 FIGTAB: +27880 SEG CS +27890 SUB BL,[STARTPOS] +27900 HAVTAB: +27910 SUB BL,DH +27920 ADD CL,BL +27930 AND CL,7 +27940 UP +27950 POP BX +27960 POP DI +27970 JZ OLDBAK +27980 TABBAK: +27990 CALL BACKMES +28000 LOOP TABBAK +28010 JP OLDBAK +28020 BACKUP: +28030 DEC DH +28040 DEC DI +28050 BACKMES: +28060 MOV AL,8 +28070 CALL OUT +28080 MOV AL," " +28090 CALL OUT +28100 MOV AL,8 +28110 JMP OUT +28120 +28130 TWOESC: +28140 MOV AL,ESCCH +28150 JMP SAVCH +28160 +28170 COPYLIN: +28180 MOV CL,BL +28190 SUB CL,BH +28200 JP COPYEACH +28210 +28220 COPYSTR: +28230 CALL FINDOLD +28240 JP COPYEACH +28250 +28260 COPYONE: +28270 MOV CL,1 +28280 COPYEACH: +28290 MOV AH,0 ;Turn off insert mode when copying +28300 CMP DH,DL +28310 JZ GETCH2 +28320 CMP BH,BL +28330 JZ GETCH2 +28340 LODB +28350 STOB +28360 CALL BUFOUT +28370 INC BH +28380 INC DH +28390 LOOP COPYEACH +28400 GETCH2: +28410 JMP GETCH +28420 +28430 SKIPONE: +28440 CMP BH,BL +28450 JZ GETCH2 +28460 INC BH +28470 INC SI +28480 JMP GETCH +28490 +28500 SKIPSTR: +28510 CALL FINDOLD +28520 ADD SI,CX +28530 ADD BH,CL +28540 JMP GETCH +28550 +28560 FINDOLD: +28570 CALL IN +28580 MOV CL,BL +28590 SUB CL,BH +28600 JZ NOTFND +28610 DEC CX +28620 JZ NOTFND +28630 PUSH ES +28640 PUSH DS +28650 POP ES +28660 PUSH DI +28670 MOV DI,SI +28680 INC DI +28690 REPNE +28700 SCAB +28710 POP DI +28720 POP ES +28730 JNZ NOTFND +28740 NOT CL +28750 ADD CL,BL +28760 SUB CL,BH +28770 RET +28780 NOTFND: +28790 POP BP +28800 JMP GETCH +28810 +28820 REEDIT: +28830 MOV AL,"@" +28840 CALL OUT +28850 POP DI +28860 PUSH DI +28870 PUSH ES +28880 PUSH DS +28890 CALL COPYNEW +28900 POP DS +28910 POP ES +28920 POP SI +28930 MOV BL,DH +28940 JMP PUTNEW +28950 +28960 TOGGLINS: +28970 NOT AH +28980 JMP GETCH +28990 +29000 CTRLZ: +29010 MOV AL,1AH +29020 JMP SAVCH +29030 +29040 ESCFUNC: +29050 DW GETCH +29060 DW TWOESC +29070 DW TOGGLINS +29080 DW BACKSP +29090 DW REEDIT +29100 DW CTRLZ +29110 DW COPYLIN +29120 DW SKIPSTR +29130 DW COPYSTR +29140 DW SKIPONE +29150 DW COPYONE +29160 DW COPYONE +29170 +29180 BUFOUT: +29190 CMP AL," " +29200 JAE OUT +29210 CMP AL,9 +29220 JZ OUT +29230 PUSH AX +29240 MOV AL,"^" +29250 CALL OUT +29260 POP AX +29270 OR AL,40H +29280 JP OUT +29290 +29300 CONOUT: ;System call 2 +29310 MOV AL,DL +29320 OUT: +29330 CMP AL,20H +29340 JB CTRLOUT +29350 CMP AL,7FH +29360 JZ OUTCH +29370 SEG CS +29380 INC B,[CARPOS] +29390 OUTCH: +29400 PUSH AX +29410 CALL STATCHK +29420 POP AX +29430 CALL BIOSOUT,BIOSSEG +29440 SEG CS +29450 TEST B,[PFLAG],-1 +29460 JZ RET +29470 CALL BIOSPRINT,BIOSSEG +29480 RET +29490 +29500 NOSTOP: +29510 CMP AL,"P"-"@" +29520 JZ INCHK +29530 CMP AL,"C"-"@" +29540 JZ INCHK +29550 RET +29560 +29570 STATCHK: +29580 CALL BIOSSTAT,BIOSSEG +29590 JZ RET +29600 CMP AL,'S'-'@' +29610 JNZ NOSTOP +29620 CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +29630 INCHK: +29640 CALL BIOSIN,BIOSSEG +29650 CMP AL,'P'-'@' +29660 JZ PRINTOGL +29670 CMP AL,'C'-'@' +29680 JNZ RET +29690 ; Ctrl-C handler. +29700 ; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +29710 ; to show line is canceled. Then the user registers are restored and the +29720 ; user CTRL-C handler is executed. At this point the top of the stack has +29730 ; 1) the interrupt return address should the user CTRL-C handler wish to +29740 ; allow processing to continue; 2) the original interrupt return address +29750 ; to the code that performed the function call in the first place. If the +29760 ; user CTRL-C handler wishes to continue, it must leave all registers +29770 ; unchanged and IRET. The function that was interrupted will simply be +29780 ; repeated. +29790 SEG CS +29800 MOV AL,[FUNC] ;Get currently executing function +29810 CMP AL,10 ;Check if buffered line input +29820 JZ CANLIN +29830 CMP AL,9 ;Check if buffered line output +29840 JNZ RESTREG +29850 CANLIN: +29860 MOV AL,"\" ;Display cancel line symbol +29870 CALL OUT +29880 CALL CRLF +29890 RESTREG: +29900 DI ;Prepare to play with stack +29910 SEG CS +29920 MOV SS,[SSSAVE] +29930 SEG CS +29940 MOV SP,[SPSAVE] ;User stack now restored +29950 POP AX +29960 POP BX +29970 POP CX +29980 POP DX +29990 POP SI +30000 POP DI +30010 POP BP +30020 POP DS +30030 POP ES ;User registers now restored +30040 INT CONTC ;Execute user Ctrl-C handler +30050 JMP COMMAND ;Repeat command otherwise +30060 +30070 PRINTOGL: +30080 SEG CS +30090 XOR B,[PFLAG],1 +30100 XOR AL,AL ;Set zero flag--character not received +30110 RET +30120 CTRLOUT: +30130 CMP AL,13 +30140 JZ ZERPOS +30150 CMP AL,8 +30160 JZ BACKPOS +30170 CMP AL,9 +30180 JNZ OUTCHJ +30190 SEG CS +30200 MOV AL,[CARPOS] +30210 OR AL,0F8H +30220 NEG AL +30230 TAB: +30240 PUSH CX +30250 MOV CL,AL +30260 MOV CH,0 +30265 JCXZ POPTAB +30270 TABLP: +30280 MOV AL," " +30290 CALL OUT +30300 LOOP TABLP +30305 POPTAB: +30310 POP CX +30320 RET +30330 +30340 ZERPOS: +30350 SEG CS +30360 MOV B,[CARPOS],0 +30370 OUTCHJ: JMP OUTCH +30380 +30390 BACKPOS: +30400 SEG CS +30410 DEC B,[CARPOS] +30420 JMP OUTCH +30430 +30440 +30450 CONSTAT: ;System call 11 +30460 CALL BIOSSTAT,BIOSSEG +30470 MOV AL,0 +30480 JZ RET +30490 OR AL,-1 +30500 RET +30510 +30520 +30530 CONIN: ;System call 1 +30540 CALL IN +30550 PUSH AX +30560 CALL OUT +30570 POP AX +30580 RET +30590 +30600 +30610 IN: ;Internal input routine +30620 CALL INCHK +30630 JZ IN +30640 RET +30650 +30660 RAWIO: ;System call 6 +30670 MOV AL,DL +30680 CMP AL,-1 +30690 JNZ RAWOUT +30700 CALL BIOSSTAT,BIOSSEG +30710 MOV AL,0 +30720 JZ RET +30730 RAWINP: ;System call 7 +30740 CALL BIOSIN,BIOSSEG +30750 RET +30760 RAWOUT: +30770 CALL BIOSOUT,BIOSSEG +30780 RET +30790 +30800 LIST: ;System call 5 +30810 MOV AL,DL +30820 LISTOUT: +30830 PUSH AX +30840 CALL STATCHK +30850 POP AX +30860 CALL BIOSPRINT,BIOSSEG +30870 RET +30880 +30890 PRTBUF: ;System call 9 +30900 MOV SI,DX +30910 OUTSTR: +30920 LODB +30930 CMP AL,"$" +30940 JZ RET +30950 CALL OUT +30960 JP OUTSTR +30970 +30980 OUTMES: ;String output for internal messages +30990 SEG CS +31000 LODB +31010 CMP AL,"$" +31020 JZ RET +31030 CALL OUT +31040 JP OUTMES +31050 +31060 +31070 MAKEFCB: ;Interrupt call 41 +31080 MOV DL,0 ;Flag--not ambiguous file name +31090 OR AL,AL ;Scan off separators if not zero +31100 JZ NOSCAN +31110 SCAN: +31120 CALL GETLET +31130 JZ SCAN ;Get rid of leading separators (e.g., blanks) +31140 DEC SI ;Point back to first non-separator +31150 NOSCAN: +31160 MOV AL,0 +31170 CMP B,[SI],20H ;Check for termination character +31180 JB HAVDRV +31190 CMP B,[SI+1],":" ;Check for potential drive specifier +31200 JNZ HAVDRV +31210 CALL GETLET +31220 SUB AL,"@" ;Convert drive letter to binary drive number +31230 JBE BADDRV ;Valid drive numbers are 1-15 +31240 SEG CS +31250 CMP AL,[NUMDRV] +31252 JBE OKDRV +31254 BADDRV: +31256 MOV DL,-1 +31258 OKDRV: +31270 INC SI ;Skip over colon +31280 HAVDRV: +31290 STOB ;Put drive specifier in first byte +31300 MOV CX,8 +31310 CALL GETWORD ;Get 8-letter file name +31320 CMP B,[SI],"." +31330 JNZ NODOT +31340 INC SI ;Skip over dot if present +31350 NODOT: +31360 MOV CX,3 ;Get 3-letter extension +31370 CALL GETWORD +31380 SEG CS +31390 LDS BX,[SPSAVE] +31400 MOV [BX+SISAVE],SI +31410 XOR AX,AX +31420 STOW +31430 STOW +31440 MOV AL,DL +31450 RET +31460 +31510 GETWORD: +31520 CALL GETLET +31530 JZ FILLNAM ;Exit if invalid character +31540 CMP AL," " +31550 JBE FILLNAM +31560 CMP AL,"*" ;Check for ambiguous file specifier +31570 JNZ NOSTAR +31580 MOV AL,"?" +31590 DEC CX +31600 REP +31610 STOB ;Fill rest of word with "?" +31620 INC CX +31630 NOSTAR: +31640 STOB +31650 CMP AL,"?" +31660 JNZ NOTQ +31670 OR DL,1 ;Flag ambiguous file name +31680 NOTQ: +31690 LOOP GETWORD +31700 INC SI ;Point to "termination" character +31710 FILLNAM: +31720 MOV AL," " +31730 REP +31740 STOB +31750 DEC SI +31760 RET +31770 +31780 GETLET: +31790 LODB +31800 AND AL,7FH +31810 CMP AL,"a" +31820 JB CHK +31830 CMP AL,"z" +31840 JA CHK +31850 SUB AL,20H ;Convert to upper case +31860 CHK: +31870 CMP AL," " +31880 JZ RET +31890 CMP AL,"=" +31900 JZ RET +31910 CMP AL,"," +31920 JZ RET +31930 CMP AL,";" +31940 JZ RET +31950 CMP AL,"." +31960 JZ RET +31970 CMP AL,":" +31980 JZ RET +31990 CMP AL,'"' +32000 JZ RET +32010 CMP AL,"+" +32020 JZ RET +32030 CMP AL,"/" +32040 JZ RET +32050 CMP AL,"[" +32060 JZ RET +32070 CMP AL,"]" +32080 JZ RET +32090 CMP AL,9 ;Filter out TABs too +32100 RET +32110 +32120 +32130 SETVECT: ; Interrupt call 37 +32140 XOR BX,BX +32150 MOV ES,BX +32160 MOV BL,AL +32170 SHL BX +32180 SHL BX +32190 SEG ES +32200 MOV [BX],DX +32210 SEG ES +32220 MOV [BX+2],DS +32230 RET +32240 +32250 +32260 NEWBASE: ; Interrupt call 38 +32270 MOV ES,DX +32280 SEG CS +32290 LDS SI,[SPSAVE] +32300 MOV DS,[SI+CSSAVE] +32310 XOR SI,SI +32320 MOV DI,SI +32330 MOV CX,80H +32340 REP +32350 MOVW +32360 +32370 SETMEM: +32380 +32390 ; Inputs: +32400 ; DX = Segment +32410 ; Function: +32420 ; Completely prepares a program base at the +32430 ; specified segment. +32440 ; Outputs: +32450 ; DS = DX +32460 ; ES = DX +32470 ; [0] has INT 20H +32480 ; [2] = First unavailable segment ([ENDMEM]) +32490 ; [5] to [9] form a long call to the entry point +32500 ; [10] to [13] have exit address (from INT 22H) +32510 ; [14] to [17] have ctrl-C exit address (from INT 23H) +32520 ; AX,DX,BP unchanged. All other registers destroyed. +32530 +32540 XOR CX,CX +32550 MOV DS,CX +32560 MOV ES,DX +32570 MOV SI,EXIT +32580 MOV DI,SAVEXIT +32590 MOVW +32600 MOVW +32610 MOVW +32620 MOVW +32630 SEG CS +32640 MOV CX,[ENDMEM] +32650 SEG ES +32660 MOV [2],CX +32670 SUB CX,DX +32680 CMP CX,MAXDIF +32690 JBE HAVDIF +32700 MOV CX,MAXDIF +32710 HAVDIF: +32720 MOV BX,ENTRYPOINTSEG +32730 SUB BX,CX +32740 SHL CX +32750 SHL CX +32760 SHL CX +32770 SHL CX +32780 MOV DS,DX +32790 MOV [6],CX +32800 MOV [8],BX +32810 MOV [0],20CDH ;"INT INTTAB" +32820 MOV B,[5],LONGCALL +32830 RET +32840 +32850 +32860 SHFTDI7: +32870 SHL DI +32880 SHL DI +32890 SHL DI +32900 SHL DI +32910 SHL DI +32920 SHL DI +32930 SHL DI +32940 RET +32950 +32960 DATE16: +32970 PUSH CX +32980 PUSH DX +32990 PUSH BX +33000 CALL READTIME +33010 POP BX +33020 POP DX +33030 POP CX +33040 MOV AX,[MONTH] ;Fetch month and year +33050 SHL AL ;Push month to left to make room for day +33060 SHL AL +33070 SHL AL +33080 SHL AL +33090 SHL AX +33100 OR AL,[DAY] +33110 RET +33120 +33130 READTIME: +33140 ;Gets tick count in CX:DX. Causes date rollover if new day has started +33150 ;since last call. Destroys AX, BX. +33160 MOV AH,0 ;Request get time +33170 INT 1AH ;Time-of-day interrupt +33180 OR AL,AL ;See if day has changed +33190 JZ RET +33200 ADD AL,[DAY] +33210 MOV [DAY],AL +33220 MOV AH,AL +33230 MOV AL,[MONTH] +33240 MOV BX,DAYTAB-1 ;Table of days in each month +33250 XLAT ;Get number of days in current month +33260 SUB AH,AL ;Have we rolled into next month? +33270 JBE RET +33280 MOV [DAY],AH ;Yes-store day of new month +33290 MOV AL,[MONTH] +33300 INC AL +33310 MOV [MONTH],AL +33320 CMP AL,12 ;Have we rolled into next year? +33330 JBE RET +33340 MOV B,[MONTH],1 ;Set first month to January +33350 MOV AL,[YEAR] +33360 INC AL +33370 SETYEAR: +33380 ;Set year with value in AL. Adjust length of February for this year. +33390 MOV [YEAR],AL +33400 AND AL,3 ;Check for leap year +33410 MOV AL,28 +33420 JNZ SAVFEB ;28 days if no leap year +33430 INC AL ;Add leap day +33440 SAVFEB: +33450 MOV [DAYTAB+1],AL ;Store for February +33460 RET +33470 +33480 DAYTAB: ;Days of each month +33490 DB 31 ;January +33500 DB 28 ;February--reset each time year changes +33510 DB 31 ;March +33520 DB 30 ;April +33530 DB 31 ;May +33540 DB 30 ;June +33550 DB 31 ;July +33560 DB 31 ;August +33570 DB 30 ;September +33580 DB 31 ;October +33590 DB 30 ;November +33600 DB 31 ;December +33610 +33620 GETDATE: ;Function call 42 +33630 PUSH CS +33640 POP DS +33650 CALL READTIME ;Check for rollover to next day +33660 MOV AX,[YEAR] +33670 MOV BX,[DAY] +33680 LDS SI,[SPSAVE] ;Get pointer to user registers +33690 MOV [SI+DXSAVE],BX ;DH=month, DL=day +33700 ADD AX,1980 ;Put bias back +33710 MOV [SI+CXSAVE],AX ;CX=year +33720 XOR AL,AL +33730 RET +33740 +33750 SETDATE: ;Function call 43 +33760 MOV AL,-1 ;Be ready to flag an error +33770 SUB CX,1980 ;Fix bias in year +33780 JC RET ;Error if not big enough +33790 CMP CX,119 ;Year must be less than 2100 +33800 JA RET +33810 OR DH,DH +33820 JZ RET +33830 OR DL,DL +33840 JZ RET ;Error if either month or day is 0 +33850 CMP DH,12 ;Check against max. month +33860 JA RET +33870 PUSH CS +33880 POP DS +33890 CMP DH,2 ;Check for Feb.--needs special handling +33900 JNE DAYCHK +33910 CMP DL,29 +33920 JA RET ;Max 29 days in Feb. +33930 JB DAYOK ;If 28 or less, definitely OK +33940 TEST CL,3 ;Check for leap year +33950 JZ DAYOK ;If it is, 29 days OK +33960 RET ;Error if it's not +33970 DAYCHK: +33980 MOV AL,DH +33990 MOV BX,DAYTAB-1 +34000 XLAT ;Look up days in month +34010 CMP AL,DL +34020 MOV AL,-1 ;Restore error flag, just in case +34030 JB RET ;Error if too many days +34040 DAYOK: +34050 PUSH DX +34060 PUSH CX +34070 MOV AH,0 +34080 INT 1AH ;Read time to clear day overflow +34090 POP AX ;Year +34100 CALL SETYEAR +34110 POP [DAY] ;Set both day and month +34120 XOR AL,AL ;Flag OK +34130 RET +34140 +34150 ;*************************************** +34160 ; Time Functions +34170 ; +34180 ; Uses clock with 1,193,180/65536 ticks per second. User sees only +34190 ; time in hours, minutes, seconds, and 1/100 second, in registers +34200 ; CH, CL, DH, DL respectively. (Each is a binary number.) To +34210 ; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +34220 ; reciprocal of the tick rate. To convert the other way, 1/100 secs +34230 ; is multiplied by 59659/(5 * 2**16). +34240 +34250 GETTIME: ;Function call 44 +34260 PUSH CS +34270 POP DS +34280 CALL READTIME ;Get tick count in CX:DX +34290 ;First multiply by 5 +34300 MOV AX,CX +34310 MOV BX,DX +34320 SHL DX +34330 RCL CX ;Times 2 +34340 SHL DX +34350 RCL CX ;Times 4 +34360 ADD DX,BX +34370 ADC AX,CX ;Times 5 +34380 XCHG AX,DX +34390 MOV CX,59659 +34400 DIV AX,CX +34410 MOV BX,AX ;Save quotient +34420 XOR AX,AX ;Extend precision +34430 DIV AX,CX +34440 ;Rounding based on the remainder may be added here +34450 ;The result in BX:AX is time in 1/100 second. +34460 MOV DX,BX +34470 MOV CX,200 ;Extract 1/100's +34480 ;Division by 200 is necessary to ensure no overflow--max result +34490 ;is number of seconds in a day/2 = 43200. +34500 DIV AX,CX +34510 CMP DL,100 ;Remainder over 100? +34520 JB NOADJ +34530 SUB DL,100 ;Keep 1/100's less than 100 +34540 NOADJ: +34550 CMC ;If we subtracted 100, carry is now set +34560 MOV BL,DL ;Save 1/100's +34570 ;To compensate for dividing by 200 instead of 100, we now multiply +34580 ;by two, shifting a one in if the remainder had exceeded 100. +34590 RCL AX +34600 MOV DL,0 +34610 RCL DX +34620 MOV CX,60 ;Divide out seconds +34630 DIV AX,CX +34640 MOV BH,DL ;Save the seconds +34650 DIV AL,CL ;Break into hours and minutes +34660 XCHG AL,AH +34670 ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) +34680 LDS SI,[SPSAVE] ;Get pointer to user registers +34690 MOV [SI+DXSAVE],BX +34700 MOV [SI+CXSAVE],AX +34710 XOR AL,AL +34720 RET +34730 +34740 SETTIME: ;Function call 45 +34750 ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec +34760 MOV AL,-1 ;Flag in case of error +34770 CMP CH,24 ;Check hours +34780 JAE RET +34790 CMP CL,60 ;Check minutes +34800 JAE RET +34810 CMP DH,60 ;Check seconds +34820 JAE RET +34830 CMP DL,100 ;Check 1/100's +34840 JAE RET +34850 MOV AL,60 +34860 MUL AL,CH ;Hours to minutes +34870 MOV CH,0 +34880 ADD AX,CX ;Total minutes +34890 MOV CX,6000 ;60*100 +34900 MOV BX,DX ;Get out of the way of the multiply +34910 MUL AX,CX ;Convert to 1/100 sec +34920 MOV CX,AX +34930 MOV AL,100 +34940 MUL AL,BH ;Convert seconds to 1/100 sec +34950 ADD CX,AX ;Combine seconds with hours and min. +34960 ADC DX,0 ;Ripple carry +34970 MOV BH,0 +34980 ADD CX,BX ;Combine 1/100 sec +34990 ADC DX,0 +35000 ;DX:CX is time in 1/100 sec +35010 XCHG AX,DX +35020 XCHG AX,CX ;Now time is in CX:AX +35030 MOV BX,59659 +35040 MUL AX,BX ;Multiply low half +35050 XCHG DX,CX +35060 XCHG AX,DX ;CX->AX, AX->DX, DX->CX +35070 MUL AX,BX ;Multiply high half +35080 ADD AX,CX ;Combine overlapping products +35090 ADC DX,0 +35100 XCHG AX,DX ;AX:DX=time*59659 +35110 MOV BX,5 +35120 DIV AL,BL ;Divide high half by 5 +35130 MOV CL,AL +35140 MOV CH,0 +35150 MOV AL,AH ;Remainder of divide-by-5 +35160 CBW +35170 XCHG AX,DX ;Use it to extend low half +35180 DIV AX,BX ;Divde low half by 5 +35190 MOV DX,AX +35200 ;CX:DX now has time in ticks +35210 MOV AH,1 +35220 INT 1AH ;Set clock +35230 XOR AL,AL ;Return no error +35240 RET +35250 +35260 ;***** DATA AREA ***** +35270 +35280 ;Device number mapping +35290 ;0,1 = CON, AUX (Bidirectional devices) +35300 ;2,3 = Printer, bit bucket (output only) +35310 +35320 IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +35330 IONUM: DB 3,0,1,1,2,2 +35340 +35350 CARPOS: DB 0 +35360 INSFLG: DB 0 +35370 STARTPOS:DB 0 +35380 PFLAG: DB 0 +35390 DAY: DB 0 +35400 MONTH: DB 0 +35410 YEAR: DW 0 +35420 DIRTYDIR:DB 0 ;Dirty buffer flag +35430 NUMDRV: DS 1 ;Number of drives +35440 CONTPOS:DW 0 +35450 DMAADD: DW 80H ;User's disk transfer address (disp/seg) +35460 DS 2 +35470 ENDMEM: DS 2 +35480 MAXSEC: DW 0 +35490 BUFFER: DS 2 +35500 BUFSECNO:DW 0 +35510 BUFDRVNO:DB -1 +35520 DIRTYBUF:DB 0 +35530 BUFDRVBP:DS 2 +35540 DIRBUFID:DW -1 +35550 CURDRVPT:DS 2 +35560 DRVTAB: DS 30 ;Enough for 15 drives +35570 INBUF: DS 15 ;Only the first part +35580 +35590 ; Init code overlaps with data area below +35600 +35610 INITCODE: +35620 +35630 DS 128-15 ;More of INBUF +35640 CONBUF: DS 130 ;The rest of INBUF and console buffer +35650 FUNC: DS 1 ;Currently executing function code +35660 LASTENT:DS 2 +35670 EXITHOLD:DS 4 +35680 FATBASE:DS 2 +35690 NAME1: DS 11 ;File name buffer +35700 ATTRIB: DS 1 ;Search attributes +35710 NAME2: DS 11 +35715 NAME3: DS 12 +35720 EXTFCB: DS 1 +35730 CREATING:DS 1 +35740 TEMP: +35750 SPSAVE: DS 2 +35760 SSSAVE: DS 2 +35770 CONTSTK:DS 2 +35780 SECCLUSPOS:DS 1 ;Position of first sector within cluster +35790 DSKERR: DS 1 +35800 TRANS: DS 1 +35810 PREREAD:DS 1 ;0 means must preread; 1 means optional +35820 READOP: DS 1 +35830 +35840 ALIGN +35850 FCB: DS 2 ;Address of user FCB +35860 NEXTADD:DS 2 +35870 RECPOS: DS 4 +35880 RECCNT: DS 2 +35890 LASTPOS:DS 2 +35900 CLUSNUM:DS 2 +35910 SECPOS: DS 2 ;Position of first sector accessed +35920 VALSEC: DS 2 ;Number of valid (previously written) sectors +35930 BYTSECPOS:DS 2 ;Position of first byte within sector +35940 BYTPOS: DS 4 ;Byte position in file of access +35950 BYTCNT1:DS 2 ;No. of bytes in first sector +35960 BYTCNT2:DS 2 ;No. of bytes in last sector +35970 SECCNT: DS 2 ;No. of whole sectors +35980 +35990 DS 100H ;Stack space +36000 IOSTACK: +36010 DS 100H +36020 DSKSTACK: +36030 +36040 IF DSKTEST +36050 NSS: DS 2 +36060 NSP: DS 2 +36070 ENDIF +36080 +36090 DIRBUF: +36100 +36110 ;Init code below overlaps with data area above +36120 +36130 ORG INITCODE +36140 PUT $+100H +36150 +36160 MOVFAT: +36170 ;This section of code is safe from being overwritten by block move +36180 SEG ES +36190 REP +36200 MOVB +36210 UP +36220 FININIT: +36230 CALL SETMEM ;Set up segment +36240 RET L +36250 +36260 DOSINIT: +36270 DI +36280 UP +36290 PUSH CS +36300 POP ES +36310 LODB +36320 SEG ES +36330 MOV [NUMDRV],AL +36340 MOV BX,DRVTAB +36350 MOV DI,MEMSTRT +36360 PERDRV: +36370 SEG ES +36380 MOV [BX],DI +36390 MOV BP,DI +36400 INC BX +36410 INC BX +36420 SEG ES +36430 MOV AL,[DRVCNT] +36440 STOB ;DRVNUM +36450 LODW ;Pointer to DPT +36460 PUSH SI +36470 MOV SI,AX +36480 LODW +36490 STOW ;SECSIZ +36500 MOV DX,AX +36510 SEG ES +36520 CMP AX,[MAXSEC] +36530 JBE NOTMAX +36540 SEG ES +36550 MOV [MAXSEC],AX +36560 NOTMAX: +36570 LODB +36580 DEC AL +36590 STOB ;CLUSMSK +36600 JZ HAVSHFT +36610 CBW +36620 FIGSHFT: +36630 INC AH +36640 SAR AL +36650 JNZ FIGSHFT +36660 MOV AL,AH +36670 HAVSHFT: +36680 STOB ;CLUSSHFT +36690 MOVW ;FIRFAT (= number of reserved sectors) +36700 MOVB ;FATCNT +36710 MOVW ;MAXENT +36720 MOV AX,DX ;SECSIZ again +36730 MOV CL,5 +36740 SHR AX,CL +36750 MOV CX,AX ;Directory entries per sector +36760 DEC AX +36770 SEG ES +36780 ADD AX,[BP+MAXENT] +36790 XOR DX,DX +36800 DIV AX,CX +36810 STOW ;DIRSEC (temporarily) +36820 SHR AX ;Divide by two +36830 ADC AX,0 ;Round up +36840 SEG ES +36850 MOV [SDIRSEC],AX ;Number of directory records for small entries +36860 MOVW ;DSKSIZ (temporarily) +36870 FNDFATSIZ: +36880 MOV AL,1 +36890 MOV DX,1 +36900 GETFATSIZ: +36910 PUSH DX +36920 CALL FIGFATSIZ +36930 POP DX +36940 CMP AL,DL ;Compare newly computed FAT size with trial +36950 JZ HAVFATSIZ ;Has sequence converged? +36960 CMP AL,DH ;Compare with previous trial +36970 MOV DH,DL +36980 MOV DL,AL ;Shuffle trials +36990 JNZ GETFATSIZ ;Continue iterations if not oscillating +37000 SEG ES +37010 DEC [BP+DSKSIZ] ;Damp those oscillations +37020 JP FNDFATSIZ ;Try again +37030 HAVFATSIZ: +37040 STOB ;FATSIZ +37050 SEG ES +37060 MUL AL,[BP+FATCNT] ;Space occupied by all FATs +37070 SEG ES +37080 ADD AX,[BP+FIRFAT] +37090 STOW ;FIRDIR +37100 +37110 IF SMALLDIR-1 +37120 SEG ES +37130 ADD AX,[BP+DIRSEC] +37140 SEG ES +37150 MOV [BP+FIRREC],AX ;Destroys DIRSEC +37160 CALL FIGMAX +37170 SEG ES +37180 MOV [BP+MAXCLUS],CX +37190 ENDIF +37200 +37210 IF SMALLDIR +37220 MOV DX,AX ;Save FIRDIR momentarily +37230 SEG ES +37240 ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry +37250 STOW ;FIRREC1 +37260 XCHG AX,CX ;Previously computed MAXCLUS +37270 STOW ;MAXCLUS1 +37280 XCHG DX,AX +37290 SEG ES +37300 ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry +37310 STOW ;FIRREC2 +37320 CALL FIGMAX +37330 XCHG AX,CX +37340 STOW ;MAXCLUS2 +37350 ENDIF +37360 +37370 MOV AX,0FFH +37380 STOB ;DIRTYFAT +37390 SEG ES +37400 MOV AL,[BP+FATSIZ] +37410 SEG ES +37420 MUL AX,[BP+SECSIZ] +37430 ADD DI,AX ;Allocate FAT +37440 POP SI ;Restore pointer to init. table +37450 SEG ES +37460 MOV AL,[DRVCNT] +37470 INC AL +37480 SEG ES +37490 MOV [DRVCNT],AL +37500 SEG ES +37510 CMP AL,[NUMDRV] +37520 JAE CONTINIT +37530 JMP PERDRV +37540 CONTINIT: +37550 LODW ;Max. buffer size +37560 SEG ES +37570 MOV BX,[MAXSEC] +37580 MOV AX,DIRBUF +37590 ADD AX,BX +37600 SEG ES +37610 MOV [BUFFER],AX ;Start of buffer +37620 PUSH DI ;Save ending location +37630 ADD DI,BX ;Allocate directory buffer +37640 ADD DI,BX ;Allocate buffer space +37650 ADD DI,ADJFAC+15 ;True start of free space +37660 MOV CL,4 +37670 SHR DI,CL ;First free segment +37680 MOV BP,DI +37690 XOR AX,AX +37700 MOV DS,AX +37710 MOV ES,AX +37720 MOV DI,INTBASE +37730 MOV AX,QUIT +37740 STOW ;Set abort address--displacement +37750 MOV AX,CS +37760 MOV B,[ENTRYPOINT],LONGJUMP +37770 MOV [ENTRYPOINT+1],ENTRY +37780 MOV [ENTRYPOINT+3],AX +37790 MOV CX,9 +37800 REP +37810 STOW ;Set 5 segments (skip 2 between each) +37820 MOV [INTBASE+4],COMMAND +37830 MOV [INTBASE+12],IRET ;CTRL-C exit +37840 MOV [INTBASE+16],IRET ;Fatal error exit +37850 MOV AX,BIOSREAD +37860 STOW +37870 MOV AX,BIOSSEG +37880 STOW +37890 STOW ;Add 2 to DI +37900 STOW +37910 MOV [INTBASE+18H],BIOSWRITE +37920 MOV DX,CS +37930 MOV DS,DX +37940 ADD DX,BP +37950 MOV [DMAADD],80H +37960 MOV [DMAADD+2],DX +37970 MOV AX,[DRVTAB] +37980 MOV [CURDRVPT],AX +37990 INT 12H ;Get memory size--1K blocks in AX +38000 MOV CL,6 +38010 SHL AX,CL ;Convert to 16-byte blocks (segment no.) +38020 SEG CS +38030 MOV [ENDMEM],AX +38040 XOR CX,CX +38050 MOV DS,CX +38060 MOV [EXIT],100H +38070 MOV [EXIT+2],DX +38080 PUSH CS +38090 POP DS +38100 PUSH CS +38110 POP ES +38120 MOV [ENDDOS],DX +38130 ;Move FATs into position. Segment of COMMAND still in DX. +38140 POP SI +38150 MOV AX,[MAXSEC] +38160 SHL AX ;Allocate two buffers +38170 ADD AX,ADJFAC +38180 JZ FINJMP +38190 MOV DI,DRVTAB +38200 MOV CX,15 +38210 ADJLP: +38220 ADD [DI],AX +38230 INC DI +38240 INC DI +38250 LOOP ADJLP +38260 MOV CX,SI +38270 MOV SI,MEMSTRT ;Place to move FATs from +38280 SUB CX,SI ;Total length of FATs +38290 MOV DI,AX +38300 ADD DI,SI ;Place to move FATs to +38310 OR AX,AX +38320 JS MOVJMP +38330 DEC CX +38340 ADD DI,CX +38350 ADD SI,CX +38360 INC CX +38370 DOWN +38380 MOVJMP: +38390 JMP MOVFAT +38400 FINJMP: JMP FININIT +38410 +38420 FIGFATSIZ: +38430 SEG ES +38440 MUL AL,[BP+FATCNT] +38450 SEG ES +38460 ADD AX,[BP+FIRFAT] +38470 SEG ES +38480 ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +38490 FIGMAX: +38500 ;AX has equivalent of FIRREC +38510 SEG ES +38520 SUB AX,[BP+DSKSIZ] +38530 NEG AX +38540 SEG ES +38550 MOV CL,[BP+CLUSSHFT] +38560 SHR AX,CL +38570 INC AX +38580 MOV CX,AX ;MAXCLUS +38590 INC AX +38600 MOV DX,AX +38610 SHR DX +38620 ADC AX,DX ;Size of FAT in bytes +38630 SEG ES +38640 MOV SI,[BP+SECSIZ] +38650 ADD AX,SI +38660 DEC AX +38670 XOR DX,DX +38680 DIV AX,SI +38690 RET +38700 +38710 DRVCNT: DB 0 +38720 SDIRSEC:DS 1 +38730 +38740 MEMSTRT: +38750 ADJFAC: EQU DIRBUF-MEMSTRT +38760 +38770 DS EXCESS +38780 DB 0 + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + * * * L P T S P L R u n L o g * * * + +13:49:36 LPDAT [LPTLSJ LPTSPL version 102(2263) running on LPT000, 08-Jul-81 13:49:36] +13:49:36 LPDAT [LPTSJS Starting Job 86DOS, Seq #2408, request created at 08-Jul-81 13:49:36] +13:49:41 LPMSG [LPTSTF Starting File DSKC:86DOS.A86<055>[500,500]] +13:52:40 LPMSG [LPTCPT Checkpoint Taken during file DSKC:86DOS.A86<055>[500,500], copy 1, page 27] +13:55:40 LPMSG [LPTCPT Checkpoint Taken during file DSKC:86DOS.A86<055>[500,500], copy 1, page 56] +13:56:35 LPMSG [LPTFPF Finished Printing File DSKC:86DOS.A86<055>[500,500]] +13:56:35 LPSUM Spooler runtime 1 Seconds, 9 KCS, 171 disk reads, 66 pages printed + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + **END** User BASLIB-86 [20,67] Job 86DOS Seq. 2408 Date 08-Jul-81 13:56:35 Monitor Microsoft 1091 603a4d80j **END** + + + + +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111 +000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 diff --git a/1_transcription/bundle_3 b/1_transcription/bundle_3 new file mode 100644 index 0000000..2a8573e --- /dev/null +++ b/1_transcription/bundle_3 @@ -0,0 +1,1012 @@ +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLL IIIIIIIII NNN NNN +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLL IIIIIIIII NNN NNN +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLL IIIIIIIII NNN NNN +EEE DDD DDD LLL III NNN NNN +EEE DDD DDD LLL III NNN NNN +EEE DDD DDD LLL III NNN NNN +EEE DDD DDD LLL III NNNNNN NNN +EEE DDD DDD LLL III NNNNNN NNN +EEE DDD DDD LLL III NNNNNN NNN +EEEEEEEEEEEE DDD DDD LLL III NNN NNN NNN +EEEEEEEEEEEE DDD DDD LLL III NNN NNN NNN +EEEEEEEEEEEE DDD DDD LLL III NNN NNN NNN +EEE DDD DDD LLL III NNN NNNNNN +EEE DDD DDD LLL III NNN NNNNNN +EEE DDD DDD LLL III NNN NNNNNN +EEE DDD DDD LLL III NNN NNN +EEE DDD DDD LLL III NNN NNN +EEE DDD DDD LLL III NNN NNN +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLLLLLLLLLLLLLL IIIIIIIII NNN NNN +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLLLLLLLLLLLLLL IIIIIIIII NNN NNN +EEEEEEEEEEEEEEE DDDDDDDDDDDD LLLLLLLLLLLLLLL IIIIIIIII NNN NNN + + + + +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF + + + + + *START* User ROS BASIC [500,500] Job EDLIN Seq. 3006 Date 28-Jul-81 14:40:32 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:EDLIN.DIF<055>[500,500] Created: 28-Jul-81 14:21:18 Printed: 28-Jul-81 14:40:48 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:119 /FORMS:NORMAL + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +1)1 ;EDLIN - Simple line-oriented editor for 86-DOS version 1.00 04/24/81 +1 FCB: EQU 5CH +**** +2) 00040 ;EDLIN - Simple line-oriented editor for 86-DOS version 0.32 04/15/81 +2) 00080 FCB: EQU 5CH +************** +1)1 HEADER: DB 13,10,"EDLIN version 1.00",13,10,"$" +1) NONAME: +1) MOV DX,NDNAME +1) JMP ERROR +1) SIMPED: +**** +2)1 00460 HEADER: DB 13,10,"The IBM Personal Computer EDITOR",13,10 +2) 00480 DB "Version 1.00 (C)Copyright IBM Corp 1981",13,10,"$" +2) 00500 DB "Licensed Material - Program Property of IBM" +2) 00540 NONAME: +2) 00560 MOV DX,NDNAME +2) 00580 ERRJ: JMP ERROR +2) 00620 SIMPED: +************** +1)1 MOV DX,HEADER +1) MOV AH,PRINT +1) INT 33 +1) CMP B,[FCB+1]," " +1) JZ NONAME +1) MOV SI,BAK +**** +2)1 00680 ; MOV DX,HEADER +2) 00700 ; MOV AH,PRINT +2) 00720 ; INT 33 +2) 00740 CMP B,[FCB+1]," " +2) 00760 JZ NONAME +2) 00780 OR AL,AL +2) 00800 MOV DX,BADDRV +2) 00820 JNZ ERRJ +2) 00840 MOV SI,BAK +************** +1)1 ADD CX,AX ;3/4 of available memory +1) ;Read in input file +**** +2)1 02200 MOV [ONE4TH],CX ;Save amount of 1/4 full +2) 02220 ADD CX,AX ;3/4 of available memory +2) 02240 MOV DX,CX +2) 02260 ADD DX,START +2) 02280 MOV [THREE4TH],DX ;Save pointer to 3/4 full +2) 02300 ;Read in input file +************** +1)1 DEC SI +1) CALL GETNUM +**** +2)1 03140 DEC SI +2) 03160 CALL GETNUM +************** +1)1 AND AL,5FH +1) MOV DI,COMTAB +**** + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2)1 03305 CMP AL,5FH +2) 03310 JBE UPCASE +2) 03320 AND AL,5FH +2) 03325 UPCASE: +2) 03340 MOV DI,COMTAB +************** +1)1 SHL BX +**** +2)1 03460 MOV AX,[PARAM2] +2) 03480 OR AX,AX +2) 03500 JZ PARMOK +2) 03520 CMP AX,[PARAM1] +2) 03540 JB COMERR ;Param. 2 must be >= param 1 +2) 03560 PARMOK: +2) 03580 SHL BX +************** +1)1 JP COMMAND +1) GETNUM: +**** +2)1 03880 JMP COMMAND +2) 03940 GETNUM: +************** +1)1 NUMLP: +1) CMP AL,"0" +1) JB RET +1) CMP AL,"9" +1) JA RET +1) SUB AL,"0" +**** +2)1 04080 MOV CL,0 ;Flag no parameter seen yet +2) 04100 NUMLP: +2) 04120 CMP AL," " +2) 04140 JB NUMCHK +2) 04160 CMP AL,"9" +2) 04180 JA NUMCHK +2) 04200 CMP DX,6553 ;Max line/10 +2) 04220 JAE COMERR ;Ten times this is too big +2) 04240 MOV CL,1 ;Parameter digit has been found +2) 04260 SUB AL,"0" +************** +1)1 CURLIN: +**** +2)1 04460 NUMCHK: +2) 04480 CMP CL,0 +2) 04500 JZ RET +2) 04520 OR DX,DX +2) 04540 JZ COMERR ;Don't allow zero as a parameter +2) 04560 RET +2) 04600 CURLIN: +************** +1)1 APPEND: +1) TEST B,[HAVEOF],-1 +1) JNZ NOMORE +1) MOV DX,[ENDTXT] +1) MOV DI,DX +**** + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2)1 05380 NOMOREJ:JMP NOMORE +2) 05420 APPEND: +2) 05440 TEST B,[HAVEOF],-1 +2) 05460 JNZ NOMOREJ +2) 05480 MOV DX,[ENDTXT] +2) 05500 CMP [PARAM1],0 ;See if parameter is missing +2) 05520 JNZ PARMAPP +2) 05540 CMP DX,[THREE4TH] ;See if already 3/4ths full +2) 05560 JAE RET ;If so, then done already +2) 05580 PARMAPP: +2) 05600 MOV DI,DX +************** +1)1 MOV BX,[PARAM1] +1) CMP BX,1 +1) SBC BX,0 ;Make a zero a -1 +1) XOR DX,DX +1) CALL SCANLN ;Look for BX lines +**** +2)1 05900 XOR DX,DX +2) 05920 MOV BX,[PARAM1] +2) 05940 OR BX,BX +2) 05960 JNZ COUNTLN +2) 05980 MOV AX,DI +2) 06000 ADD AX,CX ;First byte after loaded text +2) 06020 CMP AX,[THREE4TH] ;See if we made 3/4 full +2) 06040 JBE COUNTLN +2) 06060 MOV DI,[THREE4TH] +2) 06080 MOV CX,AX +2) 06100 SUB CX,DI ;Length remaining over 3/4 +2) 06120 MOV BX,1 ;Look for one more line +2) 06140 COUNTLN: +2) 06160 CALL SCANLN ;Look for BX lines +************** +1)1 EOFCHK: +**** +2)1 06640 NOMORE: +2) 06660 MOV DX,EOF +2) 06680 MOV AH,PRINT +2) 06700 INT 33 +2) 06720 RET +2) 06740 EOFCHK: +************** +1)1 NOMORE: +1) MOV DX,EOF +1) MOV AH,PRINT +1) INT 33 +1) RET +1) WRITE: +**** +2)1 06880 WRITE: +************** +1)1 MOV BX,[CURRENT] +1) DEC BX +1) WRT: +**** +2)1 06960 MOV CX,[ONE4TH] + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2) 06980 MOV DI,[ENDTXT] +2) 07000 SUB DI,CX ;Write everything in front of here +2) 07010 JBE RET +2) 07020 CMP DI,START ;See if there's anything to write +2) 07040 JBE RET +2) 07060 XOR DX,DX +2) 07080 MOV BX,1 ;Look for one more line +2) 07100 CALL SCANLN +2) 07120 JP WRTADD +2) 07140 WRT: +************** +1)1 MOV CX,DI +**** +2)1 07180 WRTADD: +2) 07200 MOV CX,DI +************** +1)1 INC DX +**** +2)1 12680 JAE SOMELEFT +2) 12700 MOV [SRCHCNT],0 +2) 12720 SOMELEFT: +2) 12740 INC DX +************** +1)1 MOV [CURRENT],BX +1) MOV [POINTER],DI +1) PUSH DI +**** +2)1 16620 PUSH BX +2) 16660 PUSH DI +************** +1)1 XOR CX,CX +1) JP REPLACE +1) NOCOM: +**** +2)1 16862 JBE COMERRJ +2) 16864 POP [CURRENT] +2) 16866 MOV [POINTER],DI +2) 16880 XOR CX,CX +2) 16900 JP REPLACE +2) 16910 COMERRJ:JMP COMERR +2) 16960 NOCOM: +************** +1)1 MOV BX,-2 ;Write max. no of lines +1) CALL WRT +**** +2)1 20480 MOV BX,-1 ;Write max. no of lines +2) 20500 CALL WRT +************** +1)1 NDNAME: DB "File name must be specified$" +**** +2)1 21760 BADDRV: DB "Invalid drive or file name$" +2) 21780 NDNAME: DB "File name must be specified$" +************** +1)1 END: DS 2 +**** +2)1 22340 ONE4TH: DS 2 + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2) 22360 THREE4TH:DS 2 +2) 22380 END: DS 2 +************** + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + + + + + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 + + + + + *START* User ROS BASIC [500,500] Job EDLIN Seq. 3006 Date 28-Jul-81 14:40:32 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:CHKDSK.A86<055>[500,500] Created: 15-Jul-81 12:19:22 Printed: 28-Jul-81 14:41:18 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:119 /FORMS:NORMAL + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + + + + + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 + + + + + *START* User ROS BASIC [500,500] Job EDLIN Seq. 3006 Date 28-Jul-81 14:40:32 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:CHKDSK.A86<055>[500,500] Created: 15-Jul-81 12:19:22 Printed: 28-Jul-81 14:41:25 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:119 /FORMS:NORMAL + 00100 +00200 ; CHKDSK Version 1.0 03/10/81 +00300 +00400 ; Verifies and repairs 86-DOS disk directory. +00500 +00600 SETDRV: EQU 14 +00700 GETDRV: EQU 25 +00800 GETMAP: EQU 27 +00900 OPEN: EQU 15 +01000 CLOSE: EQU 16 +01100 DELETE: EQU 19 +01200 SETDMA: EQU 26 +01300 SRCHFST:EQU 17 +01400 SRCHNXT:EQU 18 +01500 OUTCH: EQU 2 +01600 BLKWRT: EQU 40 +01700 PRINTBUF:EQU 9 +01800 +01900 ORG 100H +02000 PUT 100H +02100 +02200 CHKDSK: +02205 MOV SP,STACK +02210 OR AL,AL ;SEE IF INVALID DRIVE SPECIFIED +02215 JNZ DRVERR ;IF SO JUST EXIT +02220 CMP B,[5DH],20H ;MAKE SURE TYPED CORRECTLY +02225 JNZ PRMERR ;IF NOT PARAMETER ERROR +02300 MOV AH,GETDRV +02400 INT 21H +02500 MOV [CURDRV],AL +02600 MOV DL,[5CH] +02700 OR DL,DL +02800 JZ DRVMOV +02900 MOV AH,SETDRV +03000 DEC DL +03100 INT 21H +03110 CMP AL,DL +03120 JA DRVSET +03130 DRVERR: MOV DX,BADDRV +03135 ERROR: +03140 MOV AH,PRINTBUF +03150 INT 33 +03160 INT 32 +03170 +03171 PRMERR: MOV DX,INVPRM ;Invalid parameter +03172 JP ERROR +03175 BADDSK: +03177 MOV AX,CS +03178 MOV DS,AX +03180 MOV AH,SETDRV +03185 MOV DL,[CURDRV] +03190 INT 33 +03195 MOV DX,DIRBAD +03197 JP ERROR +03199 DRVMOV: MOV DL,AL ;Correct drive designator +03200 DRVSET: +03202 MOV B,[WRKDRV],DL ;Save drive indicator +03203 INC DL ;FOR FCB SET +03204 MOV B,[ALLDRV],DL ;FCB ok now +03205 DEC DL +03300 CALL DRVXCG ;Change drives and do map read +03410 CMP B,[BX],0FEH ;Check for initialized disk +03420 JNE BADDSK +03500 PUSH DS +03600 PUSH ES +03700 POP DS +03800 MOV [DSKSIZ],DX ;Number of allocation units +03900 MOV [SECSIZ],CX ;Size of physical sector +04000 MOV AH,0 +04100 MOV [CLUSSIZ],AX ;Sectors per cluster +04200 MOV CX,DX +04300 MOV DI,MAP +04400 XOR AX,AX +04500 REP +04600 STOW ;Zero out allocation map +04700 MOV CX,AX +04800 MOV [ALLOC],AX ;Count of allocation units used +04900 MOV [FILECNT],AX ;Number of files found +05000 MOV [DELCNT],AX ;Number of files deleted due to error +05100 MOV BP,DI +05200 MOV [NAMTAB],BP ;First address of file list +05300 MOV DX,DI +05400 MOV AH,SETDMA +05500 INT 21H +05600 MOV AH,SRCHFST +05700 MOV DX,ALLFILE +05800 INT 21H +05900 INC AL +06000 POP ES ;ES:BX point to FAT +06100 JNZ GETFILES +06200 JMP COMPMAP +06300 GETFILES: +06400 INC CX ;Count number of files +06500 ADD DI,44 ;Separate in file in list by 44 bytes +06600 MOV DX,DI +06700 MOV AH,SETDMA +06800 INT 21H +06900 MOV AH,SRCHNXT +07000 MOV DX,ALLFILE +07100 INT 21H +07200 INC AL +07300 JNZ GETFILES ;Loop until all files are in list +07400 MOV [FILECNT],CX +07500 MOV CX,1 ;File number (position in list) +07600 MOV DX,[DSKSIZ] +07700 INC DX ;Maximum cluster number +07800 MOV [MAXCLUS],DX +07900 ADD BP,34 ;Point to "first cluster" entry +08000 EACHFIL: +08100 XOR AX,AX ;No. of clusters in file +08200 MOV SI,[BP] ;First cluster of file +08300 CMP SI,[MAXCLUS] ;Make sure it's legal +08400 MOV DI,BADDIR +08500 JA BADFIRST +08600 OR SI,SI ;Check for zero-length file +08700 JZ HAVENDJ +08800 SCANFAT: +08900 MOV DI,CX +09000 SHL SI +09100 XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. +09200 SHR SI +09300 OR DI,DI ;Should be zero for unallocated cluster +09400 JNZ CROSSLINK +09500 INC AX ;Count cluster as part of this file +09600 CALL UNPACK +09700 JZ FORCEND ;Make sure cluster knows it's allocated +09800 CMP DI,0FF8H ;Bigger than this means End of File +09900 HAVENDJ:JAE HAVEND +10000 CMP DI,[MAXCLUS] ;Make sure it's a legal value +10100 JA FORCEND +10200 MOV SI,DI +10300 JP SCANFAT ;Visit each cluster allocated to file +10400 +10500 BADFIRST: +10600 PUSH AX ;Because FILERR will pop it later +10610 MOV [BP+2],AX ;AX is zero +10620 MOV [BP+4],AX ;Set size to zero so we won't change it +10700 MOV AX,CX +10800 MOV DX,44 +10900 DEC AX +11000 MUL AX,DX ;Get position in file name table +11100 MOV DX,AX +11200 ADD DX,[NAMTAB] +11300 MOV AH,DELETE +11303 INT 21H +11305 PUSH DS +11309 PUSH CX +11310 PUSH AX +11312 CALL DRVXCG ;Reset dirty bit to rewrite FAT +11313 POP AX +11315 POP CX +11318 POP DS +11321 OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY +11324 JZ DISKOK +11327 JMP BADDSK +11330 DISKOK: +11333 INC [DELCNT] ;Count one deleted file +11600 MOV DX,BADDIR +11700 JP FILERR +11800 +11900 CROSSLINK: +12000 MOV DX,LINKED +12100 PUSH AX +12200 MOV AH,PRINTBUF +12300 INT 21H +12400 MOV AX,DI +12500 CALL PRINTNAM +12600 MOV DX,FILE2 +12700 MOV AH,PRINTBUF +12800 INT 33 +12900 MOV AX,CX +13000 CALL PRINTNAM +13100 MOV DX,CRLF +13200 MOV AH,PRINTBUF +13300 INT 33 +13400 POP AX +13500 ADD [ALLOC],AX +13600 JMP SIZSET1 +13700 +13800 FORCEND: +13900 ; Come here if a cluster allocated to a file contained an illegal +14000 ; link--either a zero (meaning unallocated), or a value larger than +14100 ; the maximum cluster number, but not End of File. Put an End of File +14200 ; mark there so the FAT will at least be well-formed. +14300 MOV DX,0FFFH +14400 CALL PACK +14500 MOV DX,BADCLUS +14600 PUSH AX +14700 +14800 FILERR: +14900 MOV AH,PRINTBUF +15000 INT 21H +15100 MOV AX,CX +15200 CALL PRINTNAM +15300 MOV DX,CRLF +15400 MOV AH,PRINTBUF +15500 INT 21H +15600 POP AX +15700 +15800 HAVEND: +15900 ADD [ALLOC],AX ;Total up allocated clusters +16000 MOV SI,AX +16100 MOV AX,[BP+2] +16200 MOV DX,[BP+4] ;AX:DX now have file length +16300 PUSH CX +16400 MOV CX,[CLUSSIZ] +16500 DEC CX +16600 ADD AX,CX +16700 ADC DX,0 +16800 INC CX +16900 SCALE: +17000 SHR CX +17100 JC SCALED +17200 SHR DX +17300 RCR AX +17400 JP SCALE +17500 SCALED: +17600 DIV AX,[SECSIZ] +17700 OR DX,DX +17800 JZ HAVSIZ +17900 INC AX +18000 HAVSIZ: +18100 CMP AX,SI ;See if file size corresponds with allocation +18200 JZ SIZSET +18300 XOR DI,DI +18400 MOV CX,[CLUSSIZ] +18500 CALL UNSCALE +18600 MOV [BP+6],SI +18700 MOV [BP+8],DI +18800 MOV DX,BP +18900 SUB DX,34 +19000 MOV AH,OPEN +19100 INT 21H +19110 OR AL,AL +19120 JZ DISKOK2 +19130 JMP BADDSK +19140 DISKOK2: +19200 MOV AX,[SECSIZ] +19300 MOV [BP-27+14],AX ;Make record size=sector size +19400 MOV CX,0 +19500 MOV AH,BLKWRT +19600 INT 21H +19700 MOV AH,CLOSE ;Write back corrected directory entry +19800 INT 21H +20000 PUSH DS +20100 CALL DRVXCG ;Change the drives and get the map +20200 POP DS +20300 MOV DX,BADSIZ +20400 MOV AH,PRINTBUF +20500 INT 21H +20600 POP AX +20700 PUSH AX +20800 CALL PRINTNAM +20900 MOV DX,CRLF +21000 MOV AH,PRINTBUF +21100 INT 21H +21200 SIZSET: +21300 POP CX +21400 SIZSET1: +21500 ADD BP,44 ;Scan next file +21600 INC CX +21700 CMP CX,[FILECNT] +21800 JA COMPMAP +21900 JMP EACHFIL +22000 ; Now compare the allocation map we have made with the FAT. Any +22100 ; clusters not allocated in the map will be released. +22200 COMPMAP: +22300 XOR AX,AX ;Keep count of clusters released +22400 MOV BP,MAP +22500 MOV SI,2 ;First usable cluster number +22600 MOV CX,[DSKSIZ] +22700 RELCLUS: +22800 TEST [BP],-1 ;Allocated in our map? +22900 JNZ NXTCLUS ;If so, skip to next +23000 CALL UNPACK +23100 JZ NXTCLUS ;If not allocated, skip to next +23200 XOR DX,DX +23300 CALL PACK ;Change to "Free" status +23400 INC AX ;Count clusters released +23500 NXTCLUS: +23600 INC BP +23700 INC BP +23800 INC SI +23900 LOOP RELCLUS +24000 OR AX,AX ;Any clusters released? +24100 JZ REPORT ;If not, do final report +24200 MOV BX,FREED +24300 CALL DISPCLUS +24400 REPORT: +24500 ; Make status report. Include no. of files, total disk space, +24600 ; free space on disk, total memory, and free memory. +24610 SEG CS +24620 MOV DL,[CURDRV] +24630 MOV AH,SETDRV +24640 INT 21H +24700 MOV SI,[FILECNT] +24800 SUB SI,[DELCNT] +24900 XOR DI,DI +25000 MOV BX,NUMFIL +25100 CALL DISP32BITS +25200 MOV AX,[DSKSIZ] +25300 MOV BX,DSKSPC +25400 CALL DISPCLUS +25500 MOV AX,[DSKSIZ] +25600 SUB AX,[ALLOC] +25700 MOV BX,FRESPC +25800 CALL DISPCLUS +25900 MOV AX,[2] +26000 MOV DX,16 +26100 MUL AX,DX +26200 MOV SI,AX +26300 MOV DI,DX +26400 MOV BX,TOTMEM +26500 CALL DISP32BITS +26600 MOV AX,[2] +26700 MOV DX,CS +26800 SUB AX,DX +26900 MOV DX,16 +27000 MUL AX,DX +27100 MOV SI,AX +27200 MOV DI,DX +27300 MOV BX,FREMEM +27400 CALL DISP32BITS +27405 CALL WRTFRC ;Force all writes and handle write +27410 ;protect violation +27412 SEG CS +27414 MOV B,DL,[CURDRV] ;Get default +27416 MOV AH,SETDRV ;And make it current again +27418 INT 21H +27900 INT 20H ;All done +27902 +27904 WRTFRC: ;******************************************************** +27906 ; This code forces all writes by performing a disk +27908 ; reset (function 13). When the attempt to write +27910 ; the allocation table fails in the case of a write- +27912 ; protected diskette, this logic determines if the +27914 ; allocation table had changed and if no changes were +27916 ; made a normal termination will be forced +27918 ;********************************************************* +27919 MOV AX,DS +27920 PUSH DS ;Must first intercept INT 24H +27921 MOV ES,AX +27922 XOR AX,AX +27924 MOV DS,AX +27926 MOV SI,90H +27928 MOV DI,INT24 ;will move vector to local address +27930 MOV CX,2 +27931 CLD ;So move will increment +27932 REP +27934 MOVW ;Vector now locally stored +27936 MOV AL,24H ; +27938 MOV AH,37 +27940 MOV DX,WRTPRT ; +27942 POP DS ;Get local segment +27944 INT 21H ;Interrupt vector now set +27946 MOV AH,13 +27948 INT 21H +27953 PUSH ES ;Will now reset INT 24H vector +27955 XOR AX,AX +27957 MOV ES,AX +27959 CLD +27961 MOV DI,90H +27963 MOV SI,INT24 +27965 MOV CX,2 +27967 REP +27969 MOVW +27971 POP ES +27973 RET +27974 +27976 WRTPRT: ;********************************************************* +27978 ; This logic is designed to handle the case where +27980 ; CHKDSK found no problems and upon rewriting the +27982 ; allocation table (by the DOS) the disk was write- +27984 ; protected and an error thus occured. With no problems +27986 ; this code will cause normal termination, otherwise +27987 ; normal error handling will occur. +27988 ;********************************************************* +27990 EI ;Run with interrupts live +27992 AND DI,0FFH ;See if write-protect +27994 JNZ WRT100 ;Do normal error handling +27996 CMP AH,3 ;File allocation write? +27998 JNZ WRT100 ;If not do normal handling +27999 SEG CS +28000 CMP [WRKDRV],AL ;Correct drive? +28002 JNZ WRT100 ; +28003 SEG CS +28004 CMP B,[CHGCLS],1 ;Legitimate change? +28006 JZ WRT100 ;If so do normal handling +28007 XOR AL,AL ;Ignore the error +28008 IRET +28009 WRT100: SEG CS +28010 MOV SI,AX ;Save AX +28011 PUSH DX +28012 MOV DL,[CURDRV] ;Fetch current drive +28015 MOV AH,SETDRV +28018 INT 33 ;Drive now ok +28019 POP DX ;Restore DX +28020 MOV AX,SI ;Restore AX +28021 SEG CS +28024 JMP L,[INT24] ;Do normal recovery +28027 +28030 +28060 DRVXCG: +28061 ;********************************************** +28062 ; WILL CHANGE DEFAULT TO WRKDRV READ THE FAT +28063 ; AND CHANGE THE DEFAULT BACK TO CURDRV +28064 ;********************************************** +28065 SEG CS +28068 MOV DL,[WRKDRV] ;Will change the default to this +28070 MOV AH,SETDRV +28072 INT 33 ;Default now "WRKDRV" +28073 MOV AH,GETMAP +28074 INT 33 +28076 PUSH DX +28077 PUSH AX +28078 SEG CS +28080 MOV DL,[CURDRV] ;Get current drive +28082 MOV AH,SETDRV +28084 INT 33 +28085 POP AX +28086 POP DX +28088 RET +28090 +28092 +28094 UNPACK: +28200 MOV DI,SI +28300 SHR DI +28400 ADD DI,SI +28500 SEG ES +28600 MOV DI,[DI+BX] +28700 TEST SI,1 +28800 JZ HAVCLUS +28900 SHR DI +29000 SHR DI +29100 SHR DI +29200 SHR DI +29300 HAVCLUS: +29400 AND DI,0FFFH +29500 RET +29600 +29700 PACK: +29705 ;************************************************************* +29710 ; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +29715 ; SI CLUSTER NUMBER TO BE PACKED +29720 ; DX POINTER TO BE PLACED IN CLUSTER (SI) +29725 ;************************************************************* +29730 MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED +29800 PUSH SI +29900 MOV DI,SI +30000 SHR SI +30100 ADD SI,BX +30200 ADD SI,DI +30300 SHR DI +30400 SEG ES +30500 MOV DI,[SI] +30600 JNC ALIGNED +30700 SHL DX +30800 SHL DX +30900 SHL DX +31000 SHL DX +31100 AND DI,0FH +31200 JP PACKIN +31300 ALIGNED: +31400 AND DI,0F000H +31500 PACKIN: +31600 OR DI,DX +31700 SEG ES +31800 MOV [SI],DI +31900 POP SI +32000 RET +32100 +32200 UNSCALE: +32300 SHR CX +32400 JC RET +32500 SHL SI +32600 RCL DI +32700 JP UNSCALE +32800 +32900 DISPCLUS: +33000 MUL AX,[SECSIZ] +33100 MOV CX,[CLUSSIZ] +33200 MOV SI,AX +33300 MOV DI,DX +33400 CALL UNSCALE +33500 DISP32BITS: +33600 PUSH BX +33700 XOR AX,AX +33800 MOV BX,AX +33900 MOV BP,AX +34000 MOV CX,32 +34100 CONVLP: +34200 SHL SI +34300 RCL DI +34400 XCHG AX,BP +34500 CALL CONVWRD +34600 XCHG AX,BP +34700 XCHG AX,BX +34800 CALL CONVWRD +34900 XCHG AX,BX +35000 ADC AL,0 +35100 LOOP CONVLP +35200 ; Conversion complete. Print 10-digit number with 2 leading blanks. +35300 MOV CX,1B10H +35400 CALL OUTWORD +35500 MOV AX,BX +35600 CALL OUTWORD +35700 MOV AX,BP +35800 CALL OUTWORD +35900 POP DX +36000 MOV AH,PRINTBUF +36100 INT 21H +36200 RET +36300 +36400 OUTWORD: +36500 PUSH AX +36600 MOV DL,AH +36700 CALL OUTBYTE +36800 POP DX +36900 OUTBYTE: +37000 MOV DH,DL +37100 SHR DL +37200 SHR DL +37300 SHR DL +37400 SHR DL +37500 CALL DIGIT +37600 MOV DL,DH +37700 DIGIT: +37800 AND DL,0FH +37900 JZ BLANKZER +38000 MOV CL,0 +38100 BLANKZER: +38200 DEC CH +38300 AND CL,CH +38400 OR DL,30H +38500 SUB DL,CL +38600 MOV AH,OUTCH +38700 INT 21H +38800 RET +38900 +39000 CONVWRD: +39100 ADC AL,AL +39200 DAA +39300 XCHG AL,AH +39400 ADC AL,AL +39500 DAA +39600 XCHG AL,AH +39700 RET +39800 +39900 PRINTNAM: +39910 PUSH CX +40000 DEC AX +40100 MOV CX,44 +40200 MUL AX,CX +40300 MOV SI,AX +40400 ADD SI,[NAMTAB] +40500 ADD SI,8 +40600 MOV CX,8 +40700 MOV AH,OUTCH +40800 CALL PRINTCNT +40900 MOV DL," " +41000 INT 21H +41100 MOV CL,3 +41110 CALL PRINTCNT +41120 POP CX +41130 RET +41140 +41200 PRINTCNT: +41300 LODB +41400 MOV DL,AL +41500 INT 21H +41700 LOOP PRINTCNT +41800 RET +41900 +41950 ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB +42000 ALLDRV: DB 0,"???????????" +42100 DS 25 +42200 +42300 FILE2: DB " and $" +42305 BADDRV: DB "Invalid drive specification$" +42306 INVPRM: DB "Invalid parameter$" +42400 BADCLUS:DB "Allocation error for file $" +42500 BADDIR: DB "Directory error-file : $" +42600 LINKED: DB "Files cross-linked: " +42605 DB 13,10 +42610 DB " $" +42700 BADSIZ: DB "File size error for file $" +42705 DIRBAD: DB "Diskette not initialized $" +42800 FREED: DB " bytes disk space freed",13,10,13,10,"$" +42900 NUMFIL: DB " disk files",13,10,"$" +43000 DSKSPC: DB " bytes total disk space",13,10,"$" +43100 FRESPC: DB " bytes remain available",13,10,13,10,"$" +43200 TOTMEM: DB " bytes total memory",13,10,"$" +43300 FREMEM: DB " bytes free" +43400 CRLF: DB 13,10,"$" +43500 +43600 DSKSIZ: DS 2 +43700 SECSIZ: DS 2 +43800 CLUSSIZ:DS 2 +43805 CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +43810 WRKDRV: DB 0 +43815 INT24: DS 4 +43900 FILECNT:DS 2 +44000 NAMTAB: DS 2 +44100 ALLOC: DS 2 +44200 MAXCLUS:DS 2 +44300 DELCNT: DS 2 +44400 CURDRV: DS 1 +44405 DS 100H +44410 STACK: +44500 +44600 MAP: diff --git a/1_transcription/bundle_4 b/1_transcription/bundle_4 new file mode 100644 index 0000000..685fa9e --- /dev/null +++ b/1_transcription/bundle_4 @@ -0,0 +1,3764 @@ + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + + + + + AAAAAAAAA SSSSSSSSSSSS MMM MMM + AAAAAAAAA SSSSSSSSSSSS MMM MMM + AAAAAAAAA SSSSSSSSSSSS MMM MMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM + + + + + *START* User ROS BASIC [500,500] Job 86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:86DOS.ASM<055>[500,500] Created: 15-Jun-81 03:18:51 Printed: 16-Jun-81 15:17:10 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + + + + + AAAAAAAAA SSSSSSSSSSSS MMM MMM + AAAAAAAAA SSSSSSSSSSSS MMM MMM + AAAAAAAAA SSSSSSSSSSSS MMM MMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMMMMM MMMMMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSS MMM MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAA AAA SSSSSSSSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAAAAAAAAAAAAAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM +AAA AAA SSSSSSSSSSSS MMM MMM + + + + + *START* User ROS BASIC [500,500] Job 86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:86DOS.ASM<055>[500,500] Created: 15-Jun-81 03:18:51 Printed: 16-Jun-81 15:17:17 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL + 00010 +00020 ; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +00030 ; by Tim Paterson +00040 +00050 ; ****************** Revision History ************************* +00060 ; >> EVERY change must noted below!! << +00070 ; +00080 ; 0.34 12/29/80 General release, updating all past customers +00090 ; 0.42 02/25/81 32-byte directory entries added +00100 ; 0.56 03/23/81 Variable record and sector sizes +00110 ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +00120 ; 0.74 04/15/81 Recognize I/O devices with file names +00130 ; 0.75 04/17/81 Improve and correct buffer handling +00140 ; 0.76 04/23/81 Correct directory size when not 2^N entries +00150 ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +00160 ; 1.00 04/28/81 Renumber for general release +00170 ; +00180 ; ************************************************************* +00190 +00200 ; Use the switch below to generate code to accept the old 16-byte +00210 ; directory entry as well as the new 32-byte entry. +00220 +00230 SMALLDIR: EQU 1 ;1 to enable, 0 to disable +00240 +00250 +00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +00270 ; up a different stack for disk I/O (functions > 11) than that used for +00280 ; character I/O which effectively makes the DOS re-entrant. +00290 +00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +00310 +00320 +00330 ; Interrupt Entry Points: +00340 +00350 ; INTBASE: ABORT +00360 ; INTBASE+4: COMMAND +00370 ; INTBASE+8: BASE EXIT ADDRESS +00380 ; INTBASE+C: CONTROL-C ABORT +00390 ; INTBASE+10H: FATAL ERROR ABORT +00400 ; INTBASE+14H: BIOS DISK READ +00410 ; INTBASE+18H: BIOS DISK WRITE +00420 ; INTBASE+40H: Long jump to CALL entry point +00430 +00440 +00450 MAXCALL:EQU 36 +00460 MAXCOM: EQU 41 +00470 ESCCH: EQU 1BH +00480 INTBASE:EQU 80H +00490 INTTAB: EQU 20H +00500 ENTRYPOINTSEG: EQU 0CH +00510 ENTRYPOINT: EQU INTBASE+40H +00520 CONTC: EQU INTTAB+3 +00530 EXIT: EQU INTBASE+8 +00540 LONGJUMP:EQU 0EAH +00550 LONGCALL:EQU 9AH +00560 MAXDIF: EQU 0FFFH +00570 SAVEXIT:EQU 10 +00580 +00590 ; Field definition for FCBs +00600 +00610 ORG 0 +00620 DS 12 ;Drive code and name +00630 EXTENT: DS 2 +00640 RECSIZ: DS 2 ;Size of record (user settable) +00650 FILSIZ: DS 4 ;Size of file in bytes +00660 FDATE: DS 2 ;Date of last writing +00670 FILDIRBLK:DS 2 ;Location in directory +00680 FIRCLUS:DS 2 ;First cluster of file +00690 LSTCLUS:DS 2 ;Last cluster accessed +00700 CLUSPOS:DS 2 ;Position of last cluster accessed +00710 DIRTYFIL:DS 1 ;File has been written to if <>0 +00720 ORG 32 +00730 NR: DS 1 ;Next record +00740 RR: DS 3 ;Random record +00750 +00760 +00770 ; Description of 32-byte directory entry (same as returned by SEARCH FIRST +00780 ; and SEARCH NEXT, functions 17 and 18). +00790 ; +00800 ; Location bytes Description +00810 ; +00820 ; 0 11 File name and extension ( 0E5H if empty) +00830 ; 11 13 Zero field (for expansion) +00840 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +00850 ; 26 2 First allocation unit ( < 4080 ) +00860 ; 28 4 File size, in bytes (LSB first, 30 bits max.) +00870 ; +00880 ; The File Allocation Table uses a 12-bit entry for each allocation unit on +00890 ; the disk. These entries are packed, two for every three bytes. The contents +00900 ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +00910 ; to the base address of the Allocation Table; 3) fetching the 16-bit word at +00920 ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +00930 ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +00940 ; zero is used as an end-of-file trap in the OS and as a flag for directory +00950 ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The +00960 ; first available allocation unit is assigned entry number two, and for Drive Parameter Block +00970 +00980 ORG 0 +00990 DRVNUM: DS 1 ;Drive number +01000 SECSIZ: DS 2 ;Size of physical sector in bytes +01010 CLUSMSK:DS 1 ;Sectors/cluster - 1 +01020 CLUSSHFT:DS 1 ;Log2 of sectors/cluster +01030 FIRFAT: DS 2 ;Starting record of FATs +01040 FATCNT: DS 1 ;Number of FATs for this drive +01050 MAXENT: DS 2 ;Number of directory entries +01060 DIRSEC: ;Number of dir. sectors (init temporary) +01070 FIRREC: DS 2 ;First sector of first cluster +01080 DSKSIZ: ;Size of disk (temp used during init only) +01090 MAXCLUS:DS 2 ;Number of clusters on drive + 1 +01100 FATSIZ: DS 1 ;Number of records occupied by FAT +01110 FIRDIR: DS 2 ;Starting record of directory +01120 +01130 IF SMALLDIR +01140 FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +01150 MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +01160 FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +01170 MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries +01180 ENDIF +01190 +01200 DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +01210 FAT: ;Start of FAT +01220 DIRSIZ: ;-1=small dir. entry, else large +01230 +01240 +01250 ; BIOS entry point defintions +01260 +01270 BIOSSEG: EQU 40H +01280 ORG 0 +01290 DS 3 +01300 BIOSSTAT: DS 3 +01310 BIOSIN: DS 3 +01320 BIOSOUT: DS 3 +01330 BIOSPRINT: DS 3 +01340 BIOSAUXIN: DS 3 +01350 BIOSAUXOUT: DS 3 +01360 BIOSREAD: DS 3 +01370 BIOSWRITE: DS 3 +01380 BIOSDSKCHG: DS 3 +01390 +01400 +01410 ; Location of user registers relative user stack pointer +01420 +01430 ORG 0 +01440 AXSAVE: DS 2 +01450 BXSAVE: DS 2 +01460 CXSAVE: DS 2 +01470 DXSAVE: DS 2 +01480 SISAVE: DS 2 +01490 DISAVE: DS 2 +01500 BPSAVE: DS 2 +01510 DSSAVE: DS 2 +01520 ESSAVE: DS 2 +01530 IPSAVE: DS 2 +01540 CSSAVE: DS 2 +01550 FSAVE: DS 2 +01560 +01570 +01580 ; Start of code +01590 +01600 ORG 0 +01610 PUT 100H +01620 +01630 JMP DOSINIT +01640 +01650 ESCTAB: +01660 DB "SC" ;Copy one char +01670 DB "VN" ;Skip one char +01680 DB "TA" ;Copy to char +01690 DB "WB" ;Skip to char +01700 DB "UH" ;Copy line +01710 DB "HH" ;Kill line (no change in template) +01720 DB "RM" ;Reedit line (new template) +01730 DB "DD" ;Backspace +01740 DB "P@" ;Enter insert mode +01750 DB "QL" ;Exit insert mode +01760 DB ESCCH,ESCCH ;Escape character +01770 DB ESCCH,ESCCH ;End of table +01780 +01790 ESCTABLEN:EQU $-ESCTAB +01800 +01810 HEADER: DB 13,10,"86-DOS version 1.00" +01820 +01830 IF DSKTEST +01840 DB "D" +01850 ENDIF +01860 +01870 DB 13,10 +01880 DB "Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$" +01890 +01900 QUIT: +01910 MOV AH,0 +01920 JP SAVREGS +01930 +01940 COMMAND: ;Interrupt call entry point +01950 CMP AH,MAXCOM +01960 JBE SAVREGS +01970 BADCALL: +01980 MOV AL,0 +01990 IRET: IRET +02000 +02010 ENTRY: ;System call entry point and dispatcher +02020 POP AX ;IP from the long call at 5 +02030 POP AX ;Segment from the long call at 5 +02040 SEG CS +02050 POP [TEMP] ;IP from the CALL 5 +02060 PUSHF ;Start re-ordering the stack +02070 DI +02080 PUSH AX ;Save segment +02090 SEG CS +02100 PUSH [TEMP] ;Stack now ordered as if INT had been used +02110 CMP CL,MAXCALL ;This entry point doesn't get as many calls +02120 JA BADCALL +02130 MOV AH,CL +02140 SAVREGS: +02150 PUSH ES +02160 PUSH DS +02170 PUSH BP +02180 PUSH DI +02190 PUSH SI +02200 PUSH DX +02210 PUSH CX +02220 PUSH BX +02230 PUSH AX +02240 +02250 IF DSKTEST +02260 SEG CS +02270 MOV AX,[SPSAVE] +02280 SEG CS +02290 MOV [NSP],AX +02300 SEG CS +02310 MOV AX,[SSSAVE] +02320 SEG CS +02330 MOV [NSS],AX +02340 POP AX +02350 PUSH AX +02360 ENDIF +02370 +02380 SEG CS +02390 MOV [SPSAVE],SP +02400 SEG CS +02410 MOV [SSSAVE],SS +02420 MOV BP,SP +02430 MOV BX,[BP+CSSAVE] +02440 SEG CS +02450 MOV [CSLOC],BX +02460 MOV SP,CS +02470 MOV SS,SP +02480 MOV SP,STACK +02490 EI ;Stack OK now +02500 SEG CS +02510 MOV [FUNC],AH +02520 MOV BL,AH +02530 MOV BH,0 +02540 SHL BX +02550 UP +02560 +02570 IF DSKTEST +02580 CMP AH,12 +02590 JL SAMSTK +02600 MOV SP,TESTSTK +02610 SAMSTK: +02620 ENDIF +02630 +02640 SEG CS +02650 CALL [BX+DISPATCH] +02660 LEAVE: +02670 DI +02680 SEG CS +02690 MOV SP,[SPSAVE] +02700 SEG CS +02710 MOV SS,[SSSAVE] +02720 MOV BP,SP +02730 MOV [BP+AXSAVE],AL +02740 +02750 IF DSKTEST +02760 SEG CS +02770 MOV AX,[NSP] +02780 SEG CS +02790 MOV [SPSA ENDIF +02800 +02810 PBX +02820 POP CX +02830 POP DX +02840 POP SI +02850 POP DI +02860 POP BP +02870 POP DS +02880 POP ES +02890 IRET +02900 +02910 DISPATCH: +02920 ; Standard Functions +02930 DW ABORT ;0 +02940 DW CONIN +02950 DW CONOUT +02960 DW READER +02970 DW PUNCH +02980 DW LIST ;5 +02990 DW RAWIO +03000 DW RAWINP +03010 DW IN +03020 DW PRTBUF +03030 DW BUFIN ;10 +03040 DW CONSTAT +03050 DW VERSION +03060 DW DSKRESET +03070 DW SELDSK +03080 DW OPEN ;15 +03090 DW CLOSE +03100 DW SRCHFRST +03110 DW SRCHNXT +03120 DW DELETE +03130 DW SEQRD ;20 +03140 DW SEQWRT +03150 DW CREATE +03160 DW RENAME +03170 DW INUSE +03180 DW CURDRV ;25 +03190 DW SETDMA +03200 DW GETFATPT +03210 DW WRTPROT +03220 DW GETRDONLY +03230 DW SETATTRIB ;30 +03240 DW GETDSKPT +03250 DW USERCODE +03260 DW RNDRD +03270 DW RNDWRT +03280 DW FILESIZE ;35 +03290 DW SETRNDREC +03300 ; Extended Functions +03310 DW SETVECT +03320 DW NEWBASE +03330 DW BLKRD +03340 DW BLKWRT ;40 +03350 DW MAKEFCB +03360 +03370 VERSION: +03380 GETIO: +03390 SETIO: +03400 WRTPROT: +03410 GETRDONLY: +03420 SETATTRIB: +03430 USERCODE: +03440 MOV AL,0 +03450 RET +03460 +03470 +03480 READER: +03490 CALL BIOSAUXIN,BIOSSEG +03500 RET +03510 +03520 PUNCH: +03530 MOV AL,DL +03540 CALL BIOSAUXOUT,BIOSSEG +03550 RET +03560 +03570 +03580 UNPACK: +03590 +03600 ; Inputs: +03610 ; DS = CS +03620 ; BX = Cluster number +03630 ; BP = Base of drive parameters +03640 ; SI = Pointer to drive FAT +03650 ; Outputs: +03660 ; DI = Contents of FAT for given cluster +03670 ; Zero set means DI=0 (free cluster) +03680 ; No other registers affected. Fatal error if cluster too big. +03690 +03700 CMP BX,[BP+MAXCLUS] +03710 JA HURTFAT +03720 LEA DI,[SI+BX] +03730 SHR BX +03740 MOV DI,[DI+BX] +03750 JNC HAVCLUS +03760 SHR DI +03770 SHR DI +03780 SHR DI +03790 SHR DI +03800 STC +03810 HAVCLUS: +03820 RCL BX +03830 AND DI,0FFFH +03840 RET +03850 HURTFAT: +03860 MOV SI,BADMES +03870 CALL OUTMES +03880 JMP ERROR +03890 +03900 +03910 PACK: +03920 +03930 ; Inputs: +03940 ; DS = CS +03950 ; BX = Cluster number +03960 ; DX = Data +03970 ; SI = Pointer to drive FAT +03980 ; Outputs: +03990 ; The data is stored in the FAT at the given cluster. +04000 ; BX,DX,DI all destroyed +04010 ; No other registers affected +04020 +04030 MOV DI,BX +04040 SHR BX +04050 ADD BX,SI +04060 ADD BX,DI +04070 SHR DI +04080 MOV DI,[BX] +04090 JNC ALIGNED +04100 SHL DX +04110 SHL DX +04120 SHL DX +04130 SHL DX +04140 AND DI,0FH +04150 JP PACKIN +04160 ALIGNED: +04170 AND DI,0F000H +04180 PACKIN: +04190 OR DI,DX +04200 MOV [BX],DI +04210 RET +04220 +04230 IOCHK: +04240 MOV CX,5 ;Check rest of name but not extension +04250 CMP B,[DI],":" +04260 JNZ NOCOL +04270 INC DI ;Skip over colon +04280 DEC CX +04290 NOCOL: +04300 MOV AL," " +04310 REPE +04320 SCAB ;Make sure rest of name is blanks +04330 JNZ FILSRCH +04340 DEC BL +04350 RET +04360 +04370 GETFILE: +04380 +04390 ; Inputs: +04400 ; DS,DX point to FCB +04410 ; Function: +04420 ; Find file name in disk directory. First byte is +04430 ; drive number (0=current disk). "?" matches any +04440 ; character. +04450 ; Outputs: +04460 ; Carry set if file not found +04470 ; ELSE +04480 ; BP = Base of drive parameters +04490 ; DS = CS +04500 ; ES = CS +04510 ; BX = Pointer into directory buffer +04520 ; SI = Pointer to First Cluster field in directory entry +04530 ; [DIRBUF] has directory record with match +04540 ; [NAME1] has file name +04550 ; All other registers destroyed. +04560 +04570 CALL MOVNAME +04580 JC RET ;Bad file name? +04590 FINDNAME: +04600 MOV AX,CS +04610 MOV DS,AX +04620 MOV SI,IONAME ;List of I/O devices with file names +04630 MOV BX,0FF04H ;BL = number of devices +04640 LOOKIO: +04650 MOV DI,NAME1 +04660 MOV CX,3 ;All device names are 3 letters +04670 REPE +04680 CMPB ;Check for name in list +04690 JZ IOCHK ;If first 3 letters OK, check the rest +04700 ADD SI,CX ;Point to next device name +04710 DEC BL +04720 JNZ LOOKIO +04730 FILSRCH: ;Not a device name +04740 CALL STARTSRCH +04750 CONTSRCH: +04760 CALL GETENTRY +04770 JC RET +04780 SRCH: +04790 CMP B,[BX],0E5H +04800 JZ NEXTENT +04810 MOV SI,BX +04820 MOV DI,NAME1 +04830 MOV CX,11 +04840 WILDCRD: +04850 REPE +04860 CMPB +04870 JZ FOUND +04880 CMP B,[DI-1],"?" +04890 JZ WILDCRD +04900 NEXTENT: +04910 CALL NEXTENTRY +04920 JNC SRCH +04930 RET +04940 +04950 FOUND: +04960 IF SMALLDIR +04970 CMP B,[BP+DIRSIZ],-1 +04980 JZ RET +04990 ENDIF +05000 +05010 ADD SI,15 +05020 RET +05030 +05040 +05050 GETENTRY: +05060 +05070 ; Inputs: +05080 ; [LASTENT] has previously searched directory entry +05090 ; Function: +05100 ; Locates next sequential directory entry in preparation for search +05110 ; Outputs: +05120 ; Carry set if none +05130 ; ELSE +05140 ; AL = Current directory block +05150 ; BX = Pointer to next directory entry in [DIRBUF] +05160 ; DX = Pointer to first byte after end of DIRBUF +05170 ; [LASTENT] = New directory entry number +05180 +05190 MOV AX,[LASTENT] +05200 INC AX ;Start with next entry +05210 CMP AX,[BP+MAXENT] +05220 JAE NONE +05230 MOV [LASTENT],AX +05240 MOV CL,4 +05250 SHL AX,CL +05260 XOR DX,DX +05270 +05280 IF SMALLDIR +05290 CMP B,[BP+DIRSIZ],-1 +05300 JZ SMALENT1 +05310 ENDIF +05320 +05330 SHL AX +05340 RCL DX ;Account for overflow in last shift +05350 SMALENT1: +05360 MOV BX,[BP+SECSIZ] +05370 AND BL,255-31 ;Must be multiple of 32 +05380 DIV AX,BX +05390 MOV BX,DX ;Position within sector +05400 MOV AH,[BP+DRVNUM] ;AL=Directory sector no. +05410 CMP AX,[DIRBUFID] +05420 JZ HAVDIRBUF +05430 PUSH BX +05440 CALL DIRREAD +05450 POP BX +05460 HAVDIRBUF: +05470 MOV DX,DIRBUF +05480 ADD BX,DX +05490 ADD DX,[BP+SECSIZ] +05500 RET +05510 +05520 NEXTENTRY: +05530 +05540 ; Inputs: +05550 ; Same as outputs of GETENTRY, above +05560 ; Function: +05570 ; Update AL, BX, and [LASTENT] for next directory entry. +05580 ; Carry set if no more. +05590 +05600 MOV DI,[LASTENT] +05610 INC DI +05620 CMP DI,[BP+MAXENT] +05630 JAE NONE +05640 MOV [LASTENT],DI +05650 ADD BX,32 +05660 +05670 IF SMALLDIR +05680 CMP B,[BP+DIRSIZ],-1 +05690 JNZ BIGENT3 +05700 SUB BX,16 +05710 BIGENT3: +05720 ENDIF +05730 +05740 CMP BX,DX +05750 JB HAVIT +05760 INC AL ;Next directory sector +05770 PUSH DX ;Save limit +05780 CALL DIRREAD +05790 POP DX +05800 MOV BX,DIRBUF +05810 HAVIT: +05820 CLC +05830 RET +05840 +05850 NONE: +05860 CALL CHKDIRWRITE +05870 STC +05880 RET +05890 +05900 +05910 DELETE: ; System call 19 +05920 CALL GETFILE +05930 JC ERRET +05940 CMP BH,-1 ;Check if device name +05950 JZ ERRET ;Can't delete I/O devices +05960 DELFILE: +05970 MOV B,[DIRTYDIR],-1 +05980 MOV B,[BX],0E5H +05990 MOV BX,[SI] +06000 LEA SI,[BP+FAT] +06010 OR BX,BX +06020 JZ DELNXT +06030 CMP BX,[BP+MAXCLUS] +06040 JA DELNXT +06050 CALL RELEASE +06060 DELNXT: +06070 CALL CONTSRCH +06080 JNC DELFILE +06090 CALL FATWRT +06100 CALL CHKDIRWRITE +06110 XOR AL,AL +06120 RET +06130 +06140 +06150 RENAME: ;System call 23 +06160 CALL MOVNAME +06170 JC ERRET +06180 CMP BH,-1 ;Check if I/O device name +06190 JZ ERRET ;If so, can't rename it +06200 ADD SI,5 +06210 MOV DI,NAME2 +06220 CALL LODNAME +06230 CALL FINDNAME +06240 JC ERRET +06250 RENFIL: +06260 MOV B,[DIRTYDIR],-1 +06270 MOV DI,BX +06280 MOV SI,NAME2 +06290 MOV CX,11 +06300 NEWNAM: +06310 LODB +06320 CMP AL,"?" +06330 JZ NOCHG +06340 MOV [DI],AL +06350 NOCHG: +06360 INC DI +06370 LOOP NEWNAM +06380 CALL CONTSRCH +06390 JNC RENFIL +06400 CALL CHKDIRWRITE +06410 XOR AL,AL +06420 RET +06430 +06440 ERRET: +06450 MOV AL,-1 +06460 RET +06470 +06480 +06490 MOVNAME: +06500 +06510 ; Inputs: +06520 ; DS, DX point to FCB +06530 ; Outputs: +06540 ; ES = CS +06550 ; If file name OK: +06560 ; BP has base of driver parameters +06570 ; [NAME1] has name in upper case +06580 ; All registers except DX destroyed +06590 ; Carry set if bad file name or drive +06600 +06610 MOV AX,CS +06620 MOV ES,AX +06630 MOV DI,NAME1 +06640 MOV SI,DX +06650 LODB +06660 CALL GETBP +06670 JB RET +06680 LODNAME: +06690 ; This entry point copies a file name from DS,SI +06700 ; to ES,DI converting to upper case. +06710 MOV CX,11 +06720 MOVCHK: +06730 LODB +06740 AND AL,7FH +06750 CMP AL,60H +06760 JLE CASEOK +06770 AND AL,5FH +06780 CASEOK: +06790 CMP AL,20H +06800 JC RET +06810 STOB +06820 LOOP MOVCHK +06830 RET +06840 +06850 GETBP: +06860 SEG CS +06870 CMP [NUMDRV],AL +06880 JC RET +06890 CBW +06900 XCHG BP,AX +06910 SHL BP +06920 MOV BP,[BP+CURDRVPT] +06930 RET +06940 +06950 +06960 OPEN: ;System call 15 +06970 PUSH DX +06980 PUSH DS +06990 CALL GETFILE +07000 DOOPEN: +07010 ; Enter here to perform OPEN on file already found +07020 ; in directory. DS=ES=CS, BX points to directory +07030 ; entry in DIRBUF, SI points to First Cluster field, and +07040 ; the top of the stack has the address and segment +07050 ; of the FCB to be opened. This entry point is used +07060 ; by CREATE. +07070 POP ES +07080 POP DI +07090 JC ERRET +07100 CMP BH,-1 ;Check if file is I/O device +07110 JZ OPENDEV ;Special handler if so +07120 MOV AL,[BP+DRVNUM] +07130 INC AL +07140 STOB +07150 ADD DI,11 ;Point to extent field +07160 XOR AX,AX +07170 STOW ;Set extent field to 0 +07180 MOV AX,128 ;Default record size +07190 STOW ;Set record size +07200 LODW ;Get starting cluster +07210 MOV DX,AX ;Save it for the moment +07220 MOVW ;Transfer size to FCB +07230 MOVW +07240 MOV AX,[SI-8] ;Get date +07250 +07260 IF SMALLDIR +07270 CMP B,[BP+DIRSIZ],-1 +07280 JNZ BIGENT10 +07290 SEG ES +07300 MOV [DI-1],0 +07310 XOR AX,AX ;Date not available in small entry +07320 BIGENT10: +07330 ENDIF +07340 +07350 STOW ;Save date in FCB +07360 MOV AX,[LASTENT] +07370 STOW ;directory location +07380 MOV AX,DX ;Restore starting cluster +07390 STOW ; first cluster +07400 STOW ; last cluster accessed +07410 XOR AX,AX +07420 STOW ; position of last cluster +07430 STOB ; dirty flag +07440 RET +07450 +07460 OPENDEV: +07470 SEG ES +07480 MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag +07490 XOR AL,AL +07500 RET +07510 +07520 +07530 STARTSRCH: +07540 MOV [LASTENT],-1 +07550 FATREAD: +07560 +07570 ; Inputs: +07580 ; DS = CS +07590 ; BP = Base of drive parameters +07600 ; Function: +07610 ; If disk may have been changed, FAT is read in and buffers are +07620 ; flagged invalid. If not, no action is taken. +07630 ; Outputs: +07640 ; AL = 0 +07650 ; BP unchanged +07660 ; All other registers destroyed +07670 +07680 MOV AL,[BP+DRVNUM] +07690 CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say +07700 MOV AL,[BP+DRVNUM] +07710 OR AH,[BP+DIRTYFAT] +07720 JS NEWDSK ;If either say new disk, then it's so +07730 DEC AH ;Check for AH=1 (disk not changed) +07740 JZ RET +07750 MOV AH,1 +07760 CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? +07770 JZ RET ;If so, disk has not been changed +07780 NEWDSK: +07790 CMP AL,[BUFDRVNO] ;See if buffer is for this drive +07800 JNZ BUFOK ;If not, don't touch it +07810 MOV [BUFSECNO],0 ;Flag buffers invalid +07820 MOV [BUFDRVNO],00FFH +07830 BUFOK: +07840 MOV [DIRBUFID],-1 +07850 CALL FIGFAT +07860 NEXTFAT: +07870 PUSH DX +07880 PUSH CX +07890 PUSH BX +07900 PUSH AX +07910 CALL DREAD +07920 OR AL,AL +07930 POP AX +07940 POP BX +07950 POP CX +07960 POP DX +07970 JNZ BADFAT +07980 +07990 IF SMALLDIR +08000 MOV DL,AL +08010 LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries +08020 CMP B,[BP+DIRSIZ],-1 +08030 JZ SETSIZ +08040 ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +08050 SETSIZ: +08060 LODW +08070 MOV [BP+FIRREC],AX +08080 LODW +08090 MOV [BP+MAXCLUS],AX +08100 MOV AL,DL +08110 ENDIF +08120 +08130 SUB AL,[BP+FATCNT] +08140 JZ RET +08150 NEG AL +08160 ;{Insert error code here. AL=number of bad fats. +08170 ;Since one good FAT was read, should include option +08180 ;to rewrite all FATs.} +08190 JMP FATWRT +08200 +08210 BADFAT: +08220 ADD DX,CX +08230 DEC AL +08240 JNZ NEXTFAT +08250 POP BP +08260 ;{Insert error code here. All FATs on drive are bad.} +08270 MOV SI,BADFATMES +08280 CALL HARDERR +08290 JP FATREAD +08300 +08310 OKRET1: +08320 MOV AL,0 +08330 RET +08340 +08350 CLOSE: ;System call 16 +08360 MOV DI,DX +08370 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +08380 JZ OKRET1 ;Can't close I/O device +08390 TEST B,[DI+DIRTYFIL],-1 +08400 JZ OKRET1 ;If not written to, do nothing +08410 MOV AL,[DI] ;Get drive number +08420 CALL GETBP ;Get base of drive parameters +08430 JC BADCLOSEJ +08440 MOV AL,[BP+DRVNUM] +08450 MOV AH,1 ;Look for dirty buffer +08460 SEG CS +08470 CMP AX,[BUFDRVNO] +08480 JNZ FNDDIR +08490 ;Write back dirty buffer if on same drive +08500 PUSH DX +08510 PUSH DS +08520 PUSH CS +08530 POP DS +08540 MOV B,[DIRTYBUF],0 +08550 MOV BX,[BUFFER] +08560 MOV CX,1 +08570 MOV DX,[BUFSECNO] +08580 CALL DWRITE +08590 POP DS +08600 POP DX +08610 FNDDIR: +08620 PUSH DX +08630 PUSH DS +08640 CALL GETFILE +08650 POP ES +08660 POP DI +08670 BADCLOSEJ: +08680 JC BADCLOSE +08690 MOV AX,[LASTENT] +08700 SEG ES +08710 CMP AX,[DI+FILDIRBLK] +08720 JNZ BADCLOSE +08730 SEG ES +08740 MOV CX,[DI+FIRCLUS] +08750 MOV [SI],CX +08760 SEG ES +08770 MOV DX,[DI+FILSIZ] +08780 MOV [SI+2],DX +08790 SEG ES +08800 MOV DX,[DI+FILSIZ+2] +08810 +08820 IF SMALLDIR +08830 CMP B,[BP+DIRSIZ],-1 +08840 JNZ BIGENT11 +08850 MOV [SI+4],DL +08860 JP SMALLENT2 +08870 BIGENT11: +08880 ENDIF +08890 +08900 MOV [SI+4],DX +08910 SEG ES +08920 MOV DX,[DI+FDATE] +08930 MOV [SI-2],DX +08940 SMALLENT2: +08950 CALL DIRWRITE +08960 +08970 CHKFATWRT: +08980 ; Do FATWRT only if FAT is dirty +08990 +09000 CMP B,[BP+DIRTYFAT],1 +09010 JNZ OKRET +09020 +09030 FATWRT: +09040 +09050 ; Inputs: +09060 ; DS = CS +09070 ; BP = Base of drive parameter table +09080 ; Function: +09090 ; Write the FAT back to disk and reset FAT +09100 ; dirty bit. +09110 ; Outputs: +09120 ; AL = 0 +09130 ; BP unchanged +09140 ; All other registers destroyed +09150 +09160 MOV B,[BP+DIRTYFAT],0 +09170 CALL FIGFAT +09180 EACHFAT: +09190 PUSH DX +09200 PUSH CX +09210 PUSH BX +09220 PUSH AX +09230 CALL DWRITE +09240 POP AX +09250 POP BX +09260 POP CX +09270 POP DX +09280 ADD DX,CX +09290 DEC AL +09300 JNZ EACHFAT +09310 OKRET: +09320 MOV AL,0 +09330 RET +09340 +09350 BADCLOSE: +09360 MOV B,[BP+DIRTYFAT],0 +09370 MOV AL,-1 +09380 RET +09390 +09400 +09410 FIGFAT: +09420 ; Loads registers with values needed to read or +09430 ; write a FAT. +09440 MOV AL,[BP+FATCNT] +09450 LEA BX,[BP+FAT] +09460 MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT +09470 MOV CH,0 +09480 MOV DX,[BP+FIRFAT] ;Record number of start of FATs +09490 RET +09500 +09510 +09520 DIRCOMP: +09530 ; Prepare registers for directory read or write +09540 CBW +09550 ADD AX,[BP+FIRDIR] +09560 MOV DX,AX +09570 MOV BX,DIRBUF +09580 MOV CX,1 +09590 RET +09600 +09610 +09620 CREATE: ;System call 22 +09630 CALL MOVNAME +09640 JC ERRET3 +09650 MOV DI,NAME1 +09660 MOV CX,11 +09670 MOV AL,"?" +09680 REPNE +09690 SCAB +09700 JZ ERRET3 +09710 PUSH DX +09720 PUSH DS +09730 CALL FINDNAME +09740 JNC EXISTENT +09750 CALL STARTSRCH +09760 CALL GETENTRY +09770 LOOKFRE: +09780 CMP B,[BX],0E5H +09790 JZ FREESPOT +09800 CALL NEXTENTRY +09810 JNC LOOKFRE +09820 POP DS +09830 POP DX +09840 ERRET3: +09850 MOV AL,-1 +09860 RET +09870 +09880 EXISTENT: +09890 CMP BH,-1 ;Check if file is I/O device +09900 JZ OPENJMP ;If so, no action +09910 XOR CX,CX +09920 MOV [SI+2],CX +09930 MOV AX,[DATE] +09940 +09950 IF SMALLDIR +09960 MOV [SI+4],CL +09970 CMP B,[BP+DIRSIZ],-1 +09980 JZ SMLENT +09990 MOV [SI+5],CL +10000 MOV [SI-2],AX +10010 SMLENT: +10020 ENDIF +10030 +10040 IF 1-SMALLDIR +10050 MOV [SI+4],CX +10060 MOV [SI-2],AX +10070 ENDIF +10080 +10090 XCHG CX,[SI] +10100 PUSH SI +10110 PUSH BX +10120 JCXZ WRTBACK +10130 CMP CX,[BP+MAXCLUS] +10140 JA WRTBACK +10150 MOV BX,CX +10160 LEA SI,[BP+FAT] +10170 CALL RELEASE +10180 CALL FATWRT +10190 JP WRTBACK +10200 +10210 FREESPOT: +10220 MOV DI,BX +10230 MOV SI,NAME1 +10240 MOV CX,5 +10250 MOVB +10260 REP +10270 MOVW +10280 XOR AX,AX +10290 +10300 IF SMALLDIR +10310 CMP B,[BP+DIRSIZ],-1 +10320 JNZ BIGENT4 +10330 PUSH DI +10340 MOV CL,5 +10350 JP SMALLENT +10360 BIGENT4: +10370 ENDIF +10380 +10390 MOV CL,13 +10400 REP +10410 STOB +10420 MOV AX,[DATE] +10430 STOW +10440 XOR AX,AX +10450 PUSH DI +10460 MOV CL,6 +10470 SMALLENT: +10480 REP +10490 STOB +10500 PUSH BX +10510 WRTBACK: +10520 CALL DIRWRITE +10530 POP BX +10540 POP SI +10550 OPENJMP: +10560 CLC ;Clear carry so OPEN won't fail +10570 JMP DOOPEN +10580 +10590 +10600 DIRREAD: +10610 +10620 ; Inputs: +10630 ; DS = CS +10640 ; AL = Directory block number +10650 ; BP = Base of drive parameters +10660 ; Function: +10670 ; Read the directory block into DIRBUF. +10680 ; Outputs: +10690 ; AX,BP unchanged +10700 ; All other registers destroyed. +10710 +10720 PUSH AX +10730 CALL CHKDIRWRITE +10740 POP AX +10750 PUSH AX +10760 MOV AH,[BP+DRVNUM] +10770 MOV [DIRBUFID],AX +10780 CALL DIRCOMP +10790 CALL DREAD +10800 POP AX +10810 RET +10820 +10830 +10840 DREAD: +10850 +10860 ; Inputs: +10870 ; BX,DS = Transfer address +10880 ; CX = Number of sectors +10890 ; DX = Absolute record number +10900 ; BP = Base of drive parameters +10910 ; Function: +10920 ; Calls BIOS to perform disk read. If BIOS reports +10930 ; errors, will call HARDERR for further action. +10940 ; Outputs: +10950 ; AL = 0 if no error, otherwise non-zero +10960 ; BP preserved. All other registers destroyed. +10970 +10980 MOV AL,[BP+DRVNUM] +10990 PUSH BP +11000 PUSH BX +11010 PUSH CX +11020 PUSH DX +11030 CALL BIOSREAD,BIOSSEG +11040 POP DX +11050 POP DI +11060 POP BX +11070 POP BP +11080 JC HARDREAD +11090 XOR AL,AL +11100 RET +11110 +11120 HARDREAD: +11130 MOV SI,RDERRMES +11140 CALL HARDERR +11150 JP DREAD +11160 +11170 +11180 CHKDIRWRITE: +11190 TEST B,[DIRTYDIR],-1 +11200 JZ RET +11210 +11220 DIRWRITE: +11230 +11240 ; Inputs: +11250 ; DS = CS +11260 ; AL = Directory block number +11270 ; BP = Base of drive parameters +11280 ; Function: +11290 ; Write the directory block into DIRBUF. +11300 ; Outputs: +11310 ; BP unchanged +11320 ; All other registers destroyed. +11330 +11340 MOV B,[DIRTYDIR],0 +11350 MOV AL,[DIRBUFID] +11360 CALL DIRCOMP +11370 +11380 +11390 DWRITE: +11400 +11410 ; Inputs: +11420 ; BX,DS = Transfer address +11430 ; CX = Number of sectors +11440 ; DX = Absolute record number +11450 ; BP = Base of drive parameters +11460 ; Function: +11470 ; Calls BIOS to perform disk write. If BIOS reports +11480 ; errors, will call HARDERR for further action. +11490 ; Outputs: +11500 ; AL = 0 if no error, otherwise non-zero +11510 ; BP preserved. All other registers destroyed. +11520 +11530 MOV AL,[BP+DRVNUM] +11540 WRTDRV: +11550 PUSH AX +11560 PUSH BP +11570 PUSH BX +11580 PUSH CX +11590 PUSH DX +11600 CALL BIOSWRITE,BIOSSEG +11610 POP DX +11620 POP DI +11630 POP BX +11640 POP BP +11650 POP AX +11660 JC HARDWRITE +11670 XOR AL,AL +11680 RET +11690 HARDWRITE: +11700 MOV SI,WRTERRMES +11710 CALL HARDERR +11720 JP WRTDRV +11730 +11740 +11750 HARDERR: +11760 SUB DI,CX +11770 ADD DX,DI +11780 CALL SHFTDI7 +11790 ADD BX,DI +11800 MOV AH,AL ;Save drive number +11810 CALL OUTMES +11820 GETINSTR: +11830 CALL IN +11840 OR AL,20H +11850 CMP AL,"a" +11860 JZ ERROR +11870 CMP AL,"r" +11880 JZ RETRY +11890 CMP AL,"i" +11900 JZ IGNORE +11910 CMP AL,"c" +11920 JNZ GETINSTR +11930 CONTINUE: +11940 POP AX +11950 MOV AL,1 +11960 RET +11970 IGNORE: +11980 POP AX +11990 MOV AL,0 +12000 RET +12010 RETRY: +12020 MOV AL,AH ;Restore drive number +12030 RET +12040 +12050 +12060 ABORT: +12070 SEG CS +12080 MOV DS,[CSLOC] +12090 XOR AX,AX +12100 MOV ES,AX +12110 MOV SI,SAVEXIT +12120 MOV DI,EXIT +12130 MOVW +12140 MOVW +12150 MOVW +12160 MOVW +12170 ERROR: +12180 MOV AX,CS +12190 MOV DS,AX +12200 MOV ES,AX +12210 CALL WRTFATS +12220 XOR AX,AX +12230 DI +12240 MOV SS,[SSSAVE] +12250 MOV SP,[SPSAVE] +12260 MOV DS,AX +12270 MOV SI,EXIT +12280 MOV DI,EXITHOLD +12290 MOVW +12300 MOVW +12310 POP AX +12320 POP BX +12330 POP CX +12340 POP DX +12350 POP SI +12360 POP DI +12370 POP BP +12380 POP DS +12390 POP ES +12400 EI ;Stack OK now +12410 SEG CS +12420 JMP L,[EXITHOLD] +12430 +12440 +12450 SEQRD: ;System call 20 +12460 CALL GETREC +12470 CALL LOAD +12480 JP FINSEQ +12490 +12500 SEQWRT: ;System call 21 +12510 CALL GETREC +12520 CALL STORE +12530 FINSEQ: +12540 JCXZ SETNREX +12550 ADD AX,1 +12560 ADC DX,0 +12570 JP SETNREX +12580 +12590 RNDRD: ;System call 33 +12600 CALL GETRRPOS1 +12610 CALL LOAD +12620 JP FINRND +12630 +12640 RNDWRT: ;System call 34 +12650 CALL GETRRPOS1 +12660 CALL STORE +12670 JP FINRND +12680 +12690 BLKRD: ;System call 39 +12700 CALL GETRRPOS +12710 CALL LOAD +12720 JP FINBLK +12730 +12740 BLKWRT: ;System call 40 +12750 CALL GETRRPOS +12760 CALL STORE +12770 FINBLK: +12780 LDS SI,[SPSAVE] +12790 MOV [SI+CXSAVE],CX +12800 JCXZ FINRND +12810 ADD AX,1 +12820 ADC DX,0 +12830 FINRND: +12840 SEG ES +12850 MOV [DI+RR],AX +12860 SEG ES +12870 MOV [DI+RR+2],DL +12880 OR DH,DH +12890 JZ SETNREX +12900 SEG ES +12910 MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +12920 SETNREX: +12930 MOV CX,AX +12940 AND AL,7FH +12950 SEG ES +12960 MOV [DI+NR],AL +12970 AND CL,80H +12980 SHL CX +12990 RCL DX +13000 MOV AL,CH +13010 MOV AH,DL +13020 SEG ES +13030 MOV [DI+EXTENT],AX +13040 SEG CS +13050 MOV AL,[DSKERR] +13060 RET +13070 +13080 GETRRPOS1: +13090 MOV CX,1 +13100 GETRRPOS: +13110 MOV DI,DX +13120 MOV AX,[DI+RR] +13130 MOV DX,[DI+RR+2] +13140 RET +13150 +13160 NOFILERR: +13170 XOR CX,CX +13180 MOV B,[DSKERR],-2 +13190 POP BX +13200 RET +13210 +13220 SETUP: +13230 +13240 ; Inputs: +13250 ; DS:DI point to FCB +13260 ; DX:AX = Record position in file of disk transfer +13270 ; CX = Record count +13280 ; Outputs: +13290 ; DS = CS +13300 ; ES:DI point to FCB +13310 ; CX = No. of bytes to transfer +13320 ; BP = Base of drive parameters +13330 ; SI = FAT pointer +13340 ; [RECCNT] = Record count +13350 ; [RECPOS] = Record position in file +13360 ; [FCB] = DI +13370 ; [NEXTADD] = Displacement of disk transfer within segment +13380 ; [SECPOS] = Position of first sector +13390 ; [BYTPOS] = Byte position in file +13400 ; [BYTSECPOS] = Byte position in first sector +13410 ; [CLUSNUM] = First cluster +13420 ; [SECCLUSPOS] = Sector within first cluster +13430 ; [DSKERR] = 0 (no errors yet) +13440 ; [TRANS] = 0 (No transfers yet) +13450 ; If SETUP detects no records will be transfered, it returns 1 level up +13460 ; with CX = 0. +13470 +13480 PUSH AX +13490 MOV AL,[DI] +13500 MOV SI,[DI+RECSIZ] +13510 OR SI,SI +13520 JNZ HAVRECSIZ +13530 MOV SI,128 +13540 MOV [DI+RECSIZ],SI +13550 HAVRECSIZ: +13560 MOV BX,DS +13570 MOV ES,BX +13580 MOV BX,CS +13590 MOV DS,BX +13600 CALL GETBP +13610 POP AX +13620 JC NOFILERR +13630 CMP SI,64 ;Check if highest byte of RECPOS is significant +13640 JB SMALREC +13650 MOV DH,0 ;Ignore MSB if record >= 64 bytes +13660 SMALREC: +13670 MOV [RECCNT],CX +13680 MOV [RECPOS],AX +13690 MOV [RECPOS+2],DX +13700 MOV [FCB],DI +13710 MOV BX,[DMAADD] +13720 MOV [NEXTADD],BX +13730 MOV B,[DSKERR],0 +13740 MOV B,[TRANS],0 +13750 MOV BX,DX +13760 MUL AX,SI +13770 MOV [BYTPOS],AX +13780 PUSH DX +13790 MOV AX,BX +13800 MUL AX,SI +13810 POP BX +13820 ADD AX,BX +13830 ADC DX,0 ;Ripple carry +13840 JNZ EOFERR +13850 MOV [BYTPOS+2],AX +13860 MOV DX,AX +13870 MOV AX,[BYTPOS] +13880 DIV AX,[BP+SECSIZ] +13890 MOV [SECPOS],AX +13900 MOV [BYTSECPOS],DX +13910 MOV DX,AX +13920 AND AL,[BP+CLUSMSK] +13930 MOV [SECCLUSPOS],AL +13940 MOV AX,CX ;Record count +13950 MOV CL,[BP+CLUSSHFT] +13960 SHR DX,CL +13970 MOV [CLUSNUM],DX +13980 MUL AX,SI ;Multiply by bytes per record +13990 MOV CX,AX +14000 ADD AX,[DMAADD] ;See if it will fit in one segment +14010 ADC DX,0 +14020 JZ OK ;Must stay within 64K +14030 MOV AX,[DMAADD] +14040 NEG AX ;Amount of room left in segment +14050 XOR DX,DX +14060 DIV AX,SI ;How many records will fit? +14070 MUL AX,SI ;Translate that back into bytes +14080 MOV B,[DSKERR],2 ;Flag that trimming took place +14090 MOV CX,AX +14100 JCXZ NOROOM +14110 OK: +14120 LEA SI,[BP+FAT] +14130 RET +14140 +14150 EOFERR: +14160 MOV B,[DSKERR],1 +14170 XOR CX,CX +14180 NOROOM: +14190 POP BX ;Kill return address +14200 RET +14210 +14220 BREAKDOWN: +14230 +14240 ;Inputs: +14250 ; DS = CS +14260 ; CX = Length of disk transfer in bytes +14270 ; BP = Base of drive parameters +14280 ; [BYTSECPOS] = Byte position witin first sector +14290 ;Outputs: +14300 ; [BYTCNT1] = Bytes to transfer in first sector +14310 ; [SECCNT] = No. of whole sectors to transfer +14320 ; [BYTCNT2] = Bytes to transfer in last sector +14330 ;AX, BX, DX destroyed. No other registers affected. +14340 +14350 MOV AX,[BYTSECPOS] +14360 MOV BX,CX +14370 OR AX,AX +14380 JZ SAVFIR ;Partial first sector? +14390 SUB AX,[BP+SECSIZ] +14400 NEG AX ;Max number of bytes left in first sector +14410 SUB BX,AX ;Subtract from total length +14420 JAE SAVFIR +14430 ADD AX,BX ;Don't use all of the rest of the sector +14440 XOR BX,BX ;And no bytes are left +14450 SAVFIR: +14460 MOV [BYTCNT1],AX +14470 MOV AX,BX +14480 XOR DX,DX +14490 DIV AX,[BP+SECSIZ] ;How many whole sectors? +14500 MOV [SECCNT],AX +14510 MOV [BYTCNT2],DX ;Bytes remaining for last sector +14520 RET +14530 +14540 +14550 FNDCLUS: +14560 +14570 ; Inputs: +14580 ; DS = CS +14590 ; CX = No. of clusters to skip +14600 ; BP = Base of drive parameters +14610 ; SI = FAT pointer +14620 ; ES:DI point to FCB +14630 ; Outputs: +14640 ; BX = Last cluster skipped to +14650 ; CX = No. of clusters remaining (0 unless EOF) +14660 ; DX = Position of last cluster +14670 ; DI destroyed. No other registers affected. +14680 +14690 SEG ES +14700 MOV BX,[DI+LSTCLUS] +14710 SEG ES +14720 MOV DX,[DI+CLUSPOS] +14730 OR BX,BX +14740 JZ NOCLUS +14750 SUB CX,DX +14760 JNB FINDIT +14770 ADD CX,DX +14780 XOR DX,DX +14790 SEG ES +14800 MOV BX,[DI+FIRCLUS] +14810 FINDIT: +14820 JCXZ RET +14830 SKPCLP: +14840 CALL UNPACK +14850 CMP DI,0FF8H +14860 JAE RET +14870 XCHG BX,DI +14880 INC DX +14890 LOOP SKPCLP +14900 RET +14910 NOCLUS: +14920 INC CX +14930 DEC DX +14940 RET +14950 +14960 +14970 BUFSEC: +14980 ; Inputs: +14990 ; AL = 0 if buffer must be read, 1 if no pre-read needed +15000 ; BP = Base of drive parameters +15010 ; [CLUSNUM] = Physical cluster number +15020 ; [SECCLUSPOS] = Sector position of transfer within cluster +15030 ; [BYTCNT1] = Size of transfer +15040 ; Function: +15050 ; Insure specified sector is in buffer, flushing buffer before +15060 ; read if necessary. +15070 ; Outputs: +15080 ; SI = Pointer to buffer +15090 ; DI = Pointer to transfer address +15100 ; CX = Number of bytes +15110 ; [NEXTADD] updated +15120 ; [TRANS] set to indicate a transfer will occur +15130 +15140 MOV DX,[CLUSNUM] +15150 MOV BL,[SECCLUSPOS] +15160 CALL FIGREC +15170 OR AL,AL +15180 JNZ SETBUF +15190 CMP DX,[BUFSECNO] +15200 JNZ GETSEC +15210 MOV AL,[BUFDRVNO] +15220 CMP AL,[BP+DRVNUM] +15230 JZ FINBUF ;Already have it? +15240 GETSEC: +15250 TEST B,[DIRTYBUF],-1 +15260 JZ RDSEC +15270 PUSH DX +15280 MOV AL,[BUFDRVNO] +15290 MOV BX,[BUFFER] +15300 MOV CX,1 +15310 MOV DX,[BUFSECNO] +15320 CALL WRTDRV +15330 POP DX +15340 RDSEC: +15350 MOV BX,[BUFFER] +15360 MOV CX,1 +15370 PUSH DX +15380 CALL DREAD +15390 POP DX +15400 SETBUF: +15410 MOV [BUFSECNO],DX +15420 MOV AL,[BP+DRVNUM] +15430 MOV AH,0 +15440 MOV [BUFDRVNO],AX +15450 FINBUF: +15460 MOV B,[TRANS],1 ;A transfer is taking place +15470 MOV DI,[NEXTADD] +15480 MOV SI,DI +15490 MOV CX,[BYTCNT1] +15500 ADD SI,CX +15510 MOV [NEXTADD],SI +15520 MOV SI,[BUFFER] +15530 ADD SI,[BYTSECPOS] +15540 RET +15550 +15560 BUFRD: +15570 XOR AL,AL ;Pre-read necessary +15580 CALL BUFSEC +15590 PUSH ES +15600 MOV ES,[DMAADD+2] +15610 SHR CX +15620 JNC EVENRD +15630 MOVB +15640 EVENRD: +15650 REP +15660 MOVW +15670 POP ES +15680 RET +15690 +15700 BUFWRT: +15710 MOV AX,[SECPOS] +15720 INC AX ;Set for next sector +15730 MOV [SECPOS],AX +15740 CMP AX,[VALSEC] ;Has sector been written before? +15750 MOV AL,1 +15760 JA NOREAD ;Skip preread if SECPOS>VALSEC +15770 MOV AL,0 +15780 NOREAD: +15790 CALL BUFSEC +15800 XCHG DI,SI +15810 PUSH DS +15820 PUSH ES +15830 PUSH CS +15840 POP ES +15850 MOV DS,[DMAADD+2] +15860 SHR CX +15870 JNC EVENWRT +15880 MOVB +15890 EVENWRT: +15900 REP +15910 MOVW +15920 POP ES +15930 POP DS +15940 MOV B,[DIRTYBUF],1 +15950 RET +15960 +15970 NEXTSEC: +15980 TEST B,[TRANS],-1 +15990 JZ CLRET +16000 MOV AL,[SECCLUSPOS] +16010 INC AL +16020 CMP AL,[BP+CLUSMSK] +16030 JBE SAVPOS +16040 MOV BX,[CLUSNUM] +16050 CMP BX,0FF8H +16060 JAE NONEXT +16070 LEA SI,[BP+FAT] +16080 CALL UNPACK +16090 MOV [CLUSNUM],DI +16100 INC [LASTPOS] +16110 MOV AL,0 +16120 SAVPOS: +16130 MOV [SECCLUSPOS],AL +16140 CLRET: +16150 CLC +16160 RET +16170 NONEXT: +16180 STC +16190 RET +16200 +16210 TRANBUF: +16220 LODB +16230 STOB +16240 CMP AL,13 ;Check for carriage return +16250 JNZ NORMCH +16260 MOV [SI],10 +16270 NORMCH: +16280 CMP AL,10 +16290 LOOPNZ TRANBUF +16300 JNZ ENDRDCON +16310 CALL OUT ;Transmit linefeed +16320 XOR SI,SI +16330 OR CX,CX +16340 JNZ GETBUF +16350 OR AL,1 ;Clear zero flag--not end of file +16360 ENDRDCON: +16370 MOV [CONTPOS],SI +16380 ENDRDDEV: +16390 MOV [NEXTADD],DI +16400 POP ES +16410 JNZ SETFCBJ ;Zero set if Ctrl-Z found in input +16420 MOV DI,[FCB] +16430 SEG ES +16440 OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +16450 SETFCBJ: +16460 JMP SETFCB +16470 +16480 READDEV: +16490 PUSH ES +16500 LES DI,[DMAADD] +16510 OR BL,BL +16520 JZ READCON +16530 DEC BL +16540 JNZ ENDRDDEV +16550 READAUX: +16560 CALL BIOSAUXIN,BIOSSEG +16570 STOB +16580 CMP AL,1AH +16590 LOOPNZ READAUX +16600 JP ENDRDDEV +16610 +16620 READCON: +16630 PUSH CS +16640 POP DS +16650 MOV SI,[CONTPOS] +16660 OR SI,SI +16670 JNZ TRANBUF +16680 CMP B,[CONBUF],128 +16690 JZ GETBUF +16700 MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +16710 GETBUF: +16720 PUSH CX +16730 PUSH ES +16740 PUSH DI +16750 MOV DX,CONBUF +16760 CALL BUFIN ;Get input buffer +16770 POP DI +16780 POP ES +16790 POP CX +16800 MOV SI,CONBUF+2 +16810 CMP B,[SI],1AH ;Check for Ctrl-Z in first character +16820 JNZ TRANBUF +16830 MOV AL,1AH +16840 STOB +16850 MOV AL,10 +16860 CALL OUT ;Send linefeed +16870 XOR SI,SI +16880 JP ENDRDCON +16890 +16900 RDERR: +16910 XOR CX,CX +16920 JMP WRTERR +16930 +16940 RDLASTJ:JMP RDLAST +16950 +16960 LOAD: +16970 +16980 ; Inputs: +16990 ; DS:DI point to FCB +17000 ; DX:AX = Position in file to read +17010 ; CX = No. of records to read +17020 ; Outputs: +17030 ; DX:AX = Position of last record read +17040 ; CX = No. of bytes read +17050 ; ES:DI point to FCB +17060 ; LSTCLUS, CLUSPOS fields in FCB set +17070 +17080 CALL SETUP +17090 SEG ES +17100 MOV BX,[DI+FILDIRBLK] +17110 CMP BH,-1 ;Check for named device I/O +17120 JZ READDEV +17130 SEG ES +17140 MOV AX,[DI+FILSIZ] +17150 SEG ES +17160 MOV BX,[DI+FILSIZ+2] +17170 SUB AX,[BYTPOS] +17180 SBC BX,[BYTPOS+2] +17190 JB RDERR +17200 JNZ ENUF +17210 OR AX,AX +17220 JZ RDERR +17230 CMP AX,CX +17240 JAE ENUF +17250 MOV CX,AX +17260 ENUF: +17270 CALL BREAKDOWN +17280 MOV CX,[CLUSNUM] +17290 CALL FNDCLUS +17300 OR CX,CX +17310 JNZ RDERR +17320 MOV [LASTPOS],DX +17330 MOV [CLUSNUM],BX +17340 CMP [BYTCNT1],0 +17350 JZ RDMID +17360 CALL BUFRD +17370 RDMID: +17380 CMP [SECCNT],0 +17390 JZ RDLASTJ +17400 CALL NEXTSEC +17410 JC SETFCB +17420 MOV B,[TRANS],1 ;A transfer is taking place +17430 ONSEC: +17440 MOV DL,[SECCLUSPOS] +17450 MOV CX,[SECCNT] +17460 MOV BX,[CLUSNUM] +17470 RDLP: +17480 CALL OPTIMIZE +17490 PUSH DI +17500 PUSH AX +17510 PUSH DS +17520 MOV DS,[DMAADD+2] +17530 CALL DREAD +17540 POP DS +17550 POP CX +17560 POP BX +17570 JCXZ RDLAST +17580 CMP BX,0FF8H +17590 JAE SETFCB +17600 MOV DL,0 +17610 INC [LASTPOS] ;We'll be using next cluster +17620 JP RDLP +17630 +17640 SETFCB: +17650 MOV SI,[FCB] +17660 MOV AX,[NEXTADD] +17670 MOV DI,AX +17680 SUB AX,[DMAADD] ;Number of bytes transfered +17690 XOR DX,DX +17700 SEG ES +17710 MOV CX,[SI+RECSIZ] +17720 DIV AX,CX ;Number of records +17730 CMP AX,[RECCNT] ;Check if all records transferred +17740 JZ FULLREC +17750 MOV B,[DSKERR],1 +17760 OR DX,DX +17770 JZ FULLREC ;If remainder 0, then full record transfered +17780 MOV B,[DSKERR],3 ;Flag partial last record +17790 SUB CX,DX ;Bytes left in last record +17800 PUSH ES +17810 MOV ES,[DMAADD+2] +17820 XCHG AX,BX ;Save the record count temporarily +17830 XOR AX,AX ;Fill with zeros +17840 SHR CX +17850 JNC EVENFIL +17860 STOB +17870 EVENFIL: +17880 REP +17890 STOW +17900 XCHG AX,BX ;Restore record count to AX +17910 POP ES +17920 INC AX ;Add last (partial) record to total +17930 FULLREC: +17940 MOV CX,AX +17950 MOV DI,SI ;ES:DI point to FCB +17960 SETCLUS: +17970 MOV AX,[CLUSNUM] +17980 SEG ES +17990 MOV [DI+LSTCLUS],AX +18000 MOV AX,[LASTPOS] +18010 SEG ES +18020 MOV [DI+CLUSPOS],AX +18030 ADDREC: +18040 MOV AX,[RECPOS] +18050 MOV DX,[RECPOS+2] +18060 DEC CX +18070 ADD AX,CX ;Update current record position +18080 ADC DX,0 +18090 INC CX +18100 RET +18110 +18120 RDLAST: +18130 MOV AX,[BYTCNT2] +18140 OR AX,AX +18150 JZ SETFCB +18160 MOV [BYTCNT1],AX +18170 CALL NEXTSEC +18180 JC SETFCB +18190 MOV [BYTSECPOS],0 +18200 CALL BUFRD +18210 JP SETFCB +18220 +18230 WRTDEV: +18240 PUSH DS +18250 LDS SI,[DMAADD] +18260 AND BL,7FH +18270 OR BL,BL +18280 JZ WRTCON +18290 DEC BL +18300 JZ WRTAUX +18310 WRTLST: +18320 LODB +18330 CMP AL,1AH +18340 JZ ENDWRDEV +18350 CALL BIOSPRINT,BIOSSEG +18360 LOOP WRTLST +18370 JP ENDWRDEV +18380 +18390 WRTAUX: +18400 LODB +18410 CALL BIOSAUXOUT,BIOSSEG +18420 CMP AL,1AH +18430 LOOPNZ WRTAUX +18440 JP ENDWRDEV +18450 +18460 WRTCON: +18470 LODB +18480 CMP AL,1AH +18490 JZ ENDWRDEV +18500 CALL OUT +18510 LOOP WRTCON +18520 ENDWRDEV: +18530 POP DS +18540 MOV CX,[RECCNT] +18550 MOV DI,[FCB] +18560 JP ADDREC +18570 +18580 HAVSTART: +18590 MOV CX,AX +18600 CALL SKPCLP +18610 JCXZ DOWRTJ +18620 CALL ALLOCATE +18630 JNC DOWRTJ +18640 WRTERR: +18650 MOV B,[DSKERR],1 +18660 LVDSK: +18670 MOV AX,[RECPOS] +18680 MOV DX,[RECPOS+2] +18690 MOV DI,[FCB] +18700 RET +18710 +18720 DOWRTJ: JMP DOWRT +18730 +18740 WRTEOFJ: +18750 JMP WRTEOF +18760 +18770 STORE: +18780 +18790 ; Inputs: +18800 ; DS:DI point to FCB +18810 ; DX:AX = Position in file of disk transfer +18820 ; CX = Record count +18830 ; Outputs: +18840 ; DX:AX = Position of last record written +18850 ; CX = No. of records written +18860 ; ES:DI point to FCB +18870 ; LSTCLUS, CLUSPOS fields in FCB set +18880 +18890 MOV B,[DI+DIRTYFIL],1 +18900 SEG CS +18910 MOV BX,[DATE] +18920 MOV [DI+FDATE],BX +18930 CALL SETUP +18940 SEG ES +18950 MOV BX,[DI+FILDIRBLK] +18960 CMP BH,-1 +18970 JZ WRTDEV +18980 CALL BREAKDOWN +18990 MOV AX,[BYTPOS] +19000 MOV DX,[BYTPOS+2] +19010 JCXZ WRTEOFJ +19020 DEC CX +19030 ADD AX,CX +19040 ADC DX,0 ;AX:DX=last byte accessed +19050 DIV AX,[BP+SECSIZ] ;AX=last sector accessed +19060 MOV CL,[BP+CLUSSHFT] +19070 SHR AX,CL ;Last cluster to be accessed +19080 PUSH AX +19090 SEG ES +19100 MOV AX,[DI+FILSIZ] +19110 SEG ES +19120 MOV DX,[DI+FILSIZ] +19130 DIV AX,[BP+SECSIZ] +19140 OR DX,DX +19150 JZ NORNDUP +19160 INC AX ;Round up if any remainder +19170 NORNDUP: +19180 MOV [VALSEC],AX ;Number of sectors that have been written +19190 POP AX +19200 MOV CX,[CLUSNUM] ;First cluster accessed +19210 CALL FNDCLUS +19220 MOV [CLUSNUM],BX +19230 MOV [LASTPOS],DX +19240 SUB AX,DX ;Last cluster minus current cluster +19250 JZ DOWRT ;If we have last clus, we must have first +19260 JCXZ HAVSTART +19270 PUSH CX ;No. of clusters short of first +19280 MOV CX,AX +19290 CALL ALLOCATE +19300 POP AX +19310 JC WRTERR +19320 MOV CX,AX +19330 MOV DX,[LASTPOS] +19340 INC DX +19350 DEC CX +19360 JZ NOSKIP +19370 CALL SKPCLP +19380 NOSKIP: +19390 MOV [CLUSNUM],BX +19400 MOV [LASTPOS],DX +19410 DOWRT: +19420 CMP [BYTCNT1],0 +19430 JZ WRTMID +19440 MOV BX,[CLUSNUM] +19450 CALL BUFWRT +19460 WRTMID: +19470 MOV AX,[SECCNT] +19480 OR AX,AX +19490 JZ WRTLAST +19500 ADD [SECPOS],AX +19510 CALL NEXTSEC +19520 MOV B,[TRANS],1 ;A transfer is taking place +19530 MOV DL,[SECCLUSPOS] +19540 MOV BX,[CLUSNUM] +19550 MOV CX,[SECCNT] +19560 WRTLP: +19570 CALL OPTIMIZE +19580 PUSH DI +19590 PUSH AX +19600 PUSH DS +19610 MOV DS,[DMAADD+2] +19620 CALL DWRITE +19630 POP DS +19640 POP CX +19650 POP BX +19660 JCXZ WRTLAST +19670 MOV DL,0 +19680 INC [LASTPOS] ;We'll be using next cluster +19690 JP WRTLP +19700 WRTLAST: +19710 MOV AX,[BYTCNT2] +19720 OR AX,AX +19730 JZ FINWRT +19740 MOV [BYTCNT1],AX +19750 CALL NEXTSEC +19760 MOV [BYTSECPOS],0 +19770 CALL BUFWRT +19780 FINWRT: +19790 MOV AX,[NEXTADD] +19800 SUB AX,[DMAADD] +19810 ADD AX,[BYTPOS] +19820 MOV DX,[BYTPOS+2] +19830 ADC DX,0 +19840 MOV CX,DX +19850 MOV DI,[FCB] +19860 SEG ES +19870 CMP AX,[DI+FILSIZ] +19880 SEG ES +19890 SBB CX,[DI+FILSIZ+2] +19900 JB SAMSIZ +19910 SEG ES +19920 MOV [DI+FILSIZ],AX +19930 SEG ES +19940 MOV [DI+FILSIZ+2],DX +19950 SAMSIZ: +19960 MOV CX,[RECCNT] +19970 JMP SETCLUS +19980 +19990 +20000 WRTERRJ:JMP WRTERR +20010 +20020 WRTEOF: +20030 MOV CX,AX +20040 OR CX,DX +20050 JZ KILLFIL +20060 SUB AX,1 +20070 SBC DX,0 +20080 DIV AX,[BP+SECSIZ] +20090 MOV CL,[BP+CLUSSHFT] +20100 SHR AX,CL +20110 MOV CX,AX +20120 CALL FNDCLUS +20130 JCXZ RELFILE +20140 CALL ALLOCATE +20150 JC WRTERRJ +20160 UPDATE: +20170 MOV DI,[FCB] +20180 MOV AX,[BYTPOS] +20190 SEG ES +20200 MOV [DI+FILSIZ],AX +20210 MOV AX,[BYTPOS+2] +20220 SEG ES +20230 MOV [DI+FILSIZ+2],AX +20240 XOR CX,CX +20250 RET +20260 +20270 RELFILE: +20280 MOV DX,0FFFH +20290 CALL RELBLKS +20300 SETDIRT: +20310 MOV B,[BP+DIRTYFAT],1 +20320 JP UPDATE +20330 +20340 KILLFIL: +20350 XOR BX,BX +20360 SEG ES +20370 XCHG BX,[DI+FIRCLUS] +20380 OR BX,BX +20390 JZ UPDATE +20400 CALL RELEASE +20410 JP SETDIRT +20420 +20430 +20440 OPTIMIZE: +20450 +20460 ; Inputs: +20470 ; DS = CS +20480 ; BX = Physical cluster +20490 ; CX = No. of records +20500 ; DL = sector within cluster +20510 ; BP = Base of drives parameters +20520 ; [NEXTADD] = transfer address +20530 ; Outputs: +20540 ; AX = No. of records remaining +20550 ; BX = Transfer address +20560 ; CX = No. or records to be transferred +20570 ; DX = Physical sector address +20580 ; DI = Next cluster +20590 ; [CLUSNUM] = Last cluster accessed +20600 ; [NEXTADD] updated +20610 ; BP unchanged. Note that segment of transfer not set. +20620 +20630 PUSH DX +20640 PUSH BX +20650 MOV AL,[BP+CLUSMSK] +20660 INC AL ;Number of sectors per cluster +20670 MOV AH,AL +20680 SUB AL,DL ;AL = Number of sectors left in first cluster +20690 MOV DX,CX +20700 LEA SI,[BP+FAT] +20710 MOV CX,0 +20720 OPTCLUS: +20730 ;AL has number of sectors available in current cluster +20740 ;AH has number of sectors available in next cluster +20750 ;BX has current physical cluster +20760 ;CX has number of sequential sectors found so far +20770 ;DX has number of sectors left to transfer +20780 ;SI has FAT pointer +20790 CALL UNPACK +20800 ADD CL,AL +20810 ADC CH,0 +20820 CMP CX,DX +20830 JAE BLKDON +20840 MOV AL,AH +20850 INC BX +20860 CMP DI,BX +20870 JZ OPTCLUS +20880 DEC BX +20890 FINCLUS: +20900 MOV [CLUSNUM],BX ;Last cluster accessed +20910 SUB DX,CX ;Number of sectors still needed +20920 PUSH DX +20930 MOV AX,CX +20940 MUL AX,[BP+SECSIZ] ;Number of sectors times sector size +20950 MOV SI,[NEXTADD] +20960 ADD AX,SI ;Adjust by size of transfer +20970 MOV [NEXTADD],AX +20980 POP AX ;Number of sectors still needed +20990 POP DX ;Starting cluster +21000 SUB BX,DX ;Number of new clusters accessed +21010 ADD [LASTPOS],BX +21020 POP BX ;BL = sector postion within cluster +21030 CALL FIGREC +21040 MOV BX,SI +21050 RET +21060 BLKDON: +21070 SUB CX,DX ;Number of sectors in cluster we don't want +21080 SUB AH,CL ;Number of sectors in cluster we accepted +21090 DEC AH ;Adjust to mean position within cluster +21100 MOV [SECCLUSPOS],AH +21110 MOV CX,DX ;Anyway, make the total equal to the request +21120 JP FINCLUS +21130 +21140 +21150 FIGREC: +21160 +21170 ;Inputs: +21180 ; DX = Physical cluster number +21190 ; BL = Sector postion within cluster +21200 ; BP = Base of drive parameters +21210 ;Outputs: +21220 ; DX = physical sector number +21230 ;No other registers affected. +21240 +21250 PUSH CX +21260 MOV CL,[BP+CLUSSHFT] +21270 DEC DX +21280 DEC DX +21290 SHL DX,CL +21300 OR DL,BL +21310 ADD DX,[BP+FIRREC] +21320 POP CX +21330 RET +21340 +21350 GETREC: +21360 +21370 ; Inputs: +21380 ; DS:DX point to FCB +21390 ; Outputs: +21400 ; CX = 1 +21410 ; DX:AX = Record number determined by EXTENT and NR fields +21420 ; DS:DI point to FCB +21430 ; No other registers affected. +21440 +21450 MOV DI,DX +21460 MOV CX,1 +21470 MOV AL,[DI+NR] +21480 MOV DX,[DI+EXTENT] +21490 SHL AL +21500 SHR DX +21510 RCR AL +21520 MOV AH,DL +21530 MOV DL,DH +21540 MOV DH,0 +21550 RET +21560 +21570 +21580 ALLOCATE: +21590 +21600 ; Inputs: +21610 ; DS = CS +21620 ; ES = Segment of FCB +21630 ; BX = Last cluster of file (0 if null file) +21640 ; CX = No. of clusters to allocate +21650 ; DX = Position of cluster BX +21660 ; BP = Base of drive parameters +21670 ; SI = FAT pointer +21680 ; [FCB] = Displacement of FCB within segment +21690 ; Outputs: +21700 ; IF insufficient space +21710 ; THEN +21720 ; Carry set +21730 ; CX = max. no. of records that could be added to file +21740 ; ELSE +21750 ; Carry clear +21760 ; BX = First cluster allocated +21770 ; FAT is fully updated including dirty bit +21780 ; FIRCLUS field of FCB set if file was null +21790 ; SI,BP unchanged. All other registers destroyed. +21800 +21810 PUSH [SI] +21820 PUSH DX +21830 PUSH CX +21840 PUSH BX +21850 MOV AX,BX +21860 ALLOC: +21870 MOV DX,BX +21880 FINDFRE: +21890 INC BX +21900 CMP BX,[BP+MAXCLUS] +21910 JLE TRYOUT +21920 CMP AX,1 +21930 JG TRYIN +21940 POP BX +21950 MOV DX,0FFFH +21960 CALL RELBLKS +21970 POP AX ;No. of clusters requested +21980 SUB AX,CX ;AX=No. of clusters allocated +21990 POP DX +22000 POP [SI] +22010 INC DX ;Position of first cluster allocated +22020 ADD AX,DX ;AX=max no. of cluster in file +22030 MOV DL,[BP+CLUSMSK] +22040 MOV DH,0 +22050 INC DX ;DX=records/cluster +22060 MUL AX,DX ;AX=max no. of records in file +22070 MOV CX,AX +22080 SUB CX,[RECPOS] ;CX=max no. of records that could be written +22090 JA MAXREC +22100 XOR CX,CX ;If CX was negative, zero it +22110 MAXREC: +22120 STC +22130 RET +22140 +22150 TRYOUT: +22160 CALL UNPACK +22170 JZ HAVFRE +22180 TRYIN: +22190 DEC AX +22200 JLE FINDFRE +22210 XCHG AX,BX +22220 CALL UNPACK +22230 JZ HAVFRE +22240 XCHG AX,BX +22250 JP FINDFRE +22260 HAVFRE: +22270 XCHG BX,DX +22280 MOV AX,DX +22290 CALL PACK +22300 MOV BX,AX +22310 LOOP ALLOC +22320 MOV DX,0FFFH +22330 CALL PACK +22340 MOV B,[BP+DIRTYFAT],1 +22350 POP BX +22360 POP CX ;Don't need this stuff since we're successful +22370 POP DX +22380 CALL UNPACK +22390 POP [SI] +22400 XCHG BX,DI +22410 OR DI,DI +22420 JNZ RET +22430 MOV DI,[FCB] +22440 SEG ES +22450 MOV [DI+FIRCLUS],BX +22460 RET +22470 +22480 +22490 RELEASE: +22500 +22510 ; Inputs: +22520 ; DS = CS +22530 ; BX = Cluster in file +22540 ; SI = FAT pointer +22550 ; BP = Base of drive parameters +22560 ; Function: +22570 ; Frees cluster chain starting with [BX] +22580 ; AX,BX,DX,DI all destroyed. Other registers unchanged. +22590 +22600 XOR DX,DX +22610 RELBLKS: +22620 ; Enter here with DX=0FFFH to put an end-of-file mark +22630 ; in the first cluster and free the rest in the chain. +22640 CALL UNPACK +22650 JZ RET +22660 MOV AX,DI +22670 CALL PACK +22680 CMP AX,0FF8H +22690 MOV BX,AX +22700 JB RELEASE +22710 RET +22720 +22730 +22740 GETEOF: +22750 +22760 ; Inputs: +22770 ; BX = Cluster in a file +22780 ; SI = Base of drive FAT +22790 ; DS = CS +22800 ; Outputs: +22810 ; BX = Last cluster in the file +22820 ; DI destroyed. No other registers affected. +22830 +22840 CALL UNPACK +22850 CMP DI,0FF8H +22860 JAE RET +22870 MOV BX,DI +22880 JP GETEOF +22890 +22900 +22910 SRCHFRST: ;System call 17 +22920 PUSH DX +22930 PUSH DS +22940 CALL GETFILE +22950 SAVPLCE: +22960 ; Search-for-next enters here to save place and report +22970 ; findings. +22980 POP ES +22990 POP DI +23000 JC KILLSRCH +23010 CMP BH,-1 +23020 JZ SRCHDEV +23030 MOV AX,[LASTENT] +23040 SEG ES +23050 MOV [DI+FILDIRBLK],AX +23060 ;Information in directory entry must be copied into the first +23070 ; 33 bytes starting at the disk transfer address. +23080 MOV SI,BX +23090 LES DI,[DMAADD] +23100 MOV AL,[BP+DRVNUM] +23110 INC AL +23120 STOB ;Set drive number +23130 MOVB ;Copy first character of name +23140 MOV CX,5 +23150 REP +23160 MOVW ;Copy remaining 10 characters of name +23170 XOR AX,AX +23180 +23190 IF SMALLDIR +23200 CMP B,[BP+DIRSIZ],-1 +23210 JNZ BIGENT5 +23220 STOB ;Zero out unused portion +23230 MOV CX,7 +23240 REP +23250 STOW ;Zero a total of 15 bytes +23260 MOVW ;Copy first cluster pointer +23270 MOVW ;Copy low word of length +23280 MOVB ;Copy 3rd byte of length +23290 STOB ;4th byte of length must be zero +23300 RET +23310 BIGENT5: +23320 ENDIF +23330 +23340 MOV CX,10 +23350 REP +23360 MOVW +23370 MOVB +23380 RET +23390 +23400 KILLSRCH: +23410 SEG ES +23420 KILLSRCH1: +23430 MOV [DI+FILDIRBLK],-2 +23440 MOV AL,-1 +23450 RET +23460 +23470 SRCHDEV: +23480 SEG ES +23490 MOV [DI+FILDIRBLK],BX +23500 LES DI,[DMAADD] +23510 XOR AX,AX +23520 STOB ;Zero drive byte +23530 SUB SI,3 ;Point to device name +23540 MOVW +23550 MOVB +23560 MOV AX,2020H +23570 MOV CX,4 +23580 REP +23590 STOW ;Fill with 8 blanks +23600 XOR AX,AX +23610 MOV CX,10 +23620 REP +23630 STOW +23640 STOB +23650 RET +23660 +23670 SRCHNXT: ;System call 18 +23680 CALL MOVNAME +23690 MOV DI,DX +23700 JC KILLSRCH1 +23710 PUSH DX +23720 PUSH DS +23730 MOV AX,[DI+FILDIRBLK] +23740 PUSH CS +23750 POP DS +23760 MOV [LASTENT],AX +23770 CALL CONTSRCH +23780 JMP SAVPLCE +23790 +23800 +23810 FILESIZE: ;System call 35 +23820 PUSH DS +23830 PUSH DX +23840 CALL GETFILE +23850 POP DI +23860 POP ES +23870 MOV AL,-1 +23880 JC RET +23890 ADD DI,33 ;Write size in RR field +23900 SEG ES +23910 MOV CX,[DI-33+RECSIZ] +23920 OR CX,CX +23930 JNZ RECOK +23940 MOV CX,128 +23950 RECOK: +23960 XOR AX,AX +23970 XOR DX,DX ;Intialize size to zero +23980 CMP BH,-1 ;Check for named I/O device +23990 JZ DEVSIZ +24000 INC SI +24010 INC SI ;Point to length field +24020 MOV AX,[SI+2] ;Get high word of size +24030 +24040 IF SMALLDIR +24050 CMP B,[BP+DIRSIZ],-1 +24060 JNZ BIGSIZ +24070 MOV AH,0 +24080 BIGSIZ: +24090 ENDIF +24100 +24110 DIV AX,CX +24120 PUSH AX ;Save high part of result +24130 LODW ;Get low word of size +24140 DIV AX,CX +24150 OR DX,DX ;Check for zero remainder +24160 POP DX +24170 JZ DEVSIZ +24180 INC AX ;Round up for partial record +24190 JNZ DEVSIZ ;Propagate carry? +24200 INC DX +24210 DEVSIZ: +24220 STOW +24230 MOV AX,DX +24240 STOB +24250 MOV AL,0 +24260 CMP CX,64 +24270 JAE RET ;Only 3-byte field if RECSIZ >= 64 +24280 SEG ES +24290 MOV [DI],AH +24300 RET +24310 +24320 +24330 SETDMA: ;System call 26 +24340 SEG CS +24350 MOV [DMAADD],DX +24360 SEG CS +24370 MOV [DMAADD+2],DS +24380 RET +24390 +24400 +24410 GETFATPT: ;System call 27 +24420 MOV AX,CS +24430 MOV DS,AX +24440 MOV BP,[CURDRVPT] +24450 CALL FATREAD +24460 LEA BX,[BP+FAT] +24470 MOV AL,[BP+CLUSMSK] +24480 INC AL +24490 MOV DX,[BP+MAXCLUS] +24500 DEC DX +24510 MOV B,[BP+DIRTYFAT],1 +24520 MOV CX,[BP+SECSIZ] +24530 LDS SI,[SPSAVE] +24540 MOV [SI+BXSAVE],BX +24550 MOV [SI+DXSAVE],DX +24560 MOV [SI+CXSAVE],CX +24570 MOV [SI+DSSAVE],CS +24580 RET +24590 +24600 +24610 GETDSKPT: ;System call 31 +24620 SEG CS +24630 MOV BX,[CURDRVPT] +24640 SEG CS +24650 LDS SI,[SPSAVE] +24660 MOV [SI+BXSAVE],BX +24670 MOV [SI+DSSAVE],CS +24680 RET +24690 +24700 +24710 DSKRESET: ;System call 13 +24720 SEG CS +24730 MOV [DMAADD+2],DS +24740 MOV AX,CS +24750 MOV DS,AX +24760 MOV [DMAADD],80H +24770 MOV AX,[CURDRVPT+2] +24780 MOV [CURDRVPT],AX +24790 WRTFATS: +24800 ; DS=CS. Writes back all dirty FATs. All registers destroyed. +24810 MOV CL,[NUMDRV] +24820 MOV CH,0 +24830 MOV SI,CURDRVPT+2 +24840 WRTFAT: +24850 LODW +24860 PUSH CX +24870 PUSH SI +24880 MOV BP,AX +24890 CALL CHKFATWRT +24900 POP SI +24910 POP CX +24920 LOOP WRTFAT +24930 MOV AX,[BUFDRVNO] +24940 OR AH,AH +24950 JZ RET +24960 CBW +24970 MOV BX,AX +24980 SHL BX +24990 MOV BP,[BX+DRVTAB] +25000 MOV B,[DIRTYBUF],0 +25010 MOV DX,[BUFSECNO] +25020 MOV BX,BUFFER +25030 MOV CX,1 +25040 JMP DWRITE +25050 +25060 +25070 CURDRV: ;System call 25 +25080 SEG CS +25090 MOV BP,[CURDRVPT] +25100 MOV AL,[BP+DRVNUM] +25110 RET +25120 +25130 +25140 INUSE: ;System call 24 +25150 MOV AX,CS +25160 MOV DS,AX +25170 MOV CL,[NUMDRV] +25180 MOV CH,0 +25190 MOV SI,CX +25200 SHL SI +25210 ADD SI,CURDRVPT +25220 MOV BX,0 +25230 DOWN +25240 CHKUSE: +25250 LODW +25260 MOV BP,AX +25270 CMP B,[BP+DIRTYFAT],-1 ;Carry set if not equal +25280 RCL BX +25290 LOOP CHKUSE +25300 MOV AL,BL +25310 RET +25320 +25330 +25340 SETRNDREC: ;System call 36 +25350 CALL GETREC +25360 MOV [DI+33],AX +25370 MOV [DI+35],DL +25380 RET +25390 +25400 +25410 SELDSK: ;System call 14 +25420 MOV DH,0 +25430 MOV BX,DX +25440 PUSH CS +25450 POP DS +25460 MOV AL,[NUMDRV] +25470 CMP BL,AL +25480 JNB RET +25490 SHL BX +25500 MOV DX,[BX+CURDRVPT+2] +25510 MOV [CURDRVPT],DX +25520 RET +25530 +25540 +25550 BUFIN: ;System call 10 +25560 MOV AX,CS +25570 MOV ES,AX +25580 MOV SI,DX +25590 MOV CH,0 +25600 LODW +25610 OR AL,AL +25620 JZ RET +25630 MOV BL,AH +25640 MOV BH,CH +25650 CMP AL,BL +25660 JBE NOEDIT +25670 CMP B,[BX+SI],0DH +25680 JZ EDITON +25690 NOEDIT: +25700 MOV BL,CH +25710 EDITON: +25720 MOV DL,AL +25730 DEC DX +25740 NEWLIN: +25750 SEG CS +25760 MOV AL,[CARPOS] +25770 SEG CS +25780 MOV [STARTPOS],AL +25790 PUSH SI +25800 MOV DI,INBUF +25810 MOV AH,CH +25820 MOV BH,CH +25830 MOV DH,CH +25840 GETCH: +25850 CALL IN +25860 CMP AL,7FH +25870 JZ BACKSP +25880 CMP AL,8 +25890 JZ BACKSP +25900 CMP AL,13 +25910 JZ ENDLIN +25920 CMP AL,10 +25930 JZ PHYCRLF +25940 CMP AL,"X"-"@" +25950 JZ KILNEW +25960 CMP AL,ESCCH +25970 JZ ESC +25980 SAVCH: +25990 CMP DH,DL +26000 JAE GETCH +26010 STOB +26020 INC DH +26030 CALL BUFOUT +26040 OR AH,AH +26050 JNZ GETCH +26060 CMP BH,BL +26070 JAE GETCH +26080 INC SI +26090 INC BH +26100 JP GETCH +26110 +26120 ESC: +26130 CALL IN +26140 MOV CL,ESCTABLEN +26150 PUSH DI +26160 MOV DI,ESCTAB +26170 REPNE +26180 SCAB +26190 POP DI +26200 AND CL,0FEH +26210 MOV BP,CX +26220 SEG CS ;To work in init +26230 JMP [BP+ESCFUNC] +26240 +26250 ENDLIN: +26260 STOB +26270 CALL OUT +26280 POP DI +26290 MOV [DI-1],DH +26300 INC DH +26310 COPYNEW: +26320 MOV BP,ES +26330 MOV BX,DS +26340 MOV ES,BX +26350 MOV DS,BP +26360 MOV SI,INBUF +26370 MOV CL,DH +26380 REP +26390 MOVB +26400 RET +26410 CRLF: +26420 MOV AL,13 +26430 CALL OUT +26440 MOV AL,10 +26450 JMP OUT +26460 +26470 PHYCRLF: +26480 CALL CRLF +26490 JP GETCH +26500 +26510 KILNEW: +26520 MOV AL,"\" +26530 CALL OUT +26540 POP SI +26550 PUTNEW: +26560 CALL CRLF +26570 SEG CS +26580 MOV AL,[STARTPOS] +26590 CALL TAB +26600 JMP NEWLIN +26610 +26620 BACKSP: +26630 OR DH,DH +26640 JZ OLDBAK +26650 CALL BACKUP +26660 SEG ES +26670 MOV AL,[DI] +26680 CMP AL," " +26690 JAE OLDBAK +26700 CMP AL,9 +26710 JZ BAKTAB +26720 CALL BACKMES +26730 OLDBAK: +26740 OR AH,AH +26750 JNZ GETCH1 +26760 OR BH,BH +26770 JZ GETCH1 +26780 DEC BH +26790 DEC SI +26800 GETCH1: +26810 JMP GETCH +26820 BAKTAB: +26830 PUSH DI +26840 DEC DI +26850 DOWN +26860 MOV CL,DH +26870 MOV AL," " +26880 PUSH BX +26890 MOV BL,7 +26900 JCXZ FIGTAB +26910 FNDPOS: +26920 SCAB +26930 JNA CHKCNT +26940 SEG ES +26950 CMP B,[DI+1],9 +26960 JZ HAVTAB +26970 DEC BL +26980 CHKCNT: +26990 LOOP FNDPOS +27000 FIGTAB: +27010 SEG CS +27020 SUB BL,[STARTPOS] +27030 HAVTAB: +27040 SUB BL,DH +27050 ADD CL,BL +27060 AND CL,7 +27070 UP +27080 POP BX +27090 POP DI +27100 JZ OLDBAK +27110 TABBAK: +27120 CALL BACKMES +27130 LOOP TABBAK +27140 JP OLDBAK +27150 BACKUP: +27160 DEC DH +27170 DEC DI +27180 BACKMES: +27190 MOV AL,8 +27200 CALL OUT +27210 MOV AL," " +27220 CALL OUT +27230 MOV AL,8 +27240 JMP OUT +27250 +27260 TWOESC: +27270 MOV AL,ESCCH +27280 JMP SAVCH +27290 +27300 COPYLIN: +27310 MOV CL,BL +27320 SUB CL,BH +27330 JP COPYEACH +27340 +27350 COPYSTR: +27360 CALL FINDOLD +27370 JP COPYEACH +27380 +27390 COPYONE: +27400 MOV CL,1 +27410 COPYEACH: +27420 CMP DH,DL +27430 JZ GETCH2 +27440 CMP BH,BL +27450 JZ GETCH2 +27460 LODB +27470 STOB +27480 CALL BUFOUT +27490 INC BH +27500 INC DH +27510 LOOP COPYEACH +27520 GETCH2: +27530 JMP GETCH +27540 +27550 SKIPONE: +27560 CMP BH,BL +27570 JZ GETCH2 +27580 INC BH +27590 INC SI +27600 JMP GETCH +27610 +27620 SKIPSTR: +27630 CALL FINDOLD +27640 ADD SI,CX +27650 ADD BH,CL +27660 JMP GETCH +27670 +27680 FINDOLD: +27690 CALL IN +27700 MOV CL,BL +27710 SUB CL,BH +27720 JZ NOTFND +27730 DEC CX +27740 JZ NOTFND +27750 PUSH ES +27760 PUSH DS +27770 POP ES +27780 PUSH DI +27790 MOV DI,SI +27800 INC DI +27810 REPNE +27820 SCAB +27830 POP DI +27840 POP ES +27850 JNZ NOTFND +27860 NOT CL +27870 ADD CL,BL +27880 SUB CL,BH +27890 RET +27900 NOTFND: +27910 POP BP +27920 JMP GETCH +27930 +27940 REEDIT: +27950 MOV AL,"@" +27960 CALL OUT +27970 POP DI +27980 PUSH DI +27990 PUSH ES +28000 PUSH DS +28010 CALL COPYNEW +28020 POP DS +28030 POP ES +28040 POP SI +28050 MOV BL,DH +28060 JMP PUTNEW +28070 +28080 ENTERINS: +28090 MOV AH,-1 +28100 JMP GETCH +28110 +28120 EXITINS: +28130 MOV AH,0 +28140 JMP GETCH +28150 +28160 ESCFUNC: +28170 DW GETCH +28180 DW TWOESC +28190 DW EXITINS +28200 DW ENTERINS +28210 DW BACKSP +28220 DW REEDIT +28230 DW KILNEW +28240 DW COPYLIN +28250 DW SKIPSTR +28260 DW COPYSTR +28270 DW SKIPONE +28280 DW COPYONE +28290 +28300 BUFOUT: +28310 CMP AL," " +28320 JAE OUT +28330 CMP AL,9 +28340 JZ OUT +28350 PUSH AX +28360 MOV AL,"^" +28370 CALL OUT +28380 POP AX +28390 OR AL,40H +28400 JP OUT +28410 +28420 CONOUT: ;System call 2 +28430 MOV AL,DL +28440 OUT: +28450 CMP AL,20H +28460 JB CTRLOUT +28470 CMP AL,7FH +28480 JZ OUTCH +28490 SEG CS +28500 INC B,[CARPOS] +28510 OUTCH: +28520 CALL BIOSOUT,BIOSSEG +28530 SEG CS +28540 TEST B,[PFLAG],-1 +28550 JZ STATCHK +28560 CALL BIOSPRINT,BIOSSEG +28570 STATCHK: +28580 CALL BIOSSTAT,BIOSSEG +28590 JZ RET +28600 INCHK: +28610 CALL BIOSIN,BIOSSEG +28620 CMP AL,'S'-'@' +28630 JNZ NOSTOP +28640 CALL BIOSIN,BIOSSEG +28650 NOSTOP: +28660 CMP AL,'P'-'@' +28670 JZ PRINTON +28680 CMP AL,'N'-'@' +28690 JZ PRINTOFF +28700 CMP AL,'C'-'@' +28710 JNZ RET +28720 ; Ctrl-C handler. +28730 ; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +28740 ; to show line is canceled. Then the user registers are restored and the +28750 ; user CTRL-C handler is executed. At this point the top of the stack has +28760 ; 1) the interrupt return address should the user CTRL-C handler wish to +28770 ; allow processing to continue; 2) the original interrupt return address +28780 ; to the code that performed the function call in the first place. If the +28790 ; user CTRL-C handler wishes to continue, it must leave all registers +28800 ; unchanged and IRET. The function that was interrupted will simply be +28810 ; repeated, except for console output (function 2), which has already output +28820 ; its character before the interrupt. +28830 SEG CS +28840 MOV AL,[FUNC] ;Get currently executing function +28850 CMP AL,10 ;Check if buffered line input +28860 JZ CANLIN +28870 CMP AL,9 ;Check if buffered line output +28880 JNZ RESTREG +28890 CANLIN: +28900 MOV AL,"\" ;Display cancel line symbol +28910 CALL OUT +28920 CALL CRLF +28930 RESTREG: +28940 DI ;Prepare to play with stack +28950 SEG CS +28960 MOV SS,[SSSAVE] +28970 SEG CS +28980 MOV SP,[SPSAVE] ;User stack now restored +28990 POP AX +29000 POP BX +29010 POP CX +29020 POP DX +29030 POP SI +29040 POP DI +29050 POP BP +29060 POP DS +29070 POP ES ;User registers now restored +29080 INT CONTC ;Execute user Ctrl-C handler +29090 CMP AH,2 ;Check if function was console output +29100 JZ SETAL +29110 JMP COMMAND ;Repeat command otherwise +29120 SETAL: +29130 MOV AL,DL +29140 IRET ;Return to user program +29150 +29160 PRINTON: +29170 SEG CS +29180 MOV B,[PFLAG],1 +29190 RET +29200 PRINTOFF: +29210 SEG CS +29220 MOV B,[PFLAG],0 +29230 RET +29240 CTRLOUT: +29250 CMP AL,13 +29260 JZ ZERPOS +29270 CMP AL,8 +29280 JZ BACKPOS +29290 CMP AL,9 +29300 JNZ OUTCHJ +29310 SEG CS +29320 MOV AL,[CARPOS] +29330 OR AL,0F8H +29340 NEG AL +29350 TAB: +29360 PUSH CX +29370 MOV CL,AL +29380 MOV CH,0 +29390 TABLP: +29400 MOV AL," " +29410 CALL OUT +29420 LOOP TABLP +29430 POP CX +29440 RET +29450 +29460 ZERPOS: +29470 SEG CS +29480 MOV B,[CARPOS],0 +29490 OUTCHJ: JMP OUTCH +29500 +29510 BACKPOS: +29520 SEG CS +29530 DEC B,[CARPOS] +29540 JMP OUTCH +29550 +29560 +29570 CONSTAT: ;System call 11 +29580 CALL BIOSSTAT,BIOSSEG +29590 JZ RET +29600 OR AL,-1 +29610 RET +29620 +29630 +29640 CONIN: ;System call 1 +29650 CALL IN +29660 PUSH AX +29670 CALL OUT +29680 POP AX +29690 RET +29700 +29710 +29720 IN: ;Internal input routine +29730 CALL INCHK +29740 JZ IN +29750 RET +29760 +29770 RAWIO: ;System call 6 +29780 MOV AL,DL +29790 CMP AL,-1 +29800 JNZ RAWOUT +29810 CALL BIOSSTAT,BIOSSEG +29820 JZ RET +29830 RAWINP: ;System call 7 +29840 CALL BIOSIN,BIOSSEG +29850 RET +29860 RAWOUT: +29870 CALL BIOSOUT,BIOSSEG +29880 RET +29890 +29900 LIST: ;System call 5 +29910 MOV AL,DL +29920 CALL BIOSPRINT,BIOSSEG +29930 RET +29940 +29950 PRTBUF: ;System call 9 +29960 MOV SI,DX +29970 OUTSTR: +29980 LODB +29990 CMP AL,"$" +30000 JZ RET +30010 CALL OUT +30020 JP OUTSTR +30030 +30040 OUTMES: ;String output for internal messages +30050 SEG CS +30060 LODB +30070 CMP AL,"$" +30080 JZ RET +30090 CALL OUT +30100 JP OUTMES +30110 +30120 +30130 MAKEFCB: ;Interrupt call 41 +30140 MOV DL,0 ;Flag--not ambiguous file name +30150 OR AL,AL ;Scan off separators if not zero +30160 JZ NOSCAN +30170 SCAN: +30180 CALL GETLET +30190 JZ SCAN ;Get rid of leading separators (e.g., blanks) +30200 DEC SI ;Point back to first non-separator +30210 NOSCAN: +30220 CMP B,[SI+1],":" ;Check for potential drive specifier +30230 JNZ DEFAULT +30240 CALL GETLET +30250 SUB AL,"@" ;Convert drive letter to binary drive number +30260 JZ NODRV ;Valid drive numbers are 1-15 +30270 INCcifier--back up pointer +30280 DEFAULT: +30290 XOR AL,AL +30300 HAVDRV: +30310 STOB ;Put drive specifier in first byte +30320 MOV CX,8 +30330 CALL GETWORD ;Get 8-letter file name +30340 CMP B,[SI],"." +30350 JNZ NODOT +30360 INC SI ;Skip over dot if present +30370 NODOT: +30380 MOV CX,3 ;Get 3-letter extension +30390 CALL GETWORD +30400 SEG CS +30410 LDS BX,[SPSAVE] +30420 MOV [BX+SISAVE],SI +30430 XOR AX,AX +30440 STOW +30450 STOW +30460 MOV AL,DL +30470 RET +30480 +30490 GETWORD: +30500 CALL GETLET +30510 JZ FILLNAM ;Exit if invalid character +30520 CMP AL," " +30530 JBE FILLNAM +30540 CMP AL,"*" ;Check for ambiguous file specifier +30550 JNZ NOSTAR +30560 MOV AL,"?" +30570 DEC CX +30580 REP +30590 STOB ;Fill rest of word with "?" +30600 INC CX +30610 NOSTAR: +30620 STOB +30630 CMP AL,"?" +30640 JNZ NOTQ +30650 MOV DL,1 ;Flag ambiguous file name +30660 NOTQ: +30670 LOOP GETWORD +30680 INC SI ;Point to "termination" character +30690 FILLNAM: +30700 MOV AL," " +30710 REP +30720 STOB +30730 DEC SI +30740 RET +30750 +30760 GETLET: +30770 LODB +30780 CMP AL,"a" +30790 JB CHK +30800 CMP AL,"z" +30810 JA CHK +30820 SUB AL,20H ;Convert to upper case +30830 CHK: +30840 CMP AL," " +30850 JZ RET +30860 CMP AL,"=" +30870 JZ RET +30880 CMP AL,"," +30890 JZ RET +30900 CMP AL,";" +30910 JZ RET +30920 CMP AL,"." +30930 JZ RET +30940 CMP AL,":" +30950 JZ RET +30960 CMP AL,9 ;Filter out TABs too +30970 RET +30980 +30990 +31000 SETVECT: ; Interrupt call 37 +31010 XOR BX,BX +31020 MOV ES,BX +31030 MOV BL,AL +31040 SHL BX +31050 SHL BX +31060 SEG ES +31070 MOV [BX],DX +31080 SEG ES +31090 MOV [BX+2],DS +31100 RET +31110 +31120 +31130 NEWBASE: ; Interrupt call 38 +31140 MOV ES,DX +31150 SEG CS +31160 MOV DS,[CSLOC] +31170 XOR SI,SI +31180 MOV DI,SI +31190 MOV CX,80H +31200 REP +31210 MOVW +31220 +31230 SETMEM: +31240 +31250 ; Inputs: +31260 ; DX = Segment +31270 ; Function: +31280 ; Completely prepares a program base at the +31290 ; specified segment. +31300 ; Outputs: +31310 ; DS = DX +31320 ; ES = DX +31330 ; [0] has INT 20H +31340 ; [2] = First unavailable segment ([ENDMEM]) +31350 ; [5] to [9] form a long call to the entry point +31360 ; [10] to [13] have exit address (from INT 22H) +31370 ; [14] to [17] have ctrl-C exit address (from INT 23H) +31380 ; AX,DX,BP unchanged. All other registers destroyed. +31390 +31400 XOR CX,CX +31410 MOV DS,CX +31420 MOV ES,DX +31430 MOV SI,EXIT +31440 MOV DI,SAVEXIT +31450 MOVW +31460 MOVW +31470 MOVW +31480 MOVW +31490 SEG CS +31500 MOV CX,[ENDMEM] +31510 SEG ES +31520 MOV [2],CX +31530 SUB CX,DX +31540 CMP CX,MAXDIF +31550 JBE HAVDIF +31560 MOV CX,MAXDIF +31570 HAVDIF: +31580 MOV BX,ENTRYPOINTSEG +31590 SUB BX,CX +31600 SHL CX +31610 SHL CX +31620 SHL CX +31630 SHL CX +31640 MOV DS,DX +31650 MOV [6],CX +31660 MOV [8],BX +31670 MOV [0],20CDH ;"INT INTTAB" +31680 MOV B,[5],LONGCALL +31690 RET +31700 +31710 +31720 SHFTDI7: +31730 SHL DI +31740 SHL DI +31750 SHL DI +31760 SHL DI +31770 SHL DI +31780 SHL DI +31790 SHL DI +31800 RET +31810 +31820 +31830 ; Default handler for division overflow trap +31840 DIVOV: +31850 XOR DX,DX ;Say no remainder +31860 MOV AX,-1 ;But large quotient +31870 IRET +31880 +31890 +31900 ;***** DATA AREA ***** +31910 +31920 BADMES: DB 13,10,"Bad FAT",13,10,"$" +31930 BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$" +31940 RDERRMES:DB 13,10,"Disk read error",13,10,"$" +31950 WRTERRMES:DB 13,10,"Disk write error",13,10,"$" +31960 IONAME: DB "PRN","LST","AUX","CON" +31970 +31980 CARPOS: DB 0 +31990 STARTPOS:DB 0 +32000 PFLAG: DB 0 +32010 DIRTYDIR:DB 0 ;Dirty buffer flag +32020 NUMDRV: DS 1 ;Number of drives +32030 CONTPOS:DW 0 +32040 DMAADD: DW 80H ;User's disk transfer address (disp/seg) +32050 DS 2 +32060 ENDMEM: DS 2 +32070 MAXSEC: DW 0 +32080 BUFFER: DS 2 +32090 BUFSECNO:DW 0 +32100 BUFDRVNO:DB -1 +32110 DIRTYBUF:DB 0 +32120 DIRBUFID:DW -1 +32130 DATE: DS 2 +32140 CURDRVPT:DS 2 +32150 DRVTAB: DS 30 ;Enough for 15 drives +32160 INBUF: DS 15 ;Only the first part +32170 +32180 ; Init code overlaps with data area below +32190 +32200 INITCODE: +32210 +32220 DS 128-15 ;More of INBUF +32230 CONBUF: DS 130 ;The rest of INBUF and console buffer +32240 FUNC: DS 1 ;Currently executing function code +32250 LASTENT:DS 2 +32260 EXITHOLD:DS 4 +32270 FATBASE:DS 2 +32280 NAME1: DS 11 ;File name buffer +32290 NAME2: DS 11 +32300 TEMP: +32310 CSLOC: DS 2 +32320 SPSAVE: DS 2 +32330 SSSAVE: DS 2 +32340 SECCLUSPOS:DS 1 ;Position of first sector within cluster +32350 DSKERR: DS 1 +32360 TRANS: DS 1 +32370 +32380 ALIGN +32390 FCB: DS 2 ;Address of user FCB +32400 NEXTADD:DS 2 +32410 RECPOS: DS 4 +32420 RECCNT: DS 2 +32430 LASTPOS:DS 2 +32440 CLUSNUM:DS 2 +32450 SECPOS: DS 2 ;Position of first sector accessed +32460 VALSEC: DS 2 ;Number of valid (previously written) sectors +32470 BYTSECPOS:DS 2 ;Position of first byte within sector +32480 BYTPOS: DS 4 ;Byte position in file of access +32490 BYTCNT1:DS 2 ;No. of bytes in first sector +32500 BYTCNT2:DS 2 ;No. of bytes in last sector +32510 SECCNT: DS 2 ;No. of whole sectors +32520 +32530 DS 60 ;Stack space +32540 STACK: +32550 +32560 IF DSKTEST +32570 NSS: DS 2 +32580 NSP: DS 2 +32590 DS 60 +32600 TESTSTK: +32610 ENDIF +32620 +32630 DIRBUF: +32640 +32650 ;Init code below overlaps with data area above +32660 +32670 ORG INITCODE +32680 PUT $+100H +32690 +32700 MOVFAT: +32710 ;This section of code is safe from being overwritten by block move +32720 SEG ES +32730 REP +32740 MOVB +32750 UP +32760 FININIT: +32770 CALL SETMEM ;Set up segment +32780 RET L +32790 +32800 DOSINIT: +32810 DI +32820 UP +32830 PUSH CS +32840 POP ES +32850 LODB +32860 SEG ES +32870 MOV [NUMDRV],AL +32880 MOV BX,DRVTAB +32890 MOV DI,MEMSTRT +32900 PERDRV: +32910 SEG ES +32920 MOV [BX],DI +32930 MOV BP,DI +32940 INC BX +32950 INC BX +32960 SEG ES +32970 MOV AL,[DRVCNT] +32980 STOB ;DRVNUM +32990 LODW ;Pointer to DPT +33000 PUSH SI +33010 MOV SI,AX +33020 LODW +33030 STOW ;SECSIZ +33040 MOV DX,AX +33050 SEG ES +33060 CMP AX,[MAXSEC] +33070 JBE NOTMAX +33080 SEG ES +33090 MOV [MAXSEC],AX +33100 NOTMAX: +33110 LODB +33120 DEC AL +33130 STOB ;CLUSMSK +33140 JZ HAVSHFT +33150 CBW +33160 FIGSHFT: +33170 INC AH +33180 SAR AL +33190 JNZ FIGSHFT +33200 MOV AL,AH +33210 HAVSHFT: +33220 STOB ;CLUSSHFT +33230 MOVW ;FIRFAT (= number of reserved sectors) +33240 MOVB ;FATCNT +33250 MOVW ;MAXENT +33260 MOV AX,DX ;SECSIZ again +33270 MOV CL,5 +33280 SHR AX,CL +33290 MOV CX,AX ;Directory entries per sector +33300 DEC AX +33310 SEG ES +33320 ADD AX,[BP+MAXENT] +33330 XOR DX,DX +33340 DIV AX,CX +33350 STOW ;DIRSEC (temporarily) +33360 SHR AX ;Divide by two +33370 ADC AX,0 ;Round up +33380 SEG ES +33390 MOV [SDIRSEC],AX ;Number of directory records for small entries +33400 MOVW ;DSKSIZ (temporarily) +33410 FNDFATSIZ: +33420 MOV AL,1 +33430 MOV DX,1 +33440 GETFATSIZ: +33450 PUSH DX +33460 CALL FIGFATSIZ +33470 POP DX +33480 CMP AL,DL ;Compare newly computed FAT size with trial +33490 JZ HAVFATSIZ ;Has sequence converged? +33500 CMP AL,DH ;Compare with previous trial +33510 MOV DH,DL +33520 MOV DL,AL ;Shuffle trials +33530 JNZ GETFATSIZ ;Continue iterations if not oscillating +33540 SEG ES +33550 DEC [BP+DSKSIZ] ;Damp those oscillations +33560 JP FNDFATSIZ ;Try again +33570 HAVFATSIZ: +33580 STOB ;FATSIZ +33590 SEG ES +33600 MUL AL,[BP+FATCNT] ;Space occupied by all FATs +33610 SEG ES +33620 ADD AX,[BP+FIRFAT] +33630 STOW ;FIRDIR +33640 +33650 IF SMALLDIR-1 +33660 SEG ES +33670 ADD AX,[BP+DIRSEC] +33680 SEG ES +33690 MOV [BP+FIRREC],AX ;Destroys DIRSEC +33700 CALL FIGMAX +33710 SEG ES +33720 MOV [BP+MAXCLUS],CX +33730 ENDIF +33740 +33750 IF SMALLDIR +33760 MOV DX,AX ;Save FIRDIR momentarily +33770 SEG ES +33780 ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry +33790 STOW ;FIRREC1 +33800 XCHG AX,CX ;Previously computed MAXCLUS +33810 STOW ;MAXCLUS1 +33820 XCHG DX,AX +33830 SEG ES +33840 ADD AX,[BP+DIRSEC] ;Add number of dir. sectores for 32-byte entry +33850 STOW ;FIRREC2 +33860 CALL FIGMAX +33870 XCHG AX,CX +33880 STOW ;MAXCLUS2 +33890 ENDIF +33900 +33910 MOV AX,0FFH +33920 STOB ;DIRTYFAT +33930 SEG ES +33940 MOV AL,[BP+FATSIZ] +33950 SEG ES +33960 MUL AX,[BP+SECSIZ] +33970 ADD DI,AX ;Allocate FAT +33980 POP SI ;Restore pointer to init. table +33990 SEG ES +34000 MOV AL,[DRVCNT] +34010 INC AL +34020 SEG ES +34030 MOV [DRVCNT],AL +34040 SEG ES +34050 CMP AL,[NUMDRV] +34060 JAE CONTINIT +34070 JMP PERDRV +34080 CONTINIT: +34090 LODW ;Max. buffer size +34100 SEG ES +34110 MOV BX,[MAXSEC] +34120 MOV AX,DIRBUF +34130 ADD AX,BX +34140 SEG ES +34150 MOV [BUFFER],AX ;Start of buffer +34160 PUSH DI ;Save ending location +34170 ADD DI,BX ;Allocate directory buffer +34180 ADD DI,BX ;Allocate buffer space +34190 ADD DI,ADJFAC+15 ;True start of free space +34200 MOV CL,4 +34210 SHR DI,CL ;First free segment +34220 MOV BP,DI +34230 XOR AX,AX +34240 MOV DS,AX +34250 MOV ES,AX +34260 MOV DI,INTBASE +34270 MOV AX,QUIT +34280 STOW ;Set abort address--displacement +34290 MOV AX,CS +34300 MOV B,[ENTRYPOINT],LONGJUMP +34310 MOV [ENTRYPOINT+1],ENTRY +34320 MOV [ENTRYPOINT+3],AX +34330 MOV [0],DIVOV ;Set default divide trap address +34340 MOV [2],AX +34350 MOV CX,9 +34360 REP +34370 STOW ;Set 5 segments (skip 2 between each) +34380 MOV [INTBASE+4],COMMAND +34390 MOV [INTBASE+12],IRET ;CTRL-C exit +34400 MOV [INTBASE+16],IRET ;Fatal error exit +34410 MOV AX,BIOSREAD +34420 STOW +34430 MOV AX,BIOSSEG +34440 STOW +34450 STOW ;Add 2 to DI +34460 STOW +34470 MOV [INTBASE+18H],BIOSWRITE +34480 MOV DX,CS +34490 MOV DS,DX +34500 ADD DX,BP +34510 MOV [DMAADD],80H +34520 MOV [DMAADD+2],DX +34530 MOV AX,[DRVTAB] +34540 MOV [CURDRVPT],AX +34550 MOV CX,DX +34560 MOV BX,0FH +34570 MEMSCAN: +34580 INC CX +34590 JZ HAVMEM +34600 MOV DS,CX +34610 MOV AL,[BX] +34620 NOT AL +34630 MOV [BX],AL +34640 CMP AL,[BX] +34650 NOT AL +34660 MOV [BX],AL +34670 JZ MEMSCAN +34680 HAVMEM: +34690 SEG CS +34700 MOV [ENDMEM],CX +34710 XOR CX,CX +34720 MOV DS,CX +34730 MOV [EXIT],100H +34740 MOV [EXIT+2],DX +34750 MOV SI,HEADER +34760 CALL OUTMES +34770 PUSH CS +34780 POP DS +34790 PUSH CS +34800 POP ES +34810 PUSH DX +34820 GETDAT: +34830 MOV SI,DATMES +34840 CALL OUTMES +34850 MOV DX,DATBUF +34860 CALL BUFIN +34870 CALL CRLF +34880 MOV SI,DATBUF+2 +34890 MOV DX,12 +34900 CALL MYD +34910 JC GETDAT +34920 MOV CL,5 +34930 SHL AX,CL +34940 MOV [DATE],AX +34950 MOV DX,31 +34960 CALL MYD +34970 JC GETDAT +34980 OR [DATE],AL +34990 MOV DX,2100 +35000 CALL MYD +35010 JC GETDAT +35020 SUB AX,80 +35030 JC GETDAT +35040 CMP AX,19 +35050 JBE SAVYR +35060 SUB AX,1900 +35070 JC GETDAT +35080 SAVYR: +35090 SHL AL +35100 OR [DATE+1],AL +35110 ;Move the FATs into position and adjust the drive pointer table +35120 POP DX +35130 POP SI +35140 MOV AX,[MAXSEC] +35150 SHL AX ;Allocate two buffers +35160 ADD AX,ADJFAC +35170 JZ FINJMP +35180 MOV DI,DRVTAB +35190 MOV CX,15 +35200 ADJLP: +35210 ADD [DI],AX +35220 INC DI +35230 INC DI +35240 LOOP ADJLP +35250 MOV CX,SI +35260 MOV SI,MEMSTRT ;Place to move FATs from +35270 SUB CX,SI ;Total length of FATs +35280 MOV DI,AX +35290 ADD DI,SI ;Place to move FATs to +35300 OR AX,AX +35310 JS MOVJMP +35320 DEC CX +35330 ADD DI,CX +35340 ADD SI,CX +35350 INC CX +35360 DOWN +35370 MOVJMP: +35380 JMP MOVFAT +35390 FINJMP: JMP FININIT +35400 +35410 FIGFATSIZ: +35420 SEG ES +35430 MUL AL,[BP+FATCNT] +35440 SEG ES +35450 ADD AX,[BP+FIRFAT] +35460 SEG ES +35470 ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +35480 FIGMAX: +35490 ;AX has equivalent of FIRREC +35500 SEG ES +35510 SUB AX,[BP+DSKSIZ] +35520 NEG AX +35530 SEG ES +35540 MOV CL,[BP+CLUSSHFT] +35550 SHR AX,CL +35560 INC AX +35570 MOV CX,AX ;MAXCLUS +35580 INC AX +35590 MOV DX,AX +35600 SHR DX +35610 ADC AX,DX ;Size of FAT in bytes +35620 SEG ES +35630 MOV SI,[BP+SECSIZ] +35640 ADD AX,SI +35650 DEC AX +35660 XOR DX,DX +35670 DIV AX,SI +35680 RET +35690 +35700 MYD: +35710 ;SI points to input buffer. Get decimal number < DX and return it +35720 ;in AX. Carry set on error. +35730 XOR BX,BX +35740 MOV AH,0 +35750 GETDIG: +35760 LODB +35770 SUB AL,"0" +35780 JC CHKRET +35790 CMP AL,10 +35800 JNC CHKRET +35810 SHL BX +35820 MOV CX,BX +35830 SHL BX +35840 SHL BX +35850 ADD BX,CX +35860 ADD BX,AX +35870 JP GETDIG +35880 CHKRET: +35890 MOV AX,BX +35900 OR AX,AX +35910 STC +35920 JZ RET +35930 CMP DX,AX +35940 RET +35950 +35960 DRVCNT: DB 0 +35970 +35980 DATMES: DB "Enter today's date (m-d-y): $" +35990 DATBUF: DB 12,8,"04-28-81",13 +36000 DS 5 +36010 +36020 SDIRSEC:DS 2 +36030 +36040 MEMSTRT: +36050 ADJFAC: EQU DIRBUF-MEMSTRT + CCCCCCCCCCCC OOOOOOOOO MMM MMM AAAAAAAAA NNN NNN DDDDDDDDDDDD + СССССССССССС OOOOOOOOO MMM MMM AAAAAAAAA NNN NNN DDDDDDDDDDDD + СССССССССССС OOOOOOOOO MMM MMM AAAAAAAAA NNN NNN DDDDDDDDDDDD +CCC OOO OOO MMMMMM MMMMMM AAA AAA NNN NNN DDD DDD +CCC OOO OOO MMMMMM MMMMMM AAA AAA NNN NNN DDD DDD +CCC OOO OOO MMMMMM MMMMMM AAA AAA NNN NNN DDD DDD +CCC OOO OOO MMM MMM MMM AAA AAA NNNNNN NNN DDD DDD +CCC OOO OOO MMM MMM MMM AAA AAA NNNNNN NNN DDD DDD +CCC OOO OOO MMM MMM MMM AAA AAA NNNNNN NNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN NNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN NNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN NNN DDD DDD +CCC OOO OOO MMM MMM AAAAAAAAAAAAAAA NNN NNNNNN DDD DDD +CCC OOO OOO MMM MMM AAAAAAAAAAAAAAA NNN NNNNNN DDD DDD +CCC OOO OOO MMM MMM AAAAAAAAAAAAAAA NNN NNNNNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN DDD DDD +CCC OOO OOO MMM MMM AAA AAA NNN NNN DDD DDD + CCCCCCCCCCCC OOOOOOOOO MMM MMM AAA AAA NNN NNN DDDDDDDDDDDD + СССССССССССС OOOOOOOOO MMM MMM AAA AAA NNN NNN DDDDDDDDDDDD + СССССССССССС OOOOOOOOO MMM MMM AAA AAA NNN NNN DDDDDDDDDDDD + + + + +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF + + + + + *START* User ROS BASIC [500,500] Job 86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:COMAND.DIF<055>[500,500] Created: 16-Jun-81 13:15:48 Printed: 16-Jun-81 15:23:55 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL diff --git a/1_transcription/bundle_5 b/1_transcription/bundle_5 new file mode 100644 index 0000000..2f4aeeb --- /dev/null +++ b/1_transcription/bundle_5 @@ -0,0 +1,3758 @@ + + +Seattle Computer Products 8086 Assembler Version 2.30 +Copyright 1979,80,81 by Seattle Computer Products, Inc. + +0000 0001 ; Seattle Computer Products 8086 Assembler version 2.31 +0000 0002 ; by Tim Paterson +0000 0003 ; Runs on the 8086 under 86-DOS +0000 0004 +0000 0005 ;* * * * * * REVISION HISTORY * * * * * * +0000 0006 ; +0000 0007 ; 12/29/80 2.01 General release with 86-DOS version 0.34 +0000 0008 ; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +0000 0009 ; 03/18/81 2.11 General cleanup and more documentation +0000 0010 ; 03/24/81 2.20 Modify ESC handling for full 8087 operation +0000 0011 ; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +0000 0012 ; 04/03/81 2.22 Fix 2.21 buffer handling +0000 0013 ; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +0000 0014 ; 04/28/81 2.24 Allow nested IFs +0000 0015 ; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +0000 0016 ; 08/02/81 2.30 Re-write pass 2: +0000 0017 ; Always report errors to console +0000 0018 ; Exact byte lengths for HEX and PRN files +0000 0019 ; 08/23/81 2.40 Add 8087 mnemonics +0000 0020 ; +0000 0021 ;* * * * * * * * * * * * * * * * * * * * * +0000 0022 +0000 0023 SYMWID: EQU 10 +0000 0024 FCB: EQU 5CH +0000 0025 BUFSIZ: EQU 1024 ;Source code buffer +0000 0026 LSTBUFSIZ:EQU BUFSIZ ;List file buffer +0000 0027 HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +0000 0028 EOL: EQU 13 ;ASCII carriage return +0000 0029 OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS +0000 0030 +0000 0031 ;System call function codes +0000 0032 PRINTMES: EQU 9 +0000 0033 OPEN: EQU 15 +0000 0034 CLOSE: EQU 16 +0000 0035 READ: EQU 20 +0000 0036 SETDMA: EQU 26 +0000 0037 MAKE: EQU 22 +0000 0038 BLKWRT: EQU 40 +0000 0039 +0000 0040 ;The following equates define some token values returned by GETSYM +0000 0041 UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +0000 0042 CONST: EQU 1 ;Constant (including $) +0000 0043 REG: EQU 2 ;8-bit register +0000 0044 XREG: EQU 3 ;16-bit register (except segment registers) +0000 0045 SREG: EQU 4 ;Segment register +0000 0046 +0000 0047 ;Ouput file record definition +0000 0048 ORG 0 +0000 0049 WRTPT: DS 2 ;Pointer to next byte to be written +0002 0050 BUFEND: DS 2 ;Pointer to end of buffer plus one +0004 0051 BUFSTRT:DS 2 ;Address of start of buffer +0006 0052 BUFFCB: DS 37 ;FCB for the file +002B 0053 +002B 0054 ORG 100H +0100 0055 PUT 100H +0100 0056 +0100 EB 75 0057 JP BEGIN +0102 0058 +0102 0D 0A 53 65 61 74 74 0059 HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.31' + 6C 65 20 43 6F 6D 70 + 75 74 65 72 20 50 72 + 6F 64 75 63 74 73 20 + 38 30 38 36 20 41 73 + 73 65 6D 62 6C 65 72 + 20 56 65 72 73 69 6F + 6E 20 32 2E 33 31 +0139 0D 0A 43 6F 70 79 72 0060 DB 13,10,'Copyright 1979,80,81 by Seattle Computer Products, Inc.' + 69 67 68 74 20 31 39 + 37 39 2C 38 30 2C 38 + 31 20 62 79 20 53 65 + 61 74 74 6C 65 20 43 + 6F 6D 70 75 74 65 72 + 20 50 72 6F 64 75 63 + 74 73 2C 20 49 6E 63 + 2E +0172 0D 0A 0D 0A 24 0061 DB 13,10,13,10,'$' +0177 0062 +0177 0063 BEGIN: +0177 BC 90 24 0064 MOV SP,STACK +017A BA 02 01 0065 MOV DX,HEADER +017D B4 09 0066 MOV AH,PRINTMES +017F CD 21 0067 INT 33 +0181 A0 6D 00 0068 MOV AL,[FCB+17] +0184 A2 D0 1B 0069 MOV [SYMFLG],AL ;Save symbol table request flag +0187 BE 65 00 0070 MOV SI,FCB+9 ;Point to file extension +018A AC 0071 LODB ;Get source drive letter +018B E8 10 01 0072 CALL CHKDSK ;Valid drive? +018E 0A C0 0073 OR AL,AL +0190 74 03 0074 JZ DEFAULT ;If no extension, use existing drive spec +0192 A2 5C 00 0075 MOV [FCB],AL +0195 0076 DEFAULT: +0195 AC 0077 LODB ;Get HEX file drive letter +0196 3C 5A 0078 CMP AL,'Z' ;Suppress HEX file? +0198 74 03 0079 JZ L0000 +019A E8 01 01 0080 CALL CHKDSK +019D 0081 L0000: +019D A2 1B 1B 0082 MOV [HEXFCB],AL +01A0 AC 0083 LODB ;Get PRN file drive letter +01A1 B4 00 0084 MOV AH,0 ;Signal no PRN file +01A3 3C 5A 0085 CMP AL,'Z' ;Suppress PRN file? +01A5 74 15 0086 JZ NOPRN +01A7 3C 59 0087 CMP AL,'Y' ;Print errors only on console? +01A9 74 11 0088 JZ NOPRN +01AB B4 02 0089 MOV AH,2 +01AD 3C 58 0090 CMP AL,'X' ;PRN file to console? +01AF 74 0B 0091 JZ NOPRN +01B1 B4 04 0092 MOV AH,4 +01B3 3C 50 0093 CMP AL,'P' ;PRN file to printer? +01B5 74 05 0094 JZ NOPRN +01B7 E8 E4 00 0095 CALL CHKDSK +01BA B4 80 0096 MOV AH,80H +01BC 0097 NOPRN: +01BC A2 40 1B 0098 MOV [LSTFCB],AL +01BF 88 26 EC 1B 0099 MOV [LSTDEV],AH ;Flag device for list ouput +01C3 BE 0A 1B 0100 MOV SI,EXTEND +01C6 BF 65 00 0101 MOV DI,FCB+9 +01C9 A5 0102 MOVW +01CA A4 0103 MOVB ;Set extension to ASM +01CB A5 0104 MOVW ;Zero extent field +01CC BA 5C 00 0105 MOV DX,FCB +01CF B4 0F 0106 MOV AH,OPEN +01D1 CD 21 0107 INT 33 +01D3 BB AF 1A 0108 MOV BX,NOFILE +01D6 0A C0 0109 OR AL,AL +01D8 74 03 0110 JZ $+5 +01DA E9 97 00 0111 JMP PRERR +01DD BA 1B 1B 0112 MOV DX,HEXFCB +01E0 E8 99 00 0113 CALL MAKFIL +01E3 BA 40 1B 0114 MOV DX,LSTFCB +01E6 E8 93 00 0115 CALL MAKFIL +01E9 C6 06 7C 00 00 0116 MOV B,[FCB+32],0 ;Zero Next Record field +01EE C7 06 6A 00 00 04 0117 MOV [FCB+14],BUFSIZ ;Set record size +01F4 C7 06 3E 20 40 20 0118 MOV [BUFPT],SRCBUF ;Initialize buffer pointer +01FA C7 06 D1 1B 91 24 0119 MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE +0200 C7 06 F2 1B 90 24 0120 MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE +0206 33 C0 0121 XOR AX,AX +0208 A3 65 1B 0122 MOV [PC],AX ;DEFAULT PROGRAM COUNTER +020B A3 CC 1B 0123 MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL +020E A3 EA 1B 0124 MOV [RETPT],AX ;Pointer to last RET record +0211 A2 E4 1B 0125 MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF +0214 A2 E5 1B 0126 MOV [CHKLAB],AL ;LOOKUP ALL LABELS +0217 48 0127 DEC AX +0218 A3 E8 1B 0128 MOV [LSTRET],AX ;Location of last RET +021B A1 06 00 0129 MOV AX,[6] ;HL=END OF MEMORY +021E A3 CE 1B 0130 MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE +0221 C7 06 D5 1B 04 00 0131 MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE +0227 0132 +0227 0133 ;Assemble each line of code +0227 0134 +0227 0135 LOOP: +0227 E8 8A 00 0136 CALL NEXTCHR ;Get first character on line +022A 3C 1A 0137 CMP AL,1AH +022C 74 1E 0138 JZ ENDJ +022E B0 FF 0139 MOV AL,-1 ;Flag that no tokens have been read yet +0230 A2 CB 1B 0140 MOV [SYM],AL +0233 E8 89 06 0141 CALL ASMLIN ;Assemble the line +0236 A0 CB 1B 0142 MOV AL,[SYM] +0239 3C FF 0143 CMP AL,-1 ;Any tokens found on line? +023B 75 03 0144 JNZ L0002 +023D E8 67 03 0145 CALL GETSYM ;If no tokens read yet, read first one +0240 0146 L0002: +0240 3C 3B 0147 CMP AL,';' +0242 74 0B 0148 JZ ENDLN +0244 3C 0D 0149 CMP AL,EOL +0246 74 07 0150 JZ ENDLN +0248 B0 14 0151 MOV AL,14H ;Garbage at end of line error +024A EB 05 0152 JP ENDLIN +024C E9 B9 0D 0153 ENDJ: JMP END +024F 0154 +024F 0155 ENDLN: +024F 32 C0 0156 XOR AL,AL ;Flag no errors on line +0251 0157 ENDLIN: +0251 0158 ;AL = error code for line. Stack depth unknown +0251 BC 90 24 0159 MOV SP,STACK +0254 E8 02 00 0160 CALL NEXLIN +0257 EB CE 0161 JP LOOP +0259 0162 +0259 0163 NEXLIN: +0259 B5 C0 0164 MOV CH,0C0H ;Put end of line marker and error code (AL) +025B E8 00 08 0165 CALL PUTCD +025E E8 C7 07 0166 CALL GEN1 +0261 A0 CA 1B 0167 MOV AL,[CHR] +0264 0168 GETEOL: +0264 3C 0A 0169 CMP AL,10 +0266 74 35 0170 JZ RET +0268 3C 1A 0171 CMP AL,1AH +026A 74 E0 0172 JZ ENDJ +026C E8 45 00 0173 CALL NEXTCHR ;Scan over comments for linefeed +026F EB F3 0174 JP GETEOL +0271 0175 +0271 0176 ABORT: +0271 BB 97 1A 0177 MOV BX,NOMEM +0274 0178 PRERR: +0274 8B D3 0179 MOV DX,BX +0276 B4 09 0180 MOV AH,PRINTMES +0278 CD 21 0181 INT 33 +027A CD 20 0182 INT 32 +027C 0183 +027C 0184 MAKFIL: +027C 8B F2 0185 MOV SI,DX +027E AC 0186 LODB ;Get drive select byte +027F 3C 20 0187 CMP AL,20H ;If not valid, don't make file +0281 73 1A 0188 JNC RET +0283 B9 04 00 0189 MOV CX,4 +0286 8B FE 0190 MOV DI,SI +0288 BE 5D 00 0191 MOV SI,FCB+1 +028B F3 0192 REP +028C A5 0193 MOVW ;Copy source file name +028D B4 16 0194 MOV AH,MAKE +028F CD 21 0195 INT 33 +0291 C7 45 05 01 00 0196 MOV [DI-9+14],1 ;Set record length to 1 byte +0296 BB 7D 1A 0197 MOV BX,NOSPAC +0299 0A C0 0198 OR AL,AL ;Success? +029B 75 D7 0199 JNZ PRERR +029D C3 0200 RET +029E 0201 +029E 0202 CHKDSK: +029E 2C 20 0203 SUB AL,' ' ;If not present, set zero flag +02A0 74 FB 0204 JZ RET +02A2 2C 20 0205 SUB AL,20H +02A4 74 04 0206 JZ DSKERR ;Must be in range A-O +02A6 3C 10 0207 CMP AL,'P'-'@' +02A8 72 F3 0208 JC RET +02AA 0209 DSKERR: +02AA BB D0 1A 0210 MOV BX,BADDSK +02AD EB C5 0211 JP PRERR +02AF 0212 +02AF 0213 ERROR: +02AF 8A C1 0214 MOV AL,CL +02B1 E9 9D FF 0215 JMP ENDLIN +02B4 0216 +02B4 0217 NEXTCHR: +02B4 8B 36 3E 20 0218 MOV SI,[BUFPT] +02B8 81 FE 40 20 0219 CMP SI,SRCBUF +02BC 75 15 0220 JNZ GETCH +02BE 0221 ;Buffer empty so refill it +02BE 52 0222 PUSH DX +02BF 8B D6 0223 MOV DX,SI +02C1 B4 1A 0224 MOV AH,SETDMA +02C3 CD 21 0225 INT 33 +02C5 BA 5C 00 0226 MOV DX,FCB +02C8 B4 14 0227 MOV AH,READ +02CA CD 21 0228 INT 33 +02CC 5A 0229 POP DX +02CD 3C 01 0230 CMP AL,1 +02CF B0 1A 0231 MOV AL,1AH ;Possibly signal End of File +02D1 74 0A 0232 JZ NOMOD ;If nothing read +02D3 0233 GETCH: +02D3 AC 0234 LODB +02D4 81 FE 40 24 0235 CMP SI,SRCBUF+BUFSIZ +02D8 75 03 0236 JNZ NOMOD +02DA BE 40 20 0237 MOV SI,SRCBUF +02DD 0238 NOMOD: +02DD 89 36 3E 20 0239 MOV [BUFPT],SI +02E1 A2 CA 1B 0240 MOV [CHR],AL +02E4 C3 0241 RET +02E5 0242 +02E5 0243 +02E5 0244 MROPS: +02E5 0245 +02E5 0246 ; Get two operands and check for certain types, according to flag byte +02E5 0247 ; in CL. OP code in CH. Returns only if immediate operation. +02E5 0248 +02E5 51 0249 PUSH CX ;Save type flags +02E6 E8 D8 00 0250 CALL GETOP +02E9 52 0251 PUSH DX ;Save first operand +02EA E8 CB 00 0252 CALL GETOP2 +02ED 5B 0253 POP BX ;First op in BX, second op in DX +02EE B0 04 0254 MOV AL,SREG ;Check for a segment register +02F0 3A C7 0255 CMP AL,BH +02F2 74 41 0256 JZ SEGCHK +02F4 3A C6 0257 CMP AL,DH +02F6 74 3D 0258 JZ SEGCHK +02F8 B0 01 0259 MOV AL,CONST ;Check if the first operand is immediate +02FA B1 1A 0260 MOV CL,26 +02FC 3A C7 0261 CMP AL,BH +02FE 74 AF 0262 JZ ERROR ;Error if so +0300 59 0263 POP CX ;Restore type flags +0301 3A C6 0264 CMP AL,DH ;If second operand is immediate, then done +0303 74 DF 0265 JZ RET +0305 B0 00 0266 MOV AL,UNDEFID ;Check for memory reference +0307 3A C7 0267 CMP AL,BH +0309 74 4F 0268 JZ STORE ;Is destination memory? +030B 3A C6 0269 CMP AL,DH +030D 74 55 0270 JZ LOAD ;Is source memory? +030F F6 C1 01 0271 TEST CL,1 ;Check if register-to-register operation OK +0312 B1 1B 0272 MOV CL,27 +0314 74 99 0273 JZ ERROR +0316 8A C6 0274 MOV AL,DH +0318 3A C7 0275 CMP AL,BH ;Registers must be of same length +031A 0276 RR: +031A B1 16 0277 MOV CL,22 +031C 75 91 0278 JNZ ERROR +031E 0279 RR1: +031E 24 01 0280 AND AL,1 ;Get register length (1=16 bits) +0320 0A C5 0281 OR AL,CH ;Or in to OP code +0322 E8 F6 06 0282 CALL PUT ;And write it +0325 59 0283 POP CX ;Dump return address +0326 8A C3 0284 MOV AL,BL +0328 02 C0 0285 ADD AL,AL ;Rotate register number into middle position +032A 02 C0 0286 ADD AL,AL +032C 02 C0 0287 ADD AL,AL +032E 0C C0 0288 OR AL,0C0H ;Set register-to-register mode +0330 0A C2 0289 OR AL,DL ;Combine with other register number +0332 E9 E6 06 0290 JMP PUT +0335 0291 +0335 0292 SEGCHK: +0335 0293 ;Come here if at least one operand is a segment register +0335 59 0294 POP CX ;Restore flags +0336 F6 C1 08 0295 TEST CL,8 ;Check if segment register OK +0339 B1 16 0296 MOV CL,22 +033B 74 78 0297 JZ ERR1 +033D B9 03 8E 0298 MOV CX,8E03H ;Segment register move OP code +0340 B0 00 0299 MOV AL,UNDEFID +0342 3A C6 0300 CMP AL,DH ;Check if source is memory +0344 74 1E 0301 JZ LOAD +0346 3A C7 0302 CMP AL,BH ;Check if destination is memory +0348 74 10 0303 JZ STORE +034A B0 03 0304 MOV AL,XREG +034C 2A C6 0305 SUB AL,DH ;Check if source is 16-bit register +034E 74 CA 0306 JZ RR ;If so, AL must be zero +0350 B5 8C 0307 MOV CH,8CH ;Change direction +0352 87 DA 0308 XCHG DX,BX ;Flip which operand is first and second +0354 B0 03 0309 MOV AL,XREG +0356 2A C6 0310 SUB AL,DH ;Let RR perform finish the test +0358 EB C0 0311 JP RR +035A 0312 +035A 0313 STORE: +035A F6 C1 04 0314 TEST CL,004H ;Check if storing is OK +035D 75 52 0315 JNZ STERR +035F 87 DA 0316 XCHG DX,BX ;If so, flip operands +0361 80 E5 FD 0317 AND CH,0FDH ; and zero direction bit +0364 0318 LOAD: +0364 B6 19 0319 MOV DH,25 +0366 3A C7 0320 CMP AL,BH ;Check if memory-to-memory +0368 74 49 0321 JZ MRERR +036A 8A C7 0322 MOV AL,BH +036C 3C 02 0323 CMP AL,REG ;Check if 8-bit operation +036E 75 07 0324 JNZ XRG +0370 B6 16 0325 MOV DH,22 +0372 F6 C1 01 0326 TEST CL,1 ;See if 8-bit operation is OK +0375 74 3C 0327 JZ MRERR +0377 0328 XRG: +0377 8A C2 0329 MOV AL,DL +0379 2C 06 0330 SUB AL,6 ;Check for R/M mode 6 and register 0 +037B 0A C3 0331 OR AL,BL ; meaning direct load/store of accumulator +037D 75 19 0332 JNZ NOTAC +037F F6 C1 08 0333 TEST CL,8 ;See if direct load/store of accumulator +0382 74 14 0334 JZ NOTAC ; means anything in this case +0384 0335 ; Process direct load/store of accumulator +0384 8A C5 0336 MOV AL,CH +0386 24 02 0337 AND AL,2 ;Preserve direction bit only +0388 34 02 0338 XOR AL,2 ; but flip it +038A 0C A0 0339 OR AL,0A0H ;Combine with OP code +038C 8A E8 0340 MOV CH,AL +038E 8A C7 0341 MOV AL,BH ;Check byte/word operation +0390 24 01 0342 AND AL,1 +0392 0A C5 0343 OR AL,CH +0394 59 0344 POP CX ;Dump return address +0395 E9 47 07 0345 JMP PUTADD ;Write the address +0398 0346 +0398 0347 NOTAC: +0398 8A C7 0348 MOV AL,BH +039A 24 01 0349 AND AL,1 ;Get byte/word bit +039C 22 C1 0350 AND AL,CL ;But don't use it in word-only operations +039E 0A C5 0351 OR AL,CH ;Combine with OP code +03A0 E8 78 06 0352 CALL PUT +03A3 8A C3 0353 MOV AL,BL +03A5 02 C0 0354 ADD AL,AL ;Rotate to middle position +03A7 02 C0 0355 ADD AL,AL +03A9 02 C0 0356 ADD AL,AL +03AB 0A C2 0357 OR AL,DL ;Combine register field +03AD 59 0358 POP CX ;Dump return address +03AE E9 2E 07 0359 JMP PUTADD ;Write the address +03B1 0360 +03B1 0361 STERR: +03B1 B6 1D 0362 MOV DH,29 +03B3 0363 MRERR: +03B3 8A CE 0364 MOV CL,DH +03B5 0365 +03B5 E9 F7 FE 0366 ERR1: JMP ERROR +03B8 0367 +03B8 0368 GETOP2: +03B8 0369 ;Get the second operand: look for a comma and drop into GETOP +03B8 A0 CB 1B 0370 MOV AL,[SYM] +03BB 3C 2C 0371 CMP AL,',' +03BD B1 15 0372 MOV CL,21 +03BF 75 F4 0373 JNZ ERR1 +03C1 0374 +03C1 0375 +03C1 0376 GETOP: +03C1 0377 +03C1 0378 ; Get one operand. Operand may be a memory reference in brackets, a register, +03C1 0379 ; or a constant. If a flag (such as "B" for byte operation) is encountered, +03C1 0380 ; it is noted and processing continues to find the operand. +03C1 0381 ; +03C1 0382 ; On exit, AL (=DH) has the type of operand. Other information depends +03C1 0383 ; on the actual operand: +03C1 0384 ; +03C1 0385 ; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +03C1 0386 ; the 8086 R/M format (middle bits zero). The constant part of the address +03C1 0387 ; is in ADDR. If an undefined label needs to be added to this, a pointer to +03C1 0388 ; its information fields is in ALABEL, otherwise ALABEL is zero. +03C1 0389 ; +03C1 0390 ; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +03C1 0391 ; to be added to this, a pointer to its information fields is in DLABEL, +03C1 0392 ; otherwise DLABEL is zero. "$" and "RET" are in this class. +03C1 0393 ; +03C1 0394 ; AL=DH=2 8-bit Register. DL has the register number. +03C1 0395 ; +03C1 0396 ; AL=DH=3 16-bit Register. DL has the register number. +03C1 0397 ; +03C1 0398 ; AL=DH=4 Segment Register. DL has the register number. +03C1 0399 +03C1 E8 E3 01 0400 CALL GETSYM +03C4 0401 GETOP1: +03C4 0402 ;Enter here if we don't need a GETSYM first +03C4 3C 5B 0403 CMP AL,'[' ;Memory reference? +03C6 74 30 0404 JZ MEM +03C8 3C 05 0405 CMP AL,5 ;Flag ("B", "W", etc.)? +03CA 74 57 0406 JZ FLG +03CC 3C 02 0407 CMP AL,REG ;8-Bit register? +03CE 74 20 0408 JZ NREG +03D0 3C 03 0409 CMP AL,XREG ;16-Bit register? +03D2 74 1C 0410 JZ NREG +03D4 3C 04 0411 CMP AL,SREG ;Segment register? +03D6 74 18 0412 JZ NREG +03D8 0413 VAL: ;Must be immediate +03D8 32 C0 0414 XOR AL,AL ;No addressing modes allowed +03DA 0415 VAL1: +03DA E8 4F 00 0416 CALL GETVAL +03DD A1 75 1B 0417 MOV AX,[CON] ;Defined part +03E0 A3 71 1B 0418 MOV [DATA],AX +03E3 A1 77 1B 0419 MOV AX,[UNDEF] ;Undefined part +03E6 A3 73 1B 0420 MOV [DLABEL],AX +03E9 8A D5 0421 MOV DL,CH +03EB B6 01 0422 MOV DH,CONST +03ED 8A C6 0423 MOV AL,DH +03EF C3 0424 RET +03F0 0425 NREG: +03F0 52 0426 PUSH DX +03F1 E8 B3 01 0427 CALL GETSYM +03F4 5A 0428 POP DX +03F5 8A C6 0429 MOV AL,DH +03F7 C3 0430 RET +03F8 0431 MEM: +03F8 E8 AC 01 0432 CALL GETSYM +03FB B0 01 0433 MOV AL,1 +03FD E8 2C 00 0434 CALL GETVAL +0400 A0 CB 1B 0435 MOV AL,[SYM] +0403 3C 5D 0436 CMP AL,']' +0405 B1 18 0437 MOV CL,24 +0407 75 AC 0438 JNZ ERR1 +0409 E8 9B 01 0439 CALL GETSYM +040C 8B 1E 75 1B 0440 MOV BX,[CON] +0410 89 1E 6D 1B 0441 MOV [ADDR],BX +0414 8B 1E 77 1B 0442 MOV BX,[UNDEF] +0418 89 1E 6F 1B 0443 MOV [ALABEL],BX +041C 8A D5 0444 MOV DL,CH +041E B6 00 0445 MOV DH,UNDEFID +0420 8A C6 0446 MOV AL,DH +0422 C3 0447 RET +0423 0448 FLG: +0423 E8 81 01 0449 CALL GETSYM +0426 3C 2C 0450 CMP AL,',' +0428 74 97 0451 JZ GETOP +042A EB 98 0452 JP GETOP1 +042C 0453 +042C 0454 +042C 0455 GETVAL: +042C 0456 +042C 0457 ; Expression analyzer. On entry, if AL=0 then do not allow base or index +042C 0458 ; registers. If AL=1, we are analyzing a memory reference, so allow base +042C 0459 ; and index registers, and compute addressing mode when done. The constant +042C 0460 ; part of the expression will be found in CON. If an undefined label is to +042C 0461 ; be added to this, a pointer to its information fields will be found in +042C 0462 ; UNDEF. +042C 0463 +042C 95 0464 XCHG AX,BP ;Flag is kept in BP +042D 53 0465 PUSH BX +042E BB 00 00 0466 MOV BX,0 +0431 89 1E 75 1B 0467 MOV [CON],BX +0435 89 1E 77 1B 0468 MOV [UNDEF],BX +0439 5B 0469 POP BX +043A A0 CB 1B 0470 MOV AL,[SYM] +043D 3C 2B 0471 CMP AL,'+' +043F 74 09 0472 JZ PLSMNS +0441 3C 2D 0473 CMP AL,'-' +0443 74 05 0474 JZ PLSMNS +0445 B1 2B 0475 MOV CL,'+' +0447 51 0476 PUSH CX +0448 EB 08 0477 JP OPERATE +044A 0478 PLSMNS: +044A 50 0479 PUSH AX +044B 81 CD 04 00 0480 OR BP,4 ;Flag that a sign was found +044F E8 55 01 0481 CALL GETSYM +0452 0482 OPERATE: +0452 3C 01 0483 CMP AL,CONST +0454 75 03 0484 JNZ $+5 +0456 E9 C3 00 0485 JMP CVAL +0459 3C 00 0486 CMP AL,UNDEFID +045B 75 03 0487 JNZ $+5 +045D E9 CA 00 0488 JMP UVAL +0460 3C 22 0489 CMP AL,'"' +0462 75 03 0490 JNZ $+5 +0464 E9 DE 00 0491 STRINGJ:JMP STRING +0467 3C 27 0492 CMP AL,"'" +0469 74 F9 0493 JZ STRINGJ +046B 3C 03 0494 CMP AL,XREG ;Only 16-bit register may index +046D B1 14 0495 MOV CL,20 +046F 75 20 0496 JNZ ERR2 +0471 F7 C5 01 00 0497 TEST BP,1 ;Check to see if indexing is OK +0475 B1 01 0498 MOV CL,1 +0477 74 18 0499 JZ ERR2 +0479 8A C2 0500 MOV AL,DL +047B B1 03 0501 MOV CL,3 +047D 3C 03 0502 CMP AL,3 ;Check for BX +047F 74 25 0503 JZ BXJ +0481 2C 05 0504 SUB AL,5 ;Check for BP +0483 74 2A 0505 JZ BPJ +0485 FE C8 0506 DEC AL ;Check for SI +0487 B1 04 0507 MOV CL,4 +0489 74 12 0508 JZ SIJ +048B FE C8 0509 DEC AL ;Check for DI +048D 74 05 0510 JZ DIJ +048F B1 02 0511 MOV CL,2 ;Invalid base/index register +0491 E9 1B FE 0512 ERR2: JMP ERROR +0494 0513 DIJ: +0494 95 0514 XCHG AX,BP +0495 A8 10 0515 TEST AL,10H ;Check if already seen index register +0497 75 F8 0516 JNZ ERR2 +0499 0C 30 0517 OR AL,30H ;Flag seeing index register DI +049B EB 19 0518 JP LPCHK +049D 0519 SIJ: +049D 95 0520 XCHG AX,BP +049E A8 10 0521 TEST AL,010H ;Check if already seen index register +04A0 75 EF 0522 JNZ ERR2 +04A2 0C 10 0523 OR AL,010H ;Flag seeing index register SI +04A4 EB 10 0524 JP LPCHK +04A6 0525 BXJ: +04A6 95 0526 XCHG AX,BP +04A7 A8 80 0527 TEST AL,080H ;Check if already seen base register +04A9 75 E6 0528 JNZ ERR2 +04AB 0C 80 0529 OR AL,080H ;Flag seeing base register BX +04AD EB 07 0530 JP LPCHK +04AF 0531 BPJ: +04AF 95 0532 XCHG AX,BP +04B0 A8 80 0533 TEST AL,080H ;Check if already seen base register +04B2 75 DD 0534 JNZ ERR2 +04B4 0C C0 0535 OR AL,0C0H ;Flag seeing base register BP +04B6 0536 LPCHK: +04B6 95 0537 XCHG AX,BP +04B7 58 0538 POP AX ;Get operator +04B8 3C 2D 0539 CMP AL,'-' ;Can't subtract a register +04BA B1 05 0540 MOV CL,5 +04BC 74 D3 0541 JZ ERR2 +04BE 0542 NEXTER: +04BE E8 E6 00 0543 CALL GETSYM +04C1 3C 2B 0544 CMP AL,'+' +04C3 75 03 0545 JNZ $+5 +04C5 E9 82 FF 0546 PJ: JMP PLSMNS +04C8 3C 2D 0547 CMP AL,'-' +04CA 74 F9 0548 JZ PJ +04CC 95 0549 XCHG AX,BP +04CD B5 00 0550 MOV CH,0 +04CF A8 10 0551 TEST AL,010H ;Test INDEX bit +04D1 D0 D0 0552 RCL AL ;BASE bit (zero flag not affected) +04D3 74 3B 0553 JZ NOIND ;Jump if not indexed, with BASE bit in carry +04D5 F5 0554 CMC +04D6 D0 D5 0555 RCL CH +04D8 D0 D0 0556 RCL AL ;BP bit +04DA D0 D5 0557 RCL CH +04DC D0 D0 0558 RCL AL ;DI bit +04DE D0 D5 0559 RCL CH ;The low 3 bits now have indexing mode +04E0 0560 MODE: +04E0 80 CD 80 0561 OR CH,080H ;If undefined label, force 16-bit displacement +04E3 F7 06 77 1B FF FF 0562 TEST [UNDEF],-1 +04E9 75 1E 0563 JNZ RET +04EB 8B 1E 75 1B 0564 MOV BX,[CON] +04EF E8 18 00 0565 CALL SIGNEXT ;Check if 8-bit with sign extended +04F2 75 15 0566 JNZ RET ;If not, use 16-bit displacement +04F4 80 E5 7F 0567 AND CH,07FH ;Reset 16-bit displacement +04F7 80 CD 40 0568 OR CH,040H ;Set 8-bit displacement +04FA 0B DB 0569 OR BX,BX +04FC 75 0B 0570 JNZ RET ;Use it if not zero displacement +04FE 80 E5 07 0571 AND CH,7 ;Specify no displacement +0501 82 FD 06 0572 CMP CH,6 ;Check for BP+0 addressing mode +0504 75 03 0573 JNZ RET +0506 80 CD 40 0574 OR CH,040H ;If BP+0, use 8-bit displacement +0509 C3 0575 RET +050A 0576 +050A 0577 SIGNEXT: +050A 0578 ; Return with zero flag set if value in BX is a valid sign-extended +050A 0579 ; 8-bit value. AX destroyed +050A 8A C3 0580 MOV AL,BL +050C 98 0581 CBW +050D 3B C3 0582 CMP AX,BX +050F C3 0583 RET +0510 0584 +0510 0585 NOIND: +0510 B5 06 0586 MOV CH,6 ;Try direct address mode +0512 73 FB 0587 JNC RET ;If no base register, that's right +0514 D0 D0 0588 RCL AL ;Check BP bit +0516 72 C8 0589 JC MODE +0518 FE C5 0590 INC CH ;If not, must be BX +051A EB C4 0591 JP MODE +051C 0592 +051C 0593 CVAL: +051C 58 0594 POP AX +051D 3C 2D 0595 CMP AL,'-' +051F 75 02 0596 JNZ ADDCON +0521 F7 DA 0597 NEG DX +0523 0598 ADDCON: +0523 01 16 75 1B 0599 ADD [CON],DX +0527 E9 94 FF 0600 JMP NEXTER +052A 0601 +052A 0602 UVAL: +052A 95 0603 XCHG AX,BP +052B B1 06 0604 MOV CL,6 +052D A8 08 0605 TEST AL,008H ;Check if undefined label has been seen +052F 75 11 0606 JNZ ERR30 +0531 0C 08 0607 OR AL,008H ;Flag seeing undefined label +0533 95 0608 XCHG AX,BP +0534 89 1E 77 1B 0609 MOV [UNDEF],BX +0538 58 0610 POP AX +0539 3C 2B 0611 CMP AL,'+' ;Undefined label may only be added +053B B1 05 0612 MOV CL,5 +053D 75 03 0613 JNZ ERR30 +053F E9 7C FF 0614 JMP NEXTER +0542 0615 +0542 E9 6A FD 0616 ERR30: JMP ERROR +0545 0617 +0545 0618 STRING: +0545 8A E8 0619 MOV CH,AL +0547 A0 CA 1B 0620 MOV AL,[CHR] +054A 3A C5 0621 CMP AL,CH +054C B1 23 0622 MOV CL,35 +054E 8A D0 0623 MOV DL,AL +0550 B6 00 0624 MOV DH,0 +0552 75 03 0625 JNZ L0003 +0554 E8 36 00 0626 CALL ZERLEN +0557 0627 L0003: +0557 E8 3B 00 0628 CALL GETCHR +055A 9F 0629 LAHF +055B 95 0630 XCHG AX,BP +055C 9E 0631 SAHF +055D B1 25 0632 MOV CL,37 +055F A8 02 0633 TEST AL,002H +0561 74 DF 0634 JZ ERR30 +0563 A8 04 0635 TEST AL,004H +0565 B1 26 0636 MOV CL,38 +0567 75 D9 0637 JNZ ERR30 +0569 9F 0638 LAHF +056A 95 0639 XCHG AX,BP +056B 9E 0640 SAHF +056C 0641 STRGDAT: +056C 8A C2 0642 MOV AL,DL +056E 3C 0D 0643 CMP AL,EOL +0570 B1 27 0644 MOV CL,39 +0572 74 CE 0645 JZ ERR30 +0574 E8 A4 04 0646 CALL PUT +0577 A0 D3 1B 0647 MOV AL,[DATSIZ] +057A 0A C0 0648 OR AL,AL +057C 75 05 0649 JNZ BYTSIZ +057E 8A C6 0650 MOV AL,DH +0580 E8 98 04 0651 CALL PUT +0583 0652 BYTSIZ: +0583 A0 CA 1B 0653 MOV AL,[CHR] +0586 8A D0 0654 MOV DL,AL +0588 E8 0A 00 0655 CALL GETCHR +058B EB DF 0656 JP STRGDAT +058D 0657 ZERLEN: +058D E8 24 FD 0658 CALL NEXTCHR +0590 3A C5 0659 CMP AL,CH +0592 75 AE 0660 JNZ ERR30 +0594 C3 0661 RET +0595 0662 GETCHR: +0595 E8 1C FD 0663 CALL NEXTCHR +0598 3A C5 0664 CMP AL,CH +059A 75 F8 0665 JNZ RET +059C E8 15 FD 0666 CALL NEXTCHR +059F 3A C5 0667 CMP AL,CH +05A1 74 F1 0668 JZ RET +05A3 5B 0669 POP BX +05A4 E9 75 FF 0670 JMP CVAL +05A7 0671 +05A7 0672 +05A7 0673 GETSYM: +05A7 0674 +05A7 0675 ; The lexical scanner. Used only in the operand field. Returns with the token +05A7 0676 ; in SYM and AL, sometimes with additional info in BX or DX. +05A7 0677 ; +05A7 0678 ; AL=SYM=0 Undefined label. BX has pointer to information fields. +05A7 0679 ; +05A7 0680 ; AL=SYM=1 Constant (or defined label). DX has value. +05A7 0681 ; +05A7 0682 ; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +05A7 0683 ; respectively. DL has register number. +05A7 0684 ; +05A7 0685 ; AL=SYM=5 A mode flag (such as "B" for byte operation). Also stored in +05A7 0686 ; appropriate memory location--FLAG or LONG. +05A7 0687 ; +05A7 0688 ; All other values are the ASCII code of the character. Note that this may +05A7 0689 ; never be a letter or number. +05A7 0690 +05A7 E8 20 00 0691 CALL GETSY +05AA A0 CB 1B 0692 MOV AL,[SYM] +05AD C3 0693 RET +05AE 0694 +05AE 0695 SCANB: +05AE A0 CA 1B 0696 MOV AL,[CHR] +05B1 0697 SCANT: +05B1 3C 20 0698 CMP AL,' ' +05B3 74 04 0699 JZ NEXB +05B5 3C 09 0700 CMP AL,9 +05B7 75 F4 0701 JNZ RET +05B9 0702 NEXB: +05B9 E8 F8 FC 0703 CALL NEXTCHR +05BC EB F3 0704 JP SCANT +05BE 0705 +05BE 0706 DOLLAR: +05BE 8B 16 67 1B 0707 MOV DX,[OLDPC] +05C2 B0 01 0708 MOV AL,CONST +05C4 A2 CB 1B 0709 MOV [SYM],AL +05C7 0710 NEXTCHJ: +05C7 E9 EA FC 0711 JMP NEXTCHR +05CA 0712 +05CA 0713 GETSY: +05CA E8 E1 FF 0714 CALL SCANB +05CD 3C 24 0715 CMP AL,'$' +05CF 74 ED 0716 JZ DOLLAR +05D1 A2 CB 1B 0717 MOV [SYM],AL +05D4 0C 20 0718 OR AL,20H +05D6 3C 7B 0719 CMP AL,'z'+1 +05D8 73 ED 0720 JNC NEXTCHJ +05DA 3C 61 0721 CMP AL,'a' +05DC 72 03 0722 JC $+5 +05DE E9 BF 00 0723 JMP LETTER +05E1 3C 3A 0724 CMP AL,'9'+1 +05E3 73 E2 0725 JNC NEXTCHJ +05E5 3C 30 0726 CMP AL,'0' +05E7 72 DE 0727 JC NEXTCHJ +05E9 BB CB 1B 0728 MOV BX,SYM +05EC C6 07 01 0729 MOV B,[BX],CONST +05EF E8 83 00 0730 CALL READID +05F2 4B 0731 DEC BX +05F3 8A 07 0732 MOV AL,[BX] +05F5 B1 07 0733 MOV CL,7 +05F7 BB 00 00 0734 MOV BX,0 +05FA 3C 68 0735 CMP AL,'h' +05FC 75 03 0736 JNZ $+5 +05FE E9 32 00 0737 JMP HEX +0601 FE C1 0738 INC CL +0603 C7 06 F0 1B 7A 1B 0739 MOV [IX],ID +0609 0740 DEC: +0609 8B 36 F0 1B 0741 MOV SI,[IX] +060D 8A 04 0742 MOV AL,[SI] +060F FF 06 F0 1B 0743 INC [IX] +0613 3C 3A 0744 CMP AL,'9'+1 +0615 72 03 0745 JC $+5 +0617 E9 95 FC 0746 JMP ERROR +061A 2C 30 0747 SUB AL,'0' +061C 8B D3 0748 MOV DX,BX +061E D1 E3 0749 SHL BX +0620 D1 E3 0750 SHL BX +0622 03 DA 0751 ADD BX,DX +0624 D1 E3 0752 SHL BX +0626 8A D0 0753 MOV DL,AL +0628 B6 00 0754 MOV DH,0 +062A 03 DA 0755 ADD BX,DX +062C FE CD 0756 DEC CH +062E 75 D9 0757 JNZ DEC +0630 87 DA 0758 XCHG DX,BX +0632 C3 0759 RET +0633 0760 +0633 0761 HEX: +0633 BA 7A 1B 0762 MOV DX,ID +0636 FE CD 0763 DEC CH +0638 0764 HEX1: +0638 8B F2 0765 MOV SI,DX +063A AC 0766 LODB +063B 42 0767 INC DX +063C 2C 30 0768 SUB AL,'0' +063E 3C 0A 0769 CMP AL,10 +0640 72 06 0770 JC GOTIT +0642 3C 37 0771 CMP AL,'g'-'0' +0644 73 13 0772 JNC ERR4 +0646 2C 27 0773 SUB AL,'a'-10-'0' +0648 0774 GOTIT: +0648 D1 E3 0775 SHL BX +064A D1 E3 0776 SHL BX +064C D1 E3 0777 SHL BX +064E D1 E3 0778 SHL BX +0650 02 D8 0779 ADD BL,AL +0652 FE CD 0780 DEC CH +0654 75 E2 0781 JNZ HEX1 +0656 87 DA 0782 XCHG DX,BX +0658 C3 0783 RET +0659 0784 +0659 E9 53 FC 0785 ERR4: JMP ERROR +065C 0786 +065C 0787 GETLET: +065C E8 4F FF 0788 CALL SCANB +065F 3C 0D 0789 CMP AL,EOL +0661 F9 0790 STC +0662 74 F4 0791 JZ RET +0664 3C 3B 0792 CMP AL,';' +0666 F9 0793 STC +0667 74 EF 0794 JZ RET +0669 B1 0A 0795 MOV CL,10 +066B 0C 20 0796 OR AL,20H +066D 3C 61 0797 CMP AL,'a' +066F 72 E8 0798 JC ERR4 +0671 3C 7B 0799 CMP AL,'z'+1 +0673 73 E4 0800 JNC ERR4 +0675 0801 READID: +0675 BB 7A 1B 0802 MOV BX,ID +0678 B5 00 0803 MOV CH,0 +067A 0804 MOREID: +067A 88 07 0805 MOV [BX],AL +067C FE C5 0806 INC CH +067E 43 0807 INC BX +067F E8 32 FC 0808 CALL NEXTCHR +0682 3C 30 0809 CMP AL,'0' +0684 72 0E 0810 JC NOMORE +0686 0C 20 0811 OR AL,20H +0688 3C 7B 0812 CMP AL,'z'+1 +068A 73 08 0813 JNC NOMORE +068C 3C 3A 0814 CMP AL,'9'+1 +068E 72 EA 0815 JC MOREID +0690 3C 61 0816 CMP AL,'a' +0692 73 E6 0817 JNC MOREID +0694 0818 NOMORE: +0694 8A C8 0819 MOV CL,AL +0696 8A C5 0820 MOV AL,CH +0698 A2 79 1B 0821 MOV [LENID],AL +069B 0A C0 0822 OR AL,AL +069D 8A C1 0823 MOV AL,CL +069F C3 0824 RET +06A0 0825 +06A0 0826 LETTER: +06A0 E8 D2 FF 0827 CALL READID +06A3 8A C5 0828 MOV AL,CH +06A5 FE C8 0829 DEC AL +06A7 75 1B 0830 JNZ NOFLG +06A9 A0 7A 1B 0831 MOV AL,[ID] +06AC 3C 6C 0832 CMP AL,'l' +06AE B1 00 0833 MOV CL,0 +06B0 BA 6C 1B 0834 MOV DX,LONG +06B3 74 23 0835 JZ BWFLAG +06B5 3C 62 0836 CMP AL,'b' +06B7 BA 6B 1B 0837 MOV DX,FLAG +06BA 74 1C 0838 JZ BWFLAG +06BC 3C 77 0839 CMP AL,'w' +06BE B1 01 0840 MOV CL,1 +06C0 74 16 0841 JZ BWFLAG +06C2 32 C0 0842 XOR AL,AL +06C4 0843 NOFLG: +06C4 FE C8 0844 DEC AL +06C6 53 0845 PUSH BX +06C7 75 03 0846 JNZ L0004 +06C9 E8 1F 00 0847 CALL REGCHK +06CC 0848 L0004: +06CC 5B 0849 POP BX +06CD 8A C6 0850 MOV AL,DH +06CF 74 03 0851 JZ SYMSAV +06D1 E8 B6 00 0852 CALL LOOKRET +06D4 0853 SYMSAV: +06D4 A2 CB 1B 0854 MOV [SYM],AL +06D7 C3 0855 RET +06D8 0856 +06D8 0857 BWFLAG: +06D8 87 DA 0858 XCHG DX,BX +06DA 8A 07 0859 MOV AL,[BX] +06DC FE C0 0860 INC AL +06DE 88 0F 0861 MOV [BX],CL +06E0 B1 20 0862 MOV CL,32 +06E2 74 03 0863 JZ $+5 +06E4 E9 C8 FB 0864 JMP ERROR +06E7 B0 05 0865 MOV AL,5 +06E9 EB E9 0866 JP SYMSAV +06EB 0867 +06EB 0868 REGCHK: +06EB BB 7A 1B 0869 MOV BX,ID +06EE 8A 0F 0870 MOV CL,[BX] +06F0 9F 0871 LAHF +06F1 43 0872 INC BX +06F2 9E 0873 SAHF +06F3 8A 07 0874 MOV AL,[BX] +06F5 BB 52 07 0875 MOV BX,REGTAB +06F8 B6 03 0876 MOV DH,XREG +06FA B2 00 0877 MOV DL,0 +06FC 3C 78 0878 CMP AL,'x' +06FE 74 3B 0879 JZ SCANREG +0700 B6 02 0880 MOV DH,REG +0702 3C 6C 0881 CMP AL,'l' +0704 74 35 0882 JZ SCANREG +0706 B2 04 0883 MOV DL,4 +0708 3C 68 0884 CMP AL,'h' +070A 74 2F 0885 JZ SCANREG +070C B6 04 0886 MOV DH,SREG +070E B2 00 0887 MOV DL,0 +0710 BB 56 07 0888 MOV BX,SEGTAB +0713 3C 73 0889 CMP AL,'s' +0715 74 24 0890 JZ SCANREG +0717 B6 03 0891 MOV DH,XREG +0719 3C 70 0892 CMP AL,'p' +071B 74 11 0893 JZ PREG +071D 3C 69 0894 CMP AL,'i' +071F 75 B6 0895 JNZ RET +0721 B2 06 0896 MOV DL,6 +0723 8A C1 0897 MOV AL,CL +0725 3C 73 0898 CMP AL,'s' +0727 74 AE 0899 JZ RET +0729 FE C2 0900 INC DL +072B 3C 64 0901 CMP AL,'d' +072D C3 0902 RET +072E 0903 PREG: +072E B2 04 0904 MOV DL,4 +0730 8A C1 0905 MOV AL,CL +0732 3C 73 0906 CMP AL,'s' +0734 74 F7 0907 JZ RET +0736 FE C2 0908 INC DL +0738 3C 62 0909 CMP AL,'b' +073A C3 0910 RET +073B 0911 SCANREG: +073B 8A C1 0912 MOV AL,CL +073D B9 04 00 0913 MOV CX,4 +0740 FC 0914 UP +0741 8B FB 0915 MOV DI,BX +0743 F2 0916 REPNZ +0744 AE 0917 SCAB +0745 8B DF 0918 MOV BX,DI +0747 75 F1 0919 JNZ RET +0749 8A C1 0920 MOV AL,CL +074B 02 C2 0921 ADD AL,DL +074D 8A D0 0922 MOV DL,AL +074F 32 C0 0923 XOR AL,AL +0751 C3 0924 RET +0752 0925 +0752 62 64 63 61 0926 REGTAB: DB 'bdca' +0756 0927 +0756 64 73 63 65 0928 SEGTAB: DB 'dsce' +075A 0929 +075A 0930 LOOK: +075A 8A 2F 0931 MOV CH,[BX] +075C 43 0932 INC BX +075D BA 7A 1B 0933 MOV DX,ID +0760 E8 F4 00 0934 CALL CPSLP +0763 74 EC 0935 JZ RET +0765 34 80 0936 XOR AL,80H +0767 8A C8 0937 MOV CL,AL +0769 4B 0938 DEC BX +076A 8A 07 0939 MOV AL,[BX] +076C 34 80 0940 XOR AL,80H +076E 3A C1 0941 CMP AL,CL +0770 73 04 0942 JNC SMALL +0772 FE C5 0943 INC CH +0774 FE C5 0944 INC CH +0776 0945 SMALL: +0776 8A D5 0946 MOV DL,CH +0778 B6 00 0947 MOV DH,0 +077A 03 DA 0948 ADD BX,DX +077C 8B 17 0949 MOV DX,[BX] +077E 43 0950 INC BX +077F 8A C2 0951 MOV AL,DL +0781 0A C6 0952 OR AL,DH +0783 F9 0953 STC +0784 74 CB 0954 JZ RET +0786 87 DA 0955 XCHG DX,BX +0788 EB D0 0956 JP LOOK +078A 0957 +078A 0958 LOOKRET: +078A 8A C5 0959 MOV AL,CH +078C 3C 03 0960 CMP AL,3 ;RET has 3 letters +078E 75 4D 0961 JNZ LOOKUP +0790 4B 0962 DEC BX +0791 80 0F 80 0963 OR B,[BX],080H +0794 BA 1A 1B 0964 MOV DX,RETSTR+2 +0797 0965 CHKRET: +0797 8B F2 0966 MOV SI,DX +0799 AC 0967 LODB +079A 3A 07 0968 CMP AL,[BX] +079C 75 43 0969 JNZ LOOKIT +079E 4B 0970 DEC BX +079F 4A 0971 DEC DX +07A0 FE CD 0972 DEC CH +07A2 75 F3 0973 JNZ CHKRET +07A4 8B 16 E8 1B 0974 MOV DX,[LSTRET] +07A8 8A C2 0975 MOV AL,DL +07AA 22 C6 0976 AND AL,DH +07AC FE C0 0977 INC AL +07AE 74 0D 0978 JZ ALLRET +07B0 8B 1E 65 1B 0979 MOV BX,[PC] +07B4 2B DA 0980 SUB BX,DX +07B6 E8 51 FD 0981 CALL SIGNEXT +07B9 B0 01 0982 MOV AL,1 +07BB 74 94 0983 JZ RET +07BD 0984 ALLRET: +07BD 8B 1E EA 1B 0985 MOV BX,[RETPT] +07C1 8A C7 0986 MOV AL,BH +07C3 0A C3 0987 OR AL,BL +07C5 B0 00 0988 MOV AL,0 +07C7 75 88 0989 JNZ RET +07C9 8B 1E CE 1B 0990 MOV BX,[HEAP] +07CD 4B 0991 DEC BX +07CE 4B 0992 DEC BX +07CF 4B 0993 DEC BX +07D0 89 1E CE 1B 0994 MOV [HEAP],BX +07D4 32 C0 0995 XOR AL,AL +07D6 88 07 0996 MOV [BX],AL +07D8 89 1E EA 1B 0997 MOV [RETPT],BX +07DC C3 0998 RET +07DD 0999 +07DD 1000 LOOKUP: +07DD 4B 1001 DEC BX +07DE 80 0F 80 1002 OR B,[BX],080H +07E1 1003 LOOKIT: +07E1 8B 1E CC 1B 1004 MOV BX,[BASE] +07E5 8A C7 1005 MOV AL,BH +07E7 0A C3 1006 OR AL,BL +07E9 74 1E 1007 JZ EMPTY +07EB E8 6C FF 1008 CALL LOOK +07EE 72 10 1009 JC ENTER +07F0 BA 04 00 1010 MOV DX,4 +07F3 03 DA 1011 ADD BX,DX +07F5 8A 07 1012 MOV AL,[BX] +07F7 0A C0 1013 OR AL,AL +07F9 74 E1 1014 JZ RET +07FB 43 1015 INC BX +07FC 8B 17 1016 MOV DX,[BX] +07FE 43 1017 INC BX +07FF C3 1018 RET +0800 1019 +0800 1020 ENTER: +0800 53 1021 PUSH BX ;Save pointer to link field +0801 E8 0D 00 1022 CALL CREATE ;Add the node +0804 5E 1023 POP SI +0805 89 54 FF 1024 MOV [SI-1],DX ;Link new node +0808 C3 1025 RET ;Zero was set by CREATE +0809 1026 +0809 1027 EMPTY: +0809 E8 05 00 1028 CALL CREATE +080C 89 16 CC 1B 1029 MOV [BASE],DX +0810 C3 1030 RET +0811 1031 +0811 1032 +0811 1033 CREATE: +0811 1034 +0811 1035 ; Add a new node to the identifier tree. The identifier is at ID with +0811 1036 ; bit 7 of the last character set to one. The length of the identifier is +0811 1037 ; in LENID, which is ID-1. +0811 1038 ; +0811 1039 ; Node format: +0811 1040 ; 1. Length of identifier (1 byte) +0811 1041 ; 2. Identifier (1-80 bytes) +0811 1042 ; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +0811 1043 ; 4. Right link (0 if none larger) +0811 1044 ; 5. Data field: +0811 1045 ; a. Defined flag (0=undefined, 1=defined) +0811 1046 ; b. Value (2 bytes) +0811 1047 ; +0811 1048 ; This routine returns with AL=zero and zero flag set (which indicates +0811 1049 ; on return from LOOKUP that it has not yet been defined), DX points +0811 1050 ; to start of new node, and BX points to data field of new node. +0811 1051 +0811 A0 79 1B 1052 MOV AL,[LENID] +0814 04 08 1053 ADD AL,8 ;Storage needed for the node +0816 8B 1E CE 1B 1054 MOV BX,[HEAP] +081A 8A D0 1055 MOV DL,AL +081C B6 00 1056 MOV DH,0 +081E 2B DA 1057 SUB BX,DX ;Heap grows downward +0820 89 1E CE 1B 1058 MOV [HEAP],BX +0824 87 DA 1059 XCHG DX,BX +0826 8B 1E D1 1B 1060 MOV BX,[CODE] ;Check to make sure there's enough +082A 3B DA 1061 CMP BX,DX +082C 72 03 1062 JB $+5 +082E E9 40 FA 1063 JMP ABORT +0831 52 1064 PUSH DX +0832 BB 79 1B 1065 MOV BX,LENID +0835 8A 0F 1066 MOV CL,[BX] +0837 FE C1 1067 INC CL +0839 B5 00 1068 MOV CH,0 +083B FC 1069 UP +083C 8B F3 1070 MOV SI,BX +083E 8B FA 1071 MOV DI,DX +0840 F3 1072 REP +0841 A4 1073 MOVB ;Move identifier and length into node +0842 8B D7 1074 MOV DX,DI +0844 8B DE 1075 MOV BX,SI +0846 B5 04 1076 MOV CH,4 +0848 87 DA 1077 XCHG DX,BX +084A 1078 NILIFY: +084A 88 0F 1079 MOV [BX],CL ;Zero left and right links +084C 43 1080 INC BX +084D FE CD 1081 DEC CH +084F 75 F9 1082 JNZ NILIFY +0851 32 C0 1083 XOR AL,AL ;Set zero flag +0853 88 07 1084 MOV [BX],AL ;Zero defined flag +0855 5A 1085 POP DX ;Restore pointer to node +0856 C3 1086 RET +0857 1087 +0857 1088 CPSLP: +0857 8B F2 1089 MOV SI,DX +0859 AC 1090 LODB +085A 3A 07 1091 CMP AL,[BX] +085C 9F 1092 LAHF +085D 42 1093 INC DX +085E 43 1094 INC BX +085F 9E 1095 SAHF +0860 75 F4 1096 JNZ RET +0862 FE CD 1097 DEC CH +0864 75 F1 1098 JNZ CPSLP +0866 C3 1099 RET +0867 1100 +0867 1101 GETLAB: +0867 BB 00 00 1102 MOV BX,0 +086A 89 1E 69 1B 1103 MOV [LABPT],BX +086E B0 FF 1104 MOV AL,-1 +0870 A2 6B 1B 1105 MOV [FLAG],AL +0873 A2 6C 1B 1106 MOV [LONG],AL +0876 B6 00 1107 MOV DH,0 +0878 A0 CA 1B 1108 MOV AL,[CHR] +087B 3C 21 1109 CMP AL,' '+1 +087D 72 03 1110 JC NOT1 +087F 80 CE 01 1111 OR DH,001H +0882 1112 NOT1: +0882 E8 D7 FD 1113 CALL GETLET +0885 72 DF 1114 JC RET +0887 3C 3A 1115 CMP AL,':' +0889 75 05 1116 JNZ LABCHK +088B E8 26 FA 1117 CALL NEXTCHR +088E EB 07 1118 JP LABEL +0890 1119 LABCHK: +0890 0A C0 1120 OR AL,AL +0892 F6 C6 01 1121 TEST DH,001H +0895 74 CF 1122 JZ RET +0897 1123 LABEL: +0897 A0 E5 1B 1124 MOV AL,[CHKLAB] +089A 0A C0 1125 OR AL,AL +089C 74 03 1126 JZ $+5 +089E E9 BB FD 1127 JMP GETLET +08A1 E8 39 FF 1128 CALL LOOKUP +08A4 B1 0B 1129 MOV CL,11 +08A6 75 14 1130 JNZ ERR5 +08A8 8B 16 65 1B 1131 MOV DX,[PC] +08AC C6 07 01 1132 MOV B,[BX],1 +08AF 43 1133 INC BX +08B0 88 17 1134 MOV [BX],DL +08B2 89 1E 69 1B 1135 MOV [LABPT],BX +08B6 43 1136 INC BX +08B7 88 37 1137 MOV [BX],DH +08B9 E9 A0 FD 1138 JMP GETLET +08BC 1139 +08BC E9 F0 F9 1140 ERR5: JMP ERROR +08BF 1141 +08BF 1142 ASMLIN: +08BF 8B 1E 65 1B 1143 MOV BX,[PC] +08C3 89 1E 67 1B 1144 MOV [OLDPC],BX +08C7 E8 9D FF 1145 CALL GETLAB +08CA 73 03 1146 JNC $+5 +08CC E9 80 F9 1147 JMP ENDLN +08CF BB 79 1B 1148 MOV BX,LENID +08D2 8A 07 1149 MOV AL,[BX] +08D4 B1 0C 1150 MOV CL,12 +08D6 2C 02 1151 SUB AL,2 +08D8 8A E8 1152 MOV CH,AL +08DA 72 E0 1153 JC ERR5 +08DC 43 1154 INC BX +08DD 82 3F 66 1155 CMP B,[BX],"f" ;See if an 8087 mnemonic +08E0 74 57 1156 JZ NDPOP +08E2 3C 05 1157 CMP AL,5 +08E4 73 D6 1158 JNC ERR5 +08E6 8A 07 1159 MOV AL,[BX] +08E8 2C 61 1160 SUB AL,'a' +08EA 8A C8 1161 MOV CL,AL +08EC 02 C0 1162 ADD AL,AL +08EE 02 C0 1163 ADD AL,AL +08F0 02 C1 1164 ADD AL,CL +08F2 02 C5 1165 ADD AL,CH +08F4 02 C0 1166 ADD AL,AL +08F6 BB 35 19 1167 MOV BX,OPTAB +08F9 8A D0 1168 MOV DL,AL +08FB B6 00 1169 MOV DH,0 +08FD 03 DA 1170 ADD BX,DX +08FF 8A 17 1171 MOV DL,[BX] +0901 43 1172 INC BX +0902 8A 37 1173 MOV DH,[BX] +0904 87 DA 1174 XCHG DX,BX +0906 FE C5 1175 INC CH +0908 8A CD 1176 MOV CL,CH +090A 8A 07 1177 MOV AL,[BX] +090C 43 1178 INC BX +090D 0A C0 1179 OR AL,AL +090F 74 1E 1180 JZ OPERR +0911 1181 FINDOP: +0911 8A E9 1182 MOV CH,CL +0913 9F 1183 LAHF +0914 95 1184 XCHG AX,BP +0915 9E 1185 SAHF +0916 BA 7B 1B 1186 MOV DX,ID+1 +0919 E8 3B FF 1187 CALL CPSLP +091C 74 16 1188 JZ HAVOP +091E B6 00 1189 MOV DH,0 +0920 8A D5 1190 MOV DL,CH +0922 FE C2 1191 INC DL +0924 FE C2 1192 INC DL +0926 03 DA 1193 ADD BX,DX +0928 9F 1194 LAHF +0929 95 1195 XCHG AX,BP +092A 9E 1196 SAHF +092B FE C8 1197 DEC AL +092D 75 E2 1198 JNZ FINDOP +092F 1199 OPERR: +092F B1 0C 1200 MOV CL,12 +0931 E9 7B F9 1201 JMP ERROR +0934 1202 +0934 1203 HAVOP: +0934 8A 47 02 1204 MOV AL,[BX+2] ;Get opcode +0937 FF 27 1205 JMP [BX] +0939 1206 +0939 1207 NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") +0939 43 1208 INC BX +093A 82 3F 6E 1209 CMP B,[BX],"n" ;"No-wait" form? +093D B4 00 1210 MOV AH,0 +093F 75 05 1211 JNZ SAVNFLG +0941 B4 01 1212 MOV AH,1 +0943 FE C8 1213 DEC AL +0945 43 1214 INC BX ;Skip over the "N" +0946 1215 SAVNFLG: +0946 88 26 EF 1B 1216 MOV [NOWAIT],AH ;0 for wait, 1 for no wait +094A 3C 01 1217 CMP AL,1 +094C 72 E1 1218 JB OPERR ;Not enough char left for valid opcode? +094E 3C 05 1219 CMP AL,5 +0950 77 DD 1220 JA OPERR ;Too many? +0952 98 1221 CBW +0953 92 1222 XCHG AX,DX ;Save length in DX +0954 8B F2 1223 MOV SI,DX +0956 80 08 80 1224 OR B,[SI+BX],80H ;Set high bit of last character +0959 8A 07 1225 MOV AL,[BX] ;Get first char of opcode +095B 43 1226 INC BX +095C 2C 61 1227 SUB AL,"a" +095E 72 28 1228 JB TRY2XM1 ;Go see if opcode starts with "2" +0960 3C 19 1229 CMP AL,"z"-"a" +0962 77 CB 1230 JA OPERR +0964 98 1231 CBW +0965 D1 E0 1232 SHL AX ;Double to index into address table +0967 96 1233 XCHG AX,SI ;Put in index register +0968 8B BC 39 1A 1234 MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +096C 1235 LOOKNDP: +096C 8A 25 1236 MOV AH,[DI] ;Number of opcodes starting with this letter +096E 0A E4 1237 OR AH,AH +0970 74 BD 1238 JZ OPERR ;Any start with this letter? +0972 1239 FNDNDP: +0972 47 1240 INC DI +0973 8B F3 1241 MOV SI,BX ;Pointer to start of opcode +0975 8B CA 1242 MOV CX,DX ;Get length of opcode +0977 F3 1243 REPE +0978 A6 1244 CMPB ;Compare opcode to table entry +0979 74 16 1245 JZ HAVNDP +097B 4F 1246 DEC DI ;Back up in case that was last letter +097C B0 80 1247 MOV AL,80H ;Look for char with high bit set +097E 1248 ENDOP: +097E AE 1249 SCASB +097F 77 FD 1250 JA ENDOP +0981 47 1251 INC DI ;Skip over info about opcode +0982 FE CC 1252 DEC AH +0984 75 EC 1253 JNZ FNDNDP +0986 EB A7 1254 JP OPERR +0988 1255 +0988 1256 TRY2XM1: +0988 3C D1 1257 CMP AL,"2"-"a" +098A 75 A3 1258 JNZ OPERR +098C BF CC 17 1259 MOV DI,XM1 +098F EB DB 1260 JP LOOKNDP +0991 1261 +0991 1262 HAVNDP: +0991 8B F7 1263 MOV SI,DI +0993 82 3E EF 1B 00 1264 CMP B,[NOWAIT],0 +0998 75 05 1265 JNZ NWAIT +099A B0 9B 1266 MOV AL,9BH ;Wait opcode +099C E8 7C 00 1267 CALL PUT +099F 1268 NWAIT: +099F AD 1269 LODW ;Get opcode info +09A0 A8 F8 1270 TEST AL,0F8H ;Any operand bits set? +09A2 74 00 1271 JZ NOOPS ;If no operands, output code +09A4 1272 NOOPS: +09A4 0C D8 1273 OR AL,0D8H ;ESC hook +09A6 E8 72 00 1274 CALL PUT +09A9 8A C4 1275 MOV AL,AH +09AB E9 6D 00 1276 JMP PUT +09AE 1277 +09AE 1278 GRP1: +09AE B9 09 8A 1279 MOV CX,8A09H +09B1 E8 31 F9 1280 CALL MROPS +09B4 B9 C6 00 1281 MOV CX,0C6H +09B7 8A C7 1282 MOV AL,BH +09B9 3C 00 1283 CMP AL,UNDEFID +09BB 75 03 1284 JNZ L0006 +09BD E8 40 00 1285 CALL STIMM +09C0 1286 L0006: +09C0 24 01 1287 AND AL,1 +09C2 74 0A 1288 JZ BYTIMM +09C4 B0 B8 1289 MOV AL,0B8H +09C6 0A C3 1290 OR AL,BL +09C8 E8 50 00 1291 CALL PUT +09CB E9 9A 00 1292 JMP PUTWOR +09CE 1293 +09CE 1294 BYTIMM: +09CE B0 B0 1295 MOV AL,0B0H +09D0 0A C3 1296 OR AL,BL +09D2 E8 46 00 1297 CALL PUT +09D5 E9 97 00 1298 PUTBJ: JMP PUTBYT +09D8 1299 +09D8 1300 IMMED: +09D8 8A C7 1301 MOV AL,BH +09DA 3C 00 1302 CMP AL,UNDEFID +09DC 74 22 1303 JZ STIMM +09DE 8A C3 1304 MOV AL,BL +09E0 0A C0 1305 OR AL,AL +09E2 74 36 1306 JZ RET +09E4 8A C7 1307 MOV AL,BH +09E6 E8 22 00 1308 CALL IMM +09E9 0C C0 1309 OR AL,0C0H +09EB E8 2D 00 1310 CALL PUT +09EE 1311 FINIMM: +09EE 8A C1 1312 MOV AL,CL +09F0 59 1313 POP CX +09F1 D1 DE 1314 RCR SI +09F3 A8 01 1315 TEST AL,001H +09F5 D1 D6 1316 RCL SI +09F7 74 DC 1317 JZ PUTBJ +09F9 3C 83 1318 CMP AL,83H +09FB 74 D8 1319 JZ PUTBJ +09FD E9 68 00 1320 JMP PUTWOR +0A00 1321 +0A00 1322 STIMM: +0A00 A0 6B 1B 1323 MOV AL,[FLAG] +0A03 E8 05 00 1324 CALL IMM +0A06 E8 D6 00 1325 CALL PUTADD +0A09 EB E3 1326 JP FINIMM +0A0B 1327 +0A0B 1328 IMM: +0A0B 24 01 1329 AND AL,1 +0A0D 0A C1 1330 OR AL,CL +0A0F 8A C8 1331 MOV CL,AL +0A11 E8 07 00 1332 CALL PUT +0A14 8A C5 1333 MOV AL,CH +0A16 24 38 1334 AND AL,38H +0A18 0A C3 1335 OR AL,BL +0A1A C3 1336 RET +0A1B 1337 +0A1B 1338 PUT: +0A1B 1339 ;Save byte in AL as pure code, with intermediate code bits 00. AL and +0A1B 1340 ;DI destroyed, no other registers affected. +0A1B 53 1341 PUSH BX +0A1C 51 1342 PUSH CX +0A1D B5 00 1343 MOV CH,0 ;Flag as pure code +0A1F E8 03 00 1344 CALL GEN +0A22 59 1345 POP CX +0A23 5B 1346 POP BX +0A24 C3 1347 RET +0A25 1348 +0A25 1349 GEN: +0A25 1350 ;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. +0A25 E8 32 00 1351 CALL PUTINC ;Save it and bump code pointer +0A28 1352 GEN1: +0A28 8A 0E D4 1B 1353 MOV CL,[RELOC] +0A2C D1 C1 1354 ROL CX +0A2E D1 C1 1355 ROL CX +0A30 88 0E D4 1B 1356 MOV [RELOC],CL +0A34 BB D5 1B 1357 MOV BX,BCOUNT +0A37 FE 0F 1358 DEC B,[BX] +0A39 75 E9 1359 JNZ RET +0A3B C6 07 04 1360 MOV B,[BX],4 +0A3E BB D4 1B 1361 MOV BX,RELOC +0A41 8A 07 1362 MOV AL,[BX] +0A43 C6 07 00 1363 MOV B,[BX],0 +0A46 8B 3E F2 1B 1364 MOV DI,[IY] +0A4A 88 05 1365 MOV [DI],AL +0A4C 8B 1E D1 1B 1366 MOV BX,[CODE] +0A50 89 1E F2 1B 1367 MOV [IY],BX +0A54 43 1368 INC BX +0A55 89 1E D1 1B 1369 MOV [CODE],BX +0A59 C3 1370 RET +0A5A 1371 +0A5A 1372 PUTINC: +0A5A FF 06 65 1B 1373 INC [PC] +0A5E 1374 PUTCD: +0A5E 8B 3E D1 1B 1375 MOV DI,[CODE] +0A62 AA 1376 STOB +0A63 89 3E D1 1B 1377 MOV [CODE],DI +0A67 C3 1378 RET +0A68 1379 +0A68 1380 PUTWOR: +0A68 1381 ;Save the word value described by [DLABEL] and [DATA] as code. If defined, +0A68 1382 ;two bytes of pure code will be produced. Otherwise, appropriate intermediate +0A68 1383 ;code will be generated. +0A68 51 1384 PUSH CX +0A69 B5 80 1385 MOV CH,80H +0A6B 52 1386 PUSH DX +0A6C 53 1387 PUSH BX +0A6D EB 20 1388 JP PUTBW +0A6F 1389 +0A6F 1390 PUTBYT: +0A6F 1391 ;Same as PUTWOR, above, but for byte value. +0A6F 51 1392 PUSH CX +0A70 B5 40 1393 MOV CH,40H +0A72 52 1394 PUSH DX +0A73 53 1395 PUSH BX +0A74 8B 1E 73 1B 1396 MOV BX,[DLABEL] +0A78 8A C7 1397 MOV AL,BH +0A7A 0A C3 1398 OR AL,BL +0A7C 75 11 1399 JNZ PUTBW +0A7E 8B 1E 71 1B 1400 MOV BX,[DATA] +0A82 0A C7 1401 OR AL,BH +0A84 74 09 1402 JZ PUTBW +0A86 FE C7 1403 INC BH +0A88 74 05 1404 JZ PUTBW +0A8A B1 1F 1405 MOV CL,31 +0A8C E9 20 F8 1406 JMP ERROR +0A8F 1407 PUTBW: +0A8F 8B 16 73 1B 1408 MOV DX,[DLABEL] +0A93 8B 1E 71 1B 1409 MOV BX,[DATA] +0A97 1410 PUTCHK: +0A97 8A C6 1411 MOV AL,DH +0A99 0A C2 1412 OR AL,DL +0A9B 74 29 1413 JZ NOUNDEF +0A9D 8A C2 1414 MOV AL,DL +0A9F E8 BC FF 1415 CALL PUTCD +0AA2 8A C6 1416 MOV AL,DH +0AA4 E8 B7 FF 1417 CALL PUTCD +0AA7 8A C3 1418 MOV AL,BL +0AA9 E8 AE FF 1419 CALL PUTINC +0AAC 8A C7 1420 MOV AL,BH +0AAE D1 DE 1421 RCR SI +0AB0 F6 C5 80 1422 TEST CH,080H +0AB3 D1 D6 1423 RCL SI +0AB5 74 05 1424 JZ SMPUT +0AB7 E8 6B FF 1425 CALL GEN +0ABA EB 06 1426 JP PRET +0ABC 1427 SMPUT: +0ABC E8 9F FF 1428 CALL PUTCD +0ABF E8 66 FF 1429 CALL GEN1 +0AC2 1430 PRET: +0AC2 5B 1431 POP BX +0AC3 5A 1432 POP DX +0AC4 59 1433 POP CX +0AC5 C3 1434 RET +0AC6 1435 +0AC6 1436 NOUNDEF: +0AC6 8A C3 1437 MOV AL,BL +0AC8 8A CF 1438 MOV CL,BH +0ACA 51 1439 PUSH CX +0ACB B5 00 1440 MOV CH,0 +0ACD E8 55 FF 1441 CALL GEN +0AD0 59 1442 POP CX +0AD1 8A C1 1443 MOV AL,CL +0AD3 F6 C5 80 1444 TEST CH,080H +0AD6 B5 00 1445 MOV CH,0 +0AD8 74 E8 1446 JZ PRET +0ADA E8 48 FF 1447 CALL GEN +0ADD EB E3 1448 JP PRET +0ADF 1449 +0ADF 1450 PUTADD: +0ADF 1451 ;Save complete addressing mode. Addressing mode is in AL; if this is a register +0ADF 1452 ;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +0ADF 1453 ;the details of the addressing mode will be investigated and the optional one- +0ADF 1454 ;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. +0ADF 51 1455 PUSH CX +0AE0 52 1456 PUSH DX +0AE1 53 1457 PUSH BX +0AE2 B5 00 1458 MOV CH,0 +0AE4 8A C8 1459 MOV CL,AL +0AE6 E8 3C FF 1460 CALL GEN ;Save the addressing mode as pure code +0AE9 8A C1 1461 MOV AL,CL +0AEB B5 80 1462 MOV CH,80H +0AED 24 C7 1463 AND AL,0C7H +0AEF 3C 06 1464 CMP AL,6 +0AF1 74 0A 1465 JZ TWOBT ;Direct address? +0AF3 24 C0 1466 AND AL,0C0H +0AF5 74 CB 1467 JZ PRET ;Indirect through reg, no displacement? +0AF7 3C C0 1468 CMP AL,0C0H +0AF9 74 C7 1469 JZ PRET ;Register to register operation? +0AFB 8A E8 1470 MOV CH,AL ;Save whether one- or two-byte displacement +0AFD 1471 TWOBT: +0AFD 8B 1E 6D 1B 1472 MOV BX,[ADDR] +0B01 8B 16 6F 1B 1473 MOV DX,[ALABEL] +0B05 EB 90 1474 JP PUTCHK +0B07 1475 +0B07 1476 GRP2: +0B07 E8 B7 F8 1477 CALL GETOP +0B0A B9 30 FF 1478 MOV CX,0FF30H +0B0D 3C 00 1479 CMP AL,UNDEFID +0B0F 74 14 1480 JZ PMEM +0B11 B5 50 1481 MOV CH,50H +0B13 3C 03 1482 CMP AL,XREG +0B15 74 1A 1483 JZ PXREG +0B17 B5 06 1484 MOV CH,6 +0B19 3C 04 1485 CMP AL,SREG +0B1B 75 03 1486 JNZ $+5 +0B1D E9 2C 04 1487 JMP PACKREG +0B20 B1 14 1488 MOV CL,20 +0B22 E9 8A F7 1489 JMP ERROR +0B25 1490 +0B25 1491 PMEM: +0B25 8A C5 1492 MOV AL,CH +0B27 E8 F1 FE 1493 CALL PUT +0B2A 8A C1 1494 MOV AL,CL +0B2C 0A C2 1495 OR AL,DL +0B2E E9 AE FF 1496 JMP PUTADD +0B31 1497 +0B31 1498 PXREG: +0B31 8A C5 1499 MOV AL,CH +0B33 0A C2 1500 OR AL,DL +0B35 E9 E3 FE 1501 JMP PUT +0B38 1502 +0B38 1503 GRP3: +0B38 E8 86 F8 1504 CALL GETOP +0B3B 52 1505 PUSH DX +0B3C E8 79 F8 1506 CALL GETOP2 +0B3F 5B 1507 POP BX +0B40 B9 14 86 1508 MOV CX,8614H +0B43 B0 04 1509 MOV AL,SREG +0B45 3A C7 1510 CMP AL,BH +0B47 74 4C 1511 JZ ERR6 +0B49 3A C6 1512 CMP AL,DH +0B4B 74 48 1513 JZ ERR6 +0B4D B0 01 1514 MOV AL,CONST +0B4F 3A C7 1515 CMP AL,BH +0B51 74 42 1516 JZ ERR6 +0B53 3A C6 1517 CMP AL,DH +0B55 74 3E 1518 JZ ERR6 +0B57 B0 00 1519 MOV AL,UNDEFID +0B59 3A C7 1520 CMP AL,BH +0B5B 74 2D 1521 JZ EXMEM +0B5D 3A C6 1522 CMP AL,DH +0B5F 74 2B 1523 JZ EXMEM1 +0B61 8A C7 1524 MOV AL,BH +0B63 3A C6 1525 CMP AL,DH +0B65 B1 16 1526 MOV CL,22 +0B67 75 2C 1527 JNZ ERR6 +0B69 3C 03 1528 CMP AL,XREG +0B6B 74 03 1529 JZ L0008 +0B6D E8 AE F7 1530 CALL RR1 +0B70 1531 L0008: ;RR1 never returns +0B70 8A C3 1532 MOV AL,BL +0B72 0A C0 1533 OR AL,AL +0B74 74 0D 1534 JZ EXACC +0B76 87 DA 1535 XCHG DX,BX +0B78 8A C3 1536 MOV AL,BL +0B7A 0A C0 1537 OR AL,AL +0B7C 8A C7 1538 MOV AL,BH +0B7E 74 03 1539 JZ EXACC +0B80 E8 9B F7 1540 CALL RR1 +0B83 1541 EXACC: +0B83 B0 90 1542 MOV AL,90H +0B85 0A C2 1543 OR AL,DL +0B87 E9 91 FE 1544 JMP PUT +0B8A 1545 +0B8A 1546 EXMEM: +0B8A 87 DA 1547 XCHG DX,BX +0B8C 1548 EXMEM1: +0B8C 3A C7 1549 CMP AL,BH +0B8E 74 05 1550 JZ ERR6 +0B90 B1 01 1551 MOV CL,1 ;Flag word as OK +0B92 E8 03 F8 1552 CALL NOTAC ;NOTAC never returns +0B95 E9 17 F7 1553 ERR6: JMP ERROR +0B98 1554 +0B98 1555 GRP4: +0B98 9F 1556 LAHF +0B99 86 E0 1557 XCHG AH,AL +0B9B 50 1558 PUSH AX +0B9C 86 E0 1559 XCHG AH,AL +0B9E E8 20 F8 1560 CALL GETOP +0BA1 59 1561 POP CX +0BA2 3C 01 1562 CMP AL,CONST +0BA4 74 13 1563 JZ FIXED +0BA6 2C 03 1564 SUB AL,XREG +0BA8 FE CA 1565 DEC DL +0BAA FE CA 1566 DEC DL +0BAC 0A C2 1567 OR AL,DL +0BAE B1 14 1568 MOV CL,20 +0BB0 75 E3 1569 JNZ ERR6 +0BB2 8A C5 1570 MOV AL,CH +0BB4 0C 08 1571 OR AL,8 +0BB6 E9 62 FE 1572 JMP PUT +0BB9 1573 FIXED: +0BB9 8A C5 1574 MOV AL,CH +0BBB E8 5D FE 1575 CALL PUT +0BBE E9 AE FE 1576 JMP PUTBYT +0BC1 1577 +0BC1 1578 GRP5: +0BC1 9F 1579 LAHF +0BC2 86 E0 1580 XCHG AH,AL +0BC4 50 1581 PUSH AX +0BC5 86 E0 1582 XCHG AH,AL +0BC7 E8 F7 F7 1583 CALL GETOP +0BCA 3C 01 1584 CMP AL,CONST +0BCC 75 C7 1585 JNZ ERR6 +0BCE 8B 1E 73 1B 1586 MOV BX,[DLABEL] +0BD2 8A C7 1587 MOV AL,BH +0BD4 0A C3 1588 OR AL,BL +0BD6 B1 1E 1589 MOV CL,30 +0BD8 75 BB 1590 JNZ ERR6 +0BDA 8B 1E 71 1B 1591 MOV BX,[DATA] +0BDE 58 1592 POP AX +0BDF 86 E0 1593 XCHG AH,AL +0BE1 9E 1594 SAHF +0BE2 0A C0 1595 OR AL,AL +0BE4 74 4B 1596 JZ ORG +0BE6 FE C8 1597 DEC AL +0BE8 74 19 1598 JZ DSJ +0BEA FE C8 1599 DEC AL +0BEC 74 2D 1600 JZ EQU +0BEE FE C8 1601 DEC AL +0BF0 74 03 1602 JZ $+5 +0BF2 E9 BA 03 1603 JMP IF +0BF5 1604 PUTOP: +0BF5 B0 FD 1605 MOV AL,-3 +0BF7 EB 3E 1606 JP NEWLOC +0BF9 1607 ALIGN: +0BF9 A0 65 1B 1608 MOV AL,[PC] +0BFC 24 01 1609 AND AL,1 +0BFE 74 30 1610 JZ RET +0C00 BB 01 00 1611 MOV BX,1 +0C03 1612 DSJ: +0C03 87 DA 1613 XCHG DX,BX +0C05 8B 1E 65 1B 1614 MOV BX,[PC] +0C09 9F 1615 LAHF +0C0A 03 DA 1616 ADD BX,DX +0C0C D1 DE 1617 RCR SI +0C0E 9E 1618 SAHF +0C0F D1 D6 1619 RCL SI +0C11 89 1E 65 1B 1620 MOV [PC],BX +0C15 87 DA 1621 XCHG DX,BX +0C17 B0 FC 1622 MOV AL,-4 +0C19 EB 1C 1623 JP NEWLOC +0C1B 1624 EQU: +0C1B 87 DA 1625 XCHG DX,BX +0C1D 8B 1E 69 1B 1626 MOV BX,[LABPT] +0C21 8A C7 1627 MOV AL,BH +0C23 0A C3 1628 OR AL,BL +0C25 B1 22 1629 MOV CL,34 +0C27 74 29 1630 JZ ERR7 +0C29 88 17 1631 MOV [BX],DL +0C2B 9F 1632 LAHF +0C2C 43 1633 INC BX +0C2D 9E 1634 SAHF +0C2E 88 37 1635 MOV [BX],DH +0C30 C3 1636 RET +0C31 1637 ORG: +0C31 89 1E 65 1B 1638 MOV [PC],BX +0C35 B0 FE 1639 MOV AL,-2 +0C37 1640 NEWLOC: +0C37 E8 24 FE 1641 CALL PUTCD +0C3A 8A C3 1642 MOV AL,BL +0C3C E8 1F FE 1643 CALL PUTCD +0C3F 8A C7 1644 MOV AL,BH +0C41 E8 1A FE 1645 CALL PUTCD +0C44 B5 C0 1646 MOV CH,0C0H +0C46 E9 DF FD 1647 JMP GEN1 +0C49 1648 GRP6: +0C49 8A E8 1649 MOV CH,AL +0C4B B1 04 1650 MOV CL,4 +0C4D E8 95 F6 1651 CALL MROPS +0C50 B1 17 1652 MOV CL,23 +0C52 E9 5A F6 1653 ERR7: JMP ERROR +0C55 1654 GRP7: +0C55 8A E8 1655 MOV CH,AL +0C57 B1 01 1656 MOV CL,1 +0C59 E8 89 F6 1657 CALL MROPS +0C5C B1 80 1658 MOV CL,80H +0C5E 8B 16 73 1B 1659 MOV DX,[DLABEL] +0C62 8A C6 1660 MOV AL,DH +0C64 0A C2 1661 OR AL,DL +0C66 75 12 1662 JNZ ACCJ +0C68 87 DA 1663 XCHG DX,BX +0C6A 8B 1E 71 1B 1664 MOV BX,[DATA] +0C6E E8 99 F8 1665 CALL SIGNEXT +0C71 87 DA 1666 XCHG DX,BX +0C73 75 05 1667 JNZ ACCJ +0C75 9F 1668 LAHF +0C76 80 C9 02 1669 OR CL,002H +0C79 9E 1670 SAHF +0C7A E9 C5 00 1671 ACCJ: JMP ACCIMM +0C7D 1672 GRP8: +0C7D 8A C8 1673 MOV CL,AL +0C7F B5 FE 1674 MOV CH,0FEH +0C81 EB 04 1675 JP ONEOP +0C83 1676 GRP9: +0C83 8A C8 1677 MOV CL,AL +0C85 B5 F6 1678 MOV CH,0F6H +0C87 1679 ONEOP: +0C87 51 1680 PUSH CX +0C88 E8 36 F7 1681 CALL GETOP +0C8B 1682 ONE: +0C8B B1 1A 1683 MOV CL,26 +0C8D 3C 01 1684 CMP AL,CONST +0C8F 74 C1 1685 JZ ERR7 +0C91 3C 04 1686 CMP AL,SREG +0C93 B1 16 1687 MOV CL,22 +0C95 74 BB 1688 JZ ERR7 +0C97 59 1689 POP CX +0C98 3C 00 1690 CMP AL,UNDEFID +0C9A 74 16 1691 JZ MOP +0C9C 24 01 1692 AND AL,1 +0C9E 74 25 1693 JZ ROP +0CA0 D1 DE 1694 RCR SI +0CA2 F6 C1 01 1695 TEST CL,001H +0CA5 D1 D6 1696 RCL SI +0CA7 74 1C 1697 JZ ROP +0CA9 8A C1 1698 MOV AL,CL +0CAB 24 F8 1699 AND AL,0F8H +0CAD 0A C2 1700 OR AL,DL +0CAF E9 69 FD 1701 JMP PUT +0CB2 1702 MOP: +0CB2 A0 6B 1B 1703 MOV AL,[FLAG] +0CB5 24 01 1704 AND AL,1 +0CB7 0A C5 1705 OR AL,CH +0CB9 E8 5F FD 1706 CALL PUT +0CBC 8A C1 1707 MOV AL,CL +0CBE 24 38 1708 AND AL,38H +0CC0 0A C2 1709 OR AL,DL +0CC2 E9 1A FE 1710 JMP PUTADD +0CC5 1711 ROP: +0CC5 0A C5 1712 OR AL,CH +0CC7 E8 51 FD 1713 CALL PUT +0CCA 8A C1 1714 MOV AL,CL +0CCC 24 38 1715 AND AL,38H +0CCE 0C C0 1716 OR AL,0C0H +0CD0 0A C2 1717 OR AL,DL +0CD2 E9 46 FD 1718 JMP PUT +0CD5 1719 GRP10: +0CD5 8A C8 1720 MOV CL,AL +0CD7 B5 F6 1721 MOV CH,0F6H +0CD9 51 1722 PUSH CX +0CDA E8 E4 F6 1723 CALL GETOP +0CDD B1 14 1724 MOV CL,20 +0CDF 8A C2 1725 MOV AL,DL +0CE1 0A C0 1726 OR AL,AL +0CE3 75 08 1727 JNZ ERRJ1 +0CE5 8A C6 1728 MOV AL,DH +0CE7 3C 03 1729 CMP AL,XREG +0CE9 74 04 1730 JZ G10 +0CEB 3C 02 1731 CMP AL,REG +0CED 75 77 1732 ERRJ1: JNZ ERR8 +0CEF 1733 G10: +0CEF 9F 1734 LAHF +0CF0 86 E0 1735 XCHG AH,AL +0CF2 50 1736 PUSH AX +0CF3 86 E0 1737 XCHG AH,AL +0CF5 E8 C9 F6 1738 CALL GETOP +0CF8 58 1739 POP AX +0CF9 86 E0 1740 XCHG AH,AL +0CFB 9E 1741 SAHF +0CFC 24 01 1742 AND AL,1 +0CFE A2 6B 1B 1743 MOV [FLAG],AL +0D01 8A C6 1744 MOV AL,DH +0D03 EB 86 1745 ONEJ: JP ONE +0D05 1746 GRP11: +0D05 E8 13 FD 1747 CALL PUT +0D08 B0 0A 1748 MOV AL,0AH +0D0A E9 0E FD 1749 JMP PUT +0D0D 1750 GRP12: +0D0D 8A C8 1751 MOV CL,AL +0D0F B5 D0 1752 MOV CH,0D0H +0D11 51 1753 PUSH CX +0D12 E8 AC F6 1754 CALL GETOP +0D15 A0 CB 1B 1755 MOV AL,[SYM] +0D18 3C 2C 1756 CMP AL,',' +0D1A 8A C6 1757 MOV AL,DH +0D1C 75 E5 1758 JNZ ONEJ +0D1E 52 1759 PUSH DX +0D1F E8 9F F6 1760 CALL GETOP +0D22 2C 02 1761 SUB AL,REG +0D24 B1 14 1762 MOV CL,20 +0D26 FE CA 1763 DEC DL +0D28 0A C2 1764 OR AL,DL +0D2A 75 3A 1765 JNZ ERR8 +0D2C 5A 1766 POP DX +0D2D 8A C6 1767 MOV AL,DH +0D2F 59 1768 POP CX +0D30 9F 1769 LAHF +0D31 80 CD 02 1770 OR CH,002H +0D34 9E 1771 SAHF +0D35 51 1772 PUSH CX +0D36 E9 52 FF 1773 JMP ONE +0D39 1774 GRP13: +0D39 8A E8 1775 MOV CH,AL +0D3B B1 01 1776 MOV CL,1 +0D3D E8 A5 F5 1777 CALL MROPS +0D40 B1 80 1778 MOV CL,80H +0D42 1779 ACCIMM: +0D42 E8 93 FC 1780 CALL IMMED +0D45 80 CD 04 1781 OR CH,004H +0D48 80 E5 FD 1782 AND CH,0FDH +0D4B 1783 AIMM: +0D4B 8A C7 1784 MOV AL,BH +0D4D 24 01 1785 AND AL,1 +0D4F 9F 1786 LAHF +0D50 86 E0 1787 XCHG AH,AL +0D52 50 1788 PUSH AX +0D53 86 E0 1789 XCHG AH,AL +0D55 0A C5 1790 OR AL,CH +0D57 E8 C1 FC 1791 CALL PUT +0D5A 58 1792 POP AX +0D5B 86 E0 1793 XCHG AH,AL +0D5D 9E 1794 SAHF +0D5E 75 03 1795 JNZ $+5 +0D60 E9 0C FD 1796 JMP PUTBYT +0D63 E9 02 FD 1797 JMP PUTWOR +0D66 E9 46 F5 1798 ERR8: JMP ERROR +0D69 1799 GRP14: +0D69 9F 1800 LAHF +0D6A 86 E0 1801 XCHG AH,AL +0D6C 50 1802 PUSH AX +0D6D 86 E0 1803 XCHG AH,AL +0D6F E8 4F F6 1804 CALL GETOP +0D72 3C 01 1805 CMP AL,CONST +0D74 74 31 1806 JZ DIRECT +0D76 B1 14 1807 MOV CL,20 +0D78 3C 02 1808 CMP AL,REG +0D7A 74 EA 1809 JZ ERR8 +0D7C 3C 04 1810 CMP AL,SREG +0D7E 74 E6 1811 JZ ERR8 +0D80 3C 03 1812 CMP AL,XREG +0D82 75 06 1813 JNZ NOTRG +0D84 80 CA 40 1814 OR DL,040H +0D87 80 CA 80 1815 OR DL,080H +0D8A 1816 NOTRG: +0D8A B0 FF 1817 MOV AL,0FFH +0D8C E8 8C FC 1818 CALL PUT +0D8F 58 1819 POP AX +0D90 86 E0 1820 XCHG AH,AL +0D92 9E 1821 SAHF +0D93 24 38 1822 AND AL,38H +0D95 0A C2 1823 OR AL,DL +0D97 8A E8 1824 MOV CH,AL +0D99 A0 6C 1B 1825 MOV AL,[LONG] +0D9C 0A C0 1826 OR AL,AL +0D9E 8A C5 1827 MOV AL,CH +0DA0 74 02 1828 JZ PUTADDJ +0DA2 24 F7 1829 AND AL,0F7H +0DA4 1830 PUTADDJ: +0DA4 E9 38 FD 1831 JMP PUTADD +0DA7 1832 DIRECT: +0DA7 A0 CB 1B 1833 MOV AL,[SYM] +0DAA 3C 2C 1834 CMP AL,',' +0DAC 74 22 1835 JZ LONGJ +0DAE 58 1836 POP AX +0DAF 86 E0 1837 XCHG AH,AL +0DB1 9E 1838 SAHF +0DB2 FE C8 1839 DEC AL +0DB4 3C E9 1840 CMP AL,0E9H +0DB6 74 02 1841 JZ GOTOP +0DB8 B0 E8 1842 MOV AL,0E8H +0DBA 1843 GOTOP: +0DBA E8 5E FC 1844 CALL PUT +0DBD 8B 1E 71 1B 1845 MOV BX,[DATA] +0DC1 8B 16 65 1B 1846 MOV DX,[PC] +0DC5 42 1847 INC DX +0DC6 42 1848 INC DX +0DC7 2B DA 1849 SUB BX,DX +0DC9 89 1E 71 1B 1850 MOV [DATA],BX +0DCD E9 98 FC 1851 JMP PUTWOR +0DD0 1852 LONGJ: +0DD0 58 1853 POP AX +0DD1 86 E0 1854 XCHG AH,AL +0DD3 9E 1855 SAHF +0DD4 E8 44 FC 1856 CALL PUT +0DD7 E8 8E FC 1857 CALL PUTWOR +0DDA E8 E4 F5 1858 CALL GETOP +0DDD B1 14 1859 MOV CL,20 +0DDF 3C 01 1860 CMP AL,CONST +0DE1 75 83 1861 JNZ ERR8 +0DE3 E9 82 FC 1862 JMP PUTWOR +0DE6 1863 GRP16: +0DE6 9F 1864 LAHF +0DE7 86 E0 1865 XCHG AH,AL +0DE9 50 1866 PUSH AX +0DEA 86 E0 1867 XCHG AH,AL +0DEC E8 B8 F7 1868 CALL GETSYM +0DEF 3C 05 1869 CMP AL,5 +0DF1 74 1C 1870 JZ LONGR +0DF3 3C 0D 1871 CMP AL,EOL +0DF5 74 3F 1872 JZ NODEC +0DF7 3C 3B 1873 CMP AL,';' +0DF9 74 3B 1874 JZ NODEC +0DFB 1875 GETSP: +0DFB E8 C6 F5 1876 CALL GETOP1 +0DFE 59 1877 POP CX +0DFF 3C 01 1878 CMP AL,CONST +0E01 B1 14 1879 MOV CL,20 +0E03 75 6A 1880 JNZ ERR9 +0E05 8A C5 1881 MOV AL,CH +0E07 24 FE 1882 AND AL,0FEH +0E09 E8 0F FC 1883 CALL PUT +0E0C E9 59 FC 1884 JMP PUTWOR +0E0F 1885 LONGR: +0E0F A0 6C 1B 1886 MOV AL,[LONG] +0E12 0A C0 1887 OR AL,AL +0E14 75 0C 1888 JNZ NOTLON +0E16 58 1889 POP AX +0E17 86 E0 1890 XCHG AH,AL +0E19 9E 1891 SAHF +0E1A 0C 08 1892 OR AL,8 +0E1C 9F 1893 LAHF +0E1D 86 E0 1894 XCHG AH,AL +0E1F 50 1895 PUSH AX +0E20 86 E0 1896 XCHG AH,AL +0E22 1897 NOTLON: +0E22 E8 82 F7 1898 CALL GETSYM +0E25 3C 0D 1899 CMP AL,EOL +0E27 74 35 1900 JZ DORET +0E29 3C 3B 1901 CMP AL,';' +0E2B 74 31 1902 JZ DORET +0E2D 3C 2C 1903 CMP AL,',' +0E2F 75 03 1904 JNZ L0011 +0E31 E8 73 F7 1905 CALL GETSYM +0E34 1906 L0011: +0E34 EB C5 1907 JP GETSP +0E36 1908 NODEC: +0E36 8B 1E 65 1B 1909 MOV BX,[PC] +0E3A 89 1E E8 1B 1910 MOV [LSTRET],BX +0E3E 87 DA 1911 XCHG DX,BX +0E40 8B 1E EA 1B 1912 MOV BX,[RETPT] +0E44 8A C7 1913 MOV AL,BH +0E46 0A C3 1914 OR AL,BL +0E48 74 14 1915 JZ DORET +0E4A C6 07 01 1916 MOV B,[BX],1 +0E4D 9F 1917 LAHF +0E4E 43 1918 INC BX +0E4F 9E 1919 SAHF +0E50 88 17 1920 MOV [BX],DL +0E52 9F 1921 LAHF +0E53 43 1922 INC BX +0E54 9E 1923 SAHF +0E55 88 37 1924 MOV [BX],DH +0E57 BB 00 00 1925 MOV BX,0 +0E5A 89 1E EA 1B 1926 MOV [RETPT],BX +0E5E 1927 DORET: +0E5E 58 1928 POP AX +0E5F 86 E0 1929 XCHG AH,AL +0E61 9E 1930 SAHF +0E62 E9 B6 FB 1931 JMP PUT +0E65 1932 GRP17: +0E65 E8 B3 FB 1933 CALL PUT +0E68 E8 56 F5 1934 CALL GETOP +0E6B 3C 01 1935 CMP AL,CONST +0E6D B1 14 1936 MOV CL,20 +0E6F 75 29 1937 ERR9: JNZ ERR10 +0E71 8B 1E 71 1B 1938 MOV BX,[DATA] +0E75 8B 16 65 1B 1939 MOV DX,[PC] +0E79 9F 1940 LAHF +0E7A 42 1941 INC DX +0E7B 9E 1942 SAHF +0E7C 1B DA 1943 SBB BX,DX +0E7E 89 1E 71 1B 1944 MOV [DATA],BX +0E82 E8 EA FB 1945 CALL PUTBYT +0E85 8B 1E 73 1B 1946 MOV BX,[DLABEL] +0E89 8A C7 1947 MOV AL,BH +0E8B 0A C3 1948 OR AL,BL +0E8D 75 0E 1949 JNZ RET +0E8F 8B 1E 71 1B 1950 MOV BX,[DATA] +0E93 E8 74 F6 1951 CALL SIGNEXT +0E96 74 05 1952 JZ RET +0E98 B1 1F 1953 MOV CL,31 +0E9A E9 12 F4 1954 ERR10: JMP ERROR +0E9D C3 1955 RET +0E9E 1956 GRP18: +0E9E E8 20 F5 1957 CALL GETOP +0EA1 3C 01 1958 CMP AL,CONST +0EA3 B1 14 1959 MOV CL,20 +0EA5 75 F3 1960 JNZ ERR10 +0EA7 8B 1E 73 1B 1961 MOV BX,[DLABEL] +0EAB 8A C7 1962 MOV AL,BH +0EAD 0A C3 1963 OR AL,BL +0EAF 75 10 1964 JNZ GENINT +0EB1 8B 1E 71 1B 1965 MOV BX,[DATA] +0EB5 BA 03 00 1966 MOV DX,3 +0EB8 1B DA 1967 SBB BX,DX +0EBA 75 05 1968 JNZ GENINT +0EBC B0 CC 1969 MOV AL,0CCH +0EBE E9 5A FB 1970 JMP PUT +0EC1 1971 GENINT: +0EC1 B0 CD 1972 MOV AL,0CDH +0EC3 E8 55 FB 1973 CALL PUT +0EC6 E9 A6 FB 1974 JMP PUTBYT +0EC9 1975 +0EC9 1976 GRP19: ;ESC opcode +0EC9 E8 F5 F4 1977 CALL GETOP +0ECC B1 14 1978 MOV CL,20 +0ECE 3C 01 1979 CMP AL,CONST +0ED0 75 39 1980 JNZ ERRJ ;First operand must be immediate +0ED2 B1 1E 1981 MOV CL,1EH +0ED4 F7 06 73 1B FF FF 1982 TEST [DLABEL],-1 ;See if all labels have been defined +0EDA 75 2F 1983 JNZ ERRJ +0EDC A1 71 1B 1984 MOV AX,[DATA] +0EDF 3D 40 00 1985 CMP AX,64 ;Must only be 6 bits +0EE2 B1 1F 1986 MOV CL,1FH +0EE4 73 25 1987 JNB ERRJ +0EE6 8A D8 1988 MOV BL,AL ;Save for second byte +0EE8 D0 E8 1989 SHR AL +0EEA D0 E8 1990 SHR AL +0EEC D0 E8 1991 SHR AL +0EEE 0C D8 1992 OR AL,0D8H ;ESC opcode +0EF0 E8 28 FB 1993 CALL PUT +0EF3 53 1994 PUSH BX +0EF4 E8 C1 F4 1995 CALL GETOP2 +0EF7 5B 1996 POP BX +0EF8 80 E3 07 1997 AND BL,7 ;Low 3 bits of first operand +0EFB D0 E3 1998 SHL BL +0EFD D0 E3 1999 SHL BL +0EFF D0 E3 2000 SHL BL +0F01 3C 00 2001 CMP AL,UNDEFID ;Check for memory operand +0F03 74 09 2002 JZ ESCMEM +0F05 3C 01 2003 CMP AL,CONST ;Check for another immediate +0F07 74 0C 2004 JZ ESCIMM +0F09 B1 14 2005 MOV CL,20 +0F0B E9 A1 F3 2006 ERRJ: JMP ERROR +0F0E 2007 +0F0E 2008 ESCMEM: +0F0E 0A DA 2009 OR BL,DL ;Combine mode with first operand +0F10 8A C3 2010 MOV AL,BL +0F12 E9 CA FB 2011 JMP PUTADD +0F15 2012 +0F15 2013 ESCIMM: +0F15 B1 1E 2014 MOV CL,1EH +0F17 F7 06 73 1B FF FF 2015 TEST [DLABEL],-1 ;See if second operand is fully defined +0F1D 75 EC 2016 JNZ ERRJ +0F1F A1 71 1B 2017 MOV AX,[DATA] +0F22 B1 1F 2018 MOV CL,1FH +0F24 3D 08 00 2019 CMP AX,8 ;Must only be 3 bit value +0F27 73 E2 2020 JNB ERRJ +0F29 0A C3 2021 OR AL,BL ;Combine first and second operands +0F2B 0C C0 2022 OR AL,0C0H ;Force "register" mode +0F2D E9 EB FA 2023 JMP PUT +0F30 2024 +0F30 2025 GRP20: +0F30 8A E8 2026 MOV CH,AL +0F32 B1 01 2027 MOV CL,1 +0F34 E8 AE F3 2028 CALL MROPS +0F37 B1 F6 2029 MOV CL,0F6H +0F39 E8 9C FA 2030 CALL IMMED +0F3C B5 A8 2031 MOV CH,0A8H +0F3E E9 0A FE 2032 JMP AIMM +0F41 2033 GRP21: +0F41 E8 7D F4 2034 CALL GETOP +0F44 3C 04 2035 CMP AL,SREG +0F46 B1 1C 2036 MOV CL,28 +0F48 75 C1 2037 JNZ ERRJ +0F4A B5 26 2038 MOV CH,26H +0F4C 2039 PACKREG: +0F4C 8A C2 2040 MOV AL,DL +0F4E 02 C0 2041 ADD AL,AL +0F50 02 C0 2042 ADD AL,AL +0F52 02 C0 2043 ADD AL,AL +0F54 0A C5 2044 OR AL,CH +0F56 E9 C2 FA 2045 JMP PUT +0F59 2046 GRP22: +0F59 E8 65 F4 2047 CALL GETOP +0F5C B9 00 8F 2048 MOV CX,8F00H +0F5F 3C 00 2049 CMP AL,UNDEFID +0F61 75 03 2050 JNZ $+5 +0F63 E9 BF FB 2051 JMP PMEM +0F66 B5 58 2052 MOV CH,58H +0F68 3C 03 2053 CMP AL,XREG +0F6A 75 03 2054 JNZ $+5 +0F6C E9 C2 FB 2055 JMP PXREG +0F6F B5 07 2056 MOV CH,7 +0F71 3C 04 2057 CMP AL,SREG +0F73 74 D7 2058 JZ PACKREG +0F75 B1 14 2059 MOV CL,20 +0F77 E9 35 F3 2060 ERR11: JMP ERROR +0F7A 2061 GRP23: +0F7A A2 D3 1B 2062 MOV [DATSIZ],AL +0F7D 2063 GETDAT: +0F7D E8 27 F6 2064 CALL GETSYM +0F80 B0 02 2065 MOV AL,2 +0F82 E8 55 F4 2066 CALL VAL1 +0F85 A0 CB 1B 2067 MOV AL,[SYM] +0F88 3C 2C 2068 CMP AL,',' +0F8A A0 D3 1B 2069 MOV AL,[DATSIZ] +0F8D 75 05 2070 JNZ ENDDAT +0F8F E8 13 00 2071 CALL SAVDAT +0F92 EB E9 2072 JP GETDAT +0F94 2073 ENDDAT: +0F94 3C 02 2074 CMP AL,2 +0F96 75 0D 2075 JNZ SAVDAT +0F98 8B 1E 71 1B 2076 MOV BX,[DATA] +0F9C 9F 2077 LAHF +0F9D 80 CB 80 2078 OR BL,080H +0FA0 9E 2079 SAHF +0FA1 89 1E 71 1B 2080 MOV [DATA],BX +0FA5 2081 SAVDAT: +0FA5 0A C0 2082 OR AL,AL +0FA7 74 03 2083 JZ $+5 +0FA9 E9 C3 FA 2084 JMP PUTBYT +0FAC E9 B9 FA 2085 JMP PUTWOR +0FAF 2086 IF: +0FAF 0B DB 2087 OR BX,BX +0FB1 74 05 2088 JZ SKIPCD +0FB3 FE 06 E4 1B 2089 INC B,[IFFLG] +0FB7 C3 2090 RET +0FB8 2091 +0FB8 2092 SKIPCD: +0FB8 FE 06 E5 1B 2093 INC B,[CHKLAB] +0FBC 2094 SKIPLP: +0FBC 32 C0 2095 XOR AL,AL +0FBE E8 98 F2 2096 CALL NEXLIN +0FC1 E8 F0 F2 2097 CALL NEXTCHR +0FC4 3C 1A 2098 CMP AL,1AH +0FC6 74 40 2099 JZ END +0FC8 E8 9C F8 2100 CALL GETLAB +0FCB 72 EF 2101 JC SKIPLP +0FCD BF 79 1B 2102 MOV DI,LENID +0FD0 BE 0F 1B 2103 MOV SI,IFEND +0FD3 B5 00 2104 MOV CH,0 +0FD5 8A 0D 2105 MOV CL,[DI] +0FD7 FE C1 2106 INC CL +0FD9 F3 2107 REPE +0FDA A6 2108 CMPB +0FDB 74 14 2109 JZ ENDCOND +0FDD BF 79 1B 2110 MOV DI,LENID +0FE0 BE 15 1B 2111 MOV SI,IFNEST +0FE3 8A 0D 2112 MOV CL,[DI] +0FE5 FE C1 2113 INC CL +0FE7 F3 2114 REPE +0FE8 A6 2115 CMPB +0FE9 75 D1 2116 JNZ SKIPLP +0FEB FE 06 E5 1B 2117 INC B,[CHKLAB] +0FEF EB CB 2118 JP SKIPLP +0FF1 2119 +0FF1 2120 ENDCOND: +0FF1 FE 0E E5 1B 2121 DEC B,[CHKLAB] +0FF5 75 C5 2122 JNZ SKIPLP +0FF7 C3 2123 RET +0FF8 2124 +0FF8 2125 ENDIF: +0FF8 A0 E4 1B 2126 MOV AL,[IFFLG] +0FFB B1 24 2127 MOV CL,36 +0FFD FE C8 2128 DEC AL +0FFF 78 04 2129 JS ERRJMP +1001 A2 E4 1B 2130 MOV [IFFLG],AL +1004 C3 2131 RET +1005 2132 +1005 E9 A7 F2 2133 ERRJMP: JMP ERROR +1008 2134 +1008 2135 ;********************************************************************* +1008 2136 ; +1008 2137 ; PASS 2 +1008 2138 ; +1008 2139 ;********************************************************************* +1008 2140 +1008 2141 END: +1008 B2 04 2142 MOV DL,4 +100A 2143 WREND: +100A B5 FF 2144 MOV CH,0FFH +100C 8A C5 2145 MOV AL,CH +100E E8 14 FA 2146 CALL GEN +1011 FE CA 2147 DEC DL +1013 75 F5 2148 JNZ WREND +1015 C7 06 3E 20 40 20 2149 MOV [BUFPT],SRCBUF +101B C6 06 E0 1B FB 2150 MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY +1020 C7 06 F6 1B 3E 1C 2151 MOV [LSTPNT],LSTBUF +1026 C7 06 F4 1B F8 1B 2152 MOV [HEXPNT],HEXBUF +102C 33 C0 2153 XOR AX,AX +102E A3 E6 1B 2154 MOV [ERRCNT],AX +1031 A3 65 1B 2155 MOV [PC],AX +1034 A3 D8 1B 2156 MOV [LINE],AX ;Current line number +1037 C7 06 DC 1B 00 01 2157 MOV [HEXADD],OBJECT +103D BA 5C 00 2158 MOV DX,FCB +1040 B4 0F 2159 MOV AH,OPEN +1042 CD 21 2160 INT 33 ;Re-open source file +1044 32 C0 2161 XOR AL,AL +1046 A2 7C 00 2162 MOV [FCB+20H],AL +1049 C7 06 6A 00 00 04 2163 MOV [FCB+14],BUFSIZ +104F A2 D6 1B 2164 MOV [COUNT],AL +1052 B5 01 2165 MOV CH,1 +1054 BE 90 24 2166 MOV SI,START +1057 2167 FIXLINE: +1057 BF 90 24 2168 MOV DI,START ;Store code over used up intermediate code +105A 32 C0 2169 XOR AL,AL +105C A2 EE 1B 2170 MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) +105F A2 D7 1B 2171 MOV [ERR],AL ;No second pass errors yet +1062 2172 NEXBT: +1062 D0 E1 2173 SHL CL ;Shift out last bit of previous code +1064 FE CD 2174 DEC CH ;Still have codes left? +1066 75 05 2175 JNZ TESTTYP +1068 AC 2176 LODB ;Get next flag byte +1069 8A C8 2177 MOV CL,AL +106B B5 04 2178 MOV CH,4 +106D 2179 TESTTYP: +106D D0 E1 2180 SHL CL ;Set flags based on two bits +106F 70 06 2181 JO FIXUP +1071 AC 2182 LODB +1072 72 4E 2183 JC EMARK +1074 2184 OBJBT: +1074 AA 2185 STOB +1075 EB EB 2186 JP NEXBT +1077 2187 +1077 2188 FIXUP: +1077 2189 ;Either a word or byte fixup is needed from a forward reference +1077 AD 2190 LODW ;Get pointer to symbol +1078 93 2191 XCHG AX,BX +1079 AD 2192 LODW ;Get constant part +107A 03 47 01 2193 ADD AX,[BX+1] ;Add symbol value to constant part +107D 82 3F 00 2194 CMP B,[BX],0 ;See if symbol got defined +1080 75 07 2195 JNZ HAVDEF +1082 C6 06 D7 1B 64 2196 MOV B,[ERR],100 ;Undefined - flag error +1087 33 C0 2197 XOR AX,AX +1089 2198 HAVDEF: +1089 0A C9 2199 OR CL,CL ;See if word or byte fixup +108B 78 03 2200 JS DEFBYT +108D AB 2201 STOW +108E EB D2 2202 JP NEXBT +1090 2203 +1090 2204 DEFBYT: +1090 8B D0 2205 MOV DX,AX +1092 98 2206 CBW ;Extend sign +1093 3B C2 2207 CMP AX,DX ;See if in range +127 to -128 +1095 74 DD 2208 JZ OBJBT ;If so, it's always OK +1097 F6 D4 2209 NOT AH ;Check for range +255 to -256 +1099 3A E6 2210 CMP AH,DH +109B 75 1B 2211 JNZ RNGERR ;Must always be in this range +109D 2212 ;Check for short jump. If so, we're out of range; otherwise we're OK +109D 81 FF 91 24 2213 CMP DI,START+1 ;Only one other byte on line? +10A1 75 D1 2214 JNZ OBJBT ;Can't be short jump if not +10A3 A0 90 24 2215 MOV AL,[START] ;Get the first byte of this line +10A6 3C EB 2216 CMP AL,0EBH ;Direct short jump? +10A8 74 0E 2217 JZ RNGERR +10AA 24 FC 2218 AND AL,0FCH +10AC 3C E0 2219 CMP AL,0E0H ;LOOP or JCXZ instruction? +10AE 74 08 2220 JZ RNGERR +10B0 24 F0 2221 AND AL,0F0H +10B2 3C 70 2222 CMP AL,70H ;Conditional jump? +10B4 8A C2 2223 MOV AL,DL ;Get code byte in AL +10B6 75 BC 2224 JNZ OBJBT ;If not, we're OK +10B8 2225 RNGERR: +10B8 C6 06 D7 1B 65 2226 MOV B,[ERR],101 ;Value out of range +10BD EB B5 2227 JP OBJBT +10BF 2228 +10BF E9 7A 01 2229 FINIJ: JMP FINI +10C2 2230 +10C2 2231 EMARK: +10C2 3C FF 2232 CMP AL,-1 ;End of file? +10C4 74 F9 2233 JZ FINIJ +10C6 3C F6 2234 CMP AL,-10 ;Special item? +10C8 77 5C 2235 JA SPEND +10CA 51 2236 PUSH CX +10CB 56 2237 PUSH SI +10CC 50 2238 PUSH AX ;Save error code +10CD 8A 26 EC 1B 2239 MOV AH,[LSTDEV] +10D1 80 E4 FE 2240 AND AH,0FEH ;Reset error indicator +10D4 0A 06 D7 1B 2241 OR AL,[ERR] ;See if any errors on this line +10D8 74 03 2242 JZ NOERR +10DA 80 CC 01 2243 OR AH,1 ;Send line to console if error occured +10DD 2244 NOERR: +10DD 88 26 EC 1B 2245 MOV [LSTDEV],AH +10E1 8B CF 2246 MOV CX,DI +10E3 E8 EE 00 2247 CALL STRTLIN ;Print address of line +10E6 BE 90 24 2248 MOV SI,START +10E9 2B CE 2249 SUB CX,SI ;Get count of bytes of code +10EB 74 06 2250 JZ SHOLIN +10ED 2251 CODLP: +10ED AC 2252 LODB +10EE E8 33 02 2253 CALL SAVCD ;Ouput code to HEX and PRN files +10F1 E2 FA 2254 LOOP CODLP +10F3 2255 SHOLIN: +10F3 B0 00 2256 MOV AL,0 +10F5 86 06 D6 1B 2257 XCHG AL,[COUNT] +10F9 B9 07 00 2258 MOV CX,7 ;Allow 7 bytes of code per line +10FC 2A C8 2259 SUB CL,AL +10FE B0 20 2260 MOV AL,' ' +1100 74 0B 2261 JZ NOFIL +1102 2262 BLNK: ;Put in 3 blanks for each byte not present +1102 E8 E4 00 2263 CALL LIST +1105 E8 E1 00 2264 CALL LIST +1108 E8 DE 00 2265 CALL LIST +110B E2 F5 2266 LOOP BLNK +110D 2267 NOFIL: +110D E8 45 00 2268 CALL OUTLIN +1110 58 2269 POP AX ;Restore error code +1111 E8 46 02 2270 CALL REPERR +1114 A0 D7 1B 2271 MOV AL,[ERR] +1117 E8 40 02 2272 CALL REPERR +111A 5E 2273 POP SI +111B 59 2274 POP CX +111C A0 EE 1B 2275 MOV AL,[SPC] ;Any special funtion? +111F 0A C0 2276 OR AL,AL +1121 75 0D 2277 JNZ SPCFUN +1123 E9 31 FF 2278 JMP FIXLINE +1126 2279 +1126 2280 SPEND: +1126 A2 EE 1B 2281 MOV [SPC],AL ;Record special function +1129 AD 2282 LODW ;Get it's data +112A A3 71 1B 2283 MOV [DATA],AX +112D E9 32 FF 2284 JMP NEXBT +1130 2285 +1130 2286 SPCFUN: +1130 8B 16 71 1B 2287 MOV DX,[DATA] +1134 3C FE 2288 CMP AL,-2 +1136 74 0F 2289 JZ DORG +1138 3C FD 2290 CMP AL,-3 +113A 74 12 2291 JZ DPUT +113C 2292 DDS: +113C 2293 ;Handle DS pseudo-op +113C 01 16 65 1B 2294 ADD [PC],DX +1140 01 16 DC 1B 2295 ADD [HEXADD],DX +1144 E9 10 FF 2296 JMP FIXLINE +1147 2297 +1147 2298 DORG: +1147 2299 ;Handle ORG pseudo-op +1147 89 16 65 1B 2300 MOV [PC],DX +114B E9 09 FF 2301 JMP FIXLINE +114E 2302 +114E 2303 DPUT: +114E 2304 ;Handle PUT pseudo-op +114E 89 16 DC 1B 2305 MOV [HEXADD],DX +1152 E9 02 FF 2306 JMP FIXLINE +1155 2307 +1155 2308 OUTLIN: +1155 2309 ;Copy the source line to the ouput device. Line will be preceded by +1155 2310 ;assembler-generated line number. This routine may be called several times +1155 2311 ;on one line (once for each line of object code bytes), so it sets a flag +1155 2312 ;so the line will only be output on the first call. +1155 B0 FF 2313 MOV AL,-1 +1157 86 06 E2 1B 2314 XCHG AL,[LINFLG] +115B 0A C0 2315 OR AL,AL +115D 75 33 2316 JNZ CRLF ;Output line only if first time +115F A1 D8 1B 2317 MOV AX,[LINE] +1162 40 2318 INC AX +1163 A3 D8 1B 2319 MOV [LINE],AX +1166 B7 00 2320 MOV BH,0 ;No leading zero suppression +1168 E8 30 00 2321 CALL OUT10 +116B B0 20 2322 MOV AL," " +116D E8 79 00 2323 CALL LIST +1170 A0 40 1B 2324 MOV AL,[LSTFCB] +1173 3C 5A 2325 CMP AL,'Z' +1175 74 1B 2326 JZ CRLF ;Don't call NEXTCHR if listing suppressed +1177 56 2327 PUSH SI ;Save the only register destroyed by NEXTCHR +1178 2328 OUTLN: +1178 E8 39 F1 2329 CALL NEXTCHR +117B E8 6B 00 2330 CALL LIST +117E 3C 0A 2331 CMP AL,10 ;Output until linefeed found +1180 75 F6 2332 JNZ OUTLN +1182 5E 2333 POP SI +1183 C3 2334 RET +1184 2335 +1184 2336 PRTCNT: +1184 BB E7 1A 2337 MOV BX,ERCNTM +1187 E8 E6 01 2338 CALL PRINT +118A A1 E6 1B 2339 MOV AX,[ERRCNT] +118D B7 10 2340 MOV BH,"0"-" " ;Enable leading zero suppression +118F E8 09 00 2341 CALL OUT10 +1192 2342 CRLF: +1192 B0 0D 2343 MOV AL,13 +1194 E8 52 00 2344 CALL LIST +1197 B0 0A 2345 MOV AL,10 +1199 EB 4E 2346 JP LIST +119B 2347 +119B 2348 OUT10: +119B 33 D2 2349 XOR DX,DX +119D BF 10 27 2350 MOV DI,10000 +11A0 F7 F7 2351 DIV AX,DI +11A2 0A C0 2352 OR AL,AL ;>10,000? +11A4 75 02 2353 JNZ LEAD +11A6 2C 10 2354 SUB AL,"0"-" " ;Convert leading zero to blank +11A8 2355 LEAD: +11A8 04 30 2356 ADD AL,"0" +11AA E8 3C 00 2357 CALL LIST +11AD 92 2358 XCHG AX,DX +11AE B3 64 2359 MOV BL,100 +11B0 F6 F3 2360 DIV AL,BL +11B2 8A DC 2361 MOV BL,AH +11B4 E8 0C 00 2362 CALL HIDIG ;Convert to decimal and print 1000s digit +11B7 E8 0E 00 2363 CALL DIGIT ;Print 100s digit +11BA 8A C3 2364 MOV AL,BL +11BC E8 04 00 2365 CALL HIDIG ;Convert to decimal and print 10s digit +11BF B7 00 2366 MOV BH,0 ;Ensure leading zero suppression is off +11C1 EB 05 2367 JP DIGIT +11C3 2368 +11C3 2369 HIDIG: +11C3 D4 0A 2370 AAM ;Convert binary to unpacked BCD +11C5 0D 30 30 2371 OR AX,3030H ;Add "0" bias +11C8 2372 DIGIT: +11C8 86 C4 2373 XCHG AL,AH +11CA 3C 30 2374 CMP AL,"0" +11CC 74 02 2375 JZ SUPZ +11CE B7 00 2376 MOV BH,0 ;Turn off zero suppression if not zero +11D0 2377 SUPZ: +11D0 2A C7 2378 SUB AL,BH ;Convert leading zeros to blanks +11D2 EB 15 2379 JP LIST +11D4 2380 +11D4 2381 STRTLIN: +11D4 C6 06 E2 1B 00 2382 MOV B,[LINFLG],0 +11D9 8B 1E 65 1B 2383 MOV BX,[PC] +11DD 8A C7 2384 MOV AL,BH +11DF E8 4D 00 2385 CALL PHEX +11E2 8A C3 2386 MOV AL,BL +11E4 2387 PHEXB: +11E4 E8 48 00 2388 CALL PHEX +11E7 B0 20 2389 MOV AL,' ' +11E9 2390 LIST: +11E9 50 2391 PUSH AX +11EA 52 2392 PUSH DX +11EB 24 7F 2393 AND AL,7FH +11ED 8A D0 2394 MOV DL,AL +11EF F6 06 EC 1B 03 2395 TEST B,[LSTDEV],3 ;See if output goes to console +11F4 74 04 2396 JZ PRNCHK +11F6 B4 02 2397 MOV AH,2 +11F8 CD 21 2398 INT 33 ;Output to console +11FA 2399 PRNCHK: +11FA F6 06 EC 1B 04 2400 TEST B,[LSTDEV],4 ;See if output goes to printer +11FF 74 04 2401 JZ FILCHK +1201 B4 04 2402 MOV AH,4 +1203 CD 21 2403 INT 33 ;Output to printer +1205 2404 FILCHK: +1205 8A C2 2405 MOV AL,DL +1207 5A 2406 POP DX +1208 F6 06 EC 1B 80 2407 TEST B,[LSTDEV],80H ;See if output goes to a file +120D 74 03 2408 JZ LISTRET +120F E8 02 00 2409 CALL WRTBUF +1212 2410 LISTRET: +1212 58 2411 POP AX +1213 C3 2412 RET +1214 2413 +1214 2414 WRTBUF: +1214 57 2415 PUSH DI +1215 8B 3E F6 1B 2416 MOV DI,[LSTPNT] +1219 AA 2417 STOB +121A 81 FF 3E 20 2418 CMP DI,LSTBUF+LSTBUFSIZ +121E 75 09 2419 JNZ SAVPT +1220 50 2420 PUSH AX +1221 51 2421 PUSH CX +1222 52 2422 PUSH DX +1223 E8 22 02 2423 CALL FLUSHBUF +1226 5A 2424 POP DX +1227 59 2425 POP CX +1228 58 2426 POP AX +1229 2427 SAVPT: +1229 89 3E F6 1B 2428 MOV [LSTPNT],DI +122D 5F 2429 POP DI +122E C3 2430 RET +122F 2431 +122F 2432 PHEX: +122F 50 2433 PUSH AX +1230 E8 37 02 2434 CALL UHALF +1233 E8 B3 FF 2435 CALL LIST +1236 58 2436 POP AX +1237 E8 38 02 2437 CALL LHALF +123A EB AD 2438 JP LIST +123C 2439 +123C 2440 FINI: +123C 80 0E EC 1B 01 2441 OR B,[LSTDEV],1 +1241 E8 40 FF 2442 CALL PRTCNT +1244 80 26 EC 1B FE 2443 AND B,[LSTDEV],0FEH +1249 A0 1B 1B 2444 MOV AL,[HEXFCB] +124C 3C 5A 2445 CMP AL,'Z' +124E 74 3B 2446 JZ SYMDMP +1250 A0 E0 1B 2447 MOV AL,[HEXCNT] +1253 3C FB 2448 CMP AL,-5 +1255 74 03 2449 JZ L0012 +1257 E8 A0 01 2450 CALL ENHEXL +125A 2451 L0012: +125A B0 3A 2452 MOV AL,':' +125C E8 DF 01 2453 CALL PUTCHR +125F B5 0A 2454 MOV CH,10 +1261 2455 HEXEND: +1261 51 2456 PUSH CX +1262 B0 30 2457 MOV AL,'0' +1264 E8 D7 01 2458 CALL PUTCHR +1267 59 2459 POP CX +1268 FE CD 2460 DEC CH +126A 75 F5 2461 JNZ HEXEND +126C B0 0D 2462 MOV AL,13 +126E E8 CD 01 2463 CALL PUTCHR +1271 B0 0A 2464 MOV AL,10 +1273 E8 C8 01 2465 CALL PUTCHR +1276 B0 1A 2466 MOV AL,1AH +1278 E8 C3 01 2467 CALL PUTCHR +127B E8 A5 01 2468 CALL WRTHEX ;Flush HEX file buffer +127E A1 70 00 2469 MOV AX,[FCB+20] +1281 A3 2F 1B 2470 MOV [HEXFCB+20],AX ;Copy date to hex file +1284 BA 1B 1B 2471 MOV DX,HEXFCB +1287 B4 10 2472 MOV AH,CLOSE +1289 CD 21 2473 INT 33 +128B 2474 SYMDMP: +128B A0 D0 1B 2475 MOV AL,[SYMFLG] +128E 3C 53 2476 CMP AL,'S' +1290 75 19 2477 JNZ ENDSYM +1292 BB F8 1A 2478 MOV BX,SYMMES +1295 E8 D8 00 2479 CALL PRINT +1298 8B 16 CC 1B 2480 MOV DX,[BASE] +129C 8A C6 2481 MOV AL,DH +129E 0A C2 2482 OR AL,DL +12A0 74 22 2483 JZ EXIT +12A2 8B 1E CE 1B 2484 MOV BX,[HEAP] +12A6 8B E3 2485 MOV SP,BX +12A8 E8 1C 00 2486 CALL NODE +12AB 2487 ENDSYM: +12AB F6 06 EC 1B 80 2488 TEST B,[LSTDEV],80H ;Print listing to file? +12B0 74 12 2489 JZ EXIT +12B2 B0 1A 2490 MOV AL,1AH +12B4 E8 5D FF 2491 CALL WRTBUF ;Write end-of-file mark +12B7 E8 8E 01 2492 CALL FLUSHBUF +12BA A1 70 00 2493 MOV AX,[FCB+20] ;Get date of source file +12BD A3 54 1B 2494 MOV [LSTFCB+20],AX +12C0 B4 10 2495 MOV AH,CLOSE +12C2 CD 21 2496 INT 33 +12C4 E9 39 ED 2497 EXIT: JMP 0 +12C7 2498 +12C7 2499 NODE: +12C7 87 DA 2500 XCHG DX,BX +12C9 53 2501 PUSH BX +12CA 8A 17 2502 MOV DL,[BX] +12CC B6 00 2503 MOV DH,0 +12CE 43 2504 INC BX +12CF 03 DA 2505 ADD BX,DX +12D1 8A 17 2506 MOV DL,[BX] +12D3 43 2507 INC BX +12D4 8A 37 2508 MOV DH,[BX] +12D6 8A C2 2509 MOV AL,DL +12D8 0A C6 2510 OR AL,DH +12DA 74 03 2511 JZ L0014 +12DC E8 E8 FF 2512 CALL NODE +12DF 2513 L0014: +12DF 5B 2514 POP BX +12E0 8A 2F 2515 MOV CH,[BX] +12E2 43 2516 INC BX +12E3 B0 0A 2517 MOV AL,SYMWID +12E5 2A C5 2518 SUB AL,CH +12E7 73 02 2519 JNC LENOK +12E9 B0 01 2520 MOV AL,1 +12EB 2521 LENOK: +12EB 8A F0 2522 MOV DH,AL +12ED 2523 WRTSYM: +12ED 8A 07 2524 MOV AL,[BX] +12EF 43 2525 INC BX +12F0 E8 F6 FE 2526 CALL LIST +12F3 FE CD 2527 DEC CH +12F5 75 F6 2528 JNZ WRTSYM +12F7 8A EE 2529 MOV CH,DH +12F9 FE C5 2530 INC CH +12FB B0 20 2531 MOV AL,' ' +12FD 2532 OUTB: +12FD E8 E9 FE 2533 CALL LIST +1300 FE CD 2534 DEC CH +1302 75 F9 2535 JNZ OUTB +1304 43 2536 INC BX +1305 43 2537 INC BX +1306 53 2538 PUSH BX +1307 43 2539 INC BX +1308 43 2540 INC BX +1309 43 2541 INC BX +130A 43 2542 INC BX +130B 8A 07 2543 MOV AL,[BX] +130D E8 1F FF 2544 CALL PHEX +1310 4B 2545 DEC BX +1311 8A 07 2546 MOV AL,[BX] +1313 E8 19 FF 2547 CALL PHEX +1316 E8 79 FE 2548 CALL CRLF +1319 5B 2549 POP BX +131A 8B 17 2550 MOV DX,[BX] +131C 43 2551 INC BX +131D 8A C6 2552 MOV AL,DH +131F 0A C2 2553 OR AL,DL +1321 75 A4 2554 JNZ NODE +1323 C3 2555 RET +1324 2556 +1324 2557 SAVCD: +1324 A2 E3 1B 2558 MOV [PREV],AL +1327 53 2559 PUSH BX +1328 51 2560 PUSH CX +1329 50 2561 PUSH AX +132A 52 2562 PUSH DX +132B E8 59 00 2563 CALL CODBYT +132E 5A 2564 POP DX +132F BB D6 1B 2565 MOV BX,COUNT +1332 FE 07 2566 INC B,[BX] +1334 8A 07 2567 MOV AL,[BX] +1336 3C 08 2568 CMP AL,8 +1338 75 11 2569 JNZ NOEXT +133A C6 07 01 2570 MOV B,[BX],1 +133D E8 15 FE 2571 CALL OUTLIN +1340 B0 20 2572 MOV AL,' ' +1342 B5 05 2573 MOV CH,5 +1344 2574 TAB: +1344 E8 A2 FE 2575 CALL LIST +1347 FE CD 2576 DEC CH +1349 75 F9 2577 JNZ TAB +134B 2578 NOEXT: +134B 58 2579 POP AX +134C E8 95 FE 2580 CALL PHEXB +134F 59 2581 POP CX +1350 FF 06 65 1B 2582 INC [PC] +1354 FF 06 DC 1B 2583 INC [HEXADD] +1358 5B 2584 POP BX +1359 C3 2585 RET +135A 2586 +135A 2587 REPERR: +135A 0A C0 2588 OR AL,AL +135C 74 FB 2589 JZ RET +135E 50 2590 PUSH AX +135F BB 6D 1A 2591 MOV BX,ERRMES +1362 E8 0B 00 2592 CALL PRINT +1365 58 2593 POP AX +1366 E8 C6 FE 2594 CALL PHEX +1369 BB 94 1A 2595 MOV BX,ENDMES +136C FF 06 E6 1B 2596 INC [ERRCNT] +1370 2597 PRINT: +1370 8A 07 2598 MOV AL,[BX] +1372 E8 74 FE 2599 CALL LIST +1375 0A C0 2600 OR AL,AL +1377 78 E0 2601 JS RET +1379 43 2602 INC BX +137A EB F4 2603 JP PRINT +137C 2604 +137C 2605 OUTA: +137C 8A D0 2606 MOV DL,AL +137E 2607 OUT: +137E 80 E2 7F 2608 AND DL,7FH +1381 B1 02 2609 MOV CL,2 +1383 2610 SYSTEM: +1383 E8 7F EC 2611 CALL 5 +1386 C3 2612 RET +1387 2613 +1387 2614 CODBYT: +1387 82 3E 1B 1B 5A 2615 CMP B,[HEXFCB],"Z" +138C 74 F8 2616 JZ RET +138E 50 2617 PUSH AX +138F 8B 16 DE 1B 2618 MOV DX,[LASTAD] +1393 8B 1E DC 1B 2619 MOV BX,[HEXADD] +1397 89 1E DE 1B 2620 MOV [LASTAD],BX +139B 42 2621 INC DX +139C A0 E0 1B 2622 MOV AL,[HEXCNT] +139F 3C FB 2623 CMP AL,-5 +13A1 74 07 2624 JZ NEWLIN +13A3 3B DA 2625 CMP BX,DX +13A5 74 2E 2626 JZ AFHEX +13A7 E8 50 00 2627 CALL ENHEXL +13AA 2628 NEWLIN: +13AA B0 3A 2629 MOV AL,':' +13AC E8 8F 00 2630 CALL PUTCHR +13AF B0 FC 2631 MOV AL,-4 +13B1 A2 E0 1B 2632 MOV [HEXCNT],AL +13B4 32 C0 2633 XOR AL,AL +13B6 A2 E1 1B 2634 MOV [CHKSUM],AL +13B9 8B 1E F4 1B 2635 MOV BX,[HEXPNT] +13BD 89 1E DA 1B 2636 MOV [HEXLEN],BX +13C1 E8 12 00 2637 CALL HEXBYT +13C4 A0 DD 1B 2638 MOV AL,[HEXADD+1] +13C7 E8 0C 00 2639 CALL HEXBYT +13CA A0 DC 1B 2640 MOV AL,[HEXADD] +13CD E8 06 00 2641 CALL HEXBYT +13D0 32 C0 2642 XOR AL,AL +13D2 E8 01 00 2643 CALL HEXBYT +13D5 2644 AFHEX: +13D5 58 2645 POP AX +13D6 2646 HEXBYT: +13D6 8A E8 2647 MOV CH,AL +13D8 BB E1 1B 2648 MOV BX,CHKSUM +13DB 02 07 2649 ADD AL,[BX] +13DD 88 07 2650 MOV [BX],AL +13DF 8A C5 2651 MOV AL,CH +13E1 E8 86 00 2652 CALL UHALF +13E4 E8 57 00 2653 CALL PUTCHR +13E7 8A C5 2654 MOV AL,CH +13E9 E8 86 00 2655 CALL LHALF +13EC E8 4F 00 2656 CALL PUTCHR +13EF BB E0 1B 2657 MOV BX,HEXCNT +13F2 FE 07 2658 INC B,[BX] +13F4 8A 07 2659 MOV AL,[BX] +13F6 3C 1A 2660 CMP AL,26 +13F8 75 8C 2661 JNZ RET +13FA 2662 ENHEXL: +13FA 8B 3E DA 1B 2663 MOV DI,[HEXLEN] +13FE 8A E8 2664 MOV CH,AL +1400 E8 67 00 2665 CALL UHALF +1403 AA 2666 STOB +1404 8A C5 2667 MOV AL,CH +1406 E8 69 00 2668 CALL LHALF +1409 AA 2669 STOB +140A B0 FA 2670 MOV AL,-6 +140C A2 E0 1B 2671 MOV [HEXCNT],AL +140F A0 E1 1B 2672 MOV AL,[CHKSUM] +1412 02 C5 2673 ADD AL,CH +1414 F6 D8 2674 NEG AL +1416 E8 BD FF 2675 CALL HEXBYT +1419 B0 0D 2676 MOV AL,13 +141B E8 20 00 2677 CALL PUTCHR +141E B0 0A 2678 MOV AL,10 +1420 E8 1B 00 2679 CALL PUTCHR +1423 2680 WRTHEX: +1423 2681 ;Write out the line +1423 BA F8 1B 2682 MOV DX,HEXBUF +1426 89 16 F4 1B 2683 MOV [HEXPNT],DX +142A B4 1A 2684 MOV AH,SETDMA +142C CD 21 2685 INT 33 +142E 2B FA 2686 SUB DI,DX ;Length of buffer +1430 8B CF 2687 MOV CX,DI +1432 BA 1B 1B 2688 MOV DX,HEXFCB +1435 B4 28 2689 MOV AH,BLKWRT +1437 CD 21 2690 INT 33 +1439 0A C0 2691 OR AL,AL +143B 75 27 2692 JNZ DSKFUL +143D C3 2693 RET +143E 2694 +143E 2695 PUTCHR: +143E 8B 3E F4 1B 2696 MOV DI,[HEXPNT] +1442 AA 2697 STOB +1443 89 3E F4 1B 2698 MOV [HEXPNT],DI +1447 C3 2699 RET +1448 2700 +1448 2701 FLUSHBUF: +1448 8B 0E F6 1B 2702 MOV CX,[LSTPNT] +144C BA 3E 1C 2703 MOV DX,LSTBUF +144F 8B FA 2704 MOV DI,DX +1451 2B CA 2705 SUB CX,DX +1453 74 F2 2706 JZ RET ;Buffer empty? +1455 B4 1A 2707 MOV AH,SETDMA +1457 CD 21 2708 INT 33 +1459 BA 40 1B 2709 MOV DX,LSTFCB +145C B4 28 2710 MOV AH,BLKWRT +145E CD 21 2711 INT 33 +1460 0A C0 2712 OR AL,AL +1462 74 E3 2713 JZ RET +1464 2714 DSKFUL: +1464 BB C2 1A 2715 MOV BX,WRTERR +1467 E9 0A EE 2716 JMP PRERR +146A 2717 +146A 2718 UHALF: +146A D0 D8 2719 RCR AL +146C D0 D8 2720 RCR AL +146E D0 D8 2721 RCR AL +1470 D0 D8 2722 RCR AL +1472 2723 LHALF: +1472 24 0F 2724 AND AL,0FH +1474 0C 30 2725 OR AL,30H +1476 3C 3A 2726 CMP AL,'9'+1 +1478 72 CD 2727 JC RET +147A 04 07 2728 ADD AL,7 +147C C3 2729 RET +147D 2730 +147D 00 2731 NONE: DB 0 +147E 2732 +147E 2733 ; 8086 MNEMONIC TABLE +147E 2734 +147E 2735 ; This table is actually a sequence of subtables, each starting with a label. +147E 2736 ; The label signifies which mnemonics the subtable applies to--A3, for example, +147E 2737 ; means all 3-letter mnemonics beginning with A. +147E 2738 +147E 2739 A3: +147E 07 2740 DB 7 +147F 64 64 2741 DB 'dd' +1481 55 0C 2742 DW GRP7 +1483 02 2743 DB 2 +1484 6E 64 2744 DB 'nd' +1486 39 0D 2745 DW GRP13 +1488 22 2746 DB 22H +1489 64 63 2747 DB 'dc' +148B 55 0C 2748 DW GRP7 +148D 12 2749 DB 12H +148E 61 61 2750 DB 'aa' +1490 1B 0A 2751 DW PUT +1492 37 2752 DB 37H +1493 61 73 2753 DB 'as' +1495 1B 0A 2754 DW PUT +1497 3F 2755 DB 3FH +1498 61 6D 2756 DB 'am' +149A 05 0D 2757 DW GRP11 +149C D4 2758 DB 0D4H +149D 61 64 2759 DB 'ad' +149F 05 0D 2760 DW GRP11 +14A1 D5 2761 DB 0D5H +14A2 2762 A5: +14A2 01 2763 DB 1 +14A3 6C 69 67 6E 2764 DB 'lign' +14A7 F9 0B 2765 DW ALIGN +14A9 00 2766 DB 0 +14AA 2767 C3: +14AA 07 2768 DB 7 +14AB 6D 70 2769 DB 'mp' +14AD 55 0C 2770 DW GRP7 +14AF 3A 2771 DB 3AH +14B0 6C 63 2772 DB 'lc' +14B2 1B 0A 2773 DW PUT +14B4 F8 2774 DB 0F8H +14B5 6C 64 2775 DB 'ld' +14B7 1B 0A 2776 DW PUT +14B9 FC 2777 DB 0FCH +14BA 6C 69 2778 DB 'li' +14BC 1B 0A 2779 DW PUT +14BE FA 2780 DB 0FAH +14BF 6D 63 2781 DB 'mc' +14C1 1B 0A 2782 DW PUT +14C3 F5 2783 DB 0F5H +14C4 62 77 2784 DB 'bw' +14C6 1B 0A 2785 DW PUT +14C8 98 2786 DB 98H +14C9 77 64 2787 DB 'wd' +14CB 1B 0A 2788 DW PUT +14CD 99 2789 DB 99H +14CE 2790 C4: +14CE 03 2791 DB 3 +14CF 61 6C 6C 2792 DB 'all' +14D2 69 0D 2793 DW GRP14 +14D4 9A 2794 DB 9AH +14D5 6D 70 62 2795 DB 'mpb' +14D8 1B 0A 2796 DW PUT +14DA A6 2797 DB 0A6H +14DB 6D 70 77 2798 DB 'mpw' +14DE 1B 0A 2799 DW PUT +14E0 A7 2800 DB 0A7H +14E1 2801 C5: +14E1 02 2802 DB 2 +14E2 6D 70 73 62 2803 DB 'mpsb' +14E6 1B 0A 2804 DW PUT +14E8 A6 2805 DB 0A6H +14E9 6D 70 73 77 2806 DB 'mpsw' +14ED 1B 0A 2807 DW PUT +14EF A7 2808 DB 0A7H +14F0 2809 D2: +14F0 05 2810 DB 5 +14F1 62 2811 DB 'b' +14F2 7A 0F 2812 DW GRP23 +14F4 01 2813 DB 1 +14F5 77 2814 DB 'w' +14F6 7A 0F 2815 DW GRP23 +14F8 00 2816 DB 0 +14F9 6D 2817 DB 'm' +14FA 7A 0F 2818 DW GRP23 +14FC 02 2819 DB 2 +14FD 73 2820 DB 's' +14FE C1 0B 2821 DW GRP5 +1500 01 2822 DB 1 +1501 69 2823 DB 'i' +1502 1B 0A 2824 DW PUT +1504 FA 2825 DB 0FAH +1505 2826 D3: +1505 04 2827 DB 4 +1506 65 63 2828 DB 'ec' +1508 7D 0C 2829 DW GRP8 +150A 49 2830 DB 49H +150B 69 76 2831 DB 'iv' +150D D5 0C 2832 DW GRP10 +150F 30 2833 DB 30H +1510 61 61 2834 DB 'aa' +1512 1B 0A 2835 DW PUT +1514 27 2836 DB 27H +1515 61 73 2837 DB 'as' +1517 1B 0A 2838 DW PUT +1519 2F 2839 DB 2FH +151A 2840 D4: +151A 01 2841 DB 1 +151B 6F 77 6E 2842 DB 'own' +151E 1B 0A 2843 DW PUT +1520 FD 2844 DB 0FDH +1521 2845 E2: +1521 01 2846 DB 1 +1522 69 2847 DB 'i' +1523 1B 0A 2848 DW PUT +1525 FB 2849 DB 0FBH +1526 2850 E3: +1526 03 2851 DB 3 +1527 71 75 2852 DB 'qu' +1529 C1 0B 2853 DW GRP5 +152B 02 2854 DB 2 +152C 73 63 2855 DB 'sc' +152E C9 0E 2856 DW GRP19 +1530 D8 2857 DB 0D8H +1531 6E 64 2858 DB 'nd' +1533 08 10 2859 DW END +1535 00 2860 DB 0 +1536 2861 E5: +1536 01 2862 DB 1 +1537 6E 64 69 66 2863 DB 'ndif' +153B F8 0F 2864 DW ENDIF +153D 00 2865 DB 0 +153E 2866 H3: +153E 01 2867 DB 1 +153F 6C 74 2868 DB 'lt' +1541 1B 0A 2869 DW PUT +1543 F4 2870 DB 0F4H +1544 2871 H4: +1544 01 2872 DB 1 +1545 61 6C 74 2873 DB 'alt' +1548 1B 0A 2874 DW PUT +154A F4 2875 DB 0F4H +154B 2876 I2: +154B 02 2877 DB 2 +154C 6E 2878 DB 'n' +154D 98 0B 2879 DW GRP4 +154F E4 2880 DB 0E4H +1550 66 2881 DB 'f' +1551 C1 0B 2882 DW GRP5 +1553 04 2883 DB 4 +1554 2884 I3: +1554 04 2885 DB 4 +1555 6E 63 2886 DB 'nc' +1557 7D 0C 2887 DW GRP8 +1559 41 2888 DB 41H +155A 6E 62 2889 DB 'nb' +155C 98 0B 2890 DW GRP4 +155E E4 2891 DB 0E4H +155F 6E 77 2892 DB 'nw' +1561 98 0B 2893 DW GRP4 +1563 E5 2894 DB 0E5H +1564 6E 74 2895 DB 'nt' +1566 9E 0E 2896 DW GRP18 +1568 CC 2897 DB 0CCH +1569 2898 I4: +1569 04 2899 DB 4 +156A 6D 75 6C 2900 DB 'mul' +156D D5 0C 2901 DW GRP10 +156F 28 2902 DB 28H +1570 64 69 76 2903 DB 'div' +1573 D5 0C 2904 DW GRP10 +1575 38 2905 DB 38H +1576 72 65 74 2906 DB 'ret' +1579 1B 0A 2907 DW PUT +157B CF 2908 DB 0CFH +157C 6E 74 6F 2909 DB 'nto' +157F 1B 0A 2910 DW PUT +1581 CE 2911 DB 0CEH +1582 2912 J2: +1582 0A 2913 DB 10 +1583 70 2914 DB 'p' +1584 65 0E 2915 DW GRP17 +1586 EB 2916 DB 0EBH +1587 7A 2917 DB 'z' +1588 65 0E 2918 DW GRP17 +158A 74 2919 DB 74H +158B 65 2920 DB 'e' +158C 65 0E 2921 DW GRP17 +158E 74 2922 DB 74H +158F 6C 2923 DB 'l' +1590 65 0E 2924 DW GRP17 +1592 7C 2925 DB 7CH +1593 62 2926 DB 'b' +1594 65 0E 2927 DW GRP17 +1596 72 2928 DB 72H +1597 61 2929 DB 'a' +1598 65 0E 2930 DW GRP17 +159A 77 2931 DB 77H +159B 67 2932 DB 'g' +159C 65 0E 2933 DW GRP17 +159E 7F 2934 DB 7FH +159F 6F 2935 DB 'o' +15A0 65 0E 2936 DW GRP17 +15A2 70 2937 DB 70H +15A3 73 2938 DB 's' +15A4 65 0E 2939 DW GRP17 +15A6 78 2940 DB 78H +15A7 63 2941 DB 'c' +15A8 65 0E 2942 DW GRP17 +15AA 72 2943 DB 72H +15AB 2944 J3: +15AB 11 2945 DB 17 +15AC 6D 70 2946 DB 'mp' +15AE 69 0D 2947 DW GRP14 +15B0 EA 2948 DB 0EAH +15B1 6E 7A 2949 DB 'nz' +15B3 65 0E 2950 DW GRP17 +15B5 75 2951 DB 75H +15B6 6E 65 2952 DB 'ne' +15B8 65 0E 2953 DW GRP17 +15BA 75 2954 DB 75H +15BB 6E 6C 2955 DB 'nl' +15BD 65 0E 2956 DW GRP17 +15BF 7D 2957 DB 7DH +15C0 67 65 2958 DB 'ge' +15C2 65 0E 2959 DW GRP17 +15C4 7D 2960 DB 7DH +15C5 6E 62 2961 DB 'nb' +15C7 65 0E 2962 DW GRP17 +15C9 73 2963 DB 73H +15CA 61 65 2964 DB 'ae' +15CC 65 0E 2965 DW GRP17 +15CE 73 2966 DB 73H +15CF 6E 63 2967 DB 'nc' +15D1 65 0E 2968 DW GRP17 +15D3 73 2969 DB 73H +15D4 6E 67 2970 DB 'ng' +15D6 65 0E 2971 DW GRP17 +15D8 7E 2972 DB 7EH +15D9 6C 65 2973 DB 'le' +15DB 65 0E 2974 DW GRP17 +15DD 7E 2975 DB 7EH +15DE 6E 61 2976 DB 'na' +15E0 65 0E 2977 DW GRP17 +15E2 76 2978 DB 76H +15E3 62 65 2979 DB 'be' +15E5 65 0E 2980 DW GRP17 +15E7 76 2981 DB 76H +15E8 70 65 2982 DB 'pe' +15EA 65 0E 2983 DW GRP17 +15EC 7A 2984 DB 7AH +15ED 6E 70 2985 DB 'np' +15EF 65 0E 2986 DW GRP17 +15F1 7B 2987 DB 7BH +15F2 70 6F 2988 DB 'po' +15F4 65 0E 2989 DW GRP17 +15F6 7B 2990 DB 7BH +15F7 6E 6F 2991 DB 'no' +15F9 65 0E 2992 DW GRP17 +15FB 71 2993 DB 71H +15FC 6E 73 2994 DB 'ns' +15FE 65 0E 2995 DW GRP17 +1600 79 2996 DB 79H +1601 2997 J4: +1601 06 2998 DB 6 +1602 6D 70 73 2999 DB 'mps' +1605 65 0E 3000 DW GRP17 +1607 EB 3001 DB 0EBH +1608 63 78 7A 3002 DB 'cxz' +160B 65 0E 3003 DW GRP17 +160D E3 3004 DB 0E3H +160E 6E 67 65 3005 DB 'nge' +1611 65 0E 3006 DW GRP17 +1613 7C 3007 DB 7CH +1614 6E 61 65 3008 DB 'nae' +1617 65 0E 3009 DW GRP17 +1619 72 3010 DB 72H +161A 6E 62 65 3011 DB 'nbe' +161D 65 0E 3012 DW GRP17 +161F 77 3013 DB 77H +1620 6E 6C 65 3014 DB 'nle' +1623 65 0E 3015 DW GRP17 +1625 7F 3016 DB 7FH +1626 3017 L3: +1626 03 3018 DB 3 +1627 65 61 3019 DB 'ea' +1629 49 0C 3020 DW GRP6 +162B 8D 3021 DB 8DH +162C 64 73 3022 DB 'ds' +162E 49 0C 3023 DW GRP6 +1630 C5 3024 DB 0C5H +1631 65 73 3025 DB 'es' +1633 49 0C 3026 DW GRP6 +1635 C4 3027 DB 0C4H +1636 3028 L4: +1636 05 3029 DB 5 +1637 6F 6F 70 3030 DB 'oop' +163A 65 0E 3031 DW GRP17 +163C E2 3032 DB 0E2H +163D 6F 64 62 3033 DB 'odb' +1640 1B 0A 3034 DW PUT +1642 AC 3035 DB 0ACH +1643 6F 64 77 3036 DB 'odw' +1646 1B 0A 3037 DW PUT +1648 AD 3038 DB 0ADH +1649 61 68 66 3039 DB 'ahf' +164C 1B 0A 3040 DW PUT +164E 9F 3041 DB 9FH +164F 6F 63 6B 3042 DB 'ock' +1652 1B 0A 3043 DW PUT +1654 F0 3044 DB 0F0H +1655 3045 L5: +1655 04 3046 DB 4 +1656 6F 6F 70 65 3047 DB 'oope' +165A 65 0E 3048 DW GRP17 +165C E1 3049 DB 0E1H +165D 6F 6F 70 7A 3050 DB 'oopz' +1661 65 0E 3051 DW GRP17 +1663 E1 3052 DB 0E1H +1664 6F 64 73 62 3053 DB 'odsb' +1668 1B 0A 3054 DW PUT +166A AC 3055 DB 0ACH +166B 6F 64 73 77 3056 DB 'odsw' +166F 1B 0A 3057 DW PUT +1671 AD 3058 DB 0ADH +1672 3059 L6: +1672 02 3060 DB 2 +1673 6F 6F 70 6E 65 3061 DB 'oopne' +1678 65 0E 3062 DW GRP17 +167A E0 3063 DB 0E0H +167B 6F 6F 70 6E 7A 3064 DB 'oopnz' +1680 65 0E 3065 DW GRP17 +1682 E0 3066 DB 0E0H +1683 3067 M3: +1683 02 3068 DB 2 +1684 6F 76 3069 DB 'ov' +1686 AE 09 3070 DW GRP1 +1688 88 3071 DB 88H +1689 75 6C 3072 DB 'ul' +168B D5 0C 3073 DW GRP10 +168D 20 3074 DB 20H +168E 3075 M4: +168E 02 3076 DB 2 +168F 6F 76 62 3077 DB 'ovb' +1692 1B 0A 3078 DW PUT +1694 A4 3079 DB 0A4H +1695 6F 76 77 3080 DB 'ovw' +1698 1B 0A 3081 DW PUT +169A A5 3082 DB 0A5H +169B 3083 M5: +169B 02 3084 DB 2 +169C 6F 76 73 62 3085 DB 'ovsb' +16A0 1B 0A 3086 DW PUT +16A2 A4 3087 DB 0A4H +16A3 6F 76 73 77 3088 DB 'ovsw' +16A7 1B 0A 3089 DW PUT +16A9 A5 3090 DB 0A5H +16AA 3091 N3: +16AA 03 3092 DB 3 +16AB 6F 74 3093 DB 'ot' +16AD 83 0C 3094 DW GRP9 +16AF 10 3095 DB 10H +16B0 65 67 3096 DB 'eg' +16B2 83 0C 3097 DW GRP9 +16B4 18 3098 DB 18H +16B5 6F 70 3099 DB 'op' +16B7 1B 0A 3100 DW PUT +16B9 90 3101 DB 90H +16BA 3102 O2: +16BA 01 3103 DB 1 +16BB 72 3104 DB 'r' +16BC 39 0D 3105 DW GRP13 +16BE 0A 3106 DB 0AH +16BF 3107 O3: +16BF 02 3108 DB 2 +16C0 75 74 3109 DB 'ut' +16C2 98 0B 3110 DW GRP4 +16C4 E6 3111 DB 0E6H +16C5 72 67 3112 DB 'rg' +16C7 C1 0B 3113 DW GRP5 +16C9 00 3114 DB 0 +16CA 3115 O4: +16CA 02 3116 DB 2 +16CB 75 74 62 3117 DB 'utb' +16CE 98 0B 3118 DW GRP4 +16D0 E6 3119 DB 0E6H +16D1 75 74 77 3120 DB 'utw' +16D4 98 0B 3121 DW GRP4 +16D6 E7 3122 DB 0E7H +16D7 3123 P3: +16D7 02 3124 DB 2 +16D8 6F 70 3125 DB 'op' +16DA 59 0F 3126 DW GRP22 +16DC 8F 3127 DB 8FH +16DD 75 74 3128 DB 'ut' +16DF C1 0B 3129 DW GRP5 +16E1 03 3130 DB 3 +16E2 3131 P4: +16E2 02 3132 DB 2 +16E3 75 73 68 3133 DB 'ush' +16E6 07 0B 3134 DW GRP2 +16E8 FF 3135 DB 0FFH +16E9 6F 70 66 3136 DB 'opf' +16EC 1B 0A 3137 DW PUT +16EE 9D 3138 DB 9DH +16EF 3139 P5: +16EF 01 3140 DB 1 +16F0 75 73 68 66 3141 DB 'ushf' +16F4 1B 0A 3142 DW PUT +16F6 9C 3143 DB 9CH +16F7 3144 R3: +16F7 06 3145 DB 6 +16F8 65 74 3146 DB 'et' +16FA E6 0D 3147 DW GRP16 +16FC C3 3148 DB 0C3H +16FD 65 70 3149 DB 'ep' +16FF 1B 0A 3150 DW PUT +1701 F3 3151 DB 0F3H +1702 6F 6C 3152 DB 'ol' +1704 0D 0D 3153 DW GRP12 +1706 00 3154 DB 0 +1707 6F 72 3155 DB 'or' +1709 0D 0D 3156 DW GRP12 +170B 08 3157 DB 8 +170C 63 6C 3158 DB 'cl' +170E 0D 0D 3159 DW GRP12 +1710 10 3160 DB 10H +1711 63 72 3161 DB 'cr' +1713 0D 0D 3162 DW GRP12 +1715 18 3163 DB 18H +1716 3164 R4: +1716 02 3165 DB 2 +1717 65 70 7A 3166 DB 'epz' +171A 1B 0A 3167 DW PUT +171C F3 3168 DB 0F3H +171D 65 70 65 3169 DB 'epe' +1720 1B 0A 3170 DW PUT +1722 F3 3171 DB 0F3H +1723 3172 R5: +1723 02 3173 DB 2 +1724 65 70 6E 7A 3174 DB 'epnz' +1728 1B 0A 3175 DW PUT +172A F2 3176 DB 0F2H +172B 65 70 6E 65 3177 DB 'epne' +172F 1B 0A 3178 DW PUT +1731 F2 3179 DB 0F2H +1732 3180 S3: +1732 0B 3181 DB 11 +1733 75 62 3182 DB 'ub' +1735 55 0C 3183 DW GRP7 +1737 2A 3184 DB 2AH +1738 62 62 3185 DB 'bb' +173A 55 0C 3186 DW GRP7 +173C 1A 3187 DB 1AH +173D 62 63 3188 DB 'bc' +173F 55 0C 3189 DW GRP7 +1741 1A 3190 DB 1AH +1742 74 63 3191 DB 'tc' +1744 1B 0A 3192 DW PUT +1746 F9 3193 DB 0F9H +1747 74 64 3194 DB 'td' +1749 1B 0A 3195 DW PUT +174B FD 3196 DB 0FDH +174C 74 69 3197 DB 'ti' +174E 1B 0A 3198 DW PUT +1750 FB 3199 DB 0FBH +1751 68 6C 3200 DB 'hl' +1753 0D 0D 3201 DW GRP12 +1755 20 3202 DB 20H +1756 68 72 3203 DB 'hr' +1758 0D 0D 3204 DW GRP12 +175A 28 3205 DB 28H +175B 61 6C 3206 DB 'al' +175D 0D 0D 3207 DW GRP12 +175F 20 3208 DB 20H +1760 61 72 3209 DB 'ar' +1762 0D 0D 3210 DW GRP12 +1764 38 3211 DB 38H +1765 65 67 3212 DB 'eg' +1767 41 0F 3213 DW GRP21 +1769 26 3214 DB 26H +176A 3215 S4: +176A 05 3216 DB 5 +176B 63 61 62 3217 DB 'cab' +176E 1B 0A 3218 DW PUT +1770 AE 3219 DB 0AEH +1771 63 61 77 3220 DB 'caw' +1774 1B 0A 3221 DW PUT +1776 AF 3222 DB 0AFH +1777 74 6F 62 3223 DB 'tob' +177A 1B 0A 3224 DW PUT +177C AA 3225 DB 0AAH +177D 74 6F 77 3226 DB 'tow' +1780 1B 0A 3227 DW PUT +1782 AB 3228 DB 0ABH +1783 61 68 66 3229 DB 'ahf' +1786 1B 0A 3230 DW PUT +1788 9E 3231 DB 9EH +1789 3232 S5: +1789 04 3233 DB 4 +178A 63 61 73 62 3234 DB 'casb' +178E 1B 0A 3235 DW PUT +1790 AE 3236 DB 0AEH +1791 63 61 73 77 3237 DB 'casw' +1795 1B 0A 3238 DW PUT +1797 AF 3239 DB 0AFH +1798 74 6F 73 62 3240 DB 'tosb' +179C 1B 0A 3241 DW PUT +179E AA 3242 DB 0AAH +179F 74 6F 73 77 3243 DB 'tosw' +17A3 1B 0A 3244 DW PUT +17A5 AB 3245 DB 0ABH +17A6 3246 T4: +17A6 01 3247 DB 1 +17A7 65 73 74 3248 DB 'est' +17AA 30 0F 3249 DW GRP20 +17AC 84 3250 DB 84H +17AD 3251 U2: +17AD 01 3252 DB 1 +17AE 70 3253 DB 'p' +17AF 1B 0A 3254 DW PUT +17B1 FC 3255 DB 0FCH +17B2 3256 W4: +17B2 01 3257 DB 1 +17B3 61 69 74 3258 DB 'ait' +17B6 1B 0A 3259 DW PUT +17B8 9B 3260 DB 9BH +17B9 3261 X3: +17B9 01 3262 DB 1 +17BA 6F 72 3263 DB 'or' +17BC 39 0D 3264 DW GRP13 +17BE 32 3265 DB 32H +17BF 3266 X4: +17BF 02 3267 DB 2 +17C0 63 68 67 3268 DB 'chg' +17C3 38 0B 3269 DW GRP3 +17C5 86 3270 DB 86H +17C6 6C 61 74 3271 DB 'lat' +17C9 1B 0A 3272 DW PUT +17CB D7 3273 DB 0D7H +17CC 3274 +17CC 3275 +17CC 3276 ; 8087 MNEMONIC TABLE +17CC 3277 ; Similar to 8086 table above, except NOT distinguished by opcode length +17CC 3278 +17CC 3279 XM1: ;F2XM1 +17CC 01 3280 DB 1 ;One opcode +17CD 78 6D B1 3281 DM "xm1" +17D0 01 F0 3282 DB 1,0F0H +17D2 3283 +17D2 3284 NDPA: +17D2 03 3285 DB 3 +17D3 64 E4 3286 DM "dd" +17D5 00 C0 3287 DB 0,0C0H +17D7 64 64 F0 3288 DM "ddp" +17DA 06 C0 3289 DB 6,0C0H +17DC 62 F3 3290 DM "bs" +17DE 01 E0 3291 DB 1,0E0H +17E0 3292 +17E0 3293 NDPB: +17E0 02 3294 DB 2 +17E1 6C E4 3295 DM "ld" +17E3 07 20 3296 DB 7,20H +17E5 73 74 F0 3297 DM "stp" +17E8 07 30 3298 DB 7,30H +17EA 3299 +17EA 3300 NDPC: +17EA 05 3301 DB 5 +17EB 6F ED 3302 DM "om" +17ED 00 D0 3303 DB 0,0D0H +17EF 6F 6D F0 3304 DM "omp" +17F2 00 18 3305 DB 0,18H +17F4 68 F3 3306 DM "hs" +17F6 01 E0 3307 DB 1,0E0H +17F8 6F 6D 70 F0 3308 DM "ompp" +17FC 06 D9 3309 DB 6,0D9H +17FE 6C 65 F8 3310 DM "lex" +1801 03 E2 3311 DB 3,0E2H +1803 3312 +1803 3313 NDPD: +1803 06 3314 DB 6 +1804 69 F6 3315 DM "iv" +1806 00 30 3316 DB 0,30H +1808 69 76 F0 3317 DM "ivp" +180B 06 F0 3318 DB 6,0F0H +180D 69 76 F2 3319 DM "ivr" +1810 00 38 3320 DB 0,38H +1812 69 76 72 F0 3321 DM "ivrp" +1816 06 F8 3322 DB 6,0F8H +1818 65 63 73 74 F0 3323 DM "ecstp" +181D 01 F6 3324 DB 1,0F6H +181F 69 73 E9 3325 DM "isi" +1822 03 E1 3326 DB 3,0E1H +1824 3327 +1824 3328 NDPE: +1824 01 3329 DB 1 +1825 6E E9 3330 DM "ni" +1827 03 E0 3331 DB 3,0E0H +1829 3332 +1829 3333 NDPF: +1829 01 3334 DB 1 +182A 72 65 E5 3335 DM "ree" +182D 05 C0 3336 DB 5,0C0H +182F 3337 +182F 3338 NDPI: +182F 0D 3339 DB 13 +1830 61 64 E4 3340 DM "add" +1833 00 00 3341 DB 0,0 +1835 6C E4 3342 DM "ld" +1837 00 00 3343 DB 0,0 +1839 73 75 E2 3344 DM "sub" +183C 00 00 3345 DB 0,0 +183E 73 74 F0 3346 DM "stp" +1841 00 00 3347 DB 0,0 +1843 73 F4 3348 DM "st" +1845 00 00 3349 DB 0,0 +1847 6D 75 EC 3350 DM "mul" +184A 00 00 3351 DB 0,0 +184C 64 69 F6 3352 DM "div" +184F 00 00 3353 DB 0,0 +1851 73 75 62 F2 3354 DM "subr" +1855 00 00 3355 DB 0,0 +1857 64 69 76 F2 3356 DM "divr" +185B 00 00 3357 DB 0,0 +185D 63 6F ED 3358 DM "com" +1860 00 00 3359 DB 0,0 +1862 63 6F 6D F0 3360 DM "comp" +1866 00 00 3361 DB 0,0 +1868 6E 63 73 74 F0 3362 DM "ncstp" +186D 01 F7 3363 DB 1,0F7H +186F 6E 69 F4 3364 DM "nit" +1872 03 E3 3365 DB 3,0E3H +1874 3366 +1874 3367 NDPL: +1874 0A 3368 DB 10 +1875 E4 3369 DM "d" +1876 00 00 3370 DB 0,0 +1878 64 FA 3371 DM "dz" +187A 01 EE 3372 DB 1,0EEH +187C 64 B1 3373 DM "d1" +187E 01 E8 3374 DB 1,0E8H +1880 64 70 E9 3375 DM "dpi" +1883 01 EB 3376 DB 1,0EBH +1885 64 6C 32 F4 3377 DM "dl2t" +1889 01 E9 3378 DB 1,0E9H +188B 64 6C 32 E5 3379 DM "dl2e" +188F 01 EA 3380 DB 1,0EAH +1891 64 6C 67 B2 3381 DM "dlg2" +1895 01 EC 3382 DB 1,0ECH +1897 64 6C 6E B2 3383 DM "dln2" +189B 01 EB 3384 DB 1,0EBH +189D 64 63 F7 3385 DM "dcw" +18A0 01 00 3386 DB 1,0 +18A2 64 65 6E F6 3387 DM "denv" +18A6 00 00 3388 DB 0,0 +18A8 3389 +18A8 3390 NDPM: +18A8 02 3391 DB 2 +18A9 75 EC 3392 DM "ul" +18AB 00 00 3393 DB 0,0 +18AD 75 6C F0 3394 DM "ulp" +18B0 00 00 3395 DB 0,0 +18B2 3396 +18B2 3397 NDPP: +18B2 03 3398 DB 3 +18B3 72 65 ED 3399 DM "rem" +18B6 01 F8 3400 DB 1,0F8H +18B8 74 61 EE 3401 DM "tan" +18BB 01 F2 3402 DB 1,0F2H +18BD 61 74 61 EE 3403 DM "atan" +18C1 01 F3 3404 DB 1,0F3H +18C3 3405 +18C3 3406 NDPR: +18C3 02 3407 DB 2 +18C4 6E 64 69 6E F4 3408 DM "ndint" +18C9 01 FC 3409 DB 1,0FCH +18CB 73 74 6F F2 3410 DM "stor" +18CF 05 00 3411 DB 5,0 +18D1 3412 +18D1 3413 NDPS: +18D1 0C 3414 DB 12 +18D2 F4 3415 DM "t" +18D3 00 00 3416 DB 0,0 +18D5 74 F0 3417 DM "tp" +18D7 00 00 3418 DB 0,0 +18D9 75 E2 3419 DM "ub" +18DB 00 00 3420 DB 0,0 +18DD 75 62 F0 3421 DM "ubp" +18E0 00 00 3422 DB 0,0 +18E2 75 62 F2 3423 DM "ubr" +18E5 00 00 3424 DB 0,0 +18E7 75 62 72 F0 3425 DM "ubrp" +18EB 00 00 3426 DB 0,0 +18ED 71 72 F4 3427 DM "qrt" +18F0 01 FA 3428 DB 1,0FAH +18F2 63 61 6C E5 3429 DM "cale" +18F6 01 FD 3430 DB 1,0FDH +18F8 61 76 E5 3431 DM "ave" +18FB 05 00 3432 DB 5,0 +18FD 74 63 F7 3433 DM "tcw" +1900 05 00 3434 DB 5,0 +1902 74 65 6E F6 3435 DM "tenv" +1906 05 00 3436 DB 5,0 +1908 74 73 F7 3437 DM "tsw" +190B 05 00 3438 DB 5,0 +190D 3439 +190D 3440 NDPT: +190D 01 3441 DB 1 +190E 73 F4 3442 DM "st" +1910 01 E4 3443 DB 1,0E4H +1912 3444 +1912 3445 NDPW: +1912 01 3446 DB 1 +1913 61 69 F4 3447 DM "ait" +1916 00 00 3448 DB 0,0 +1918 3449 +1918 3450 NDPX: +1918 03 3451 DB 3 +1919 63 E8 3452 DM "ch" +191B 01 C4 3453 DB 1,0C4H +191D 61 ED 3454 DM "am" +191F 01 E5 3455 DB 1,0E5H +1921 74 72 61 63 F4 3456 DM "tract" +1926 01 F4 3457 DB 1,0F4H +1928 3458 +1928 3459 NDPY: +1928 02 3460 DB 2 +1929 6C 32 F8 3461 DM "l2x" +192C 01 F1 3462 DB 1,0F1H +192E 6C 32 78 70 B1 3463 DM "l2xp1" +1933 01 F9 3464 DB 1,0F9H +1935 3465 +1935 3466 +1935 3467 OPTAB: +1935 3468 ; Table of pointers to mnemonics. For each letter of the alphabet (the +1935 3469 ; starting letter of the mnemonic), there are 5 entries. Each entry +1935 3470 ; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +1935 3471 ; long, respectively. If there are no mnemonics for a given combination +1935 3472 ; of first letter and length (such as A-2), then the corresponding entry +1935 3473 ; points to NONE. Otherwise, it points to a place in the mnemonic table +1935 3474 ; for that type. +1935 3475 +1935 3476 ; This table only needs to be modified if a mnemonic is added to a group +1935 3477 ; previously marked NONE. Change the NONE to a label made up of the first +1935 3478 ; letter of the mnemonic and its length, then add a new subsection to +1935 3479 ; the mnemonic table in alphabetical order. +1935 3480 +1935 7D 14 3481 DW NONE +1937 7E 14 3482 DW A3 +1939 7D 14 3483 DW NONE +193B A2 14 3484 DW A5 +193D 7D 14 3485 DW NONE +193F 7D 14 3486 DW NONE ;B +1941 7D 14 3487 DW NONE +1943 7D 14 3488 DW NONE +1945 7D 14 3489 DW NONE +1947 7D 14 3490 DW NONE +1949 7D 14 3491 DW NONE ;C +194B AA 14 3492 DW C3 +194D CE 14 3493 DW C4 +194F E1 14 3494 DW C5 +1951 7D 14 3495 DW NONE +1953 F0 14 3496 DW D2 ;D +1955 05 15 3497 DW D3 +1957 1A 15 3498 DW D4 +1959 7D 14 3499 DW NONE +195B 7D 14 3500 DW NONE +195D 21 15 3501 DW E2 ;E +195F 26 15 3502 DW E3 +1961 7D 14 3503 DW NONE +1963 36 15 3504 DW E5 +1965 7D 14 3505 DW NONE +1967 7D 14 3506 DW NONE ;F +1969 7D 14 3507 DW NONE +196B 7D 14 3508 DW NONE +196D 7D 14 3509 DW NONE +196F 7D 14 3510 DW NONE +1971 7D 14 3511 DW NONE ;G +1973 7D 14 3512 DW NONE +1975 7D 14 3513 DW NONE +1977 7D 14 3514 DW NONE +1979 7D 14 3515 DW NONE +197B 7D 14 3516 DW NONE ;H +197D 3E 15 3517 DW H3 +197F 44 15 3518 DW H4 +1981 7D 14 3519 DW NONE +1983 7D 14 3520 DW NONE +1985 4B 15 3521 DW I2 ;I +1987 54 15 3522 DW I3 +1989 69 15 3523 DW I4 +198B 7D 14 3524 DW NONE +198D 7D 14 3525 DW NONE +198F 82 15 3526 DW J2 ;J +1991 AB 15 3527 DW J3 +1993 01 16 3528 DW J4 +1995 7D 14 3529 DW NONE +1997 7D 14 3530 DW NONE +1999 7D 14 3531 DW NONE ;K +199B 7D 14 3532 DW NONE +199D 7D 14 3533 DW NONE +199F 7D 14 3534 DW NONE +19A1 7D 14 3535 DW NONE +19A3 7D 14 3536 DW NONE ;L +19A5 26 16 3537 DW L3 +19A7 36 16 3538 DW L4 +19A9 55 16 3539 DW L5 +19AB 72 16 3540 DW L6 +19AD 7D 14 3541 DW NONE ;M +19AF 83 16 3542 DW M3 +19B1 8E 16 3543 DW M4 +19B3 9B 16 3544 DW M5 +19B5 7D 14 3545 DW NONE +19B7 7D 14 3546 DW NONE ;N +19B9 AA 16 3547 DW N3 +19BB 7D 14 3548 DW NONE +19BD 7D 14 3549 DW NONE +19BF 7D 14 3550 DW NONE +19C1 BA 16 3551 DW O2 ;O +19C3 BF 16 3552 DW O3 +19C5 CA 16 3553 DW O4 +19C7 7D 14 3554 DW NONE +19C9 7D 14 3555 DW NONE +19CB 7D 14 3556 DW NONE ;P +19CD D7 16 3557 DW P3 +19CF E2 16 3558 DW P4 +19D1 EF 16 3559 DW P5 +19D3 7D 14 3560 DW NONE +19D5 7D 14 3561 DW NONE ;Q +19D7 7D 14 3562 DW NONE +19D9 7D 14 3563 DW NONE +19DB 7D 14 3564 DW NONE +19DD 7D 14 3565 DW NONE +19DF 7D 14 3566 DW NONE ;R +19E1 F7 16 3567 DW R3 +19E3 16 17 3568 DW R4 +19E5 23 17 3569 DW R5 +19E7 7D 14 3570 DW NONE +19E9 7D 14 3571 DW NONE ;S +19EB 32 17 3572 DW S3 +19ED 6A 17 3573 DW S4 +19EF 89 17 3574 DW S5 +19F1 7D 14 3575 DW NONE +19F3 7D 14 3576 DW NONE ;T +19F5 7D 14 3577 DW NONE +19F7 A6 17 3578 DW T4 +19F9 7D 14 3579 DW NONE +19FB 7D 14 3580 DW NONE +19FD AD 17 3581 DW U2 ;U +19FF 7D 14 3582 DW NONE +1A01 7D 14 3583 DW NONE +1A03 7D 14 3584 DW NONE +1A05 7D 14 3585 DW NONE +1A07 7D 14 3586 DW NONE ;V +1A09 7D 14 3587 DW NONE +1A0B 7D 14 3588 DW NONE +1A0D 7D 14 3589 DW NONE +1A0F 7D 14 3590 DW NONE +1A11 7D 14 3591 DW NONE ;W +1A13 7D 14 3592 DW NONE +1A15 B2 17 3593 DW W4 +1A17 7D 14 3594 DW NONE +1A19 7D 14 3595 DW NONE +1A1B 7D 14 3596 DW NONE ;X +1A1D B9 17 3597 DW X3 +1A1F BF 17 3598 DW X4 +1A21 7D 14 3599 DW NONE +1A23 7D 14 3600 DW NONE +1A25 7D 14 3601 DW NONE ;Y +1A27 7D 14 3602 DW NONE +1A29 7D 14 3603 DW NONE +1A2B 7D 14 3604 DW NONE +1A2D 7D 14 3605 DW NONE +1A2F 7D 14 3606 DW NONE ;Z +1A31 7D 14 3607 DW NONE +1A33 7D 14 3608 DW NONE +1A35 7D 14 3609 DW NONE +1A37 7D 14 3610 DW NONE +1A39 3611 +1A39 3612 NDPTAB: +1A39 3613 ;Lookup table for 8087 mnemonics. There is one entry for each letter of the +1A39 3614 ;alphabet +1A39 D2 17 3615 DW NDPA +1A3B E0 17 3616 DW NDPB +1A3D EA 17 3617 DW NDPC +1A3F 03 18 3618 DW NDPD +1A41 24 18 3619 DW NDPE +1A43 29 18 3620 DW NDPF +1A45 7D 14 3621 DW NONE ;G +1A47 7D 14 3622 DW NONE ;H +1A49 2F 18 3623 DW NDPI +1A4B 7D 14 3624 DW NONE ;J +1A4D 7D 14 3625 DW NONE ;K +1A4F 74 18 3626 DW NDPL +1A51 A8 18 3627 DW NDPM +1A53 7D 14 3628 DW NONE ;N +1A55 7D 14 3629 DW NONE ;O +1A57 B2 18 3630 DW NDPP +1A59 7D 14 3631 DW NONE ;Q +1A5B C3 18 3632 DW NDPR +1A5D D1 18 3633 DW NDPS +1A5F 0D 19 3634 DW NDPT +1A61 7D 14 3635 DW NONE ;U +1A63 7D 14 3636 DW NONE ;V +1A65 12 19 3637 DW NDPW +1A67 18 19 3638 DW NDPX +1A69 28 19 3639 DW NDPY +1A6B 7D 14 3640 DW NONE ;Z +1A6D 3641 +1A6D 3642 +1A6D 2A 2A 2A 2A 2A 20 45 3643 ERRMES: DM '***** ERROR no. ' + 52 52 4F 52 20 6E 6F + 2E A0 +1A7D 0D 0A 4E 6F 20 64 69 3644 NOSPAC: DB 13,10,'No directory space',13,10,24H + 72 65 63 74 6F 72 79 + 20 73 70 61 63 65 0D + 0A 24 +1A94 48 0D 8A 3645 ENDMES: DM 'H',13,10 +1A97 0D 0A 49 6E 73 75 66 3646 NOMEM: DB 13,10,'Insufficient memory',13,10,'$' + 66 69 63 69 65 6E 74 + 20 6D 65 6D 6F 72 79 + 0D 0A 24 +1AAF 0D 0A 46 69 6C 65 20 3647 NOFILE: DB 13,10,'File not found',13,10,'$' + 6E 6F 74 20 66 6F 75 + 6E 64 0D 0A 24 +1AC2 0D 0A 44 69 73 6B 20 3648 WRTERR: DB 13,10,'Disk full',13,10,'$' + 66 75 6C 6C 0D 0A 24 +1AD0 0D 0A 42 61 64 20 64 3649 BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' + 69 73 6B 20 73 70 65 + 63 69 66 69 65 72 0D + 0A 24 +1AE7 0D 0A 0D 0A 45 72 72 3650 ERCNTM: DM 13,10,13,10,'Error Count =' + 6F 72 20 43 6F 75 6E + 74 20 BD +1AF8 0D 0A 53 79 6D 62 6F 3651 SYMMES: DM 13,10,'Symbol Table',13,10,13,10 + 6C 20 54 61 62 6C 65 + 0D 0A 0D 8A +1B0A 41 53 4D 00 00 3652 EXTEND: DB 'ASM',0,0 +1B0F 05 65 6E 64 69 66 3653 IFEND: DB 5,'endif' +1B15 02 69 66 3654 IFNEST: DB 2,'if' +1B18 72 65 F4 3655 RETSTR: DM 'ret' +1B1B 00 20 20 20 20 20 20 3656 HEXFCB: DB 0,' HEX',0,0,0,0 + 20 20 48 45 58 00 00 + 00 00 +1B2B 3657 DS 16 +1B3B 00 00 00 00 00 3658 DB 0,0,0,0,0 +1B40 00 20 20 20 20 20 20 3659 LSTFCB: DB 0,' PRN',0,0,0,0 + 20 20 50 52 4E 00 00 + 00 00 +1B50 3660 DS 16 +1B60 00 00 00 00 00 3661 DB 0,0,0,0,0 +1B65 3662 PC: DS 2 +1B67 3663 OLDPC: DS 2 +1B69 3664 LABPT: DS 2 +1B6B 3665 FLAG: DS 1 +1B6C 3666 LONG: DS 1 +1B6D 3667 ADDR: DS 2 +1B6F 3668 ALABEL: DS 2 +1B71 3669 DATA: DS 2 +1B73 3670 DLABEL: DS 2 +1B75 3671 CON: DS 2 +1B77 3672 UNDEF: DS 2 +1B79 3673 LENID: DS 1 +1B7A 3674 ID: DS 80 +1BCA 3675 CHR: DS 1 +1BCB 3676 SYM: DS 1 +1BCC 3677 BASE: DS 2 +1BCE 3678 HEAP: DS 2 +1BD0 3679 SYMFLG: DS 1 +1BD1 3680 CODE: DS 2 +1BD3 3681 DATSIZ: DS 1 +1BD4 3682 RELOC: DS 1 +1BD5 3683 BCOUNT: DS 1 +1BD6 3684 COUNT: DS 1 +1BD7 3685 ERR: DS 1 +1BD8 3686 LINE: DS 2 +1BDA 3687 HEXLEN: DS 2 +1BDC 3688 HEXADD: DS 2 +1BDE 3689 LASTAD: DS 2 +1BE0 3690 HEXCNT: DS 1 +1BE1 3691 CHKSUM: DS 1 +1BE2 3692 LINFLG: DS 1 +1BE3 3693 PREV: DS 1 +1BE4 3694 IFFLG: DS 1 +1BE5 3695 CHKLAB: DS 1 +1BE6 3696 ERRCNT: DS 2 +1BE8 3697 LSTRET: DS 2 +1BEA 3698 RETPT: DS 2 +1BEC 3699 LSTDEV: DS 2 +1BEE 3700 SPC: DS 1 +1BEF 3701 NOWAIT: DS 1 +1BF0 3702 IX: DS 2 +1BF2 3703 IY: DS 2 +1BF4 3704 HEXPNT: DS 2 +1BF6 3705 LSTPNT: DS 2 +1BF8 3706 HEXBUF: DS HEXBUFSIZ +1C3E 3707 LSTBUF: DS LSTBUFSIZ +203E 3708 BUFPT: DS 2 +2040 3709 SRCBUF: DS BUFSIZ +2440 3710 DS 80 +2490 3711 ALIGN +2490 3712 STACK: EQU $ +2490 3713 START: EQU $ + + +Error Count = 0 diff --git a/1_transcription/bundle_6 b/1_transcription/bundle_6 new file mode 100644 index 0000000..dfe6fec --- /dev/null +++ b/1_transcription/bundle_6 @@ -0,0 +1,4259 @@ + + +Seattle Computer Products 8086 Assembler Version 2.43 +Copyright 1979-1982 by Seattle Computer Products, Inc. + +0000 0001 ; Seattle Computer Products 8086 Assembler version 2.43 +0000 0002 ; by Tim Paterson +0000 0003 ; Runs on the 8086 under MS-DOS +0000 0004 +0000 0005 ;* * * * * * REVISION HISTORY * * * * * * +0000 0006 ; +0000 0007 ; 12/29/80 2.01 General release with 86-DOS version 0.34 +0000 0008 ; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +0000 0009 ; 03/18/81 2.11 General cleanup and more documentation +0000 0010 ; 03/24/81 2.20 Modify ESC handling for full 8087 operation +0000 0011 ; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +0000 0012 ; 04/03/81 2.22 Fix 2.21 buffer handling +0000 0013 ; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +0000 0014 ; 04/28/81 2.24 Allow nested IFs +0000 0015 ; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +0000 0016 ; 08/02/81 2.30 Re-write pass 2: +0000 0017 ; Always report errors to console +0000 0018 ; Exact byte lengths for HEX and PRN files +0000 0019 ; 11/08/81 2.40 Add 8087 mnemonics; print full error messages; +0000 0020 ; allow expressions with *, /, and () +0000 0021 ; 07/04/82 2.41 Fix Intel's 8087 "reverse-bit" bug; don't copy date +0000 0022 ; 08/18/82 2.42 Increase stack from 80 to 256 (Damn! Overflowed again!) +0000 0023 ; 01/05/82 2.43 Correct over-zealous optimization in 2.42 +0000 0024 ; +0000 0025 ;* * * * * * * * * * * * * * * * * * * * * +0000 0026 +0000 0027 SYMWID: EQU 5 ;5 symbols per line in dump +0000 0028 FCB: EQU 5CH +0000 0029 BUFSIZ: EQU 1024 ;Source code buffer +0000 0030 LSTBUFSIZ:EQU BUFSIZ ;List file buffer +0000 0031 HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +0000 0032 EOL: EQU 13 ;ASCII carriage return +0000 0033 OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS +0000 0034 +0000 0035 ;System call function codes +0000 0036 PRINTMES: EQU 9 +0000 0037 OPEN: EQU 15 +0000 0038 CLOSE: EQU 16 +0000 0039 READ: EQU 20 +0000 0040 SETDMA: EQU 26 +0000 0041 MAKE: EQU 22 +0000 0042 BLKWRT: EQU 40 +0000 0043 +0000 0044 ;The following equates define some token values returned by GETSYM +0000 0045 UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +0000 0046 CONST: EQU 1 ;Constant (including $) +0000 0047 REG: EQU 2 ;8-bit register +0000 0048 XREG: EQU 3 ;16-bit register (except segment registers) +0000 0049 SREG: EQU 4 ;Segment register +0000 0050 FREG: EQU 6 ;8087 floating point register +0000 0051 +0000 0052 ;Bits to build 8087 opcode table entries +0000 0053 ONEREG: EQU 40H ;Single ST register OK as operand +0000 0054 NEEDOP: EQU 80H ;Must have an operand +0000 0055 INTEGER:EQU 20H ;For integer operations +0000 0056 REAL: EQU 28H ;For real operations +0000 0057 EXTENDED EQU 10H ;For Long integers or Temporary real +0000 0058 MEMORY: EQU 18H ;For general memory operations +0000 0059 STACKOP:EQU 10H ;Two register arithmetic with pop +0000 0060 ARITH: EQU 8 ;Non-pop arithmetic operations +0000 0061 +0000 0062 ORG 100H +0100 0063 PUT 100H +0100 0064 +0100 EB 74 0065 JMPS BEGIN +0102 0066 +0102 0D 0A 53 65 61 74 74 0067 HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.43' + 6C 65 20 43 6F 6D 70 + 75 74 65 72 20 50 72 + 6F 64 75 63 74 73 20 + 38 30 38 36 20 41 73 + 73 65 6D 62 6C 65 72 + 20 56 65 72 73 69 6F + 6E 20 32 2E 34 33 +0139 0D 0A 43 6F 70 79 72 0068 DB 13,10,'Copyright 1979-1982 by Seattle Computer Products, Inc.' + 69 67 68 74 20 31 39 + 37 39 2D 31 39 38 32 + 20 62 79 20 53 65 61 + 74 74 6C 65 20 43 6F + 6D 70 75 74 65 72 20 + 50 72 6F 64 75 63 74 + 73 2C 20 49 6E 63 2E +0171 0D 0A 0D 0A 24 0069 DB 13,10,13,10,'$' +0176 0070 +0176 0071 BEGIN: +0176 BC A6 2A 0072 MOV SP,STACK +0179 BA 02 01 0073 MOV DX,HEADER +017C B4 09 0074 MOV AH,PRINTMES +017E CD 21 0075 INT 33 +0180 A0 6D 00 0076 MOV AL,[FCB+17] +0183 A2 35 21 0077 MOV [SYMFLG],AL ;Save symbol table request flag +0186 BE 65 00 0078 MOV SI,FCB+9 ;Point to file extension +0189 AC 0079 LODB ;Get source drive letter +018A E8 13 01 0080 CALL CHKDSK ;Valid drive? +018D 0A C0 0081 OR AL,AL +018F 74 03 0082 JZ DEFAULT ;If no extension, use existing drive spec +0191 A2 5C 00 0083 MOV [FCB],AL +0194 0084 DEFAULT: +0194 AC 0085 LODB ;Get HEX file drive letter +0195 3C 5A 0086 CMP AL,'Z' ;Suppress HEX file? +0197 74 03 0087 JZ L0000 +0199 E8 04 01 0088 CALL CHKDSK +019C 0089 L0000: +019C A2 80 20 0090 MOV [HEXFCB],AL +019F AC 0091 LODB ;Get PRN file drive letter +01A0 B4 00 0092 MOV AH,0 ;Signal no PRN file +01A2 3C 5A 0093 CMP AL,'Z' ;Suppress PRN file? +01A4 74 15 0094 JZ NOPRN +01A6 3C 59 0095 CMP AL,'Y' ;Print errors only on console? +01A8 74 11 0096 JZ NOPRN +01AA B4 02 0097 MOV AH,2 +01AC 3C 58 0098 CMP AL,'X' ;PRN file to console? +01AE 74 0B 0099 JZ NOPRN +01B0 B4 04 0100 MOV AH,4 +01B2 3C 50 0101 CMP AL,'P' ;PRN file to printer? +01B4 74 05 0102 JZ NOPRN +01B6 E8 E7 00 0103 CALL CHKDSK +01B9 B4 80 0104 MOV AH,80H +01BB 0105 NOPRN: +01BB A2 A5 20 0106 MOV [LSTFCB],AL +01BE 88 26 52 21 0107 MOV [LSTDEV],AH ;Flag device for list ouput +01C2 BE 6F 20 0108 MOV SI,EXTEND +01C5 BF 65 00 0109 MOV DI,FCB+9 +01C8 A5 0110 MOVW +01C9 A4 0111 MOVB ;Set extension to ASM +01CA A5 0112 MOVW ;Zero extent field +01CB BA 5C 00 0113 MOV DX,FCB +01CE B4 0F 0114 MOV AH,OPEN +01D0 CD 21 0115 INT 33 +01D2 BB 14 20 0116 MOV BX,NOFILE +01D5 0A C0 0117 OR AL,AL +01D7 74 03 0118 JZ $+5 +01D9 E9 9A 00 0119 JMP PRERR +01DC BA 80 20 0120 MOV DX,HEXFCB +01DF E8 9C 00 0121 CALL MAKFIL +01E2 BA A5 20 0122 MOV DX,LSTFCB +01E5 E8 96 00 0123 CALL MAKFIL +01E8 33 C0 0124 XOR AX,AX +01EA A3 68 00 0125 MOV [FCB+12],AX ;Zero CURRENT BLOCK field +01ED A2 7C 00 0126 MOV [FCB+32],AL ;Zero Next Record field +01F0 C7 06 6A 00 00 04 0127 MOV [FCB+14],BUFSIZ ;Set record size +01F6 C7 06 A4 25 A6 25 0128 MOV [BUFPT],SRCBUF ;Initialize buffer pointer +01FC C7 06 37 21 A7 2A 0129 MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE +0202 C7 06 58 21 A6 2A 0130 MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE +0208 33 C0 0131 XOR AX,AX +020A A3 CA 20 0132 MOV [PC],AX ;DEFAULT PROGRAM COUNTER +020D A3 31 21 0133 MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL +0210 A3 50 21 0134 MOV [RETPT],AX ;Pointer to last RET record +0213 A2 4A 21 0135 MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF +0216 A2 4B 21 0136 MOV [CHKLAB],AL ;LOOKUP ALL LABELS +0219 48 0137 DEC AX +021A A3 4E 21 0138 MOV [LSTRET],AX ;Location of last RET +021D A1 06 00 0139 MOV AX,[6] ;HL=END OF MEMORY +0220 A3 33 21 0140 MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE +0223 C7 06 3B 21 04 00 0141 MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE +0229 0142 +0229 0143 ;Assemble each line of code +0229 0144 +0229 0145 LOOP: +0229 E8 8A 00 0146 CALL NEXTCHR ;Get first character on line +022C 3C 1A 0147 CMP AL,1AH +022E 74 1E 0148 JZ ENDJ +0230 B0 FF 0149 MOV AL,-1 ;Flag that no tokens have been read yet +0232 A2 30 21 0150 MOV [SYM],AL +0235 E8 1C 07 0151 CALL ASMLIN ;Assemble the line +0238 A0 30 21 0152 MOV AL,[SYM] +023B 3C FF 0153 CMP AL,-1 ;Any tokens found on line? +023D 75 03 0154 JNZ L0002 +023F E8 C0 03 0155 CALL GETSYM ;If no tokens read yet, read first one +0242 0156 L0002: +0242 3C 3B 0157 CMP AL,';' +0244 74 0B 0158 JZ ENDLN +0246 3C 0D 0159 CMP AL,EOL +0248 74 07 0160 JZ ENDLN +024A B0 14 0161 MOV AL,14H ;Garbage at end of line error +024C EB 05 0162 JP ENDLIN +024E E9 09 0F 0163 ENDJ: JMP END +0251 0164 +0251 0165 ENDLN: +0251 32 C0 0166 XOR AL,AL ;Flag no errors on line +0253 0167 ENDLIN: +0253 0168 ;AL = error code for line. Stack depth unknown +0253 BC A6 2A 0169 MOV SP,STACK +0256 E8 02 00 0170 CALL NEXLIN +0259 EB CE 0171 JP LOOP +025B 0172 +025B 0173 NEXLIN: +025B B5 C0 0174 MOV CH,0C0H ;Put end of line marker and error code (AL) +025D E8 81 09 0175 CALL PUTCD +0260 E8 46 09 0176 CALL GEN1 +0263 A0 2F 21 0177 MOV AL,[CHR] +0266 0178 GETEOL: +0266 3C 0A 0179 CMP AL,10 +0268 74 35 0180 JZ RET +026A 3C 1A 0181 CMP AL,1AH +026C 74 E0 0182 JZ ENDJ +026E E8 45 00 0183 CALL NEXTCHR ;Scan over comments for linefeed +0271 EB F3 0184 JP GETEOL +0273 0185 +0273 0186 ABORT: +0273 BB FC 1F 0187 MOV BX,NOMEM +0276 0188 PRERR: +0276 8B D3 0189 MOV DX,BX +0278 B4 09 0190 MOV AH,PRINTMES +027A CD 21 0191 INT 33 +027C CD 20 0192 INT 32 +027E 0193 +027E 0194 MAKFIL: +027E 8B F2 0195 MOV SI,DX +0280 AC 0196 LODB ;Get drive select byte +0281 3C 20 0197 CMP AL,20H ;If not valid, don't make file +0283 73 1A 0198 JNC RET +0285 B9 04 00 0199 MOV CX,4 +0288 8B FE 0200 MOV DI,SI +028A BE 5D 00 0201 MOV SI,FCB+1 +028D F3 0202 REP +028E A5 0203 MOVW ;Copy source file name +028F B4 16 0204 MOV AH,MAKE +0291 CD 21 0205 INT 33 +0293 C7 45 05 01 00 0206 MOV [DI-9+14],1 ;Set record length to 1 byte +0298 BB E4 1F 0207 MOV BX,NOSPAC +029B 0A C0 0208 OR AL,AL ;Success? +029D 75 D7 0209 JNZ PRERR +029F C3 0210 RET +02A0 0211 +02A0 0212 CHKDSK: +02A0 2C 20 0213 SUB AL,' ' ;If not present, set zero flag +02A2 74 FB 0214 JZ RET +02A4 2C 20 0215 SUB AL,20H +02A6 74 04 0216 JZ DSKERR ;Must be in range A-O +02A8 3C 10 0217 CMP AL,'P'-'@' +02AA 72 F3 0218 JC RET +02AC 0219 DSKERR: +02AC BB 35 20 0220 MOV BX,BADDSK +02AF EB C5 0221 JP PRERR +02B1 0222 +02B1 0223 ERROR: +02B1 8A C1 0224 MOV AL,CL +02B3 E9 9D FF 0225 JMP ENDLIN +02B6 0226 +02B6 0227 NEXTCHR: +02B6 8B 36 A4 25 0228 MOV SI,[BUFPT] +02BA 81 FE A6 25 0229 CMP SI,SRCBUF +02BE 75 1A 0230 JNZ GETCH +02C0 0231 ;Buffer empty so refill it +02C0 52 0232 PUSH DX +02C1 50 0233 PUSH AX ;AH must be saved +02C2 8B D6 0234 MOV DX,SI +02C4 B4 1A 0235 MOV AH,SETDMA +02C6 CD 21 0236 INT 33 +02C8 BA 5C 00 0237 MOV DX,FCB +02CB B4 14 0238 MOV AH,READ +02CD CD 21 0239 INT 33 +02CF 92 0240 XCHG AX,DX ;Put error code in DL +02D0 58 0241 POP AX ;Restore AH +02D1 8A C2 0242 MOV AL,DL ;Error code back in AL +02D3 5A 0243 POP DX +02D4 3C 01 0244 CMP AL,1 +02D6 B0 1A 0245 MOV AL,1AH ;Possibly signal End of File +02D8 74 0A 0246 JZ NOMOD ;If nothing read +02DA 0247 GETCH: +02DA AC 0248 LODB +02DB 81 FE A6 29 0249 CMP SI,SRCBUF+BUFSIZ +02DF 75 03 0250 JNZ NOMOD +02E1 BE A6 25 0251 MOV SI,SRCBUF +02E4 0252 NOMOD: +02E4 89 36 A4 25 0253 MOV [BUFPT],SI +02E8 A2 2F 21 0254 MOV [CHR],AL +02EB C3 0255 RET +02EC 0256 +02EC 0257 +02EC 0258 MROPS: +02EC 0259 +02EC 0260 ; Get two operands and check for certain types, according to flag byte +02EC 0261 ; in CL. OP code in CH. Returns only if immediate operation. +02EC 0262 +02EC 51 0263 PUSH CX ;Save type flags +02ED E8 D8 00 0264 CALL GETOP +02F0 52 0265 PUSH DX ;Save first operand +02F1 E8 CB 00 0266 CALL GETOP2 +02F4 5B 0267 POP BX ;First op in BX, second op in DX +02F5 B0 04 0268 MOV AL,SREG ;Check for a segment register +02F7 3A C7 0269 CMP AL,BH +02F9 74 41 0270 JZ SEGCHK +02FB 3A C6 0271 CMP AL,DH +02FD 74 3D 0272 JZ SEGCHK +02FF B0 01 0273 MOV AL,CONST ;Check if the first operand is immediate +0301 B1 1A 0274 MOV CL,26 +0303 3A C7 0275 CMP AL,BH +0305 74 AA 0276 JZ ERROR ;Error if so +0307 59 0277 POP CX ;Restore type flags +0308 3A C6 0278 CMP AL,DH ;If second operand is immediate, then done +030A 74 DF 0279 JZ RET +030C B0 00 0280 MOV AL,UNDEFID ;Check for memory reference +030E 3A C7 0281 CMP AL,BH +0310 74 4F 0282 JZ STORE ;Is destination memory? +0312 3A C6 0283 CMP AL,DH +0314 74 55 0284 JZ LOAD ;Is source memory? +0316 F6 C1 01 0285 TEST CL,1 ;Check if register-to-register operation OK +0319 B1 1B 0286 MOV CL,27 +031B 74 94 0287 JZ ERROR +031D 8A C6 0288 MOV AL,DH +031F 3A C7 0289 CMP AL,BH ;Registers must be of same length +0321 0290 RR: +0321 B1 16 0291 MOV CL,22 +0323 75 8C 0292 JNZ ERROR +0325 0293 RR1: +0325 24 01 0294 AND AL,1 ;Get register length (1=16 bits) +0327 0A C5 0295 OR AL,CH ;Or in to OP code +0329 E8 70 08 0296 CALL PUT ;And write it +032C 59 0297 POP CX ;Dump return address +032D 8A C3 0298 MOV AL,BL +032F 02 C0 0299 ADD AL,AL ;Rotate register number into middle position +0331 02 C0 0300 ADD AL,AL +0333 02 C0 0301 ADD AL,AL +0335 0C C0 0302 OR AL,0C0H ;Set register-to-register mode +0337 0A C2 0303 OR AL,DL ;Combine with other register number +0339 E9 60 08 0304 JMP PUT +033C 0305 +033C 0306 SEGCHK: +033C 0307 ;Come here if at least one operand is a segment register +033C 59 0308 POP CX ;Restore flags +033D F6 C1 08 0309 TEST CL,8 ;Check if segment register OK +0340 B1 16 0310 MOV CL,22 +0342 74 78 0311 JZ ERR1 +0344 B9 03 8E 0312 MOV CX,8E03H ;Segment register move OP code +0347 B0 00 0313 MOV AL,UNDEFID +0349 3A C6 0314 CMP AL,DH ;Check if source is memory +034B 74 1E 0315 JZ LOAD +034D 3A C7 0316 CMP AL,BH ;Check if destination is memory +034F 74 10 0317 JZ STORE +0351 B0 03 0318 MOV AL,XREG +0353 2A C6 0319 SUB AL,DH ;Check if source is 16-bit register +0355 74 CA 0320 JZ RR ;If so, AL must be zero +0357 B5 8C 0321 MOV CH,8CH ;Change direction +0359 87 DA 0322 XCHG DX,BX ;Flip which operand is first and second +035B B0 03 0323 MOV AL,XREG +035D 2A C6 0324 SUB AL,DH ;Let RR perform finish the test +035F EB C0 0325 JP RR +0361 0326 +0361 0327 STORE: +0361 F6 C1 04 0328 TEST CL,004H ;Check if storing is OK +0364 75 52 0329 JNZ STERR +0366 87 DA 0330 XCHG DX,BX ;If so, flip operands +0368 80 E5 FD 0331 AND CH,0FDH ; and zero direction bit +036B 0332 LOAD: +036B B6 19 0333 MOV DH,25 +036D 3A C7 0334 CMP AL,BH ;Check if memory-to-memory +036F 74 49 0335 JZ MRERR +0371 8A C7 0336 MOV AL,BH +0373 3C 02 0337 CMP AL,REG ;Check if 8-bit operation +0375 75 07 0338 JNZ XRG +0377 B6 16 0339 MOV DH,22 +0379 F6 C1 01 0340 TEST CL,1 ;See if 8-bit operation is OK +037C 74 3C 0341 JZ MRERR +037E 0342 XRG: +037E 8A C2 0343 MOV AL,DL +0380 2C 06 0344 SUB AL,6 ;Check for R/M mode 6 and register 0 +0382 0A C3 0345 OR AL,BL ; meaning direct load/store of accumulator +0384 75 19 0346 JNZ NOTAC +0386 F6 C1 08 0347 TEST CL,8 ;See if direct load/store of accumulator +0389 74 14 0348 JZ NOTAC ; means anything in this case +038B 0349 ; Process direct load/store of accumulator +038B 8A C5 0350 MOV AL,CH +038D 24 02 0351 AND AL,2 ;Preserve direction bit only +038F 34 02 0352 XOR AL,2 ; but flip it +0391 0C A0 0353 OR AL,0A0H ;Combine with OP code +0393 8A E8 0354 MOV CH,AL +0395 8A C7 0355 MOV AL,BH ;Check byte/word operation +0397 24 01 0356 AND AL,1 +0399 0A C5 0357 OR AL,CH +039B 59 0358 POP CX ;Dump return address +039C E9 BD 08 0359 JMP PUTADD ;Write the address +039F 0360 +039F 0361 NOTAC: +039F 8A C7 0362 MOV AL,BH +03A1 24 01 0363 AND AL,1 ;Get byte/word bit +03A3 22 C1 0364 AND AL,CL ;But don't use it in word-only operations +03A5 0A C5 0365 OR AL,CH ;Combine with OP code +03A7 E8 F2 07 0366 CALL PUT +03AA 8A C3 0367 MOV AL,BL +03AC 02 C0 0368 ADD AL,AL ;Rotate to middle position +03AE 02 C0 0369 ADD AL,AL +03B0 02 C0 0370 ADD AL,AL +03B2 0A C2 0371 OR AL,DL ;Combine register field +03B4 59 0372 POP CX ;Dump return address +03B5 E9 A4 08 0373 JMP PUTADD ;Write the address +03B8 0374 +03B8 0375 STERR: +03B8 B6 1D 0376 MOV DH,29 +03BA 0377 MRERR: +03BA 8A CE 0378 MOV CL,DH +03BC 0379 +03BC E9 F2 FE 0380 ERR1: JMP ERROR +03BF 0381 +03BF 0382 GETOP2: +03BF 0383 ;Get the second operand: look for a comma and drop into GETOP +03BF A0 30 21 0384 MOV AL,[SYM] +03C2 3C 2C 0385 CMP AL,',' +03C4 B1 15 0386 MOV CL,21 +03C6 75 F4 0387 JNZ ERR1 +03C8 0388 +03C8 0389 +03C8 0390 GETOP: +03C8 0391 +03C8 0392 ; Get one operand. Operand may be a memory reference in brackets, a register, +03C8 0393 ; or a constant. If a flag (such as "B" for byte operation) is encountered, +03C8 0394 ; it is noted and processing continues to find the operand. +03C8 0395 ; +03C8 0396 ; On exit, AL (=DH) has the type of operand. Other information depends +03C8 0397 ; on the actual operand: +03C8 0398 ; +03C8 0399 ; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +03C8 0400 ; the 8086 R/M format (middle bits zero). The constant part of the address +03C8 0401 ; is in ADDR. If an undefined label needs to be added to this, a pointer to +03C8 0402 ; its information fields is in ALABEL, otherwise ALABEL is zero. +03C8 0403 ; +03C8 0404 ; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +03C8 0405 ; to be added to this, a pointer to its information fields is in DLABEL, +03C8 0406 ; otherwise DLABEL is zero. "$" and "RET" are in this class. +03C8 0407 ; +03C8 0408 ; AL=DH=2 8-bit Register. DL has the register number. +03C8 0409 ; +03C8 0410 ; AL=DH=3 16-bit Register. DL has the register number. +03C8 0411 ; +03C8 0412 ; AL=DH=4 Segment Register. DL has the register number. +03C8 0413 +03C8 E8 37 02 0414 CALL GETSYM +03CB 0415 GETOP1: +03CB 0416 ;Enter here if we don't need a GETSYM first +03CB 3C 5B 0417 CMP AL,'[' ;Memory reference? +03CD 74 30 0418 JZ MEM +03CF 3C 05 0419 CMP AL,5 ;Flag ("B", "W", etc.)? +03D1 74 57 0420 JZ FLG +03D3 3C 02 0421 CMP AL,REG ;8-Bit register? +03D5 74 20 0422 JZ NREG +03D7 3C 03 0423 CMP AL,XREG ;16-Bit register? +03D9 74 1C 0424 JZ NREG +03DB 3C 04 0425 CMP AL,SREG ;Segment register? +03DD 74 18 0426 JZ NREG +03DF 0427 VAL: ;Must be immediate +03DF 32 C0 0428 XOR AL,AL ;No addressing modes allowed +03E1 0429 VAL1: +03E1 E8 57 00 0430 CALL GETVAL +03E4 A1 DA 20 0431 MOV AX,[CON] ;Defined part +03E7 A3 D6 20 0432 MOV [DATA],AX +03EA A1 DC 20 0433 MOV AX,[UNDEF] ;Undefined part +03ED A3 D8 20 0434 MOV [DLABEL],AX +03F0 8A D5 0435 MOV DL,CH +03F2 B6 01 0436 MOV DH,CONST +03F4 8A C6 0437 MOV AL,DH +03F6 C3 0438 RET +03F7 0439 NREG: +03F7 52 0440 PUSH DX +03F8 E8 07 02 0441 CALL GETSYM +03FB 5A 0442 POP DX +03FC 8A C6 0443 MOV AL,DH +03FE C3 0444 RET +03FF 0445 MEM: +03FF E8 00 02 0446 CALL GETSYM +0402 B0 01 0447 MOV AL,1 +0404 E8 34 00 0448 CALL GETVAL +0407 A0 30 21 0449 MOV AL,[SYM] +040A 3C 5D 0450 CMP AL,']' +040C B1 18 0451 MOV CL,24 +040E 75 AC 0452 JNZ ERR1 +0410 E8 EF 01 0453 CALL GETSYM +0413 8B 1E DA 20 0454 MOV BX,[CON] +0417 89 1E D2 20 0455 MOV [ADDR],BX +041B 8B 1E DC 20 0456 MOV BX,[UNDEF] +041F 89 1E D4 20 0457 MOV [ALABEL],BX +0423 8A D5 0458 MOV DL,CH +0425 B6 00 0459 MOV DH,UNDEFID +0427 8A C6 0460 MOV AL,DH +0429 C3 0461 RET +042A 0462 FLG: +042A 3A 16 D1 20 0463 CMP DL,[MAXFLG] ;Invalid flag for this operation? +042E B1 27 0464 MOV CL,27H +0430 7F 8A 0465 JG ERR1 +0432 E8 CD 01 0466 CALL GETSYM +0435 3C 2C 0467 CMP AL,',' +0437 74 8F 0468 JZ GETOP +0439 EB 90 0469 JP GETOP1 +043B 0470 +043B 0471 +043B 0472 GETVAL: +043B 0473 +043B 0474 ; Expression analyzer. On entry, if AL=0 then do not allow base or index +043B 0475 ; registers. If AL=1, we are analyzing a memory reference, so allow base +043B 0476 ; and index registers, and compute addressing mode when done. The constant +043B 0477 ; part of the expression will be found in CON. If an undefined label is to +043B 0478 ; be added to this, a pointer to its information fields will be found in +043B 0479 ; UNDEF. +043B 0480 +043B 8A E0 0481 MOV AH,AL ;Flag is kept in AH +043D C7 06 DC 20 00 00 0482 MOV [UNDEF],0 +0443 A0 30 21 0483 MOV AL,[SYM] +0446 E8 51 00 0484 CALL EXPRESSION +0449 89 16 DA 20 0485 MOV [CON],DX +044D 8A C4 0486 MOV AL,AH +044F B5 00 0487 MOV CH,0 ;Initial mode +0451 A8 10 0488 TEST AL,10H ;Test INDEX bit +0453 D0 D0 0489 RCL AL ;BASE bit (zero flag not affected) +0455 74 37 0490 JZ NOIND ;Jump if not indexed, with BASE bit in carry +0457 F5 0491 CMC +0458 D0 D5 0492 RCL CH ;Rotate in BASE bit +045A D0 D0 0493 RCL AL ;BP bit +045C D0 D5 0494 RCL CH +045E D0 D0 0495 RCL AL ;DI bit +0460 D0 D5 0496 RCL CH ;The low 3 bits now have indexing mode +0462 0497 MODE: +0462 80 CD 80 0498 OR CH,080H ;If undefined label, force 16-bit displacement +0465 F7 06 DC 20 FF FF 0499 TEST [UNDEF],-1 +046B 75 BC 0500 JNZ RET +046D 8B 1E DA 20 0501 MOV BX,[CON] +0471 8A C3 0502 MOV AL,BL +0473 98 0503 CBW ;Extend sign +0474 3B C3 0504 CMP AX,BX ;Is it a signed 8-bit number? +0476 75 B1 0505 JNZ RET ;If not, use 16-bit displacement +0478 80 E5 7F 0506 AND CH,07FH ;Reset 16-bit displacement +047B 80 CD 40 0507 OR CH,040H ;Set 8-bit displacement +047E 0B DB 0508 OR BX,BX +0480 75 A7 0509 JNZ RET ;Use it if not zero displacement +0482 80 E5 07 0510 AND CH,7 ;Specify no displacement +0485 82 FD 06 0511 CMP CH,6 ;Check for BP+0 addressing mode +0488 75 9F 0512 JNZ RET +048A 80 CD 40 0513 OR CH,040H ;If BP+0, use 8-bit displacement +048D C3 0514 RET +048E 0515 +048E 0516 NOIND: +048E B5 06 0517 MOV CH,6 ;Try direct address mode +0490 73 FB 0518 JNC RET ;If no base register, that's right +0492 D0 D0 0519 RCL AL ;Check BP bit +0494 72 CC 0520 JC MODE +0496 FE C5 0521 INC CH ;If not, must be BX +0498 EB C8 0522 JP MODE +049A 0523 +049A 0524 EXPRESSION: +049A 0525 ;Analyze arbitrary expression. Flag byte in AH. +049A 0526 ;On exit, AL has type byte: 0=register or undefined label +049A B5 FF 0527 MOV CH,-1 ;Initial type +049C 8B FA 0528 MOV DI,DX +049E 33 D2 0529 XOR DX,DX ;Initial value +04A0 3C 2B 0530 CMP AL,'+' +04A2 74 0C 0531 JZ PLSMNS +04A4 3C 2D 0532 CMP AL,'-' +04A6 74 08 0533 JZ PLSMNS +04A8 B1 2B 0534 MOV CL,'+' +04AA 52 0535 PUSH DX +04AB 51 0536 PUSH CX +04AC 8B D7 0537 MOV DX,DI +04AE EB 0A 0538 JP OPERATE +04B0 0539 PLSMNS: +04B0 8A C8 0540 MOV CL,AL +04B2 52 0541 PUSH DX +04B3 51 0542 PUSH CX +04B4 80 CC 04 0543 OR AH,4 ;Flag that a sign was found +04B7 E8 48 01 0544 CALL GETSYM +04BA 0545 OPERATE: +04BA E8 2B 00 0546 CALL TERM +04BD 59 0547 POP CX ;Recover operator +04BE 5B 0548 POP BX ;Recover current value +04BF 87 DA 0549 XCHG DX,BX +04C1 22 E8 0550 AND CH,AL +04C3 0A C0 0551 OR AL,AL ;Is it register or undefined label? +04C5 74 17 0552 JZ NOCON ;If so, then no constant part +04C7 82 F9 2D 0553 CMP CL,"-" ;Subtract it? +04CA 75 02 0554 JNZ ADD +04CC F7 DB 0555 NEG BX +04CE 0556 ADD: +04CE 03 D3 0557 ADD DX,BX +04D0 0558 NEXTERM: +04D0 A0 30 21 0559 MOV AL,[SYM] +04D3 3C 2B 0560 CMP AL,'+' +04D5 74 D9 0561 JZ PLSMNS +04D7 3C 2D 0562 CMP AL,'-' +04D9 74 D5 0563 JZ PLSMNS +04DB 8A C5 0564 MOV AL,CH +04DD C3 0565 RET +04DE 0566 NOCON: +04DE 82 F9 2D 0567 CMP CL,"-" +04E1 75 ED 0568 JNZ NEXTERM +04E3 0569 BADOP: +04E3 B1 05 0570 MOV CL,5 +04E5 E9 C9 FD 0571 JMP ERROR +04E8 0572 +04E8 0573 TERM: +04E8 E8 40 00 0574 CALL FACTOR +04EB 0575 MULOP: +04EB 52 0576 PUSH DX ;Save value +04EC 50 0577 PUSH AX ;Save type +04ED E8 12 01 0578 CALL GETSYM +04F0 59 0579 POP CX +04F1 3C 2A 0580 CMP AL,"*" +04F3 74 04 0581 JZ GETFACT +04F5 3C 2F 0582 CMP AL,"/" +04F7 75 2E 0583 JNZ ENDTERM +04F9 0584 GETFACT: +04F9 0A C9 0585 OR CL,CL ;Can we operate on this type? +04FB 74 E6 0586 JZ BADOP +04FD 50 0587 PUSH AX ;Save operator +04FE E8 01 01 0588 CALL GETSYM ;Get past operator +0501 E8 27 00 0589 CALL FACTOR +0504 0A C0 0590 OR AL,AL +0506 74 DB 0591 JZ BADOP +0508 59 0592 POP CX ;Recover operator +0509 5D 0593 POP BP ;And current value +050A 95 0594 XCHG AX,BP ;Save AH in BP +050B 82 F9 2F 0595 CMP CL,"/" ;Do we divide? +050E 75 0E 0596 JNZ DOMUL +0510 0B D2 0597 OR DX,DX ;Dividing by zero? +0512 B1 29 0598 MOV CL,29H +0514 74 51 0599 JZ ERR2 +0516 8B DA 0600 MOV BX,DX +0518 33 D2 0601 XOR DX,DX ;Make 32-bit dividend +051A F7 F3 0602 DIV AX,BX +051C EB 02 0603 JMPS NEXFACT +051E 0604 DOMUL: +051E F7 E2 0605 MUL AX,DX +0520 0606 NEXFACT: +0520 8B D0 0607 MOV DX,AX ;Result in DX +0522 95 0608 XCHG AX,BP ;Restore flags to AH +0523 B0 FF 0609 MOV AL,-1 ;Indicate a number +0525 EB C4 0610 JMPS MULOP +0527 0611 ENDTERM: +0527 5A 0612 POP DX +0528 8A C1 0613 MOV AL,CL +052A C3 0614 RET +052B 0615 +052B 0616 FACTOR: +052B A0 30 21 0617 MOV AL,[SYM] +052E 3C 01 0618 CMP AL,CONST +0530 74 F8 0619 JZ RET +0532 3C 00 0620 CMP AL,UNDEFID +0534 74 5C 0621 JZ UVAL +0536 3C 28 0622 CMP AL,"(" +0538 74 48 0623 JZ PAREN +053A 3C 22 0624 CMP AL,'"' +053C 74 66 0625 JZ STRING +053E 3C 27 0626 CMP AL,"'" +0540 74 62 0627 JZ STRING +0542 3C 03 0628 CMP AL,XREG ;Only 16-bit register may index +0544 B1 14 0629 MOV CL,20 +0546 75 1F 0630 JNZ ERR2 +0548 F6 C4 01 0631 TEST AH,1 ;Check to see if indexing is OK +054B B1 01 0632 MOV CL,1 +054D 74 18 0633 JZ ERR2 +054F 8A C2 0634 MOV AL,DL +0551 B1 03 0635 MOV CL,3 +0553 2C 03 0636 SUB AL,3 ;Check for BX +0555 74 22 0637 JZ BXJ +0557 2C 02 0638 SUB AL,2 ;Check for BP +0559 74 1B 0639 JZ BPJ +055B FE C8 0640 DEC AL ;Check for SI +055D B1 04 0641 MOV CL,4 +055F 74 0C 0642 JZ SIJ +0561 FE C8 0643 DEC AL ;Check for DI +0563 74 05 0644 JZ DIJ +0565 B1 02 0645 MOV CL,2 ;Invalid base/index register +0567 E9 47 FD 0646 ERR2: JMP ERROR +056A 0647 +056A 0648 DIJ: +056A 80 CC 20 0649 OR AH,20H ;Flag seeing index register DI +056D 0650 SIJ: +056D F6 C4 10 0651 TEST AH,10H ;Check if already seen index register +0570 75 F5 0652 JNZ ERR2 +0572 80 CC 10 0653 OR AH,10H ;Flag seeing index register +0575 C3 0654 RET +0576 0655 +0576 0656 BPJ: +0576 80 CC 40 0657 OR AH,40H ;Flag seeing base register BP +0579 0658 BXJ: +0579 F6 C4 80 0659 TEST AH,80H ;Check if already seen base register +057C 75 E9 0660 JNZ ERR2 +057E 80 CC 80 0661 OR AH,80H ;Flag seeing base register +0581 C3 0662 RET +0582 0663 +0582 0664 PAREN: +0582 E8 7D 00 0665 CALL GETSYM ;Eat the "(" +0585 E8 12 FF 0666 CALL EXPRESSION +0588 82 3E 30 21 29 0667 CMP B,[SYM],")" ;Better have closing paren +058D B1 14 0668 MOV CL,20 +058F 75 10 0669 JNZ ERR30 +0591 C3 0670 RET +0592 0671 +0592 0672 UVAL: +0592 B1 06 0673 MOV CL,6 +0594 F6 C4 08 0674 TEST AH,8 ;Check if undefined label has been seen +0597 75 08 0675 JNZ ERR30 +0599 80 CC 08 0676 OR AH,8 ;Flag seeing undefined label +059C 89 1E DC 20 0677 MOV [UNDEF],BX +05A0 C3 0678 RET +05A1 0679 +05A1 E9 0D FD 0680 ERR30: JMP ERROR +05A4 0681 +05A4 0682 STRING: +05A4 8A E8 0683 MOV CH,AL +05A6 A0 2F 21 0684 MOV AL,[CHR] +05A9 3A C5 0685 CMP AL,CH +05AB B1 23 0686 MOV CL,35 +05AD 8A D0 0687 MOV DL,AL +05AF B6 00 0688 MOV DH,0 +05B1 75 03 0689 JNZ L0003 +05B3 E8 32 00 0690 CALL ZERLEN +05B6 0691 L0003: +05B6 E8 37 00 0692 CALL GETCHR +05B9 B1 25 0693 MOV CL,37 +05BB F6 C4 02 0694 TEST AH,2 +05BE 74 E1 0695 JZ ERR30 +05C0 F6 C4 04 0696 TEST AH,4 +05C3 B1 26 0697 MOV CL,38 +05C5 75 DA 0698 JNZ ERR30 +05C7 0699 STRGDAT: +05C7 8A C2 0700 MOV AL,DL +05C9 3C 0D 0701 CMP AL,EOL +05CB B1 27 0702 MOV CL,39 +05CD 74 D2 0703 JZ ERR30 +05CF E8 CA 05 0704 CALL PUT +05D2 A0 39 21 0705 MOV AL,[DATSIZ] +05D5 0A C0 0706 OR AL,AL +05D7 75 05 0707 JNZ BYTSIZ +05D9 8A C6 0708 MOV AL,DH +05DB E8 BE 05 0709 CALL PUT +05DE 0710 BYTSIZ: +05DE A0 2F 21 0711 MOV AL,[CHR] +05E1 8A D0 0712 MOV DL,AL +05E3 E8 0A 00 0713 CALL GETCHR +05E6 EB DF 0714 JP STRGDAT +05E8 0715 +05E8 0716 ZERLEN: +05E8 E8 CB FC 0717 CALL NEXTCHR +05EB 3A C5 0718 CMP AL,CH +05ED 75 B2 0719 JNZ ERR30 +05EF C3 0720 RET +05F0 0721 +05F0 0722 GETCHR: +05F0 E8 C3 FC 0723 CALL NEXTCHR +05F3 3A C5 0724 CMP AL,CH +05F5 75 F8 0725 JNZ RET +05F7 E8 BC FC 0726 CALL NEXTCHR +05FA 3A C5 0727 CMP AL,CH +05FC 74 F1 0728 JZ RET +05FE 5B 0729 POP BX ;Kill return address to STRGDAT loop +05FF B0 FF 0730 MOV AL,-1 ;Flag type as constant +0601 C3 0731 RET +0602 0732 +0602 0733 +0602 0734 GETSYM: +0602 0735 +0602 0736 ; The lexical scanner. Used only in the operand field. Returns with the token +0602 0737 ; in SYM and AL, sometimes with additional info in BX or DX. +0602 0738 ; +0602 0739 ; AL=SYM=0 Undefined label. BX has pointer to information fields. +0602 0740 ; +0602 0741 ; AL=SYM=1 Constant (or defined label). DX has value. +0602 0742 ; +0602 0743 ; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +0602 0744 ; respectively. DL has register number. +0602 0745 ; +0602 0746 ; AL=SYM=5 A mode flag (such as "B" for byte operation). Type of flag in DL +0602 0747 ; and also stored in FLAG: -1=no flags, 0=B, 1=W, 2=S, 3=L, 4=T. +0602 0748 ; +0602 0749 ; AL=SYM=6 8087 floating point register, ST(n) or ST. DL has register number. +0602 0750 ; +0602 0751 ; All other values are the ASCII code of the character. Note that this may +0602 0752 ; never be a letter or number. +0602 0753 +0602 50 0754 PUSH AX ;Save AH +0603 E8 21 00 0755 CALL GETSY +0606 58 0756 POP AX +0607 A0 30 21 0757 MOV AL,[SYM] +060A C3 0758 RET +060B 0759 +060B 0760 SCANB: +060B A0 2F 21 0761 MOV AL,[CHR] +060E 0762 SCANT: +060E 3C 20 0763 CMP AL,' ' +0610 74 04 0764 JZ NEXB +0612 3C 09 0765 CMP AL,9 +0614 75 F4 0766 JNZ RET +0616 0767 NEXB: +0616 E8 9D FC 0768 CALL NEXTCHR +0619 EB F3 0769 JP SCANT +061B 0770 +061B 0771 DOLLAR: +061B 8B 16 CC 20 0772 MOV DX,[OLDPC] +061F B0 01 0773 MOV AL,CONST +0621 A2 30 21 0774 MOV [SYM],AL +0624 0775 NEXTCHJ: +0624 E9 8F FC 0776 JMP NEXTCHR +0627 0777 +0627 0778 GETSY: +0627 E8 E1 FF 0779 CALL SCANB +062A 3C 24 0780 CMP AL,'$' +062C 74 ED 0781 JZ DOLLAR +062E A2 30 21 0782 MOV [SYM],AL +0631 0C 20 0783 OR AL,20H +0633 3C 7B 0784 CMP AL,'z'+1 +0635 73 ED 0785 JNC NEXTCHJ +0637 3C 61 0786 CMP AL,'a' +0639 72 03 0787 JC $+5 +063B E9 BF 00 0788 JMP LETTER +063E 3C 3A 0789 CMP AL,'9'+1 +0640 73 E2 0790 JNC NEXTCHJ +0642 3C 30 0791 CMP AL,'0' +0644 72 DE 0792 JC NEXTCHJ +0646 BB 30 21 0793 MOV BX,SYM +0649 C6 07 01 0794 MOV B,[BX],CONST +064C E8 83 00 0795 CALL READID +064F 4B 0796 DEC BX +0650 8A 07 0797 MOV AL,[BX] +0652 B1 07 0798 MOV CL,7 +0654 BB 00 00 0799 MOV BX,0 +0657 3C 68 0800 CMP AL,'h' +0659 75 03 0801 JNZ $+5 +065B E9 32 00 0802 JMP HEX +065E FE C1 0803 INC CL +0660 C7 06 56 21 DF 20 0804 MOV [IX],ID +0666 0805 DEC: +0666 8B 36 56 21 0806 MOV SI,[IX] +066A 8A 04 0807 MOV AL,[SI] +066C FF 06 56 21 0808 INC [IX] +0670 3C 3A 0809 CMP AL,'9'+1 +0672 72 03 0810 JC $+5 +0674 E9 3A FC 0811 JMP ERROR +0677 2C 30 0812 SUB AL,'0' +0679 8B D3 0813 MOV DX,BX +067B D1 E3 0814 SHL BX +067D D1 E3 0815 SHL BX +067F 03 DA 0816 ADD BX,DX +0681 D1 E3 0817 SHL BX +0683 8A D0 0818 MOV DL,AL +0685 B6 00 0819 MOV DH,0 +0687 03 DA 0820 ADD BX,DX +0689 FE CD 0821 DEC CH +068B 75 D9 0822 JNZ DEC +068D 87 DA 0823 XCHG DX,BX +068F C3 0824 RET +0690 0825 +0690 0826 HEX: +0690 BA DF 20 0827 MOV DX,ID +0693 FE CD 0828 DEC CH +0695 0829 HEX1: +0695 8B F2 0830 MOV SI,DX +0697 AC 0831 LODB +0698 42 0832 INC DX +0699 2C 30 0833 SUB AL,'0' +069B 3C 0A 0834 CMP AL,10 +069D 72 06 0835 JC GOTIT +069F 3C 37 0836 CMP AL,'g'-'0' +06A1 73 13 0837 JNC ERR4 +06A3 2C 27 0838 SUB AL,'a'-10-'0' +06A5 0839 GOTIT: +06A5 D1 E3 0840 SHL BX +06A7 D1 E3 0841 SHL BX +06A9 D1 E3 0842 SHL BX +06AB D1 E3 0843 SHL BX +06AD 02 D8 0844 ADD BL,AL +06AF FE CD 0845 DEC CH +06B1 75 E2 0846 JNZ HEX1 +06B3 87 DA 0847 XCHG DX,BX +06B5 C3 0848 RET +06B6 0849 +06B6 E9 F8 FB 0850 ERR4: JMP ERROR +06B9 0851 +06B9 0852 GETLET: +06B9 E8 4F FF 0853 CALL SCANB +06BC 3C 0D 0854 CMP AL,EOL +06BE F9 0855 STC +06BF 74 F4 0856 JZ RET +06C1 3C 3B 0857 CMP AL,';' +06C3 F9 0858 STC +06C4 74 EF 0859 JZ RET +06C6 B1 0A 0860 MOV CL,10 +06C8 0C 20 0861 OR AL,20H +06CA 3C 61 0862 CMP AL,'a' +06CC 72 E8 0863 JC ERR4 +06CE 3C 7B 0864 CMP AL,'z'+1 +06D0 73 E4 0865 JNC ERR4 +06D2 0866 READID: +06D2 BB DF 20 0867 MOV BX,ID +06D5 B5 00 0868 MOV CH,0 +06D7 0869 MOREID: +06D7 88 07 0870 MOV [BX],AL +06D9 FE C5 0871 INC CH +06DB 43 0872 INC BX +06DC E8 D7 FB 0873 CALL NEXTCHR +06DF 3C 30 0874 CMP AL,'0' +06E1 72 0E 0875 JC NOMORE +06E3 0C 20 0876 OR AL,20H +06E5 3C 7B 0877 CMP AL,'z'+1 +06E7 73 08 0878 JNC NOMORE +06E9 3C 3A 0879 CMP AL,'9'+1 +06EB 72 EA 0880 JC MOREID +06ED 3C 61 0881 CMP AL,'a' +06EF 73 E6 0882 JNC MOREID +06F1 0883 NOMORE: +06F1 8A C8 0884 MOV CL,AL +06F3 8A C5 0885 MOV AL,CH +06F5 A2 DE 20 0886 MOV [LENID],AL +06F8 0A C0 0887 OR AL,AL +06FA 8A C1 0888 MOV AL,CL +06FC C3 0889 RET +06FD 0890 +06FD 0891 LETTER: +06FD E8 D2 FF 0892 CALL READID +0700 8A C5 0893 MOV AL,CH +0702 FE C8 0894 DEC AL +0704 75 14 0895 JNZ NOFLG +0706 A0 DF 20 0896 MOV AL,[ID] +0709 B9 05 00 0897 MOV CX,5 +070C BF 40 07 0898 MOV DI,FLGTAB +070F FC 0899 UP +0710 F2 0900 REPNE +0711 AE 0901 SCAB ;See if one of B,W,S,L,T +0712 74 1A 0902 JZ SAVFLG ;Go save flag +0714 32 C0 0903 XOR AL,AL +0716 8A 2E DE 20 0904 MOV CH,[LENID] +071A 0905 NOFLG: +071A FE C8 0906 DEC AL +071C 53 0907 PUSH BX +071D 75 03 0908 JNZ L0004 +071F E8 5A 00 0909 CALL REGCHK +0722 0910 L0004: +0722 5B 0911 POP BX +0723 8A C6 0912 MOV AL,DH +0725 74 03 0913 JZ SYMSAV +0727 E8 F9 00 0914 CALL LOOKRET +072A 0915 SYMSAV: +072A A2 30 21 0916 MOV [SYM],AL +072D C3 0917 RET +072E 0918 +072E 0919 SAVFLG: +072E 8A D1 0920 MOV DL,CL ;Need flag type in DL +0730 86 0E D0 20 0921 XCHG [FLAG],CL +0734 82 F9 FF 0922 CMP CL,-1 +0737 B1 20 0923 MOV CL,32 +0739 B0 05 0924 MOV AL,5 +073B 74 ED 0925 JZ SYMSAV +073D E9 71 FB 0926 ERRJ3: JMP ERROR +0740 0927 +0740 74 6C 73 77 62 0928 FLGTAB: DB "tlswb" +0745 0929 +0745 0930 FPREG: +0745 0931 ;Have detected "ST" for 8087 floating point stack register +0745 B2 00 0932 MOV DL,0 ;Default is ST(0) +0747 E8 C1 FE 0933 CALL SCANB ;Get next character +074A 3C 28 0934 CMP AL,"(" ;Specifying register number? +074C 75 29 0935 JNZ HAVREG +074E 0936 ;Get register number +074E E8 65 FB 0937 CALL NEXTCHR ;Skip over the "(" +0751 E8 74 FC 0938 CALL GETOP ;A little recursion never hurt anybody +0754 3C 01 0939 CMP AL,CONST ;Better have found a constant +0756 B1 14 0940 MOV CL,20 ;Operand error if not +0758 75 E3 0941 JNZ ERRJ3 +075A 83 3E D8 20 00 0942 CMP [DLABEL],0 ;Constant must be defined +075F B1 1E 0943 MOV CL,30 +0761 75 DA 0944 JNZ ERRJ3 +0763 8B 16 D6 20 0945 MOV DX,[DATA] ;Get constant +0767 83 FA 07 0946 CMP DX,7 ;Constant must be in range 0-7 +076A B1 1F 0947 MOV CL,31 +076C 77 CF 0948 JA ERRJ3 +076E A0 30 21 0949 MOV AL,[SYM] +0771 3C 29 0950 CMP AL,")" +0773 B1 18 0951 MOV CL,24 +0775 75 C6 0952 JNZ ERRJ3 +0777 0953 HAVREG: +0777 B6 06 0954 MOV DH,FREG +0779 32 C0 0955 XOR AL,AL ;Zero set means register found +077B C3 0956 RET +077C 0957 +077C 0958 REGCHK: +077C BB DF 20 0959 MOV BX,ID +077F 81 3F 73 74 0960 CMP [BX],"s"+7400H ;"st" +0783 74 C0 0961 JZ FPREG +0785 8A 0F 0962 MOV CL,[BX] +0787 43 0963 INC BX +0788 8A 07 0964 MOV AL,[BX] +078A BB E7 07 0965 MOV BX,REGTAB +078D B6 03 0966 MOV DH,XREG +078F B2 00 0967 MOV DL,0 +0791 3C 78 0968 CMP AL,'x' +0793 74 3B 0969 JZ SCANREG +0795 B6 02 0970 MOV DH,REG +0797 3C 6C 0971 CMP AL,'l' +0799 74 35 0972 JZ SCANREG +079B B2 04 0973 MOV DL,4 +079D 3C 68 0974 CMP AL,'h' +079F 74 2F 0975 JZ SCANREG +07A1 B6 04 0976 MOV DH,SREG +07A3 B2 00 0977 MOV DL,0 +07A5 BB EB 07 0978 MOV BX,SEGTAB +07A8 3C 73 0979 CMP AL,'s' +07AA 74 24 0980 JZ SCANREG +07AC B6 03 0981 MOV DH,XREG +07AE 3C 70 0982 CMP AL,'p' +07B0 74 11 0983 JZ PREG +07B2 3C 69 0984 CMP AL,'i' +07B4 75 C5 0985 JNZ RET +07B6 B2 06 0986 MOV DL,6 +07B8 8A C1 0987 MOV AL,CL +07BA 3C 73 0988 CMP AL,'s' +07BC 74 BD 0989 JZ RET +07BE FE C2 0990 INC DL +07C0 3C 64 0991 CMP AL,'d' +07C2 C3 0992 RET +07C3 0993 PREG: +07C3 B2 04 0994 MOV DL,4 +07C5 8A C1 0995 MOV AL,CL +07C7 3C 73 0996 CMP AL,'s' +07C9 74 F7 0997 JZ RET +07CB FE C2 0998 INC DL +07CD 3C 62 0999 CMP AL,'b' +07CF C3 1000 RET +07D0 1001 SCANREG: +07D0 8A C1 1002 MOV AL,CL +07D2 B9 04 00 1003 MOV CX,4 +07D5 FC 1004 UP +07D6 8B FB 1005 MOV DI,BX +07D8 F2 1006 REPNZ +07D9 AE 1007 SCAB +07DA 8B DF 1008 MOV BX,DI +07DC 75 F1 1009 JNZ RET +07DE 8A C1 1010 MOV AL,CL +07E0 02 C2 1011 ADD AL,DL +07E2 8A D0 1012 MOV DL,AL +07E4 32 C0 1013 XOR AL,AL +07E6 C3 1014 RET +07E7 1015 +07E7 62 64 63 61 1016 REGTAB: DB 'bdca' +07EB 1017 +07EB 64 73 63 65 1018 SEGTAB: DB 'dsce' +07EF 1019 +07EF 1020 LOOK: +07EF 8A 2F 1021 MOV CH,[BX] +07F1 43 1022 INC BX +07F2 BA DF 20 1023 MOV DX,ID +07F5 E8 FA 00 1024 CALL CPSLP +07F8 74 EC 1025 JZ RET +07FA 34 80 1026 XOR AL,80H +07FC D0 C0 1027 ROL AL ;Make end-of-symbol bit least significant +07FE 8A C8 1028 MOV CL,AL +0800 4B 1029 DEC BX +0801 8A 07 1030 MOV AL,[BX] +0803 34 80 1031 XOR AL,80H +0805 D0 C0 1032 ROL AL +0807 3A C1 1033 CMP AL,CL +0809 73 04 1034 JNC SMALL +080B FE C5 1035 INC CH +080D FE C5 1036 INC CH +080F 1037 SMALL: +080F 8A D5 1038 MOV DL,CH +0811 B6 00 1039 MOV DH,0 +0813 03 DA 1040 ADD BX,DX +0815 8B 17 1041 MOV DX,[BX] +0817 43 1042 INC BX +0818 8A C2 1043 MOV AL,DL +081A 0A C6 1044 OR AL,DH +081C F9 1045 STC +081D 74 C7 1046 JZ RET +081F 87 DA 1047 XCHG DX,BX +0821 EB CC 1048 JP LOOK +0823 1049 +0823 1050 LOOKRET: +0823 8A C5 1051 MOV AL,CH +0825 3C 03 1052 CMP AL,3 ;RET has 3 letters +0827 75 4F 1053 JNZ LOOKUP +0829 4B 1054 DEC BX +082A 80 0F 80 1055 OR B,[BX],080H +082D BA 7F 20 1056 MOV DX,RETSTR+2 +0830 1057 CHKRET: +0830 8B F2 1058 MOV SI,DX +0832 AC 1059 LODB +0833 3A 07 1060 CMP AL,[BX] +0835 75 45 1061 JNZ LOOKIT +0837 4B 1062 DEC BX +0838 4A 1063 DEC DX +0839 FE CD 1064 DEC CH +083B 75 F3 1065 JNZ CHKRET +083D 8B 16 4E 21 1066 MOV DX,[LSTRET] +0841 8A C2 1067 MOV AL,DL +0843 22 C6 1068 AND AL,DH +0845 FE C0 1069 INC AL +0847 74 0F 1070 JZ ALLRET +0849 8B 1E CA 20 1071 MOV BX,[PC] +084D 2B DA 1072 SUB BX,DX +084F 8A C3 1073 MOV AL,BL +0851 98 1074 CBW +0852 3B C3 1075 CMP AX,BX ;Signed 8-bit number? +0854 B0 01 1076 MOV AL,1 +0856 74 8E 1077 JZ RET +0858 1078 ALLRET: +0858 8B 1E 50 21 1079 MOV BX,[RETPT] +085C 8A C7 1080 MOV AL,BH +085E 0A C3 1081 OR AL,BL +0860 B0 00 1082 MOV AL,0 +0862 75 82 1083 JNZ RET +0864 8B 1E 33 21 1084 MOV BX,[HEAP] +0868 4B 1085 DEC BX +0869 4B 1086 DEC BX +086A 4B 1087 DEC BX +086B 89 1E 33 21 1088 MOV [HEAP],BX +086F 32 C0 1089 XOR AL,AL +0871 88 07 1090 MOV [BX],AL +0873 89 1E 50 21 1091 MOV [RETPT],BX +0877 C3 1092 RET +0878 1093 +0878 1094 LOOKUP: +0878 4B 1095 DEC BX +0879 80 0F 80 1096 OR B,[BX],080H +087C 1097 LOOKIT: +087C 8B 1E 31 21 1098 MOV BX,[BASE] +0880 8A C7 1099 MOV AL,BH +0882 0A C3 1100 OR AL,BL +0884 74 1E 1101 JZ EMPTY +0886 E8 66 FF 1102 CALL LOOK +0889 72 10 1103 JC ENTER +088B BA 04 00 1104 MOV DX,4 +088E 03 DA 1105 ADD BX,DX +0890 8A 07 1106 MOV AL,[BX] +0892 0A C0 1107 OR AL,AL +0894 74 E1 1108 JZ RET +0896 43 1109 INC BX +0897 8B 17 1110 MOV DX,[BX] +0899 43 1111 INC BX +089A C3 1112 RET +089B 1113 +089B 1114 ENTER: +089B 53 1115 PUSH BX ;Save pointer to link field +089C E8 0D 00 1116 CALL CREATE ;Add the node +089F 5E 1117 POP SI +08A0 89 54 FF 1118 MOV [SI-1],DX ;Link new node +08A3 C3 1119 RET ;Zero was set by CREATE +08A4 1120 +08A4 1121 EMPTY: +08A4 E8 05 00 1122 CALL CREATE +08A7 89 16 31 21 1123 MOV [BASE],DX +08AB C3 1124 RET +08AC 1125 +08AC 1126 +08AC 1127 CREATE: +08AC 1128 +08AC 1129 ; Add a new node to the identifier tree. The identifier is at ID with +08AC 1130 ; bit 7 of the last character set to one. The length of the identifier is +08AC 1131 ; in LENID, which is ID-1. +08AC 1132 ; +08AC 1133 ; Node format: +08AC 1134 ; 1. Length of identifier (1 byte) +08AC 1135 ; 2. Identifier (1-80 bytes) +08AC 1136 ; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +08AC 1137 ; 4. Right link (0 if none larger) +08AC 1138 ; 5. Data field: +08AC 1139 ; a. Defined flag (0=undefined, 1=defined) +08AC 1140 ; b. Value (2 bytes) +08AC 1141 ; +08AC 1142 ; This routine returns with AL=zero and zero flag set (which indicates +08AC 1143 ; on return from LOOKUP that it has not yet been defined), DX points +08AC 1144 ; to start of new node, and BX points to data field of new node. +08AC 1145 +08AC A0 DE 20 1146 MOV AL,[LENID] +08AF 04 08 1147 ADD AL,8 ;Storage needed for the node +08B1 8B 1E 33 21 1148 MOV BX,[HEAP] +08B5 8A D0 1149 MOV DL,AL +08B7 B6 00 1150 MOV DH,0 +08B9 2B DA 1151 SUB BX,DX ;Heap grows downward +08BB 89 1E 33 21 1152 MOV [HEAP],BX +08BF 87 DA 1153 XCHG DX,BX +08C1 8B 1E 37 21 1154 MOV BX,[CODE] ;Check to make sure there's enough +08C5 3B DA 1155 CMP BX,DX +08C7 72 03 1156 JB $+5 +08C9 E9 A7 F9 1157 JMP ABORT +08CC 52 1158 PUSH DX +08CD BB DE 20 1159 MOV BX,LENID +08D0 8A 0F 1160 MOV CL,[BX] +08D2 FE C1 1161 INC CL +08D4 B5 00 1162 MOV CH,0 +08D6 FC 1163 UP +08D7 8B F3 1164 MOV SI,BX +08D9 8B FA 1165 MOV DI,DX +08DB F3 1166 REP +08DC A4 1167 MOVB ;Move identifier and length into node +08DD 8B D7 1168 MOV DX,DI +08DF 8B DE 1169 MOV BX,SI +08E1 B5 04 1170 MOV CH,4 +08E3 87 DA 1171 XCHG DX,BX +08E5 1172 NILIFY: +08E5 88 0F 1173 MOV [BX],CL ;Zero left and right links +08E7 43 1174 INC BX +08E8 FE CD 1175 DEC CH +08EA 75 F9 1176 JNZ NILIFY +08EC 32 C0 1177 XOR AL,AL ;Set zero flag +08EE 88 07 1178 MOV [BX],AL ;Zero defined flag +08F0 5A 1179 POP DX ;Restore pointer to node +08F1 C3 1180 RET +08F2 1181 +08F2 1182 CPSLP: +08F2 8B F2 1183 MOV SI,DX +08F4 AC 1184 LODB +08F5 3A 07 1185 CMP AL,[BX] +08F7 9F 1186 LAHF +08F8 42 1187 INC DX +08F9 43 1188 INC BX +08FA 9E 1189 SAHF +08FB 75 F4 1190 JNZ RET +08FD FE CD 1191 DEC CH +08FF 75 F1 1192 JNZ CPSLP +0901 C3 1193 RET +0902 1194 +0902 1195 GETLAB: +0902 BB 00 00 1196 MOV BX,0 +0905 89 1E CE 20 1197 MOV [LABPT],BX +0909 C6 06 D0 20 FF 1198 MOV B,[FLAG],-1 +090E B6 00 1199 MOV DH,0 +0910 A0 2F 21 1200 MOV AL,[CHR] +0913 3C 21 1201 CMP AL,' '+1 +0915 72 03 1202 JC NOT1 +0917 80 CE 01 1203 OR DH,001H +091A 1204 NOT1: +091A E8 9C FD 1205 CALL GETLET +091D 72 E2 1206 JC RET +091F 3C 3A 1207 CMP AL,':' +0921 75 05 1208 JNZ LABCHK +0923 E8 90 F9 1209 CALL NEXTCHR +0926 EB 07 1210 JP LABEL +0928 1211 LABCHK: +0928 0A C0 1212 OR AL,AL +092A F6 C6 01 1213 TEST DH,001H +092D 74 D2 1214 JZ RET +092F 1215 LABEL: +092F A0 4B 21 1216 MOV AL,[CHKLAB] +0932 0A C0 1217 OR AL,AL +0934 74 03 1218 JZ $+5 +0936 E9 80 FD 1219 JMP GETLET +0939 E8 3C FF 1220 CALL LOOKUP +093C B1 0B 1221 MOV CL,11 +093E 75 11 1222 JNZ ERR5 +0940 8B 16 CA 20 1223 MOV DX,[PC] +0944 C6 07 01 1224 MOV B,[BX],1 +0947 43 1225 INC BX +0948 89 17 1226 MOV [BX],DX +094A 89 1E CE 20 1227 MOV [LABPT],BX +094E E9 68 FD 1228 JMP GETLET +0951 1229 +0951 E9 5D F9 1230 ERR5: JMP ERROR +0954 1231 +0954 1232 ASMLIN: +0954 C6 06 D1 20 01 1233 MOV B,[MAXFLG],1 ;Allow only B and W flags normally +0959 8B 1E CA 20 1234 MOV BX,[PC] +095D 89 1E CC 20 1235 MOV [OLDPC],BX +0961 E8 9E FF 1236 CALL GETLAB +0964 73 03 1237 JNC $+5 +0966 E9 E8 F8 1238 JMP ENDLN +0969 BB DE 20 1239 MOV BX,LENID +096C 8A 07 1240 MOV AL,[BX] +096E B1 0C 1241 MOV CL,12 +0970 2C 02 1242 SUB AL,2 +0972 8A E8 1243 MOV CH,AL +0974 72 DB 1244 JC ERR5 +0976 43 1245 INC BX +0977 82 3F 66 1246 CMP B,[BX],"f" ;See if an 8087 mnemonic +097A 74 4C 1247 JZ NDPOP +097C 3C 05 1248 CMP AL,5 +097E 73 D1 1249 JNC ERR5 +0980 8A 07 1250 MOV AL,[BX] +0982 2C 61 1251 SUB AL,'a' +0984 8A C8 1252 MOV CL,AL +0986 02 C0 1253 ADD AL,AL +0988 02 C0 1254 ADD AL,AL +098A 02 C1 1255 ADD AL,CL +098C 02 C5 1256 ADD AL,CH +098E 02 C0 1257 ADD AL,AL +0990 BB D0 1A 1258 MOV BX,OPTAB +0993 8A D0 1259 MOV DL,AL +0995 B6 00 1260 MOV DH,0 +0997 03 DA 1261 ADD BX,DX +0999 8B 1F 1262 MOV BX,[BX] +099B FE C5 1263 INC CH +099D 8A CD 1264 MOV CL,CH +099F 8A 27 1265 MOV AH,[BX] +09A1 43 1266 INC BX +09A2 0A E4 1267 OR AH,AH +09A4 74 18 1268 JZ OPERR +09A6 1269 FINDOP: +09A6 8A E9 1270 MOV CH,CL +09A8 BA E0 20 1271 MOV DX,ID+1 +09AB 95 1272 XCHG AX,BP ;Save count of opcodes in BP +09AC E8 43 FF 1273 CALL CPSLP +09AF 74 12 1274 JZ HAVOP +09B1 95 1275 XCHG AX,BP +09B2 B6 00 1276 MOV DH,0 +09B4 8A D5 1277 MOV DL,CH +09B6 42 1278 INC DX +09B7 42 1279 INC DX +09B8 03 DA 1280 ADD BX,DX +09BA FE CC 1281 DEC AH +09BC 75 E8 1282 JNZ FINDOP +09BE 1283 OPERR: +09BE B1 0C 1284 MOV CL,12 +09C0 E9 EE F8 1285 JMP ERROR +09C3 1286 +09C3 1287 HAVOP: +09C3 8A 47 02 1288 MOV AL,[BX+2] ;Get opcode +09C6 FF 27 1289 JMP [BX] +09C8 1290 +09C8 1291 NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") +09C8 C6 06 D1 20 04 1292 MOV B,[MAXFLG],4 ;Allow all type flags +09CD 43 1293 INC BX +09CE 82 3F 6E 1294 CMP B,[BX],"n" ;"No-wait" form? +09D1 B4 00 1295 MOV AH,0 +09D3 75 05 1296 JNZ SAVNFLG +09D5 B4 01 1297 MOV AH,1 +09D7 FE C8 1298 DEC AL +09D9 43 1299 INC BX ;Skip over the "N" +09DA 1300 SAVNFLG: +09DA 88 26 55 21 1301 MOV [NOWAIT],AH ;0 for wait, 1 for no wait +09DE 3C 01 1302 CMP AL,1 +09E0 72 DC 1303 JB OPERR ;Not enough char left for valid opcode? +09E2 3C 05 1304 CMP AL,5 +09E4 77 D8 1305 JA OPERR ;Too many? +09E6 98 1306 CBW +09E7 92 1307 XCHG AX,DX ;Save length in DX +09E8 8B F2 1308 MOV SI,DX +09EA 80 08 80 1309 OR B,[SI+BX],80H ;Set high bit of last character +09ED 8A 07 1310 MOV AL,[BX] ;Get first char of opcode +09EF 43 1311 INC BX +09F0 2C 61 1312 SUB AL,"a" +09F2 72 28 1313 JB TRY2XM1 ;Go see if opcode starts with "2" +09F4 3C 19 1314 CMP AL,"z"-"a" +09F6 77 C6 1315 JA OPERR +09F8 98 1316 CBW +09F9 D1 E0 1317 SHL AX ;Double to index into address table +09FB 96 1318 XCHG AX,SI ;Put in index register +09FC 8B BC D4 1B 1319 MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +0A00 1320 LOOKNDP: +0A00 8A 25 1321 MOV AH,[DI] ;Number of opcodes starting with this letter +0A02 0A E4 1322 OR AH,AH +0A04 74 B8 1323 JZ OPERR ;Any start with this letter? +0A06 1324 FNDNDP: +0A06 47 1325 INC DI +0A07 8B F3 1326 MOV SI,BX ;Pointer to start of opcode +0A09 8B CA 1327 MOV CX,DX ;Get length of opcode +0A0B F3 1328 REPE +0A0C A6 1329 CMPB ;Compare opcode to table entry +0A0D 74 38 1330 JZ HAVNDP +0A0F 4F 1331 DEC DI ;Back up in case that was last letter +0A10 B0 80 1332 MOV AL,80H ;Look for char with high bit set +0A12 1333 ENDOP: +0A12 AE 1334 SCASB +0A13 77 FD 1335 JA ENDOP +0A15 47 1336 INC DI ;Skip over info about opcode +0A16 FE CC 1337 DEC AH +0A18 75 EC 1338 JNZ FNDNDP +0A1A EB A2 1339 OPERRJ: JP OPERR +0A1C 1340 +0A1C 1341 TRY2XM1: +0A1C 3C D1 1342 CMP AL,"2"-"a" +0A1E 75 9E 1343 JNZ OPERR +0A20 BF 5E 19 1344 MOV DI,XM1 +0A23 EB DB 1345 JP LOOKNDP +0A25 1346 +0A25 1347 SPECIALOP: +0A25 24 07 1348 AND AL,7 ;Mask to special op number +0A27 74 16 1349 JZ FWAIT ;If zero, go handle FWAIT +0A29 1350 ;Handle FNOP +0A29 82 3E 55 21 00 1351 CMP B,[NOWAIT],0 ;Was "N" present (If not opcode was "FOP") +0A2E 74 8E 1352 JZ OPERR +0A30 B0 9B 1353 MOV AL,9BH ;Need Wait opcode after all +0A32 E8 67 01 1354 CALL PUT +0A35 B0 D9 1355 MOV AL,0D9H +0A37 E8 62 01 1356 CALL PUT +0A3A B0 D0 1357 MOV AL,0D0H +0A3C E9 5D 01 1358 JMP PUT +0A3F 1359 +0A3F 1360 FWAIT: +0A3F 82 3E 55 21 00 1361 CMP B,[NOWAIT],0 ;"FNWAIT" not legal +0A44 75 D4 1362 JNZ OPERRJ +0A46 C3 1363 RET ;Nothing to do - "WAIT" already sent +0A47 1364 +0A47 1365 HAVNDP: +0A47 8B F7 1366 MOV SI,DI +0A49 82 3E 55 21 00 1367 CMP B,[NOWAIT],0 +0A4E 75 05 1368 JNZ NWAIT +0A50 B0 9B 1369 MOV AL,9BH ;Wait opcode +0A52 E8 47 01 1370 CALL PUT +0A55 1371 NWAIT: +0A55 AD 1372 LODW ;Get opcode info +0A56 A8 F8 1373 TEST AL,0F8H ;Any operand bits set? +0A58 74 66 1374 JZ NOOPS ;If no operands, output code +0A5A A8 78 1375 TEST AL,78H ;Special case? +0A5C 74 C7 1376 JZ SPECIALOP +0A5E 50 1377 PUSH AX +0A5F E8 A0 FB 1378 CALL GETSYM ;See if any operands +0A62 59 1379 POP CX +0A63 3C 3B 1380 CMP AL,";" +0A65 74 52 1381 JZ NOOPCHK +0A67 3C 0D 1382 CMP AL,EOL +0A69 74 4E 1383 JZ NOOPCHK +0A6B 3C 06 1384 CMP AL,FREG ;Is it 8087 register? +0A6D 75 6F 1385 JNZ MEMOP +0A6F 91 1386 XCHG AX,CX +0A70 A8 40 1387 TEST AL,ONEREG ;One register OK as operand? +0A72 75 36 1388 JNZ PUTREG ;Yes - save it +0A74 A8 20 1389 TEST AL,20H ;Memory-only operation? +0A76 B1 14 1390 MOV CL,20 +0A78 75 61 1391 JNZ ERRJ4 +0A7A A8 18 1392 TEST AL,18H ;Two-register operation? +0A7C 7A 5D 1393 JPE ERRJ4 ;Must be exactly one bit set +0A7E 52 1394 PUSH DX ;Save register number +0A7F 50 1395 PUSH AX ;Save opcode +0A80 E8 7F FB 1396 CALL GETSYM +0A83 3C 2C 1397 CMP AL,"," +0A85 B1 15 1398 MOV CL,15H +0A87 75 52 1399 JNZ ERRJ4 +0A89 E8 76 FB 1400 CALL GETSYM +0A8C B1 14 1401 MOV CL,20 +0A8E 3C 06 1402 CMP AL,FREG +0A90 75 49 1403 JNZ ERRJ4 +0A92 58 1404 POP AX +0A93 5B 1405 POP BX +0A94 34 02 1406 XOR AL,2 ;Flip "POP" bit +0A96 24 FB 1407 AND AL,0FBH ;Reset direction bit to ST(0) +0A98 0A DB 1408 OR BL,BL ;Is first register ST(0)? +0A9A 74 0A 1409 JZ ST0DEST +0A9C 87 DA 1410 XCHG DX,BX +0A9E 0A DB 1411 OR BL,BL ;One of these must be ST(0) +0AA0 75 39 1412 JNZ ERRJ4 +0AA2 34 04 1413 XOR AL,4 ;Flip direction +0AA4 EB 04 1414 JMPS PUTREG +0AA6 1415 ST0DEST: +0AA6 A8 02 1416 TEST AL,2 ;Is POP bit set? +0AA8 75 31 1417 JNZ ERRJ4 ;Don't allow destination ST(0) then pop +0AAA 1418 PUTREG: +0AAA 80 E4 F8 1419 AND AH,0F8H ;Zero out register field +0AAD 0A E2 1420 OR AH,DL +0AAF 80 CC C0 1421 OR AH,0C0H +0AB2 50 1422 PUSH AX +0AB3 E8 4C FB 1423 CALL GETSYM ;Get to next symbol +0AB6 58 1424 POP AX +0AB7 EB 07 1425 JMPS NOOPS +0AB9 1426 +0AB9 1427 NOOPCHK: +0AB9 91 1428 XCHG AX,CX +0ABA A8 80 1429 TEST AL,80H ;Is no operands OK? +0ABC B1 14 1430 MOV CL,20 +0ABE 75 1B 1431 JNZ ERRJ4 +0AC0 1432 NOOPS: +0AC0 1433 ;First test for FDIV or FSUB and reverse "R" bit if "D" bit is set +0AC0 50 1434 PUSH AX +0AC1 25 05 E0 1435 AND AX,0E005H +0AC4 3D 04 E0 1436 CMP AX,0E004H +0AC7 58 1437 POP AX +0AC8 75 03 1438 JNZ NOREV +0ACA 80 F4 08 1439 XOR AH,8 ;Reverse "R" bit +0ACD 1440 NOREV: +0ACD 24 07 1441 AND AL,7 +0ACF 0C D8 1442 OR AL,0D8H ;ESC hook +0AD1 E8 C8 00 1443 CALL PUT +0AD4 8A C4 1444 MOV AL,AH +0AD6 E9 C3 00 1445 JMP PUT +0AD9 1446 +0AD9 1447 BADFLAG: +0AD9 B1 20 1448 MOV CL,20H +0ADB E9 D3 F7 1449 ERRJ4: JMP ERROR +0ADE 1450 +0ADE 1451 MEMOP: +0ADE 51 1452 PUSH CX ;Save opcode +0ADF E8 E9 F8 1453 CALL GETOP1 ;Get memory operand +0AE2 3C 00 1454 CMP AL,UNDEFID ;Is it? +0AE4 B1 14 1455 MOV CL,20 +0AE6 75 F3 1456 JNZ ERRJ4 +0AE8 58 1457 POP AX +0AE9 A8 20 1458 TEST AL,20H ;Does it have memory format field? +0AEB 75 08 1459 JNZ GETFORMAT +0AED A8 08 1460 TEST AL,8 ;Check if any memory operand legal +0AEF 74 EA 1461 JZ ERRJ4 +0AF1 A8 10 1462 TEST AL,10H ;Check for 2-op arithmetic +0AF3 75 1E 1463 JNZ PUTMEM ;If not, just use as plain memory op +0AF5 1464 GETFORMAT: +0AF5 24 F9 1465 AND AL,0F9H ;Zero memory format bits +0AF7 8A 0E D0 20 1466 MOV CL,[FLAG] +0AFB FE C9 1467 DEC CL ;Must now be in range 0-3 +0AFD 7C DA 1468 JL BADFLAG +0AFF 8A E8 1469 MOV CH,AL ;Save opcode byte +0B01 D0 E8 1470 SHR AL ;Put format bits in bits 2 & 3 +0B03 24 0C 1471 AND AL,0CH +0B05 0A C1 1472 OR AL,CL ;Combine format bits with flag +0B07 BB 23 0B 1473 MOV BX,FORMATTAB +0B0A D7 1474 XLAT +0B0B 0A C0 1475 OR AL,AL ;Valid combination? +0B0D 78 CA 1476 JS BADFLAG +0B0F 0A E0 1477 OR AH,AL ;Possibly set new bits in second byte +0B11 0A C5 1478 OR AL,CH ;Set memory format bits +0B13 1479 PUTMEM: +0B13 24 07 1480 AND AL,7 +0B15 0C D8 1481 OR AL,0D8H +0B17 E8 82 00 1482 CALL PUT +0B1A 8A C4 1483 MOV AL,AH +0B1C 24 38 1484 AND AL,38H +0B1E 0A C2 1485 OR AL,DL ;Combine addressing mode +0B20 E9 39 01 1486 JMP PUTADD +0B23 1487 +0B23 1488 FORMATTAB: +0B23 1489 ;There are 16 entries in this table. The 4-bit index is built like this: +0B23 1490 ; Bit 3 0 for normal memory ops, 1 if extended is OK +0B23 1491 ; Bit 2 0 for integer, 1 for real +0B23 1492 ; Bit 0 & 1 Flag: 00=W, 01=S, 10=L, 11=T +0B23 1493 ; +0B23 1494 ;The entries in the table are used as two 3-bit fields. Bits 0-2 are ORed +0B23 1495 ;into the first byte of the opcode for the Memory Format field. Bits 3-6 +0B23 1496 ;are ORed into the second byte to modify the opcode for extended operands. +0B23 1497 ;If bit 7 is set, then that combination is illegal. +0B23 1498 +0B23 06 02 80 80 1499 DB 6,2,80H,80H ;Normal integers +0B27 80 00 04 80 1500 DB 80H,0,4,80H ;Normal reals +0B2B 06 02 2E 80 1501 DB 6,2,2EH,80H ;Extended integers +0B2F 80 00 04 2B 1502 DB 80H,0,4,2BH ;Extended reals +0B33 1503 +0B33 1504 GRP1: +0B33 B9 09 8A 1505 MOV CX,8A09H +0B36 E8 B3 F7 1506 CALL MROPS +0B39 B9 C6 00 1507 MOV CX,0C6H +0B3C 8A C7 1508 MOV AL,BH +0B3E 3C 00 1509 CMP AL,UNDEFID +0B40 75 03 1510 JNZ L0006 +0B42 E8 3C 00 1511 CALL STIMM +0B45 1512 L0006: +0B45 24 01 1513 AND AL,1 +0B47 74 0A 1514 JZ BYTIMM +0B49 B0 B8 1515 MOV AL,0B8H +0B4B 0A C3 1516 OR AL,BL +0B4D E8 4C 00 1517 CALL PUT +0B50 E9 98 00 1518 JMP PUTWOR +0B53 1519 +0B53 1520 BYTIMM: +0B53 B0 B0 1521 MOV AL,0B0H +0B55 0A C3 1522 OR AL,BL +0B57 E8 42 00 1523 CALL PUT +0B5A E9 95 00 1524 PUTBJ: JMP PUTBYT +0B5D 1525 +0B5D 1526 IMMED: +0B5D 8A C7 1527 MOV AL,BH +0B5F 3C 00 1528 CMP AL,UNDEFID +0B61 74 1E 1529 JZ STIMM +0B63 8A C3 1530 MOV AL,BL +0B65 0A C0 1531 OR AL,AL +0B67 74 32 1532 JZ RET +0B69 8A C7 1533 MOV AL,BH +0B6B E8 1E 00 1534 CALL IMM +0B6E 0C C0 1535 OR AL,0C0H +0B70 E8 29 00 1536 CALL PUT +0B73 1537 FINIMM: +0B73 8A C1 1538 MOV AL,CL +0B75 59 1539 POP CX +0B76 A8 01 1540 TEST AL,1 +0B78 74 E0 1541 JZ PUTBJ +0B7A 3C 83 1542 CMP AL,83H +0B7C 74 DC 1543 JZ PUTBJ +0B7E E9 6A 00 1544 JMP PUTWOR +0B81 1545 +0B81 1546 STIMM: +0B81 A0 D0 20 1547 MOV AL,[FLAG] +0B84 E8 05 00 1548 CALL IMM +0B87 E8 D2 00 1549 CALL PUTADD +0B8A EB E7 1550 JP FINIMM +0B8C 1551 +0B8C 1552 IMM: +0B8C 24 01 1553 AND AL,1 +0B8E 0A C1 1554 OR AL,CL +0B90 8A C8 1555 MOV CL,AL +0B92 E8 07 00 1556 CALL PUT +0B95 8A C5 1557 MOV AL,CH +0B97 24 38 1558 AND AL,38H +0B99 0A C3 1559 OR AL,BL +0B9B C3 1560 RET +0B9C 1561 +0B9C 1562 PUT: +0B9C 1563 ;Save byte in AL as pure code, with intermediate code bits 00. AL and +0B9C 1564 ;DI destroyed, no other registers affected. +0B9C 53 1565 PUSH BX +0B9D 51 1566 PUSH CX +0B9E B5 00 1567 MOV CH,0 ;Flag as pure code +0BA0 E8 03 00 1568 CALL GEN +0BA3 59 1569 POP CX +0BA4 5B 1570 POP BX +0BA5 C3 1571 RET +0BA6 1572 +0BA6 1573 GEN: +0BA6 1574 ;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. +0BA6 E8 34 00 1575 CALL PUTINC ;Save it and bump code pointer +0BA9 1576 GEN1: +0BA9 A0 3A 21 1577 MOV AL,[RELOC] +0BAC D0 D5 1578 RCL CH +0BAE D0 D0 1579 RCL AL +0BB0 D0 D5 1580 RCL CH +0BB2 D0 D0 1581 RCL AL +0BB4 A2 3A 21 1582 MOV [RELOC],AL +0BB7 BB 3B 21 1583 MOV BX,BCOUNT +0BBA FE 0F 1584 DEC B,[BX] +0BBC 75 E7 1585 JNZ RET +0BBE C6 07 04 1586 MOV B,[BX],4 +0BC1 BB 3A 21 1587 MOV BX,RELOC +0BC4 8A 07 1588 MOV AL,[BX] +0BC6 C6 07 00 1589 MOV B,[BX],0 +0BC9 8B 3E 58 21 1590 MOV DI,[IY] +0BCD 88 05 1591 MOV [DI],AL +0BCF 8B 1E 37 21 1592 MOV BX,[CODE] +0BD3 89 1E 58 21 1593 MOV [IY],BX +0BD7 43 1594 INC BX +0BD8 89 1E 37 21 1595 MOV [CODE],BX +0BDC C3 1596 RET +0BDD 1597 +0BDD 1598 PUTINC: +0BDD FF 06 CA 20 1599 INC [PC] +0BE1 1600 PUTCD: +0BE1 8B 3E 37 21 1601 MOV DI,[CODE] +0BE5 AA 1602 STOB +0BE6 89 3E 37 21 1603 MOV [CODE],DI +0BEA C3 1604 RET +0BEB 1605 +0BEB 1606 PUTWOR: +0BEB 1607 ;Save the word value described by [DLABEL] and [DATA] as code. If defined, +0BEB 1608 ;two bytes of pure code will be produced. Otherwise, appropriate intermediate +0BEB 1609 ;code will be generated. +0BEB 51 1610 PUSH CX +0BEC B5 80 1611 MOV CH,80H +0BEE 52 1612 PUSH DX +0BEF 53 1613 PUSH BX +0BF0 EB 20 1614 JP PUTBW +0BF2 1615 +0BF2 1616 PUTBYT: +0BF2 1617 ;Same as PUTWOR, above, but for byte value. +0BF2 51 1618 PUSH CX +0BF3 B5 40 1619 MOV CH,40H +0BF5 52 1620 PUSH DX +0BF6 53 1621 PUSH BX +0BF7 8B 1E D8 20 1622 MOV BX,[DLABEL] +0BFB 8A C7 1623 MOV AL,BH +0BFD 0A C3 1624 OR AL,BL +0BFF 75 11 1625 JNZ PUTBW +0C01 8B 1E D6 20 1626 MOV BX,[DATA] +0C05 0A C7 1627 OR AL,BH +0C07 74 09 1628 JZ PUTBW +0C09 FE C7 1629 INC BH +0C0B 74 05 1630 JZ PUTBW +0C0D B1 1F 1631 MOV CL,31 +0C0F E9 9F F6 1632 JMP ERROR +0C12 1633 PUTBW: +0C12 8B 16 D8 20 1634 MOV DX,[DLABEL] +0C16 8B 1E D6 20 1635 MOV BX,[DATA] +0C1A 1636 PUTCHK: +0C1A 0B D2 1637 OR DX,DX +0C1C 74 25 1638 JZ NOUNDEF +0C1E 8A C2 1639 MOV AL,DL +0C20 E8 BE FF 1640 CALL PUTCD +0C23 8A C6 1641 MOV AL,DH +0C25 E8 B9 FF 1642 CALL PUTCD +0C28 8A C3 1643 MOV AL,BL +0C2A E8 B0 FF 1644 CALL PUTINC +0C2D 8A C7 1645 MOV AL,BH +0C2F F6 C5 80 1646 TEST CH,080H +0C32 74 05 1647 JZ SMPUT +0C34 E8 6F FF 1648 CALL GEN +0C37 EB 06 1649 JP PRET +0C39 1650 SMPUT: +0C39 E8 A5 FF 1651 CALL PUTCD +0C3C E8 6A FF 1652 CALL GEN1 +0C3F 1653 PRET: +0C3F 5B 1654 POP BX +0C40 5A 1655 POP DX +0C41 59 1656 POP CX +0C42 C3 1657 RET +0C43 1658 +0C43 1659 NOUNDEF: +0C43 8A C3 1660 MOV AL,BL +0C45 8A CF 1661 MOV CL,BH +0C47 51 1662 PUSH CX +0C48 B5 00 1663 MOV CH,0 +0C4A E8 59 FF 1664 CALL GEN +0C4D 59 1665 POP CX +0C4E 8A C1 1666 MOV AL,CL +0C50 F6 C5 80 1667 TEST CH,080H +0C53 B5 00 1668 MOV CH,0 +0C55 74 E8 1669 JZ PRET +0C57 E8 4C FF 1670 CALL GEN +0C5A EB E3 1671 JP PRET +0C5C 1672 +0C5C 1673 PUTADD: +0C5C 1674 ;Save complete addressing mode. Addressing mode is in AL; if this is a register +0C5C 1675 ;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +0C5C 1676 ;the details of the addressing mode will be investigated and the optional one- +0C5C 1677 ;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. +0C5C 51 1678 PUSH CX +0C5D 52 1679 PUSH DX +0C5E 53 1680 PUSH BX +0C5F B5 00 1681 MOV CH,0 +0C61 8A C8 1682 MOV CL,AL +0C63 E8 40 FF 1683 CALL GEN ;Save the addressing mode as pure code +0C66 8A C1 1684 MOV AL,CL +0C68 B5 80 1685 MOV CH,80H +0C6A 24 C7 1686 AND AL,0C7H +0C6C 3C 06 1687 CMP AL,6 +0C6E 74 0A 1688 JZ TWOBT ;Direct address? +0C70 24 C0 1689 AND AL,0C0H +0C72 74 CB 1690 JZ PRET ;Indirect through reg, no displacement? +0C74 3C C0 1691 CMP AL,0C0H +0C76 74 C7 1692 JZ PRET ;Register to register operation? +0C78 8A E8 1693 MOV CH,AL ;Save whether one- or two-byte displacement +0C7A 1694 TWOBT: +0C7A 8B 1E D2 20 1695 MOV BX,[ADDR] +0C7E 8B 16 D4 20 1696 MOV DX,[ALABEL] +0C82 EB 96 1697 JP PUTCHK +0C84 1698 +0C84 1699 GRP2: +0C84 E8 41 F7 1700 CALL GETOP +0C87 B9 30 FF 1701 MOV CX,0FF30H +0C8A 3C 00 1702 CMP AL,UNDEFID +0C8C 74 14 1703 JZ PMEM +0C8E B5 50 1704 MOV CH,50H +0C90 3C 03 1705 CMP AL,XREG +0C92 74 1A 1706 JZ PXREG +0C94 B5 06 1707 MOV CH,6 +0C96 3C 04 1708 CMP AL,SREG +0C98 75 03 1709 JNZ $+5 +0C9A E9 01 04 1710 JMP PACKREG +0C9D B1 14 1711 MOV CL,20 +0C9F E9 0F F6 1712 JMP ERROR +0CA2 1713 +0CA2 1714 PMEM: +0CA2 8A C5 1715 MOV AL,CH +0CA4 E8 F5 FE 1716 CALL PUT +0CA7 8A C1 1717 MOV AL,CL +0CA9 0A C2 1718 OR AL,DL +0CAB E9 AE FF 1719 JMP PUTADD +0CAE 1720 +0CAE 1721 PXREG: +0CAE 8A C5 1722 MOV AL,CH +0CB0 0A C2 1723 OR AL,DL +0CB2 E9 E7 FE 1724 JMP PUT +0CB5 1725 +0CB5 1726 GRP3: +0CB5 E8 10 F7 1727 CALL GETOP +0CB8 52 1728 PUSH DX +0CB9 E8 03 F7 1729 CALL GETOP2 +0CBC 5B 1730 POP BX +0CBD B9 14 86 1731 MOV CX,8614H +0CC0 B0 04 1732 MOV AL,SREG +0CC2 3A C7 1733 CMP AL,BH +0CC4 74 4C 1734 JZ ERR6 +0CC6 3A C6 1735 CMP AL,DH +0CC8 74 48 1736 JZ ERR6 +0CCA B0 01 1737 MOV AL,CONST +0CCC 3A C7 1738 CMP AL,BH +0CCE 74 42 1739 JZ ERR6 +0CD0 3A C6 1740 CMP AL,DH +0CD2 74 3E 1741 JZ ERR6 +0CD4 B0 00 1742 MOV AL,UNDEFID +0CD6 3A C7 1743 CMP AL,BH +0CD8 74 2D 1744 JZ EXMEM +0CDA 3A C6 1745 CMP AL,DH +0CDC 74 2B 1746 JZ EXMEM1 +0CDE 8A C7 1747 MOV AL,BH +0CE0 3A C6 1748 CMP AL,DH +0CE2 B1 16 1749 MOV CL,22 +0CE4 75 2C 1750 JNZ ERR6 +0CE6 3C 03 1751 CMP AL,XREG +0CE8 74 03 1752 JZ L0008 +0CEA E8 38 F6 1753 CALL RR1 +0CED 1754 L0008: ;RR1 never returns +0CED 8A C3 1755 MOV AL,BL +0CEF 0A C0 1756 OR AL,AL +0CF1 74 0D 1757 JZ EXACC +0CF3 87 DA 1758 XCHG DX,BX +0CF5 8A C3 1759 MOV AL,BL +0CF7 0A C0 1760 OR AL,AL +0CF9 8A C7 1761 MOV AL,BH +0CFB 74 03 1762 JZ EXACC +0CFD E8 25 F6 1763 CALL RR1 +0D00 1764 EXACC: +0D00 B0 90 1765 MOV AL,90H +0D02 0A C2 1766 OR AL,DL +0D04 E9 95 FE 1767 JMP PUT +0D07 1768 +0D07 1769 EXMEM: +0D07 87 DA 1770 XCHG DX,BX +0D09 1771 EXMEM1: +0D09 3A C7 1772 CMP AL,BH +0D0B 74 05 1773 JZ ERR6 +0D0D B1 01 1774 MOV CL,1 ;Flag word as OK +0D0F E8 8D F6 1775 CALL NOTAC ;NOTAC never returns +0D12 E9 9C F5 1776 ERR6: JMP ERROR +0D15 1777 +0D15 1778 GRP4: +0D15 50 1779 PUSH AX +0D16 E8 AF F6 1780 CALL GETOP +0D19 59 1781 POP CX +0D1A 86 CD 1782 XCHG CL,CH +0D1C 3C 01 1783 CMP AL,CONST +0D1E 74 13 1784 JZ FIXED +0D20 2C 03 1785 SUB AL,XREG +0D22 FE CA 1786 DEC DL +0D24 FE CA 1787 DEC DL +0D26 0A C2 1788 OR AL,DL +0D28 B1 14 1789 MOV CL,20 +0D2A 75 E6 1790 JNZ ERR6 +0D2C 8A C5 1791 MOV AL,CH +0D2E 0C 08 1792 OR AL,8 +0D30 E9 69 FE 1793 JMP PUT +0D33 1794 FIXED: +0D33 8A C5 1795 MOV AL,CH +0D35 E8 64 FE 1796 CALL PUT +0D38 E9 B7 FE 1797 JMP PUTBYT +0D3B 1798 +0D3B 1799 GRP5: +0D3B 50 1800 PUSH AX +0D3C E8 89 F6 1801 CALL GETOP +0D3F B1 14 1802 MOV CL,20 +0D41 3C 01 1803 CMP AL,CONST +0D43 75 CD 1804 JNZ ERR6 +0D45 8B 1E D8 20 1805 MOV BX,[DLABEL] +0D49 8A C7 1806 MOV AL,BH +0D4B 0A C3 1807 OR AL,BL +0D4D B1 1E 1808 MOV CL,30 +0D4F 75 C1 1809 JNZ ERR6 +0D51 8B 1E D6 20 1810 MOV BX,[DATA] +0D55 58 1811 POP AX +0D56 0A C0 1812 OR AL,AL +0D58 74 43 1813 JZ ORG +0D5A FE C8 1814 DEC AL +0D5C 74 19 1815 JZ DSJ +0D5E FE C8 1816 DEC AL +0D60 74 27 1817 JZ EQU +0D62 FE C8 1818 DEC AL +0D64 74 03 1819 JZ $+5 +0D66 E9 98 03 1820 JMP IF +0D69 1821 PUTOP: +0D69 B0 FD 1822 MOV AL,-3 +0D6B EB 36 1823 JP NEWLOC +0D6D 1824 ALIGN: +0D6D A0 CA 20 1825 MOV AL,[PC] +0D70 24 01 1826 AND AL,1 +0D72 74 28 1827 JZ RET +0D74 BB 01 00 1828 MOV BX,1 +0D77 1829 DSJ: +0D77 87 DA 1830 XCHG DX,BX +0D79 8B 1E CA 20 1831 MOV BX,[PC] +0D7D 03 DA 1832 ADD BX,DX +0D7F 89 1E CA 20 1833 MOV [PC],BX +0D83 87 DA 1834 XCHG DX,BX +0D85 B0 FC 1835 MOV AL,-4 +0D87 EB 1A 1836 JP NEWLOC +0D89 1837 EQU: +0D89 87 DA 1838 XCHG DX,BX +0D8B 8B 1E CE 20 1839 MOV BX,[LABPT] +0D8F 8A C7 1840 MOV AL,BH +0D91 0A C3 1841 OR AL,BL +0D93 B1 22 1842 MOV CL,34 +0D95 74 27 1843 JZ ERR7 +0D97 88 17 1844 MOV [BX],DL +0D99 43 1845 INC BX +0D9A 88 37 1846 MOV [BX],DH +0D9C C3 1847 RET +0D9D 1848 ORG: +0D9D 89 1E CA 20 1849 MOV [PC],BX +0DA1 B0 FE 1850 MOV AL,-2 +0DA3 1851 NEWLOC: +0DA3 E8 3B FE 1852 CALL PUTCD +0DA6 8A C3 1853 MOV AL,BL +0DA8 E8 36 FE 1854 CALL PUTCD +0DAB 8A C7 1855 MOV AL,BH +0DAD E8 31 FE 1856 CALL PUTCD +0DB0 B5 C0 1857 MOV CH,0C0H +0DB2 E9 F4 FD 1858 JMP GEN1 +0DB5 1859 GRP6: +0DB5 8A E8 1860 MOV CH,AL +0DB7 B1 04 1861 MOV CL,4 +0DB9 E8 30 F5 1862 CALL MROPS +0DBC B1 17 1863 MOV CL,23 +0DBE E9 F0 F4 1864 ERR7: JMP ERROR +0DC1 1865 GRP7: +0DC1 8A E8 1866 MOV CH,AL +0DC3 B1 01 1867 MOV CL,1 +0DC5 E8 24 F5 1868 CALL MROPS +0DC8 B1 80 1869 MOV CL,80H +0DCA 8B 16 D8 20 1870 MOV DX,[DLABEL] +0DCE 8A C6 1871 MOV AL,DH +0DD0 0A C2 1872 OR AL,DL +0DD2 75 12 1873 JNZ ACCJ +0DD4 87 DA 1874 XCHG DX,BX +0DD6 8B 1E D6 20 1875 MOV BX,[DATA] +0DDA 8A C3 1876 MOV AL,BL +0DDC 98 1877 CBW +0DDD 3B C3 1878 CMP AX,BX +0DDF 87 DA 1879 XCHG DX,BX +0DE1 75 03 1880 JNZ ACCJ +0DE3 80 C9 02 1881 OR CL,002H +0DE6 E9 B7 00 1882 ACCJ: JMP ACCIMM +0DE9 1883 GRP8: +0DE9 8A C8 1884 MOV CL,AL +0DEB B5 FE 1885 MOV CH,0FEH +0DED EB 04 1886 JP ONEOP +0DEF 1887 GRP9: +0DEF 8A C8 1888 MOV CL,AL +0DF1 B5 F6 1889 MOV CH,0F6H +0DF3 1890 ONEOP: +0DF3 51 1891 PUSH CX +0DF4 E8 D1 F5 1892 CALL GETOP +0DF7 1893 ONE: +0DF7 B1 1A 1894 MOV CL,26 +0DF9 3C 01 1895 CMP AL,CONST +0DFB 74 C1 1896 JZ ERR7 +0DFD 3C 04 1897 CMP AL,SREG +0DFF B1 16 1898 MOV CL,22 +0E01 74 BB 1899 JZ ERR7 +0E03 59 1900 POP CX +0E04 3C 00 1901 CMP AL,UNDEFID +0E06 74 12 1902 JZ MOP +0E08 24 01 1903 AND AL,1 +0E0A 74 21 1904 JZ ROP +0E0C F6 C1 01 1905 TEST CL,001H +0E0F 74 1C 1906 JZ ROP +0E11 8A C1 1907 MOV AL,CL +0E13 24 F8 1908 AND AL,0F8H +0E15 0A C2 1909 OR AL,DL +0E17 E9 82 FD 1910 JMP PUT +0E1A 1911 MOP: +0E1A A0 D0 20 1912 MOV AL,[FLAG] +0E1D 24 01 1913 AND AL,1 +0E1F 0A C5 1914 OR AL,CH +0E21 E8 78 FD 1915 CALL PUT +0E24 8A C1 1916 MOV AL,CL +0E26 24 38 1917 AND AL,38H +0E28 0A C2 1918 OR AL,DL +0E2A E9 2F FE 1919 JMP PUTADD +0E2D 1920 ROP: +0E2D 0A C5 1921 OR AL,CH +0E2F E8 6A FD 1922 CALL PUT +0E32 8A C1 1923 MOV AL,CL +0E34 24 38 1924 AND AL,38H +0E36 0C C0 1925 OR AL,0C0H +0E38 0A C2 1926 OR AL,DL +0E3A E9 5F FD 1927 JMP PUT +0E3D 1928 GRP10: +0E3D 8A C8 1929 MOV CL,AL +0E3F B5 F6 1930 MOV CH,0F6H +0E41 51 1931 PUSH CX +0E42 E8 83 F5 1932 CALL GETOP +0E45 B1 14 1933 MOV CL,20 +0E47 8A C2 1934 MOV AL,DL +0E49 0A C0 1935 OR AL,AL +0E4B 75 08 1936 JNZ ERRJ1 +0E4D 8A C6 1937 MOV AL,DH +0E4F 3C 03 1938 CMP AL,XREG +0E51 74 04 1939 JZ G10 +0E53 3C 02 1940 CMP AL,REG +0E55 75 67 1941 ERRJ1: JNZ ERR8 +0E57 1942 G10: +0E57 50 1943 PUSH AX +0E58 E8 6D F5 1944 CALL GETOP +0E5B 58 1945 POP AX +0E5C 24 01 1946 AND AL,1 +0E5E A2 D0 20 1947 MOV [FLAG],AL +0E61 8A C6 1948 MOV AL,DH +0E63 EB 92 1949 ONEJ: JP ONE +0E65 1950 GRP11: +0E65 E8 34 FD 1951 CALL PUT +0E68 B0 0A 1952 MOV AL,0AH +0E6A E9 2F FD 1953 JMP PUT +0E6D 1954 GRP12: +0E6D 8A C8 1955 MOV CL,AL +0E6F B5 D0 1956 MOV CH,0D0H +0E71 51 1957 PUSH CX +0E72 E8 53 F5 1958 CALL GETOP +0E75 A0 30 21 1959 MOV AL,[SYM] +0E78 3C 2C 1960 CMP AL,',' +0E7A 8A C6 1961 MOV AL,DH +0E7C 75 E5 1962 JNZ ONEJ +0E7E 52 1963 PUSH DX +0E7F E8 46 F5 1964 CALL GETOP +0E82 2C 02 1965 SUB AL,REG +0E84 B1 14 1966 MOV CL,20 +0E86 FE CA 1967 DEC DL +0E88 0A C2 1968 OR AL,DL +0E8A 75 32 1969 JNZ ERR8 +0E8C 5A 1970 POP DX +0E8D 8A C6 1971 MOV AL,DH +0E8F 59 1972 POP CX +0E90 80 CD 02 1973 OR CH,002H +0E93 51 1974 PUSH CX +0E94 E9 60 FF 1975 JMP ONE +0E97 1976 GRP13: +0E97 8A E8 1977 MOV CH,AL +0E99 B1 01 1978 MOV CL,1 +0E9B E8 4E F4 1979 CALL MROPS +0E9E B1 80 1980 MOV CL,80H +0EA0 1981 ACCIMM: +0EA0 E8 BA FC 1982 CALL IMMED +0EA3 80 CD 04 1983 OR CH,004H +0EA6 80 E5 FD 1984 AND CH,0FDH +0EA9 1985 AIMM: +0EA9 8A C7 1986 MOV AL,BH +0EAB 24 01 1987 AND AL,1 +0EAD 9F 1988 LAHF +0EAE 50 1989 PUSH AX +0EAF 0A C5 1990 OR AL,CH +0EB1 E8 E8 FC 1991 CALL PUT +0EB4 58 1992 POP AX +0EB5 9E 1993 SAHF +0EB6 75 03 1994 JNZ $+5 +0EB8 E9 37 FD 1995 JMP PUTBYT +0EBB E9 2D FD 1996 JMP PUTWOR +0EBE 1997 +0EBE E9 F0 F3 1998 ERR8: JMP ERROR +0EC1 1999 +0EC1 2000 GRP14: +0EC1 2001 ;JMP and CALL mnemonics +0EC1 9F 2002 LAHF +0EC2 86 E0 2003 XCHG AH,AL +0EC4 50 2004 PUSH AX +0EC5 86 E0 2005 XCHG AH,AL +0EC7 C6 06 D1 20 03 2006 MOV B,[MAXFLG],3 ;Allow "L" flag +0ECC E8 F9 F4 2007 CALL GETOP +0ECF 3C 01 2008 CMP AL,CONST +0ED1 74 33 2009 JZ DIRECT +0ED3 B1 14 2010 MOV CL,20 +0ED5 3C 02 2011 CMP AL,REG +0ED7 74 E5 2012 JZ ERR8 +0ED9 3C 04 2013 CMP AL,SREG +0EDB 74 E1 2014 JZ ERR8 +0EDD 3C 03 2015 CMP AL,XREG +0EDF 75 03 2016 JNZ NOTRG +0EE1 80 CA C0 2017 OR DL,0C0H +0EE4 2018 NOTRG: +0EE4 2019 ;Indirect jump. DL has addressing mode. +0EE4 B0 FF 2020 MOV AL,0FFH +0EE6 E8 B3 FC 2021 CALL PUT +0EE9 58 2022 POP AX +0EEA 86 E0 2023 XCHG AH,AL +0EEC 9E 2024 SAHF +0EED 24 38 2025 AND AL,38H +0EEF 0A C2 2026 OR AL,DL +0EF1 8A 2E D0 20 2027 MOV CH,[FLAG] +0EF5 82 FD 03 2028 CMP CH,3 ;Flag "L" present? +0EF8 74 09 2029 JZ PUTADDJ ;If so, do inter-segment +0EFA B1 27 2030 MOV CL,27H +0EFC 82 FD FF 2031 CMP CH,-1 ;Better not be a flag +0EFF 75 BD 2032 JNZ ERR8 +0F01 24 F7 2033 AND AL,0F7H ;Convert to intra-segment +0F03 2034 PUTADDJ: +0F03 E9 56 FD 2035 JMP PUTADD +0F06 2036 DIRECT: +0F06 A0 30 21 2037 MOV AL,[SYM] +0F09 3C 2C 2038 CMP AL,',' +0F0B 74 1C 2039 JZ LONGJ +0F0D 58 2040 POP AX +0F0E 86 E0 2041 XCHG AH,AL +0F10 9E 2042 SAHF +0F11 FE C8 2043 DEC AL +0F13 3C E9 2044 CMP AL,0E9H +0F15 74 02 2045 JZ GOTOP +0F17 B0 E8 2046 MOV AL,0E8H +0F19 2047 GOTOP: +0F19 E8 80 FC 2048 CALL PUT +0F1C 8B 16 CA 20 2049 MOV DX,[PC] +0F20 42 2050 INC DX +0F21 42 2051 INC DX +0F22 29 16 D6 20 2052 SUB [DATA],DX +0F26 E9 C2 FC 2053 JMP PUTWOR +0F29 2054 LONGJ: +0F29 58 2055 POP AX +0F2A 86 E0 2056 XCHG AH,AL +0F2C 9E 2057 SAHF +0F2D E8 6C FC 2058 CALL PUT +0F30 E8 B8 FC 2059 CALL PUTWOR +0F33 E8 92 F4 2060 CALL GETOP +0F36 B1 14 2061 MOV CL,20 +0F38 3C 01 2062 CMP AL,CONST +0F3A 75 82 2063 JNZ ERR8 +0F3C E9 AC FC 2064 JMP PUTWOR +0F3F 2065 +0F3F 2066 GRP16: +0F3F 2067 ;RET mnemonic +0F3F 9F 2068 LAHF +0F40 86 E0 2069 XCHG AH,AL +0F42 50 2070 PUSH AX +0F43 86 E0 2071 XCHG AH,AL +0F45 E8 BA F6 2072 CALL GETSYM +0F48 3C 05 2073 CMP AL,5 +0F4A 74 1C 2074 JZ LONGR +0F4C 3C 0D 2075 CMP AL,EOL +0F4E 74 3F 2076 JZ NODEC +0F50 3C 3B 2077 CMP AL,';' +0F52 74 3B 2078 JZ NODEC +0F54 2079 GETSP: +0F54 E8 74 F4 2080 CALL GETOP1 +0F57 59 2081 POP CX +0F58 3C 01 2082 CMP AL,CONST +0F5A B1 14 2083 MOV CL,20 +0F5C 75 63 2084 JNZ ERR9 +0F5E 8A C5 2085 MOV AL,CH +0F60 24 FE 2086 AND AL,0FEH +0F62 E8 37 FC 2087 CALL PUT +0F65 E9 83 FC 2088 JMP PUTWOR +0F68 2089 LONGR: +0F68 82 FA 03 2090 CMP DL,3 ;Is flag "L"? +0F6B B1 27 2091 MOV CL,27H +0F6D 75 7D 2092 JNZ ERR10 ;If not, bad flag +0F6F 58 2093 POP AX +0F70 86 E0 2094 XCHG AH,AL +0F72 9E 2095 SAHF +0F73 0C 08 2096 OR AL,8 +0F75 9F 2097 LAHF +0F76 86 E0 2098 XCHG AH,AL +0F78 50 2099 PUSH AX +0F79 86 E0 2100 XCHG AH,AL +0F7B 2101 NOTLON: +0F7B E8 84 F6 2102 CALL GETSYM +0F7E 3C 0D 2103 CMP AL,EOL +0F80 74 2E 2104 JZ DORET +0F82 3C 3B 2105 CMP AL,';' +0F84 74 2A 2106 JZ DORET +0F86 3C 2C 2107 CMP AL,',' +0F88 75 03 2108 JNZ L0011 +0F8A E8 75 F6 2109 CALL GETSYM +0F8D 2110 L0011: +0F8D EB C5 2111 JP GETSP +0F8F 2112 NODEC: +0F8F 2113 ;Return is intra-segment (short) without add to SP. +0F8F 2114 ;Record position for RET symbol. +0F8F 8B 1E CA 20 2115 MOV BX,[PC] +0F93 89 1E 4E 21 2116 MOV [LSTRET],BX +0F97 87 DA 2117 XCHG DX,BX +0F99 8B 1E 50 21 2118 MOV BX,[RETPT] +0F9D 8A C7 2119 MOV AL,BH +0F9F 0A C3 2120 OR AL,BL +0FA1 74 0D 2121 JZ DORET +0FA3 C6 07 01 2122 MOV B,[BX],1 +0FA6 43 2123 INC BX +0FA7 89 17 2124 MOV [BX],DX +0FA9 BB 00 00 2125 MOV BX,0 +0FAC 89 1E 50 21 2126 MOV [RETPT],BX +0FB0 2127 DORET: +0FB0 58 2128 POP AX +0FB1 86 E0 2129 XCHG AH,AL +0FB3 9E 2130 SAHF +0FB4 E9 E5 FB 2131 JMP PUT +0FB7 2132 +0FB7 2133 GRP17: +0FB7 E8 E2 FB 2134 CALL PUT +0FBA E8 0B F4 2135 CALL GETOP +0FBD 3C 01 2136 CMP AL,CONST +0FBF B1 14 2137 MOV CL,20 +0FC1 75 29 2138 ERR9: JNZ ERR10 +0FC3 8B 1E D6 20 2139 MOV BX,[DATA] +0FC7 8B 16 CA 20 2140 MOV DX,[PC] +0FCB 42 2141 INC DX +0FCC 2B DA 2142 SUB BX,DX +0FCE 89 1E D6 20 2143 MOV [DATA],BX +0FD2 E8 1D FC 2144 CALL PUTBYT +0FD5 8B 1E D8 20 2145 MOV BX,[DLABEL] +0FD9 8A C7 2146 MOV AL,BH +0FDB 0A C3 2147 OR AL,BL +0FDD 75 10 2148 JNZ RET +0FDF 8B 1E D6 20 2149 MOV BX,[DATA] +0FE3 8A C3 2150 MOV AL,BL +0FE5 98 2151 CBW +0FE6 3B C3 2152 CMP AX,BX ;Signed 8-bit number? +0FE8 74 05 2153 JZ RET +0FEA B1 1F 2154 MOV CL,31 +0FEC E9 C2 F2 2155 ERR10: JMP ERROR +0FEF C3 2156 RET +0FF0 2157 GRP18: +0FF0 E8 D5 F3 2158 CALL GETOP +0FF3 3C 01 2159 CMP AL,CONST +0FF5 B1 14 2160 MOV CL,20 +0FF7 75 F3 2161 JNZ ERR10 +0FF9 8B 1E D8 20 2162 MOV BX,[DLABEL] +0FFD 8A C7 2163 MOV AL,BH +0FFF 0A C3 2164 OR AL,BL +1001 75 10 2165 JNZ GENINT +1003 8B 1E D6 20 2166 MOV BX,[DATA] +1007 BA 03 00 2167 MOV DX,3 +100A 1B DA 2168 SBB BX,DX +100C 75 05 2169 JNZ GENINT +100E B0 CC 2170 MOV AL,0CCH +1010 E9 89 FB 2171 JMP PUT +1013 2172 GENINT: +1013 B0 CD 2173 MOV AL,0CDH +1015 E8 84 FB 2174 CALL PUT +1018 E9 D7 FB 2175 JMP PUTBYT +101B 2176 +101B 2177 GRP19: ;ESC opcode +101B E8 AA F3 2178 CALL GETOP +101E B1 14 2179 MOV CL,20 +1020 3C 01 2180 CMP AL,CONST +1022 75 39 2181 JNZ ERRJ ;First operand must be immediate +1024 B1 1E 2182 MOV CL,1EH +1026 F7 06 D8 20 FF FF 2183 TEST [DLABEL],-1 ;See if all labels have been defined +102C 75 2F 2184 JNZ ERRJ +102E A1 D6 20 2185 MOV AX,[DATA] +1031 3D 40 00 2186 CMP AX,64 ;Must only be 6 bits +1034 B1 1F 2187 MOV CL,1FH +1036 73 25 2188 JNB ERRJ +1038 8A D8 2189 MOV BL,AL ;Save for second byte +103A D0 E8 2190 SHR AL +103C D0 E8 2191 SHR AL +103E D0 E8 2192 SHR AL +1040 0C D8 2193 OR AL,0D8H ;ESC opcode +1042 E8 57 FB 2194 CALL PUT +1045 53 2195 PUSH BX +1046 E8 76 F3 2196 CALL GETOP2 +1049 5B 2197 POP BX +104A 80 E3 07 2198 AND BL,7 ;Low 3 bits of first operand +104D D0 E3 2199 SHL BL +104F D0 E3 2200 SHL BL +1051 D0 E3 2201 SHL BL +1053 3C 00 2202 CMP AL,UNDEFID ;Check for memory operand +1055 74 09 2203 JZ ESCMEM +1057 3C 01 2204 CMP AL,CONST ;Check for another immediate +1059 74 0C 2205 JZ ESCIMM +105B B1 14 2206 MOV CL,20 +105D E9 51 F2 2207 ERRJ: JMP ERROR +1060 2208 +1060 2209 ESCMEM: +1060 0A DA 2210 OR BL,DL ;Combine mode with first operand +1062 8A C3 2211 MOV AL,BL +1064 E9 F5 FB 2212 JMP PUTADD +1067 2213 +1067 2214 ESCIMM: +1067 B1 1E 2215 MOV CL,1EH +1069 F7 06 D8 20 FF FF 2216 TEST [DLABEL],-1 ;See if second operand is fully defined +106F 75 EC 2217 JNZ ERRJ +1071 A1 D6 20 2218 MOV AX,[DATA] +1074 B1 1F 2219 MOV CL,1FH +1076 3D 08 00 2220 CMP AX,8 ;Must only be 3 bit value +1079 73 E2 2221 JNB ERRJ +107B 0A C3 2222 OR AL,BL ;Combine first and second operands +107D 0C C0 2223 OR AL,0C0H ;Force "register" mode +107F E9 1A FB 2224 JMP PUT +1082 2225 +1082 2226 GRP20: +1082 8A E8 2227 MOV CH,AL +1084 B1 01 2228 MOV CL,1 +1086 E8 63 F2 2229 CALL MROPS +1089 B1 F6 2230 MOV CL,0F6H +108B E8 CF FA 2231 CALL IMMED +108E B5 A8 2232 MOV CH,0A8H +1090 E9 16 FE 2233 JMP AIMM +1093 2234 GRP21: +1093 E8 32 F3 2235 CALL GETOP +1096 3C 04 2236 CMP AL,SREG +1098 B1 1C 2237 MOV CL,28 +109A 75 C1 2238 JNZ ERRJ +109C B5 26 2239 MOV CH,26H +109E 2240 PACKREG: +109E 8A C2 2241 MOV AL,DL +10A0 02 C0 2242 ADD AL,AL +10A2 02 C0 2243 ADD AL,AL +10A4 02 C0 2244 ADD AL,AL +10A6 0A C5 2245 OR AL,CH +10A8 E9 F1 FA 2246 JMP PUT +10AB 2247 GRP22: +10AB E8 1A F3 2248 CALL GETOP +10AE B9 00 8F 2249 MOV CX,8F00H +10B1 3C 00 2250 CMP AL,UNDEFID +10B3 75 03 2251 JNZ $+5 +10B5 E9 EA FB 2252 JMP PMEM +10B8 B5 58 2253 MOV CH,58H +10BA 3C 03 2254 CMP AL,XREG +10BC 75 03 2255 JNZ $+5 +10BE E9 ED FB 2256 JMP PXREG +10C1 B5 07 2257 MOV CH,7 +10C3 3C 04 2258 CMP AL,SREG +10C5 74 D7 2259 JZ PACKREG +10C7 B1 14 2260 MOV CL,20 +10C9 E9 E5 F1 2261 ERR11: JMP ERROR +10CC 2262 GRP23: +10CC A2 39 21 2263 MOV [DATSIZ],AL +10CF 2264 GETDAT: +10CF E8 30 F5 2265 CALL GETSYM +10D2 B0 02 2266 MOV AL,2 +10D4 E8 0A F3 2267 CALL VAL1 +10D7 A0 30 21 2268 MOV AL,[SYM] +10DA 3C 2C 2269 CMP AL,',' +10DC A0 39 21 2270 MOV AL,[DATSIZ] +10DF 75 05 2271 JNZ ENDDAT +10E1 E8 13 00 2272 CALL SAVDAT +10E4 EB E9 2273 JP GETDAT +10E6 2274 ENDDAT: +10E6 3C 02 2275 CMP AL,2 +10E8 75 0D 2276 JNZ SAVDAT +10EA 8B 1E D6 20 2277 MOV BX,[DATA] +10EE 9F 2278 LAHF +10EF 80 CB 80 2279 OR BL,080H +10F2 9E 2280 SAHF +10F3 89 1E D6 20 2281 MOV [DATA],BX +10F7 2282 SAVDAT: +10F7 0A C0 2283 OR AL,AL +10F9 74 03 2284 JZ $+5 +10FB E9 F4 FA 2285 JMP PUTBYT +10FE E9 EA FA 2286 JMP PUTWOR +1101 2287 IF: +1101 0B DB 2288 OR BX,BX +1103 74 05 2289 JZ SKIPCD +1105 FE 06 4A 21 2290 INC B,[IFFLG] +1109 C3 2291 RET +110A 2292 +110A 2293 SKIPCD: +110A FE 06 4B 21 2294 INC B,[CHKLAB] +110E 2295 SKIPLP: +110E 32 C0 2296 XOR AL,AL +1110 E8 48 F1 2297 CALL NEXLIN +1113 E8 A0 F1 2298 CALL NEXTCHR +1116 3C 1A 2299 CMP AL,1AH +1118 74 40 2300 JZ END +111A E8 E5 F7 2301 CALL GETLAB +111D 72 EF 2302 JC SKIPLP +111F BF DE 20 2303 MOV DI,LENID +1122 BE 74 20 2304 MOV SI,IFEND +1125 B5 00 2305 MOV CH,0 +1127 8A 0D 2306 MOV CL,[DI] +1129 FE C1 2307 INC CL +112B F3 2308 REPE +112C A6 2309 CMPB +112D 74 14 2310 JZ ENDCOND +112F BF DE 20 2311 MOV DI,LENID +1132 BE 7A 20 2312 MOV SI,IFNEST +1135 8A 0D 2313 MOV CL,[DI] +1137 FE C1 2314 INC CL +1139 F3 2315 REPE +113A A6 2316 CMPB +113B 75 D1 2317 JNZ SKIPLP +113D FE 06 4B 21 2318 INC B,[CHKLAB] +1141 EB CB 2319 JP SKIPLP +1143 2320 +1143 2321 ENDCOND: +1143 FE 0E 4B 21 2322 DEC B,[CHKLAB] +1147 75 C5 2323 JNZ SKIPLP +1149 C3 2324 RET +114A 2325 +114A 2326 ENDIF: +114A A0 4A 21 2327 MOV AL,[IFFLG] +114D B1 24 2328 MOV CL,36 +114F FE C8 2329 DEC AL +1151 78 04 2330 JS ERRJMP +1153 A2 4A 21 2331 MOV [IFFLG],AL +1156 C3 2332 RET +1157 2333 +1157 E9 57 F1 2334 ERRJMP: JMP ERROR +115A 2335 +115A 2336 ;********************************************************************* +115A 2337 ; +115A 2338 ; PASS 2 +115A 2339 ; +115A 2340 ;********************************************************************* +115A 2341 +115A 2342 END: +115A B2 04 2343 MOV DL,4 +115C 2344 WREND: +115C B5 FF 2345 MOV CH,0FFH +115E 8A C5 2346 MOV AL,CH +1160 E8 43 FA 2347 CALL GEN +1163 FE CA 2348 DEC DL +1165 75 F5 2349 JNZ WREND +1167 C7 06 A4 25 A6 25 2350 MOV [BUFPT],SRCBUF +116D C6 06 46 21 FB 2351 MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY +1172 C7 06 5C 21 A4 21 2352 MOV [LSTPNT],LSTBUF +1178 C7 06 5A 21 5E 21 2353 MOV [HEXPNT],HEXBUF +117E 33 C0 2354 XOR AX,AX +1180 A3 4C 21 2355 MOV [ERRCNT],AX +1183 A3 CA 20 2356 MOV [PC],AX +1186 A3 3E 21 2357 MOV [LINE],AX ;Current line number +1189 C7 06 42 21 00 01 2358 MOV [HEXADD],OBJECT +118F BA 5C 00 2359 MOV DX,FCB +1192 B4 0F 2360 MOV AH,OPEN +1194 CD 21 2361 INT 33 ;Re-open source file +1196 33 C0 2362 XOR AX,AX +1198 A3 68 00 2363 MOV [FCB+12],AX ;Set CURRENT BLOCK to zero +119B A2 7C 00 2364 MOV [FCB+20H],AL ;Set NEXT RECORD field to zero +119E C7 06 6A 00 00 04 2365 MOV [FCB+14],BUFSIZ +11A4 A2 3C 21 2366 MOV [COUNT],AL +11A7 B5 01 2367 MOV CH,1 +11A9 BE A6 2A 2368 MOV SI,START +11AC 2369 FIXLINE: +11AC BF A6 2A 2370 MOV DI,START ;Store code over used up intermediate code +11AF 32 C0 2371 XOR AL,AL +11B1 A2 54 21 2372 MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) +11B4 A2 3D 21 2373 MOV [ERR],AL ;No second pass errors yet +11B7 2374 NEXBT: +11B7 D0 E1 2375 SHL CL ;Shift out last bit of previous code +11B9 FE CD 2376 DEC CH ;Still have codes left? +11BB 75 05 2377 JNZ TESTTYP +11BD AC 2378 LODB ;Get next flag byte +11BE 8A C8 2379 MOV CL,AL +11C0 B5 04 2380 MOV CH,4 +11C2 2381 TESTTYP: +11C2 D0 E1 2382 SHL CL ;Set flags based on two bits +11C4 70 06 2383 JO FIXUP +11C6 AC 2384 LODB +11C7 72 4E 2385 JC EMARK +11C9 2386 OBJBT: +11C9 AA 2387 STOB +11CA EB EB 2388 JP NEXBT +11CC 2389 +11CC 2390 FIXUP: +11CC 2391 ;Either a word or byte fixup is needed from a forward reference +11CC AD 2392 LODW ;Get pointer to symbol +11CD 93 2393 XCHG AX,BX +11CE AD 2394 LODW ;Get constant part +11CF 03 47 01 2395 ADD AX,[BX+1] ;Add symbol value to constant part +11D2 82 3F 00 2396 CMP B,[BX],0 ;See if symbol got defined +11D5 75 07 2397 JNZ HAVDEF +11D7 C6 06 3D 21 64 2398 MOV B,[ERR],100 ;Undefined - flag error +11DC 33 C0 2399 XOR AX,AX +11DE 2400 HAVDEF: +11DE 0A C9 2401 OR CL,CL ;See if word or byte fixup +11E0 78 03 2402 JS DEFBYT +11E2 AB 2403 STOW +11E3 EB D2 2404 JP NEXBT +11E5 2405 +11E5 2406 DEFBYT: +11E5 8B D0 2407 MOV DX,AX +11E7 98 2408 CBW ;Extend sign +11E8 3B C2 2409 CMP AX,DX ;See if in range +127 to -128 +11EA 74 DD 2410 JZ OBJBT ;If so, it's always OK +11EC F6 D4 2411 NOT AH ;Check for range +255 to -256 +11EE 3A E6 2412 CMP AH,DH +11F0 75 1B 2413 JNZ RNGERR ;Must always be in this range +11F2 2414 ;Check for short jump. If so, we're out of range; otherwise we're OK +11F2 81 FF A7 2A 2415 CMP DI,START+1 ;Only one other byte on line? +11F6 75 D1 2416 JNZ OBJBT ;Can't be short jump if not +11F8 A0 A6 2A 2417 MOV AL,[START] ;Get the first byte of this line +11FB 3C EB 2418 CMP AL,0EBH ;Direct short jump? +11FD 74 0E 2419 JZ RNGERR +11FF 24 FC 2420 AND AL,0FCH +1201 3C E0 2421 CMP AL,0E0H ;LOOP or JCXZ instruction? +1203 74 08 2422 JZ RNGERR +1205 24 F0 2423 AND AL,0F0H +1207 3C 70 2424 CMP AL,70H ;Conditional jump? +1209 8A C2 2425 MOV AL,DL ;Get code byte in AL +120B 75 BC 2426 JNZ OBJBT ;If not, we're OK +120D 2427 RNGERR: +120D C6 06 3D 21 65 2428 MOV B,[ERR],101 ;Value out of range +1212 EB B5 2429 JP OBJBT +1214 2430 +1214 E9 7A 01 2431 FINIJ: JMP FINI +1217 2432 +1217 2433 EMARK: +1217 3C FF 2434 CMP AL,-1 ;End of file? +1219 74 F9 2435 JZ FINIJ +121B 3C F6 2436 CMP AL,-10 ;Special item? +121D 77 5C 2437 JA SPEND +121F 51 2438 PUSH CX +1220 56 2439 PUSH SI +1221 50 2440 PUSH AX ;Save error code +1222 8A 26 52 21 2441 MOV AH,[LSTDEV] +1226 80 E4 FE 2442 AND AH,0FEH ;Reset error indicator +1229 0A 06 3D 21 2443 OR AL,[ERR] ;See if any errors on this line +122D 74 03 2444 JZ NOERR +122F 80 CC 01 2445 OR AH,1 ;Send line to console if error occured +1232 2446 NOERR: +1232 88 26 52 21 2447 MOV [LSTDEV],AH +1236 8B CF 2448 MOV CX,DI +1238 E8 EE 00 2449 CALL STRTLIN ;Print address of line +123B BE A6 2A 2450 MOV SI,START +123E 2B CE 2451 SUB CX,SI ;Get count of bytes of code +1240 74 06 2452 JZ SHOLIN +1242 2453 CODLP: +1242 AC 2454 LODB +1243 E8 59 02 2455 CALL SAVCD ;Ouput code to HEX and PRN files +1246 E2 FA 2456 LOOP CODLP +1248 2457 SHOLIN: +1248 B0 00 2458 MOV AL,0 +124A 86 06 3C 21 2459 XCHG AL,[COUNT] +124E B9 07 00 2460 MOV CX,7 ;Allow 7 bytes of code per line +1251 2A C8 2461 SUB CL,AL +1253 B0 20 2462 MOV AL,' ' +1255 74 0B 2463 JZ NOFIL +1257 2464 BLNK: ;Put in 3 blanks for each byte not present +1257 E8 E4 00 2465 CALL LIST +125A E8 E1 00 2466 CALL LIST +125D E8 DE 00 2467 CALL LIST +1260 E2 F5 2468 LOOP BLNK +1262 2469 NOFIL: +1262 E8 45 00 2470 CALL OUTLIN +1265 58 2471 POP AX ;Restore error code +1266 E8 6C 02 2472 CALL REPERR +1269 A0 3D 21 2473 MOV AL,[ERR] +126C E8 66 02 2474 CALL REPERR +126F 5E 2475 POP SI +1270 59 2476 POP CX +1271 A0 54 21 2477 MOV AL,[SPC] ;Any special funtion? +1274 0A C0 2478 OR AL,AL +1276 75 0D 2479 JNZ SPCFUN +1278 E9 31 FF 2480 JMP FIXLINE +127B 2481 +127B 2482 SPEND: +127B A2 54 21 2483 MOV [SPC],AL ;Record special function +127E AD 2484 LODW ;Get it's data +127F A3 D6 20 2485 MOV [DATA],AX +1282 E9 32 FF 2486 JMP NEXBT +1285 2487 +1285 2488 SPCFUN: +1285 8B 16 D6 20 2489 MOV DX,[DATA] +1289 3C FE 2490 CMP AL,-2 +128B 74 0F 2491 JZ DORG +128D 3C FD 2492 CMP AL,-3 +128F 74 12 2493 JZ DPUT +1291 2494 DDS: +1291 2495 ;Handle DS pseudo-op +1291 01 16 CA 20 2496 ADD [PC],DX +1295 01 16 42 21 2497 ADD [HEXADD],DX +1299 E9 10 FF 2498 JMP FIXLINE +129C 2499 +129C 2500 DORG: +129C 2501 ;Handle ORG pseudo-op +129C 89 16 CA 20 2502 MOV [PC],DX +12A0 E9 09 FF 2503 JMP FIXLINE +12A3 2504 +12A3 2505 DPUT: +12A3 2506 ;Handle PUT pseudo-op +12A3 89 16 42 21 2507 MOV [HEXADD],DX +12A7 E9 02 FF 2508 JMP FIXLINE +12AA 2509 +12AA 2510 OUTLIN: +12AA 2511 ;Copy the source line to the ouput device. Line will be preceded by +12AA 2512 ;assembler-generated line number. This routine may be called several times +12AA 2513 ;on one line (once for each line of object code bytes), so it sets a flag +12AA 2514 ;so the line will only be output on the first call. +12AA B0 FF 2515 MOV AL,-1 +12AC 86 06 48 21 2516 XCHG AL,[LINFLG] +12B0 0A C0 2517 OR AL,AL +12B2 75 33 2518 JNZ CRLF ;Output line only if first time +12B4 A1 3E 21 2519 MOV AX,[LINE] +12B7 40 2520 INC AX +12B8 A3 3E 21 2521 MOV [LINE],AX +12BB B7 00 2522 MOV BH,0 ;No leading zero suppression +12BD E8 30 00 2523 CALL OUT10 +12C0 B0 20 2524 MOV AL," " +12C2 E8 79 00 2525 CALL LIST +12C5 A0 A5 20 2526 MOV AL,[LSTFCB] +12C8 3C 5A 2527 CMP AL,'Z' +12CA 74 1B 2528 JZ CRLF ;Don't call NEXTCHR if listing suppressed +12CC 56 2529 PUSH SI ;Save the only register destroyed by NEXTCHR +12CD 2530 OUTLN: +12CD E8 E6 EF 2531 CALL NEXTCHR +12D0 E8 6B 00 2532 CALL LIST +12D3 3C 0A 2533 CMP AL,10 ;Output until linefeed found +12D5 75 F6 2534 JNZ OUTLN +12D7 5E 2535 POP SI +12D8 C3 2536 RET +12D9 2537 +12D9 2538 PRTCNT: +12D9 BB 4C 20 2539 MOV BX,ERCNTM +12DC E8 25 02 2540 CALL PRINT +12DF A1 4C 21 2541 MOV AX,[ERRCNT] +12E2 B7 10 2542 MOV BH,"0"-" " ;Enable leading zero suppression +12E4 E8 09 00 2543 CALL OUT10 +12E7 2544 CRLF: +12E7 B0 0D 2545 MOV AL,13 +12E9 E8 52 00 2546 CALL LIST +12EC B0 0A 2547 MOV AL,10 +12EE EB 4E 2548 JP LIST +12F0 2549 +12F0 2550 OUT10: +12F0 33 D2 2551 XOR DX,DX +12F2 BF 10 27 2552 MOV DI,10000 +12F5 F7 F7 2553 DIV AX,DI +12F7 0A C0 2554 OR AL,AL ;>10,000? +12F9 75 02 2555 JNZ LEAD +12FB 2C 10 2556 SUB AL,"0"-" " ;Convert leading zero to blank +12FD 2557 LEAD: +12FD 04 30 2558 ADD AL,"0" +12FF E8 3C 00 2559 CALL LIST +1302 92 2560 XCHG AX,DX +1303 B3 64 2561 MOV BL,100 +1305 F6 F3 2562 DIV AL,BL +1307 8A DC 2563 MOV BL,AH +1309 E8 0C 00 2564 CALL HIDIG ;Convert to decimal and print 1000s digit +130C E8 0E 00 2565 CALL DIGIT ;Print 100s digit +130F 8A C3 2566 MOV AL,BL +1311 E8 04 00 2567 CALL HIDIG ;Convert to decimal and print 10s digit +1314 B7 00 2568 MOV BH,0 ;Ensure leading zero suppression is off +1316 EB 05 2569 JP DIGIT +1318 2570 +1318 2571 HIDIG: +1318 D4 0A 2572 AAM ;Convert binary to unpacked BCD +131A 0D 30 30 2573 OR AX,3030H ;Add "0" bias +131D 2574 DIGIT: +131D 86 C4 2575 XCHG AL,AH +131F 3C 30 2576 CMP AL,"0" +1321 74 02 2577 JZ SUPZ +1323 B7 00 2578 MOV BH,0 ;Turn off zero suppression if not zero +1325 2579 SUPZ: +1325 2A C7 2580 SUB AL,BH ;Convert leading zeros to blanks +1327 EB 15 2581 JP LIST +1329 2582 +1329 2583 STRTLIN: +1329 C6 06 48 21 00 2584 MOV B,[LINFLG],0 +132E 8B 1E CA 20 2585 MOV BX,[PC] +1332 8A C7 2586 MOV AL,BH +1334 E8 4D 00 2587 CALL PHEX +1337 8A C3 2588 MOV AL,BL +1339 2589 PHEXB: +1339 E8 48 00 2590 CALL PHEX +133C B0 20 2591 MOV AL,' ' +133E 2592 LIST: +133E 50 2593 PUSH AX +133F 52 2594 PUSH DX +1340 24 7F 2595 AND AL,7FH +1342 8A D0 2596 MOV DL,AL +1344 F6 06 52 21 03 2597 TEST B,[LSTDEV],3 ;See if output goes to console +1349 74 04 2598 JZ PRNCHK +134B B4 02 2599 MOV AH,2 +134D CD 21 2600 INT 33 ;Output to console +134F 2601 PRNCHK: +134F F6 06 52 21 04 2602 TEST B,[LSTDEV],4 ;See if output goes to printer +1354 74 04 2603 JZ FILCHK +1356 B4 05 2604 MOV AH,5 +1358 CD 21 2605 INT 33 ;Output to printer +135A 2606 FILCHK: +135A 8A C2 2607 MOV AL,DL +135C 5A 2608 POP DX +135D F6 06 52 21 80 2609 TEST B,[LSTDEV],80H ;See if output goes to a file +1362 74 03 2610 JZ LISTRET +1364 E8 02 00 2611 CALL WRTBUF +1367 2612 LISTRET: +1367 58 2613 POP AX +1368 C3 2614 RET +1369 2615 +1369 2616 WRTBUF: +1369 57 2617 PUSH DI +136A 8B 3E 5C 21 2618 MOV DI,[LSTPNT] +136E AA 2619 STOB +136F 81 FF A4 25 2620 CMP DI,LSTBUF+LSTBUFSIZ +1373 75 09 2621 JNZ SAVPT +1375 50 2622 PUSH AX +1376 51 2623 PUSH CX +1377 52 2624 PUSH DX +1378 E8 61 02 2625 CALL FLUSHBUF +137B 5A 2626 POP DX +137C 59 2627 POP CX +137D 58 2628 POP AX +137E 2629 SAVPT: +137E 89 3E 5C 21 2630 MOV [LSTPNT],DI +1382 5F 2631 POP DI +1383 C3 2632 RET +1384 2633 +1384 2634 PHEX: +1384 50 2635 PUSH AX +1385 E8 74 02 2636 CALL UHALF +1388 E8 B3 FF 2637 CALL LIST +138B 58 2638 POP AX +138C E8 75 02 2639 CALL LHALF +138F EB AD 2640 JP LIST +1391 2641 +1391 2642 FINI: +1391 80 0E 52 21 01 2643 OR B,[LSTDEV],1 +1396 E8 40 FF 2644 CALL PRTCNT +1399 80 26 52 21 FE 2645 AND B,[LSTDEV],0FEH +139E A0 80 20 2646 MOV AL,[HEXFCB] +13A1 3C 5A 2647 CMP AL,'Z' +13A3 74 35 2648 JZ SYMDMP +13A5 A0 46 21 2649 MOV AL,[HEXCNT] +13A8 3C FB 2650 CMP AL,-5 +13AA 74 03 2651 JZ L0012 +13AC E8 DF 01 2652 CALL ENHEXL +13AF 2653 L0012: +13AF B0 3A 2654 MOV AL,':' +13B1 E8 1E 02 2655 CALL PUTCHR +13B4 B5 0A 2656 MOV CH,10 +13B6 2657 HEXEND: +13B6 51 2658 PUSH CX +13B7 B0 30 2659 MOV AL,'0' +13B9 E8 16 02 2660 CALL PUTCHR +13BC 59 2661 POP CX +13BD FE CD 2662 DEC CH +13BF 75 F5 2663 JNZ HEXEND +13C1 B0 0D 2664 MOV AL,13 +13C3 E8 0C 02 2665 CALL PUTCHR +13C6 B0 0A 2666 MOV AL,10 +13C8 E8 07 02 2667 CALL PUTCHR +13CB B0 1A 2668 MOV AL,1AH +13CD E8 02 02 2669 CALL PUTCHR +13D0 E8 E4 01 2670 CALL WRTHEX ;Flush HEX file buffer +13D3 BA 80 20 2671 MOV DX,HEXFCB +13D6 B4 10 2672 MOV AH,CLOSE +13D8 CD 21 2673 INT 33 +13DA 2674 SYMDMP: +13DA A0 35 21 2675 MOV AL,[SYMFLG] +13DD 3C 53 2676 CMP AL,'S' +13DF 75 2A 2677 JNZ ENDSYM +13E1 A0 52 21 2678 MOV AL,[LSTDEV] +13E4 0A C0 2679 OR AL,AL ;Any output device for symbol table dump? +13E6 75 05 2680 JNZ DOSYMTAB +13E8 0C 01 2681 OR AL,1 ;If not, send it to console +13EA A2 52 21 2682 MOV [LSTDEV],AL +13ED 2683 DOSYMTAB: +13ED BB 5D 20 2684 MOV BX,SYMMES +13F0 E8 11 01 2685 CALL PRINT +13F3 8B 16 31 21 2686 MOV DX,[BASE] +13F7 8A C6 2687 MOV AL,DH +13F9 0A C2 2688 OR AL,DL +13FB 74 0E 2689 JZ ENDSYM +13FD C6 06 36 21 05 2690 MOV B,[SYMLIN],SYMWID ;No symbols on this line yet +1402 8B 1E 33 21 2691 MOV BX,[HEAP] +1406 8B E3 2692 MOV SP,BX ;Need maximum stack for recursive tree walk +1408 E8 1A 00 2693 CALL NODE +140B 2694 ENDSYM: +140B F6 06 52 21 80 2695 TEST B,[LSTDEV],80H ;Print listing to file? +1410 74 10 2696 JZ EXIT +1412 B0 1A 2697 MOV AL,1AH +1414 E8 52 FF 2698 CALL WRTBUF ;Write end-of-file mark +1417 8B 3E 5C 21 2699 MOV DI,[LSTPNT] +141B E8 BE 01 2700 CALL FLUSHBUF +141E B4 10 2701 MOV AH,CLOSE +1420 CD 21 2702 INT 33 +1422 E9 DB EB 2703 EXIT: JMP 0 +1425 2704 +1425 2705 NODE: +1425 87 DA 2706 XCHG DX,BX +1427 53 2707 PUSH BX +1428 8A 17 2708 MOV DL,[BX] +142A B6 00 2709 MOV DH,0 +142C 43 2710 INC BX +142D 03 DA 2711 ADD BX,DX +142F 8B 17 2712 MOV DX,[BX] +1431 0B D2 2713 OR DX,DX +1433 74 03 2714 JZ L0014 +1435 E8 ED FF 2715 CALL NODE +1438 2716 L0014: +1438 5B 2717 POP BX +1439 8A 07 2718 MOV AL,[BX] +143B 43 2719 INC BX +143C 8A E8 2720 MOV CH,AL +143E 04 18 2721 ADD AL,24 +1440 D0 E8 2722 SHR AL +1442 D0 E8 2723 SHR AL +1444 D0 E8 2724 SHR AL +1446 8A C8 2725 MOV CL,AL +1448 FE C1 2726 INC CL ;Invert last bit +144A 80 E1 01 2727 AND CL,1 ;Number of extra tabs needed (0 or 1) +144D D0 E8 2728 SHR AL ;Number of positions wide this symbol needs +144F 28 06 36 21 2729 SUB [SYMLIN],AL +1453 73 0A 2730 JNC WRTSYM ;Will it fit? +1455 2C 05 2731 SUB AL,SYMWID +1457 F6 D8 2732 NEG AL +1459 A2 36 21 2733 MOV [SYMLIN],AL +145C E8 88 FE 2734 CALL CRLF ;Start new line if not +145F 2735 WRTSYM: +145F 8A 07 2736 MOV AL,[BX] +1461 43 2737 INC BX +1462 E8 D9 FE 2738 CALL LIST +1465 FE CD 2739 DEC CH +1467 75 F6 2740 JNZ WRTSYM +1469 FE C1 2741 INC CL +146B 2742 TABVAL: +146B B0 09 2743 MOV AL,9 +146D E8 CE FE 2744 CALL LIST +1470 E2 F9 2745 LOOP TABVAL +1472 43 2746 INC BX +1473 43 2747 INC BX +1474 53 2748 PUSH BX +1475 8A 47 04 2749 MOV AL,[BX+4] +1478 E8 09 FF 2750 CALL PHEX +147B 8A 47 03 2751 MOV AL,[BX+3] +147E E8 03 FF 2752 CALL PHEX +1481 82 3E 36 21 00 2753 CMP B,[SYMLIN],0 ;Will any more fit on line? +1486 74 07 2754 JZ NEXSYMLIN +1488 B0 09 2755 MOV AL,9 +148A E8 B1 FE 2756 CALL LIST +148D EB 08 2757 JP RIGHTSON +148F 2758 NEXSYMLIN: +148F E8 55 FE 2759 CALL CRLF +1492 C6 06 36 21 05 2760 MOV B,[SYMLIN],SYMWID +1497 2761 RIGHTSON: +1497 5B 2762 POP BX +1498 8B 17 2763 MOV DX,[BX] +149A 0B D2 2764 OR DX,DX +149C 75 87 2765 JNZ NODE +149E C3 2766 RET +149F 2767 +149F 2768 SAVCD: +149F A2 49 21 2769 MOV [PREV],AL +14A2 53 2770 PUSH BX +14A3 51 2771 PUSH CX +14A4 50 2772 PUSH AX +14A5 52 2773 PUSH DX +14A6 E8 72 00 2774 CALL CODBYT +14A9 5A 2775 POP DX +14AA BB 3C 21 2776 MOV BX,COUNT +14AD FE 07 2777 INC B,[BX] +14AF 8A 07 2778 MOV AL,[BX] +14B1 3C 08 2779 CMP AL,8 +14B3 75 11 2780 JNZ NOEXT +14B5 C6 07 01 2781 MOV B,[BX],1 +14B8 E8 EF FD 2782 CALL OUTLIN +14BB B0 20 2783 MOV AL,' ' +14BD B5 05 2784 MOV CH,5 +14BF 2785 TAB: +14BF E8 7C FE 2786 CALL LIST +14C2 FE CD 2787 DEC CH +14C4 75 F9 2788 JNZ TAB +14C6 2789 NOEXT: +14C6 58 2790 POP AX +14C7 E8 6F FE 2791 CALL PHEXB +14CA 59 2792 POP CX +14CB FF 06 CA 20 2793 INC [PC] +14CF FF 06 42 21 2794 INC [HEXADD] +14D3 5B 2795 POP BX +14D4 C3 2796 RET +14D5 2797 +14D5 2798 REPERR: +14D5 0A C0 2799 OR AL,AL ;Did an error occur? +14D7 74 FB 2800 JZ RET +14D9 FF 06 4C 21 2801 INC [ERRCNT] +14DD 50 2802 PUSH AX +14DE BB D6 1F 2803 MOV BX,ERRMES ;Print "ERROR" +14E1 E8 20 00 2804 CALL PRINT +14E4 58 2805 POP AX +14E5 2806 ;We have error number in AL. See if there's an error message for it +14E5 BF 08 1C 2807 MOV DI,ERRTAB +14E8 B3 80 2808 MOV BL,80H +14EA 2809 ERRLOOK: +14EA AE 2810 SCASB ;Do we have the error message +14EB 76 07 2811 JBE HAVMES ;Quit looking if we have it or passed it +14ED 93 2812 XCHG AX,BX ;Put 80H in AL to look for end of this message +14EE 2813 NEXTMES: +14EE AE 2814 SCASB ;Look for high bit set in message +14EF 77 FD 2815 JA NEXTMES ; which means we've reached the end +14F1 93 2816 XCHG AX,BX ;Restore error number to AL +14F2 EB F6 2817 JMPS ERRLOOK ;Keep looking +14F4 2818 +14F4 2819 HAVMES: +14F4 8B DF 2820 MOV BX,DI ;Put address of message in BX +14F6 74 06 2821 JZ PRNERR ;Do we have a message for this error? +14F8 E8 89 FE 2822 CALL PHEX ;If not, just print error number +14FB E9 E9 FD 2823 JMP CRLF +14FE 2824 +14FE 2825 PRNERR: +14FE E8 03 00 2826 CALL PRINT +1501 E9 E3 FD 2827 JMP CRLF +1504 2828 +1504 2829 PRINT: +1504 8A 07 2830 MOV AL,[BX] +1506 E8 35 FE 2831 CALL LIST +1509 0A C0 2832 OR AL,AL +150B 78 C7 2833 JS RET +150D 43 2834 INC BX +150E EB F4 2835 JP PRINT +1510 2836 +1510 2837 OUTA: +1510 8A D0 2838 MOV DL,AL +1512 2839 OUT: +1512 80 E2 7F 2840 AND DL,7FH +1515 B1 02 2841 MOV CL,2 +1517 2842 SYSTEM: +1517 E8 EB EA 2843 CALL 5 +151A C3 2844 RET +151B 2845 +151B 2846 CODBYT: +151B 82 3E 80 20 5A 2847 CMP B,[HEXFCB],"Z" +1520 74 F8 2848 JZ RET +1522 50 2849 PUSH AX +1523 8B 16 44 21 2850 MOV DX,[LASTAD] +1527 8B 1E 42 21 2851 MOV BX,[HEXADD] +152B 89 1E 44 21 2852 MOV [LASTAD],BX +152F 42 2853 INC DX +1530 A0 46 21 2854 MOV AL,[HEXCNT] +1533 3C FB 2855 CMP AL,-5 +1535 74 07 2856 JZ NEWLIN +1537 3B DA 2857 CMP BX,DX +1539 74 2E 2858 JZ AFHEX +153B E8 50 00 2859 CALL ENHEXL +153E 2860 NEWLIN: +153E B0 3A 2861 MOV AL,':' +1540 E8 8F 00 2862 CALL PUTCHR +1543 B0 FC 2863 MOV AL,-4 +1545 A2 46 21 2864 MOV [HEXCNT],AL +1548 32 C0 2865 XOR AL,AL +154A A2 47 21 2866 MOV [CHKSUM],AL +154D 8B 1E 5A 21 2867 MOV BX,[HEXPNT] +1551 89 1E 40 21 2868 MOV [HEXLEN],BX +1555 E8 12 00 2869 CALL HEXBYT +1558 A0 43 21 2870 MOV AL,[HEXADD+1] +155B E8 0C 00 2871 CALL HEXBYT +155E A0 42 21 2872 MOV AL,[HEXADD] +1561 E8 06 00 2873 CALL HEXBYT +1564 32 C0 2874 XOR AL,AL +1566 E8 01 00 2875 CALL HEXBYT +1569 2876 AFHEX: +1569 58 2877 POP AX +156A 2878 HEXBYT: +156A 8A E8 2879 MOV CH,AL +156C BB 47 21 2880 MOV BX,CHKSUM +156F 02 07 2881 ADD AL,[BX] +1571 88 07 2882 MOV [BX],AL +1573 8A C5 2883 MOV AL,CH +1575 E8 84 00 2884 CALL UHALF +1578 E8 57 00 2885 CALL PUTCHR +157B 8A C5 2886 MOV AL,CH +157D E8 84 00 2887 CALL LHALF +1580 E8 4F 00 2888 CALL PUTCHR +1583 BB 46 21 2889 MOV BX,HEXCNT +1586 FE 07 2890 INC B,[BX] +1588 8A 07 2891 MOV AL,[BX] +158A 3C 1A 2892 CMP AL,26 +158C 75 8C 2893 JNZ RET +158E 2894 ENHEXL: +158E 8B 3E 40 21 2895 MOV DI,[HEXLEN] +1592 8A E8 2896 MOV CH,AL +1594 E8 65 00 2897 CALL UHALF +1597 AA 2898 STOB +1598 8A C5 2899 MOV AL,CH +159A E8 67 00 2900 CALL LHALF +159D AA 2901 STOB +159E B0 FA 2902 MOV AL,-6 +15A0 A2 46 21 2903 MOV [HEXCNT],AL +15A3 A0 47 21 2904 MOV AL,[CHKSUM] +15A6 02 C5 2905 ADD AL,CH +15A8 F6 D8 2906 NEG AL +15AA E8 BD FF 2907 CALL HEXBYT +15AD B0 0D 2908 MOV AL,13 +15AF E8 20 00 2909 CALL PUTCHR +15B2 B0 0A 2910 MOV AL,10 +15B4 E8 1B 00 2911 CALL PUTCHR +15B7 2912 WRTHEX: +15B7 2913 ;Write out the line +15B7 BA 5E 21 2914 MOV DX,HEXBUF +15BA 89 16 5A 21 2915 MOV [HEXPNT],DX +15BE B4 1A 2916 MOV AH,SETDMA +15C0 CD 21 2917 INT 33 +15C2 2B FA 2918 SUB DI,DX ;Length of buffer +15C4 8B CF 2919 MOV CX,DI +15C6 BA 80 20 2920 MOV DX,HEXFCB +15C9 B4 28 2921 MOV AH,BLKWRT +15CB CD 21 2922 INT 33 +15CD 0A C0 2923 OR AL,AL +15CF 75 25 2924 JNZ DSKFUL +15D1 C3 2925 RET +15D2 2926 +15D2 2927 PUTCHR: +15D2 8B 3E 5A 21 2928 MOV DI,[HEXPNT] +15D6 AA 2929 STOB +15D7 89 3E 5A 21 2930 MOV [HEXPNT],DI +15DB C3 2931 RET +15DC 2932 +15DC 2933 FLUSHBUF: +15DC 8B CF 2934 MOV CX,DI +15DE BA A4 21 2935 MOV DX,LSTBUF +15E1 8B FA 2936 MOV DI,DX +15E3 2B CA 2937 SUB CX,DX +15E5 74 F4 2938 JZ RET ;Buffer empty? +15E7 B4 1A 2939 MOV AH,SETDMA +15E9 CD 21 2940 INT 33 +15EB BA A5 20 2941 MOV DX,LSTFCB +15EE B4 28 2942 MOV AH,BLKWRT +15F0 CD 21 2943 INT 33 +15F2 0A C0 2944 OR AL,AL +15F4 74 E5 2945 JZ RET +15F6 2946 DSKFUL: +15F6 BB 27 20 2947 MOV BX,WRTERR +15F9 E9 7A EC 2948 JMP PRERR +15FC 2949 +15FC 2950 UHALF: +15FC D0 D8 2951 RCR AL +15FE D0 D8 2952 RCR AL +1600 D0 D8 2953 RCR AL +1602 D0 D8 2954 RCR AL +1604 2955 LHALF: +1604 24 0F 2956 AND AL,0FH +1606 0C 30 2957 OR AL,30H +1608 3C 3A 2958 CMP AL,'9'+1 +160A 72 CF 2959 JC RET +160C 04 07 2960 ADD AL,7 +160E C3 2961 RET +160F 2962 +160F 00 2963 NONE: DB 0 +1610 2964 +1610 2965 ; 8086 MNEMONIC TABLE +1610 2966 +1610 2967 ; This table is actually a sequence of subtables, each starting with a label. +1610 2968 ; The label signifies which mnemonics the subtable applies to--A3, for example, +1610 2969 ; means all 3-letter mnemonics beginning with A. +1610 2970 +1610 2971 A3: +1610 07 2972 DB 7 +1611 64 64 2973 DB 'dd' +1613 C1 0D 2974 DW GRP7 +1615 02 2975 DB 2 +1616 6E 64 2976 DB 'nd' +1618 97 0E 2977 DW GRP13 +161A 22 2978 DB 22H +161B 64 63 2979 DB 'dc' +161D C1 0D 2980 DW GRP7 +161F 12 2981 DB 12H +1620 61 61 2982 DB 'aa' +1622 9C 0B 2983 DW PUT +1624 37 2984 DB 37H +1625 61 73 2985 DB 'as' +1627 9C 0B 2986 DW PUT +1629 3F 2987 DB 3FH +162A 61 6D 2988 DB 'am' +162C 65 0E 2989 DW GRP11 +162E D4 2990 DB 0D4H +162F 61 64 2991 DB 'ad' +1631 65 0E 2992 DW GRP11 +1633 D5 2993 DB 0D5H +1634 2994 A5: +1634 01 2995 DB 1 +1635 6C 69 67 6E 2996 DB 'lign' +1639 6D 0D 2997 DW ALIGN +163B 00 2998 DB 0 +163C 2999 C3: +163C 07 3000 DB 7 +163D 6D 70 3001 DB 'mp' +163F C1 0D 3002 DW GRP7 +1641 3A 3003 DB 3AH +1642 6C 63 3004 DB 'lc' +1644 9C 0B 3005 DW PUT +1646 F8 3006 DB 0F8H +1647 6C 64 3007 DB 'ld' +1649 9C 0B 3008 DW PUT +164B FC 3009 DB 0FCH +164C 6C 69 3010 DB 'li' +164E 9C 0B 3011 DW PUT +1650 FA 3012 DB 0FAH +1651 6D 63 3013 DB 'mc' +1653 9C 0B 3014 DW PUT +1655 F5 3015 DB 0F5H +1656 62 77 3016 DB 'bw' +1658 9C 0B 3017 DW PUT +165A 98 3018 DB 98H +165B 77 64 3019 DB 'wd' +165D 9C 0B 3020 DW PUT +165F 99 3021 DB 99H +1660 3022 C4: +1660 03 3023 DB 3 +1661 61 6C 6C 3024 DB 'all' +1664 C1 0E 3025 DW GRP14 +1666 9A 3026 DB 9AH +1667 6D 70 62 3027 DB 'mpb' +166A 9C 0B 3028 DW PUT +166C A6 3029 DB 0A6H +166D 6D 70 77 3030 DB 'mpw' +1670 9C 0B 3031 DW PUT +1672 A7 3032 DB 0A7H +1673 3033 C5: +1673 02 3034 DB 2 +1674 6D 70 73 62 3035 DB 'mpsb' +1678 9C 0B 3036 DW PUT +167A A6 3037 DB 0A6H +167B 6D 70 73 77 3038 DB 'mpsw' +167F 9C 0B 3039 DW PUT +1681 A7 3040 DB 0A7H +1682 3041 D2: +1682 05 3042 DB 5 +1683 62 3043 DB 'b' +1684 CC 10 3044 DW GRP23 +1686 01 3045 DB 1 +1687 77 3046 DB 'w' +1688 CC 10 3047 DW GRP23 +168A 00 3048 DB 0 +168B 6D 3049 DB 'm' +168C CC 10 3050 DW GRP23 +168E 02 3051 DB 2 +168F 73 3052 DB 's' +1690 3B 0D 3053 DW GRP5 +1692 01 3054 DB 1 +1693 69 3055 DB 'i' +1694 9C 0B 3056 DW PUT +1696 FA 3057 DB 0FAH +1697 3058 D3: +1697 04 3059 DB 4 +1698 65 63 3060 DB 'ec' +169A E9 0D 3061 DW GRP8 +169C 49 3062 DB 49H +169D 69 76 3063 DB 'iv' +169F 3D 0E 3064 DW GRP10 +16A1 30 3065 DB 30H +16A2 61 61 3066 DB 'aa' +16A4 9C 0B 3067 DW PUT +16A6 27 3068 DB 27H +16A7 61 73 3069 DB 'as' +16A9 9C 0B 3070 DW PUT +16AB 2F 3071 DB 2FH +16AC 3072 D4: +16AC 01 3073 DB 1 +16AD 6F 77 6E 3074 DB 'own' +16B0 9C 0B 3075 DW PUT +16B2 FD 3076 DB 0FDH +16B3 3077 E2: +16B3 01 3078 DB 1 +16B4 69 3079 DB 'i' +16B5 9C 0B 3080 DW PUT +16B7 FB 3081 DB 0FBH +16B8 3082 E3: +16B8 03 3083 DB 3 +16B9 71 75 3084 DB 'qu' +16BB 3B 0D 3085 DW GRP5 +16BD 02 3086 DB 2 +16BE 73 63 3087 DB 'sc' +16C0 1B 10 3088 DW GRP19 +16C2 D8 3089 DB 0D8H +16C3 6E 64 3090 DB 'nd' +16C5 5A 11 3091 DW END +16C7 00 3092 DB 0 +16C8 3093 E5: +16C8 01 3094 DB 1 +16C9 6E 64 69 66 3095 DB 'ndif' +16CD 4A 11 3096 DW ENDIF +16CF 00 3097 DB 0 +16D0 3098 H3: +16D0 01 3099 DB 1 +16D1 6C 74 3100 DB 'lt' +16D3 9C 0B 3101 DW PUT +16D5 F4 3102 DB 0F4H +16D6 3103 H4: +16D6 01 3104 DB 1 +16D7 61 6C 74 3105 DB 'alt' +16DA 9C 0B 3106 DW PUT +16DC F4 3107 DB 0F4H +16DD 3108 I2: +16DD 02 3109 DB 2 +16DE 6E 3110 DB 'n' +16DF 15 0D 3111 DW GRP4 +16E1 E4 3112 DB 0E4H +16E2 66 3113 DB 'f' +16E3 3B 0D 3114 DW GRP5 +16E5 04 3115 DB 4 +16E6 3116 I3: +16E6 04 3117 DB 4 +16E7 6E 63 3118 DB 'nc' +16E9 E9 0D 3119 DW GRP8 +16EB 41 3120 DB 41H +16EC 6E 62 3121 DB 'nb' +16EE 15 0D 3122 DW GRP4 +16F0 E4 3123 DB 0E4H +16F1 6E 77 3124 DB 'nw' +16F3 15 0D 3125 DW GRP4 +16F5 E5 3126 DB 0E5H +16F6 6E 74 3127 DB 'nt' +16F8 F0 0F 3128 DW GRP18 +16FA CC 3129 DB 0CCH +16FB 3130 I4: +16FB 04 3131 DB 4 +16FC 6D 75 6C 3132 DB 'mul' +16FF 3D 0E 3133 DW GRP10 +1701 28 3134 DB 28H +1702 64 69 76 3135 DB 'div' +1705 3D 0E 3136 DW GRP10 +1707 38 3137 DB 38H +1708 72 65 74 3138 DB 'ret' +170B 9C 0B 3139 DW PUT +170D CF 3140 DB 0CFH +170E 6E 74 6F 3141 DB 'nto' +1711 9C 0B 3142 DW PUT +1713 CE 3143 DB 0CEH +1714 3144 J2: +1714 0A 3145 DB 10 +1715 70 3146 DB 'p' +1716 B7 0F 3147 DW GRP17 +1718 EB 3148 DB 0EBH +1719 7A 3149 DB 'z' +171A B7 0F 3150 DW GRP17 +171C 74 3151 DB 74H +171D 65 3152 DB 'e' +171E B7 0F 3153 DW GRP17 +1720 74 3154 DB 74H +1721 6C 3155 DB 'l' +1722 B7 0F 3156 DW GRP17 +1724 7C 3157 DB 7CH +1725 62 3158 DB 'b' +1726 B7 0F 3159 DW GRP17 +1728 72 3160 DB 72H +1729 61 3161 DB 'a' +172A B7 0F 3162 DW GRP17 +172C 77 3163 DB 77H +172D 67 3164 DB 'g' +172E B7 0F 3165 DW GRP17 +1730 7F 3166 DB 7FH +1731 6F 3167 DB 'o' +1732 B7 0F 3168 DW GRP17 +1734 70 3169 DB 70H +1735 73 3170 DB 's' +1736 B7 0F 3171 DW GRP17 +1738 78 3172 DB 78H +1739 63 3173 DB 'c' +173A B7 0F 3174 DW GRP17 +173C 72 3175 DB 72H +173D 3176 J3: +173D 11 3177 DB 17 +173E 6D 70 3178 DB 'mp' +1740 C1 0E 3179 DW GRP14 +1742 EA 3180 DB 0EAH +1743 6E 7A 3181 DB 'nz' +1745 B7 0F 3182 DW GRP17 +1747 75 3183 DB 75H +1748 6E 65 3184 DB 'ne' +174A B7 0F 3185 DW GRP17 +174C 75 3186 DB 75H +174D 6E 6C 3187 DB 'nl' +174F B7 0F 3188 DW GRP17 +1751 7D 3189 DB 7DH +1752 67 65 3190 DB 'ge' +1754 B7 0F 3191 DW GRP17 +1756 7D 3192 DB 7DH +1757 6E 62 3193 DB 'nb' +1759 B7 0F 3194 DW GRP17 +175B 73 3195 DB 73H +175C 61 65 3196 DB 'ae' +175E B7 0F 3197 DW GRP17 +1760 73 3198 DB 73H +1761 6E 63 3199 DB 'nc' +1763 B7 0F 3200 DW GRP17 +1765 73 3201 DB 73H +1766 6E 67 3202 DB 'ng' +1768 B7 0F 3203 DW GRP17 +176A 7E 3204 DB 7EH +176B 6C 65 3205 DB 'le' +176D B7 0F 3206 DW GRP17 +176F 7E 3207 DB 7EH +1770 6E 61 3208 DB 'na' +1772 B7 0F 3209 DW GRP17 +1774 76 3210 DB 76H +1775 62 65 3211 DB 'be' +1777 B7 0F 3212 DW GRP17 +1779 76 3213 DB 76H +177A 70 65 3214 DB 'pe' +177C B7 0F 3215 DW GRP17 +177E 7A 3216 DB 7AH +177F 6E 70 3217 DB 'np' +1781 B7 0F 3218 DW GRP17 +1783 7B 3219 DB 7BH +1784 70 6F 3220 DB 'po' +1786 B7 0F 3221 DW GRP17 +1788 7B 3222 DB 7BH +1789 6E 6F 3223 DB 'no' +178B B7 0F 3224 DW GRP17 +178D 71 3225 DB 71H +178E 6E 73 3226 DB 'ns' +1790 B7 0F 3227 DW GRP17 +1792 79 3228 DB 79H +1793 3229 J4: +1793 06 3230 DB 6 +1794 6D 70 73 3231 DB 'mps' +1797 B7 0F 3232 DW GRP17 +1799 EB 3233 DB 0EBH +179A 63 78 7A 3234 DB 'cxz' +179D B7 0F 3235 DW GRP17 +179F E3 3236 DB 0E3H +17A0 6E 67 65 3237 DB 'nge' +17A3 B7 0F 3238 DW GRP17 +17A5 7C 3239 DB 7CH +17A6 6E 61 65 3240 DB 'nae' +17A9 B7 0F 3241 DW GRP17 +17AB 72 3242 DB 72H +17AC 6E 62 65 3243 DB 'nbe' +17AF B7 0F 3244 DW GRP17 +17B1 77 3245 DB 77H +17B2 6E 6C 65 3246 DB 'nle' +17B5 B7 0F 3247 DW GRP17 +17B7 7F 3248 DB 7FH +17B8 3249 L3: +17B8 03 3250 DB 3 +17B9 65 61 3251 DB 'ea' +17BB B5 0D 3252 DW GRP6 +17BD 8D 3253 DB 8DH +17BE 64 73 3254 DB 'ds' +17C0 B5 0D 3255 DW GRP6 +17C2 C5 3256 DB 0C5H +17C3 65 73 3257 DB 'es' +17C5 B5 0D 3258 DW GRP6 +17C7 C4 3259 DB 0C4H +17C8 3260 L4: +17C8 05 3261 DB 5 +17C9 6F 6F 70 3262 DB 'oop' +17CC B7 0F 3263 DW GRP17 +17CE E2 3264 DB 0E2H +17CF 6F 64 62 3265 DB 'odb' +17D2 9C 0B 3266 DW PUT +17D4 AC 3267 DB 0ACH +17D5 6F 64 77 3268 DB 'odw' +17D8 9C 0B 3269 DW PUT +17DA AD 3270 DB 0ADH +17DB 61 68 66 3271 DB 'ahf' +17DE 9C 0B 3272 DW PUT +17E0 9F 3273 DB 9FH +17E1 6F 63 6B 3274 DB 'ock' +17E4 9C 0B 3275 DW PUT +17E6 F0 3276 DB 0F0H +17E7 3277 L5: +17E7 04 3278 DB 4 +17E8 6F 6F 70 65 3279 DB 'oope' +17EC B7 0F 3280 DW GRP17 +17EE E1 3281 DB 0E1H +17EF 6F 6F 70 7A 3282 DB 'oopz' +17F3 B7 0F 3283 DW GRP17 +17F5 E1 3284 DB 0E1H +17F6 6F 64 73 62 3285 DB 'odsb' +17FA 9C 0B 3286 DW PUT +17FC AC 3287 DB 0ACH +17FD 6F 64 73 77 3288 DB 'odsw' +1801 9C 0B 3289 DW PUT +1803 AD 3290 DB 0ADH +1804 3291 L6: +1804 02 3292 DB 2 +1805 6F 6F 70 6E 65 3293 DB 'oopne' +180A B7 0F 3294 DW GRP17 +180C E0 3295 DB 0E0H +180D 6F 6F 70 6E 7A 3296 DB 'oopnz' +1812 B7 0F 3297 DW GRP17 +1814 E0 3298 DB 0E0H +1815 3299 M3: +1815 02 3300 DB 2 +1816 6F 76 3301 DB 'ov' +1818 33 0B 3302 DW GRP1 +181A 88 3303 DB 88H +181B 75 6C 3304 DB 'ul' +181D 3D 0E 3305 DW GRP10 +181F 20 3306 DB 20H +1820 3307 M4: +1820 02 3308 DB 2 +1821 6F 76 62 3309 DB 'ovb' +1824 9C 0B 3310 DW PUT +1826 A4 3311 DB 0A4H +1827 6F 76 77 3312 DB 'ovw' +182A 9C 0B 3313 DW PUT +182C A5 3314 DB 0A5H +182D 3315 M5: +182D 02 3316 DB 2 +182E 6F 76 73 62 3317 DB 'ovsb' +1832 9C 0B 3318 DW PUT +1834 A4 3319 DB 0A4H +1835 6F 76 73 77 3320 DB 'ovsw' +1839 9C 0B 3321 DW PUT +183B A5 3322 DB 0A5H +183C 3323 N3: +183C 03 3324 DB 3 +183D 6F 74 3325 DB 'ot' +183F EF 0D 3326 DW GRP9 +1841 10 3327 DB 10H +1842 65 67 3328 DB 'eg' +1844 EF 0D 3329 DW GRP9 +1846 18 3330 DB 18H +1847 6F 70 3331 DB 'op' +1849 9C 0B 3332 DW PUT +184B 90 3333 DB 90H +184C 3334 O2: +184C 01 3335 DB 1 +184D 72 3336 DB 'r' +184E 97 0E 3337 DW GRP13 +1850 0A 3338 DB 0AH +1851 3339 O3: +1851 02 3340 DB 2 +1852 75 74 3341 DB 'ut' +1854 15 0D 3342 DW GRP4 +1856 E6 3343 DB 0E6H +1857 72 67 3344 DB 'rg' +1859 3B 0D 3345 DW GRP5 +185B 00 3346 DB 0 +185C 3347 O4: +185C 02 3348 DB 2 +185D 75 74 62 3349 DB 'utb' +1860 15 0D 3350 DW GRP4 +1862 E6 3351 DB 0E6H +1863 75 74 77 3352 DB 'utw' +1866 15 0D 3353 DW GRP4 +1868 E7 3354 DB 0E7H +1869 3355 P3: +1869 02 3356 DB 2 +186A 6F 70 3357 DB 'op' +186C AB 10 3358 DW GRP22 +186E 8F 3359 DB 8FH +186F 75 74 3360 DB 'ut' +1871 3B 0D 3361 DW GRP5 +1873 03 3362 DB 3 +1874 3363 P4: +1874 02 3364 DB 2 +1875 75 73 68 3365 DB 'ush' +1878 84 0C 3366 DW GRP2 +187A FF 3367 DB 0FFH +187B 6F 70 66 3368 DB 'opf' +187E 9C 0B 3369 DW PUT +1880 9D 3370 DB 9DH +1881 3371 P5: +1881 01 3372 DB 1 +1882 75 73 68 66 3373 DB 'ushf' +1886 9C 0B 3374 DW PUT +1888 9C 3375 DB 9CH +1889 3376 R3: +1889 06 3377 DB 6 +188A 65 74 3378 DB 'et' +188C 3F 0F 3379 DW GRP16 +188E C3 3380 DB 0C3H +188F 65 70 3381 DB 'ep' +1891 9C 0B 3382 DW PUT +1893 F3 3383 DB 0F3H +1894 6F 6C 3384 DB 'ol' +1896 6D 0E 3385 DW GRP12 +1898 00 3386 DB 0 +1899 6F 72 3387 DB 'or' +189B 6D 0E 3388 DW GRP12 +189D 08 3389 DB 8 +189E 63 6C 3390 DB 'cl' +18A0 6D 0E 3391 DW GRP12 +18A2 10 3392 DB 10H +18A3 63 72 3393 DB 'cr' +18A5 6D 0E 3394 DW GRP12 +18A7 18 3395 DB 18H +18A8 3396 R4: +18A8 02 3397 DB 2 +18A9 65 70 7A 3398 DB 'epz' +18AC 9C 0B 3399 DW PUT +18AE F3 3400 DB 0F3H +18AF 65 70 65 3401 DB 'epe' +18B2 9C 0B 3402 DW PUT +18B4 F3 3403 DB 0F3H +18B5 3404 R5: +18B5 02 3405 DB 2 +18B6 65 70 6E 7A 3406 DB 'epnz' +18BA 9C 0B 3407 DW PUT +18BC F2 3408 DB 0F2H +18BD 65 70 6E 65 3409 DB 'epne' +18C1 9C 0B 3410 DW PUT +18C3 F2 3411 DB 0F2H +18C4 3412 S3: +18C4 0B 3413 DB 11 +18C5 75 62 3414 DB 'ub' +18C7 C1 0D 3415 DW GRP7 +18C9 2A 3416 DB 2AH +18CA 62 62 3417 DB 'bb' +18CC C1 0D 3418 DW GRP7 +18CE 1A 3419 DB 1AH +18CF 62 63 3420 DB 'bc' +18D1 C1 0D 3421 DW GRP7 +18D3 1A 3422 DB 1AH +18D4 74 63 3423 DB 'tc' +18D6 9C 0B 3424 DW PUT +18D8 F9 3425 DB 0F9H +18D9 74 64 3426 DB 'td' +18DB 9C 0B 3427 DW PUT +18DD FD 3428 DB 0FDH +18DE 74 69 3429 DB 'ti' +18E0 9C 0B 3430 DW PUT +18E2 FB 3431 DB 0FBH +18E3 68 6C 3432 DB 'hl' +18E5 6D 0E 3433 DW GRP12 +18E7 20 3434 DB 20H +18E8 68 72 3435 DB 'hr' +18EA 6D 0E 3436 DW GRP12 +18EC 28 3437 DB 28H +18ED 61 6C 3438 DB 'al' +18EF 6D 0E 3439 DW GRP12 +18F1 20 3440 DB 20H +18F2 61 72 3441 DB 'ar' +18F4 6D 0E 3442 DW GRP12 +18F6 38 3443 DB 38H +18F7 65 67 3444 DB 'eg' +18F9 93 10 3445 DW GRP21 +18FB 26 3446 DB 26H +18FC 3447 S4: +18FC 05 3448 DB 5 +18FD 63 61 62 3449 DB 'cab' +1900 9C 0B 3450 DW PUT +1902 AE 3451 DB 0AEH +1903 63 61 77 3452 DB 'caw' +1906 9C 0B 3453 DW PUT +1908 AF 3454 DB 0AFH +1909 74 6F 62 3455 DB 'tob' +190C 9C 0B 3456 DW PUT +190E AA 3457 DB 0AAH +190F 74 6F 77 3458 DB 'tow' +1912 9C 0B 3459 DW PUT +1914 AB 3460 DB 0ABH +1915 61 68 66 3461 DB 'ahf' +1918 9C 0B 3462 DW PUT +191A 9E 3463 DB 9EH +191B 3464 S5: +191B 04 3465 DB 4 +191C 63 61 73 62 3466 DB 'casb' +1920 9C 0B 3467 DW PUT +1922 AE 3468 DB 0AEH +1923 63 61 73 77 3469 DB 'casw' +1927 9C 0B 3470 DW PUT +1929 AF 3471 DB 0AFH +192A 74 6F 73 62 3472 DB 'tosb' +192E 9C 0B 3473 DW PUT +1930 AA 3474 DB 0AAH +1931 74 6F 73 77 3475 DB 'tosw' +1935 9C 0B 3476 DW PUT +1937 AB 3477 DB 0ABH +1938 3478 T4: +1938 01 3479 DB 1 +1939 65 73 74 3480 DB 'est' +193C 82 10 3481 DW GRP20 +193E 84 3482 DB 84H +193F 3483 U2: +193F 01 3484 DB 1 +1940 70 3485 DB 'p' +1941 9C 0B 3486 DW PUT +1943 FC 3487 DB 0FCH +1944 3488 W4: +1944 01 3489 DB 1 +1945 61 69 74 3490 DB 'ait' +1948 9C 0B 3491 DW PUT +194A 9B 3492 DB 9BH +194B 3493 X3: +194B 01 3494 DB 1 +194C 6F 72 3495 DB 'or' +194E 97 0E 3496 DW GRP13 +1950 32 3497 DB 32H +1951 3498 X4: +1951 02 3499 DB 2 +1952 63 68 67 3500 DB 'chg' +1955 B5 0C 3501 DW GRP3 +1957 86 3502 DB 86H +1958 6C 61 74 3503 DB 'lat' +195B 9C 0B 3504 DW PUT +195D D7 3505 DB 0D7H +195E 3506 +195E 3507 +195E 3508 ; 8087 MNEMONIC TABLE +195E 3509 ; Similar to 8086 table above, except NOT distinguished by opcode length +195E 3510 +195E 3511 XM1: ;F2XM1 +195E 01 3512 DB 1 ;One opcode +195F 78 6D B1 3513 DM "xm1" +1962 01 F0 3514 DB 1,0F0H +1964 3515 +1964 3516 NDPA: +1964 03 3517 DB 3 +1965 64 E4 3518 DM "dd" +1967 0E C1 3519 DB 6+ARITH,0C1H +1969 64 64 F0 3520 DM "ddp" +196C 90 00 3521 DB NEEDOP+STACKOP,0 +196E 62 F3 3522 DM "bs" +1970 01 E1 3523 DB 1,0E1H +1972 3524 +1972 3525 NDPB: +1972 02 3526 DB 2 +1973 6C E4 3527 DM "ld" +1975 9F 20 3528 DB 7+NEEDOP+MEMORY,20H +1977 73 74 F0 3529 DM "stp" +197A 9F 30 3530 DB 7+NEEDOP+MEMORY,30H +197C 3531 +197C 3532 NDPC: +197C 05 3533 DB 5 +197D 6F ED 3534 DM "om" +197F 68 D1 3535 DB 0+ONEREG+REAL,0D1H +1981 6F 6D F0 3536 DM "omp" +1984 68 D9 3537 DB 0+ONEREG+REAL,0D9H +1986 68 F3 3538 DM "hs" +1988 01 E0 3539 DB 1,0E0H +198A 6F 6D 70 F0 3540 DM "ompp" +198E 06 D9 3541 DB 6,0D9H +1990 6C 65 F8 3542 DM "lex" +1993 03 E2 3543 DB 3,0E2H +1995 3544 +1995 3545 NDPD: +1995 06 3546 DB 6 +1996 69 F6 3547 DM "iv" +1998 0E F1 3548 DB 6+ARITH,0F1H +199A 69 76 F0 3549 DM "ivp" +199D 90 30 3550 DB NEEDOP+STACKOP,30H +199F 69 76 F2 3551 DM "ivr" +19A2 0E F9 3552 DB 6+ARITH,0F9H +19A4 69 76 72 F0 3553 DM "ivrp" +19A8 90 38 3554 DB NEEDOP+STACKOP,38H +19AA 65 63 73 74 F0 3555 DM "ecstp" +19AF 01 F6 3556 DB 1,0F6H +19B1 69 73 E9 3557 DM "isi" +19B4 03 E1 3558 DB 3,0E1H +19B6 3559 +19B6 3560 NDPE: +19B6 01 3561 DB 1 +19B7 6E E9 3562 DM "ni" +19B9 03 E0 3563 DB 3,0E0H +19BB 3564 +19BB 3565 NDPF: +19BB 01 3566 DB 1 +19BC 72 65 E5 3567 DM "ree" +19BF C5 00 3568 DB 5+NEEDOP+ONEREG,0 +19C1 3569 +19C1 3570 NDPI: +19C1 0D 3571 DB 13 +19C2 61 64 E4 3572 DM "add" +19C5 A2 00 3573 DB 2+NEEDOP+INTEGER,0 +19C7 6C E4 3574 DM "ld" +19C9 B3 00 3575 DB 3+NEEDOP+INTEGER+EXTENDED,0 +19CB 73 75 E2 3576 DM "sub" +19CE A2 20 3577 DB 2+NEEDOP+INTEGER,20H +19D0 73 74 F0 3578 DM "stp" +19D3 B3 18 3579 DB 3+NEEDOP+INTEGER+EXTENDED,18H +19D5 73 F4 3580 DM "st" +19D7 A3 10 3581 DB 3+NEEDOP+INTEGER,10H +19D9 6D 75 EC 3582 DM "mul" +19DC A2 08 3583 DB 2+NEEDOP+INTEGER,8 +19DE 64 69 F6 3584 DM "div" +19E1 A2 30 3585 DB 2+NEEDOP+INTEGER,30H +19E3 73 75 62 F2 3586 DM "subr" +19E7 A2 28 3587 DB 2+NEEDOP+INTEGER,28H +19E9 64 69 76 F2 3588 DM "divr" +19ED A2 38 3589 DB 2+NEEDOP+INTEGER,38H +19EF 63 6F ED 3590 DM "com" +19F2 A2 10 3591 DB 2+NEEDOP+INTEGER,10H +19F4 63 6F 6D F0 3592 DM "comp" +19F8 A2 18 3593 DB 2+NEEDOP+INTEGER,18H +19FA 6E 63 73 74 F0 3594 DM "ncstp" +19FF 01 F7 3595 DB 1,0F7H +1A01 6E 69 F4 3596 DM "nit" +1A04 03 E3 3597 DB 3,0E3H +1A06 3598 +1A06 3599 NDPL: +1A06 0A 3600 DB 10 +1A07 E4 3601 DM "d" +1A08 F9 00 3602 DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0 +1A0A 64 FA 3603 DM "dz" +1A0C 01 EE 3604 DB 1,0EEH +1A0E 64 B1 3605 DM "d1" +1A10 01 E8 3606 DB 1,0E8H +1A12 64 70 E9 3607 DM "dpi" +1A15 01 EB 3608 DB 1,0EBH +1A17 64 6C 32 F4 3609 DM "dl2t" +1A1B 01 E9 3610 DB 1,0E9H +1A1D 64 6C 32 E5 3611 DM "dl2e" +1A21 01 EA 3612 DB 1,0EAH +1A23 64 6C 67 B2 3613 DM "dlg2" +1A27 01 EC 3614 DB 1,0ECH +1A29 64 6C 6E B2 3615 DM "dln2" +1A2D 01 ED 3616 DB 1,0EDH +1A2F 64 63 F7 3617 DM "dcw" +1A32 99 28 3618 DB 1+NEEDOP+MEMORY,28H +1A34 64 65 6E F6 3619 DM "denv" +1A38 99 20 3620 DB 1+NEEDOP+MEMORY,20H +1A3A 3621 +1A3A 3622 NDPM: +1A3A 02 3623 DB 2 +1A3B 75 EC 3624 DM "ul" +1A3D 0E C9 3625 DB 6+ARITH,0C9H +1A3F 75 6C F0 3626 DM "ulp" +1A42 90 08 3627 DB NEEDOP+STACKOP,8 +1A44 3628 +1A44 3629 NDPO: +1A44 01 3630 DB 1 +1A45 F0 3631 DM "p" +1A46 81 00 3632 DB NEEDOP+1,0 ;Flag special handling +1A48 3633 +1A48 3634 NDPN: +1A48 01 3635 DB 1 +1A49 6F F0 3636 DM "op" +1A4B 01 D0 3637 DB 1,0D0H +1A4D 3638 +1A4D 3639 NDPP: +1A4D 03 3640 DB 3 +1A4E 72 65 ED 3641 DM "rem" +1A51 01 F8 3642 DB 1,0F8H +1A53 74 61 EE 3643 DM "tan" +1A56 01 F2 3644 DB 1,0F2H +1A58 61 74 61 EE 3645 DM "atan" +1A5C 01 F3 3646 DB 1,0F3H +1A5E 3647 +1A5E 3648 NDPR: +1A5E 02 3649 DB 2 +1A5F 6E 64 69 6E F4 3650 DM "ndint" +1A64 01 FC 3651 DB 1,0FCH +1A66 73 74 6F F2 3652 DM "stor" +1A6A 9D 20 3653 DB 5+NEEDOP+MEMORY,20H +1A6C 3654 +1A6C 3655 NDPS: +1A6C 0C 3656 DB 12 +1A6D F4 3657 DM "t" +1A6E ED D0 3658 DB 5+NEEDOP+ONEREG+REAL,0D0H +1A70 74 F0 3659 DM "tp" +1A72 FF D8 3660 DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H +1A74 75 E2 3661 DM "ub" +1A76 0E E1 3662 DB 6+ARITH,0E1H +1A78 75 62 F0 3663 DM "ubp" +1A7B 90 E0 3664 DB NEEDOP+STACKOP,0E0H +1A7D 75 62 F2 3665 DM "ubr" +1A80 0E E9 3666 DB 6+ARITH,0E9H +1A82 75 62 72 F0 3667 DM "ubrp" +1A86 90 E8 3668 DB NEEDOP+STACKOP,0E8H +1A88 71 72 F4 3669 DM "qrt" +1A8B 01 FA 3670 DB 1,0FAH +1A8D 63 61 6C E5 3671 DM "cale" +1A91 01 FD 3672 DB 1,0FDH +1A93 61 76 E5 3673 DM "ave" +1A96 9D 30 3674 DB 5+NEEDOP+MEMORY,30H +1A98 74 63 F7 3675 DM "tcw" +1A9B 99 38 3676 DB 1+NEEDOP+MEMORY,38H +1A9D 74 65 6E F6 3677 DM "tenv" +1AA1 99 30 3678 DB 1+NEEDOP+MEMORY,30H +1AA3 74 73 F7 3679 DM "tsw" +1AA6 9D 38 3680 DB 5+NEEDOP+MEMORY,38H +1AA8 3681 +1AA8 3682 NDPT: +1AA8 01 3683 DB 1 +1AA9 73 F4 3684 DM "st" +1AAB 01 E4 3685 DB 1,0E4H +1AAD 3686 +1AAD 3687 NDPW: +1AAD 01 3688 DB 1 +1AAE 61 69 F4 3689 DM "ait" +1AB1 80 00 3690 DB NEEDOP,0 ;Flag special handling +1AB3 3691 +1AB3 3692 NDPX: +1AB3 03 3693 DB 3 +1AB4 63 E8 3694 DM "ch" +1AB6 41 C9 3695 DB 1+ONEREG,0C9H +1AB8 61 ED 3696 DM "am" +1ABA 01 E5 3697 DB 1,0E5H +1ABC 74 72 61 63 F4 3698 DM "tract" +1AC1 01 F4 3699 DB 1,0F4H +1AC3 3700 +1AC3 3701 NDPY: +1AC3 02 3702 DB 2 +1AC4 6C 32 F8 3703 DM "l2x" +1AC7 01 F1 3704 DB 1,0F1H +1AC9 6C 32 78 70 B1 3705 DM "l2xp1" +1ACE 01 F9 3706 DB 1,0F9H +1AD0 3707 +1AD0 3708 +1AD0 3709 OPTAB: +1AD0 3710 ; Table of pointers to mnemonics. For each letter of the alphabet (the +1AD0 3711 ; starting letter of the mnemonic), there are 5 entries. Each entry +1AD0 3712 ; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +1AD0 3713 ; long, respectively. If there are no mnemonics for a given combination +1AD0 3714 ; of first letter and length (such as A-2), then the corresponding entry +1AD0 3715 ; points to NONE. Otherwise, it points to a place in the mnemonic table +1AD0 3716 ; for that type. +1AD0 3717 +1AD0 3718 ; This table only needs to be modified if a mnemonic is added to a group +1AD0 3719 ; previously marked NONE. Change the NONE to a label made up of the first +1AD0 3720 ; letter of the mnemonic and its length, then add a new subsection to +1AD0 3721 ; the mnemonic table in alphabetical order. +1AD0 3722 +1AD0 0F 16 3723 DW NONE +1AD2 10 16 3724 DW A3 +1AD4 0F 16 3725 DW NONE +1AD6 34 16 3726 DW A5 +1AD8 0F 16 3727 DW NONE +1ADA 0F 16 3728 DW NONE ;B +1ADC 0F 16 3729 DW NONE +1ADE 0F 16 3730 DW NONE +1AE0 0F 16 3731 DW NONE +1AE2 0F 16 3732 DW NONE +1AE4 0F 16 3733 DW NONE ;C +1AE6 3C 16 3734 DW C3 +1AE8 60 16 3735 DW C4 +1AEA 73 16 3736 DW C5 +1AEC 0F 16 3737 DW NONE +1AEE 82 16 3738 DW D2 ;D +1AF0 97 16 3739 DW D3 +1AF2 AC 16 3740 DW D4 +1AF4 0F 16 3741 DW NONE +1AF6 0F 16 3742 DW NONE +1AF8 B3 16 3743 DW E2 ;E +1AFA B8 16 3744 DW E3 +1AFC 0F 16 3745 DW NONE +1AFE C8 16 3746 DW E5 +1B00 0F 16 3747 DW NONE +1B02 0F 16 3748 DW NONE ;F +1B04 0F 16 3749 DW NONE +1B06 0F 16 3750 DW NONE +1B08 0F 16 3751 DW NONE +1B0A 0F 16 3752 DW NONE +1B0C 0F 16 3753 DW NONE ;G +1B0E 0F 16 3754 DW NONE +1B10 0F 16 3755 DW NONE +1B12 0F 16 3756 DW NONE +1B14 0F 16 3757 DW NONE +1B16 0F 16 3758 DW NONE ;H +1B18 D0 16 3759 DW H3 +1B1A D6 16 3760 DW H4 +1B1C 0F 16 3761 DW NONE +1B1E 0F 16 3762 DW NONE +1B20 DD 16 3763 DW I2 ;I +1B22 E6 16 3764 DW I3 +1B24 FB 16 3765 DW I4 +1B26 0F 16 3766 DW NONE +1B28 0F 16 3767 DW NONE +1B2A 14 17 3768 DW J2 ;J +1B2C 3D 17 3769 DW J3 +1B2E 93 17 3770 DW J4 +1B30 0F 16 3771 DW NONE +1B32 0F 16 3772 DW NONE +1B34 0F 16 3773 DW NONE ;K +1B36 0F 16 3774 DW NONE +1B38 0F 16 3775 DW NONE +1B3A 0F 16 3776 DW NONE +1B3C 0F 16 3777 DW NONE +1B3E 0F 16 3778 DW NONE ;L +1B40 B8 17 3779 DW L3 +1B42 C8 17 3780 DW L4 +1B44 E7 17 3781 DW L5 +1B46 04 18 3782 DW L6 +1B48 0F 16 3783 DW NONE ;M +1B4A 15 18 3784 DW M3 +1B4C 20 18 3785 DW M4 +1B4E 2D 18 3786 DW M5 +1B50 0F 16 3787 DW NONE +1B52 0F 16 3788 DW NONE ;N +1B54 3C 18 3789 DW N3 +1B56 0F 16 3790 DW NONE +1B58 0F 16 3791 DW NONE +1B5A 0F 16 3792 DW NONE +1B5C 4C 18 3793 DW O2 ;O +1B5E 51 18 3794 DW O3 +1B60 5C 18 3795 DW O4 +1B62 0F 16 3796 DW NONE +1B64 0F 16 3797 DW NONE +1B66 0F 16 3798 DW NONE ;P +1B68 69 18 3799 DW P3 +1B6A 74 18 3800 DW P4 +1B6C 81 18 3801 DW P5 +1B6E 0F 16 3802 DW NONE +1B70 0F 16 3803 DW NONE ;Q +1B72 0F 16 3804 DW NONE +1B74 0F 16 3805 DW NONE +1B76 0F 16 3806 DW NONE +1B78 0F 16 3807 DW NONE +1B7A 0F 16 3808 DW NONE ;R +1B7C 89 18 3809 DW R3 +1B7E A8 18 3810 DW R4 +1B80 B5 18 3811 DW R5 +1B82 0F 16 3812 DW NONE +1B84 0F 16 3813 DW NONE ;S +1B86 C4 18 3814 DW S3 +1B88 FC 18 3815 DW S4 +1B8A 1B 19 3816 DW S5 +1B8C 0F 16 3817 DW NONE +1B8E 0F 16 3818 DW NONE ;T +1B90 0F 16 3819 DW NONE +1B92 38 19 3820 DW T4 +1B94 0F 16 3821 DW NONE +1B96 0F 16 3822 DW NONE +1B98 3F 19 3823 DW U2 ;U +1B9A 0F 16 3824 DW NONE +1B9C 0F 16 3825 DW NONE +1B9E 0F 16 3826 DW NONE +1BA0 0F 16 3827 DW NONE +1BA2 0F 16 3828 DW NONE ;V +1BA4 0F 16 3829 DW NONE +1BA6 0F 16 3830 DW NONE +1BA8 0F 16 3831 DW NONE +1BAA 0F 16 3832 DW NONE +1BAC 0F 16 3833 DW NONE ;W +1BAE 0F 16 3834 DW NONE +1BB0 44 19 3835 DW W4 +1BB2 0F 16 3836 DW NONE +1BB4 0F 16 3837 DW NONE +1BB6 0F 16 3838 DW NONE ;X +1BB8 4B 19 3839 DW X3 +1BBA 51 19 3840 DW X4 +1BBC 0F 16 3841 DW NONE +1BBE 0F 16 3842 DW NONE +1BC0 0F 16 3843 DW NONE ;Y +1BC2 0F 16 3844 DW NONE +1BC4 0F 16 3845 DW NONE +1BC6 0F 16 3846 DW NONE +1BC8 0F 16 3847 DW NONE +1BCA 0F 16 3848 DW NONE ;Z +1BCC 0F 16 3849 DW NONE +1BCE 0F 16 3850 DW NONE +1BD0 0F 16 3851 DW NONE +1BD2 0F 16 3852 DW NONE +1BD4 3853 +1BD4 3854 NDPTAB: +1BD4 3855 ;Lookup table for 8087 mnemonics. There is one entry for each letter of the +1BD4 3856 ;alphabet +1BD4 64 19 3857 DW NDPA +1BD6 72 19 3858 DW NDPB +1BD8 7C 19 3859 DW NDPC +1BDA 95 19 3860 DW NDPD +1BDC B6 19 3861 DW NDPE +1BDE BB 19 3862 DW NDPF +1BE0 0F 16 3863 DW NONE ;G +1BE2 0F 16 3864 DW NONE ;H +1BE4 C1 19 3865 DW NDPI +1BE6 0F 16 3866 DW NONE ;J +1BE8 0F 16 3867 DW NONE ;K +1BEA 06 1A 3868 DW NDPL +1BEC 3A 1A 3869 DW NDPM +1BEE 48 1A 3870 DW NDPN +1BF0 44 1A 3871 DW NDPO +1BF2 4D 1A 3872 DW NDPP +1BF4 0F 16 3873 DW NONE ;Q +1BF6 5E 1A 3874 DW NDPR +1BF8 6C 1A 3875 DW NDPS +1BFA A8 1A 3876 DW NDPT +1BFC 0F 16 3877 DW NONE ;U +1BFE 0F 16 3878 DW NONE ;V +1C00 AD 1A 3879 DW NDPW +1C02 B3 1A 3880 DW NDPX +1C04 C3 1A 3881 DW NDPY +1C06 0F 16 3882 DW NONE ;Z +1C08 3883 +1C08 3884 ;Error message table +1C08 3885 +1C08 3886 ERRTAB: +1C08 01 52 65 67 69 73 74 3887 DM 1,"Register not allowed in immediate value" + 65 72 20 6E 6F 74 20 + 61 6C 6C 6F 77 65 64 + 20 69 6E 20 69 6D 6D + 65 64 69 61 74 65 20 + 76 61 6C 75 E5 +1C30 02 49 6E 64 65 78 20 3888 DM 2,"Index or base register must be BP, BX, SI, or DI" + 6F 72 20 62 61 73 65 + 20 72 65 67 69 73 74 + 65 72 20 6D 75 73 74 + 20 62 65 20 42 50 2C + 20 42 58 2C 20 53 49 + 2C 20 6F 72 20 44 C9 +1C61 03 4F 6E 6C 79 20 6F 3889 DM 3,"Only one base register (BX, BP) allowed" + 6E 65 20 62 61 73 65 + 20 72 65 67 69 73 74 + 65 72 20 28 42 58 2C + 20 42 50 29 20 61 6C + 6C 6F 77 65 E4 +1C89 04 4F 6E 6C 79 20 6F 3890 DM 4,"Only one index register (SI or DI) allowed" + 6E 65 20 69 6E 64 65 + 78 20 72 65 67 69 73 + 74 65 72 20 28 53 49 + 20 6F 72 20 44 49 29 + 20 61 6C 6C 6F 77 65 + E4 +1CB4 05 4F 6E 6C 79 20 61 3891 DM 5,"Only addition allowed on register or undefined label" + 64 64 69 74 69 6F 6E + 20 61 6C 6C 6F 77 65 + 64 20 6F 6E 20 72 65 + 67 69 73 74 65 72 20 + 6F 72 20 75 6E 64 65 + 66 69 6E 65 64 20 6C + 61 62 65 EC +1CE9 06 4F 6E 6C 79 20 6F 3892 DM 6,"Only one undefined label per expression allowed" + 6E 65 20 75 6E 64 65 + 66 69 6E 65 64 20 6C + 61 62 65 6C 20 70 65 + 72 20 65 78 70 72 65 + 73 73 69 6F 6E 20 61 + 6C 6C 6F 77 65 E4 +1D19 07 49 6C 6C 65 67 61 3893 DM 7,"Illegal digit in hexadecimal number" + 6C 20 64 69 67 69 74 + 20 69 6E 20 68 65 78 + 61 64 65 63 69 6D 61 + 6C 20 6E 75 6D 62 65 + F2 +1D3D 08 49 6C 6C 65 67 61 3894 DM 8,"Illegal digit in decimal number" + 6C 20 64 69 67 69 74 + 20 69 6E 20 64 65 63 + 69 6D 61 6C 20 6E 75 + 6D 62 65 F2 +1D5D 0A 49 6C 6C 65 67 61 3895 DM 10,"Illegal character in label or opcode" + 6C 20 63 68 61 72 61 + 63 74 65 72 20 69 6E + 20 6C 61 62 65 6C 20 + 6F 72 20 6F 70 63 6F + 64 E5 +1D82 0B 4C 61 62 65 6C 20 3896 DM 11,"Label defined twice" + 64 65 66 69 6E 65 64 + 20 74 77 69 63 E5 +1D96 0C 4F 70 63 6F 64 65 3897 DM 12,"Opcode not recognized" + 20 6E 6F 74 20 72 65 + 63 6F 67 6E 69 7A 65 + E4 +1DAC 14 49 6E 76 61 6C 69 3898 DM 20,"Invalid operand" + 64 20 6F 70 65 72 61 + 6E E4 +1DBC 15 22 2C 22 20 61 6E 3899 DM 21,'"," and second operand expected' + 64 20 73 65 63 6F 6E + 64 20 6F 70 65 72 61 + 6E 64 20 65 78 70 65 + 63 74 65 E4 +1DDC 16 52 65 67 69 73 74 3900 DM 22,"Register mismatch" + 65 72 20 6D 69 73 6D + 61 74 63 E8 +1DEE 17 49 6D 6D 65 64 69 3901 DM 23,"Immediate operand not allowed" + 61 74 65 20 6F 70 65 + 72 61 6E 64 20 6E 6F + 74 20 61 6C 6C 6F 77 + 65 E4 +1E0C 18 22 5D 22 20 65 78 3902 DM 24,'"]" expected' + 70 65 63 74 65 E4 +1E19 19 54 77 6F 20 6D 65 3903 DM 25,"Two memory operands not allowed" + 6D 6F 72 79 20 6F 70 + 65 72 61 6E 64 73 20 + 6E 6F 74 20 61 6C 6C + 6F 77 65 E4 +1E39 1A 44 65 73 74 69 6E 3904 DM 26,"Destination must not be immediate value" + 61 74 69 6F 6E 20 6D + 75 73 74 20 6E 6F 74 + 20 62 65 20 69 6D 6D + 65 64 69 61 74 65 20 + 76 61 6C 75 E5 +1E61 1B 42 6F 74 68 20 6F 3905 DM 27,"Both operands must not be registers" + 70 65 72 61 6E 64 73 + 20 6D 75 73 74 20 6E + 6F 74 20 62 65 20 72 + 65 67 69 73 74 65 72 + F3 +1E85 1C 4F 70 65 72 61 6E 3906 DM 28,"Operand must be segment register" + 64 20 6D 75 73 74 20 + 62 65 20 73 65 67 6D + 65 6E 74 20 72 65 67 + 69 73 74 65 F2 +1EA6 1D 46 69 72 73 74 20 3907 DM 29,"First operand must be register" + 6F 70 65 72 61 6E 64 + 20 6D 75 73 74 20 62 + 65 20 72 65 67 69 73 + 74 65 F2 +1EC5 1E 55 6E 64 65 66 69 3908 DM 30,"Undefined label not allowed" + 6E 65 64 20 6C 61 62 + 65 6C 20 6E 6F 74 20 + 61 6C 6C 6F 77 65 E4 +1EE1 1F 56 61 6C 75 65 20 3909 DM 31,"Value out of range" + 6F 75 74 20 6F 66 20 + 72 61 6E 67 E5 +1EF4 20 4D 69 73 73 69 6E 3910 DM 32,"Missing or illegal operand size flag" + 67 20 6F 72 20 69 6C + 6C 65 67 61 6C 20 6F + 70 65 72 61 6E 64 20 + 73 69 7A 65 20 66 6C + 61 E7 +1F19 21 4D 75 73 74 20 68 3911 DM 33,"Must have label on same line" + 61 76 65 20 6C 61 62 + 65 6C 20 6F 6E 20 73 + 61 6D 65 20 6C 69 6E + E5 +1F36 23 5A 65 72 6F 2D 6C 3912 DM 35,"Zero-length string illegal" + 65 6E 67 74 68 20 73 + 74 72 69 6E 67 20 69 + 6C 6C 65 67 61 EC +1F51 24 45 4E 44 49 46 20 3913 DM 36,"ENDIF without IF" + 77 69 74 68 6F 75 74 + 20 49 C6 +1F62 25 4F 6E 65 2D 63 68 3914 DM 37,"One-character strings only" + 61 72 61 63 74 65 72 + 20 73 74 72 69 6E 67 + 73 20 6F 6E 6C F9 +1F7D 26 49 6C 6C 65 67 61 3915 DM 38,"Illegal expression" + 6C 20 65 78 70 72 65 + 73 73 69 6F EE +1F90 27 45 6E 64 20 6F 66 3916 DM 39,"End of string not found" + 20 73 74 72 69 6E 67 + 20 6E 6F 74 20 66 6F + 75 6E E4 +1FA8 64 55 6E 64 65 66 69 3917 DM 100,"Undefined label" + 6E 65 64 20 6C 61 62 + 65 EC +1FB8 65 56 61 6C 75 65 20 3918 DM 101,"Value out of range (forward)" + 6F 75 74 20 6F 66 20 + 72 61 6E 67 65 20 28 + 66 6F 72 77 61 72 64 + A9 +1FD5 FF 3919 DB 255 +1FD6 3920 +1FD6 2A 2A 2A 2A 2A 20 45 3921 ERRMES: DM '***** ERROR: ' + 52 52 4F 52 3A 20 A0 +1FE4 0D 0A 46 69 6C 65 20 3922 NOSPAC: DB 13,10,'File creation error',13,10,"$" + 63 72 65 61 74 69 6F + 6E 20 65 72 72 6F 72 + 0D 0A 24 +1FFC 0D 0A 49 6E 73 75 66 3923 NOMEM: DB 13,10,'Insufficient memory',13,10,'$' + 66 69 63 69 65 6E 74 + 20 6D 65 6D 6F 72 79 + 0D 0A 24 +2014 0D 0A 46 69 6C 65 20 3924 NOFILE: DB 13,10,'File not found',13,10,'$' + 6E 6F 74 20 66 6F 75 + 6E 64 0D 0A 24 +2027 0D 0A 44 69 73 6B 20 3925 WRTERR: DB 13,10,'Disk full',13,10,'$' + 66 75 6C 6C 0D 0A 24 +2035 0D 0A 42 61 64 20 64 3926 BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' + 69 73 6B 20 73 70 65 + 63 69 66 69 65 72 0D + 0A 24 +204C 0D 0A 0D 0A 45 72 72 3927 ERCNTM: DM 13,10,13,10,'Error Count =' + 6F 72 20 43 6F 75 6E + 74 20 BD +205D 0D 0A 53 79 6D 62 6F 3928 SYMMES: DM 13,10,'Symbol Table',13,10,13,10 + 6C 20 54 61 62 6C 65 + 0D 0A 0D 8A +206F 41 53 4D 00 00 3929 EXTEND: DB 'ASM',0,0 +2074 05 65 6E 64 69 66 3930 IFEND: DB 5,'endif' +207A 02 69 66 3931 IFNEST: DB 2,'if' +207D 72 65 F4 3932 RETSTR: DM 'ret' +2080 00 20 20 20 20 20 20 3933 HEXFCB: DB 0,' HEX',0,0,0,0 + 20 20 48 45 58 00 00 + 00 00 +2090 3934 DS 16 +20A0 00 00 00 00 00 3935 DB 0,0,0,0,0 +20A5 00 20 20 20 20 20 20 3936 LSTFCB: DB 0,' PRN',0,0,0,0 + 20 20 50 52 4E 00 00 + 00 00 +20B5 3937 DS 16 +20C5 00 00 00 00 00 3938 DB 0,0,0,0,0 +20CA 3939 PC: DS 2 +20CC 3940 OLDPC: DS 2 +20CE 3941 LABPT: DS 2 +20D0 3942 FLAG: DS 1 +20D1 3943 MAXFLG: DS 1 +20D2 3944 ADDR: DS 2 +20D4 3945 ALABEL: DS 2 +20D6 3946 DATA: DS 2 +20D8 3947 DLABEL: DS 2 +20DA 3948 CON: DS 2 +20DC 3949 UNDEF: DS 2 +20DE 3950 LENID: DS 1 +20DF 3951 ID: DS 80 +212F 3952 CHR: DS 1 +2130 3953 SYM: DS 1 +2131 3954 BASE: DS 2 +2133 3955 HEAP: DS 2 +2135 3956 SYMFLG: DS 1 +2136 3957 SYMLIN: DS 1 +2137 3958 CODE: DS 2 +2139 3959 DATSIZ: DS 1 +213A 3960 RELOC: DS 1 +213B 3961 BCOUNT: DS 1 +213C 3962 COUNT: DS 1 +213D 3963 ERR: DS 1 +213E 3964 LINE: DS 2 +2140 3965 HEXLEN: DS 2 +2142 3966 HEXADD: DS 2 +2144 3967 LASTAD: DS 2 +2146 3968 HEXCNT: DS 1 +2147 3969 CHKSUM: DS 1 +2148 3970 LINFLG: DS 1 +2149 3971 PREV: DS 1 +214A 3972 IFFLG: DS 1 +214B 3973 CHKLAB: DS 1 +214C 3974 ERRCNT: DS 2 +214E 3975 LSTRET: DS 2 +2150 3976 RETPT: DS 2 +2152 3977 LSTDEV: DS 2 +2154 3978 SPC: DS 1 +2155 3979 NOWAIT: DS 1 +2156 3980 IX: DS 2 +2158 3981 IY: DS 2 +215A 3982 HEXPNT: DS 2 +215C 3983 LSTPNT: DS 2 +215E 3984 HEXBUF: DS HEXBUFSIZ +21A4 3985 LSTBUF: DS LSTBUFSIZ +25A4 3986 BUFPT: DS 2 +25A6 3987 SRCBUF: DS BUFSIZ +29A6 3988 DS 100H +2AA6 3989 ALIGN +2AA6 3990 STACK: EQU $ +2AA6 3991 START: EQU $ + + +Error Count = 0 + +Symbol Table + +a3 1610 a5 1634 abort 0273 accimm 0EA0 accj 0DE6 +add 04CE addr 20D2 afhex 1569 aimm 0EA9 alabel 20D4 +align 0D6D allret 0858 arith 0008 asmlin 0954 baddsk 2035 +badflag 0AD9 badop 04E3 base 2131 bcount 213B begin 0176 +blkwrt 0028 blnk 1257 bpj 0576 bufpt 25A4 bufsiz 0400 +bxj 0579 bytimm 0B53 bytsiz 05DE c3 163C c4 1660 +c5 1673 chkdsk 02A0 chklab 214B chkret 0830 chksum 2147 +chr 212F close 0010 codbyt 151B code 2137 codlp 1242 +con 20DA const 0001 count 213C cpslp 08F2 create 08AC +crlf 12E7 d2 1682 d3 1697 d4 16AC data 20D6 +datsiz 2139 dds 1291 dec 0666 default 0194 defbyt 11E5 +digit 131D dij 056A direct 0F06 dlabel 20D8 dollar 061B +domul 051E doret 0FB0 dorg 129C dosymtab 13ED +dput 12A3 dsj 0D77 dskerr 02AC dskful 15F6 e2 16B3 +e3 16B8 e5 16C8 emark 1217 empty 08A4 end 115A +endcond 1143 enddat 10E6 endif 114A endj 024E endlin 0253 +endln 0251 endop 0A12 endsym 140B endterm 0527 enhexl 158E +enter 089B eol 000D equ 0D89 ercntm 204C err 213D +err1 03BC err10 0FEC err11 10C9 err2 0567 err30 05A1 +err4 06B6 err5 0951 err6 0D12 err7 0DBE err8 0EBE +err9 0FC1 errcnt 214C errj 105D errj1 0E55 errj3 073D +errj4 0ADB errjmp 1157 errlook 14EA errmes 1FD6 error 02B1 +errtab 1C08 escimm 1067 escmem 1060 exacc 0D00 exit 1422 +exmem 0D07 exmem1 0D09 expression 049A extend 206F +extended 0010 factor 052B fcb 005C filchk 135A +findop 09A6 fini 1391 finij 1214 finimm 0B73 fixed 0D33 +fixline 11AC fixup 11CC flag 20D0 flg 042A flgtab 0740 +flushbuf 15DC fndndp 0A06 formattab 0B23 +fpreg 0745 freg 0006 fwait 0A3F g10 0E57 gen 0BA6 +gen1 0BA9 genint 1013 getch 02DA getchr 05F0 getdat 10CF +geteol 0266 getfact 04F9 getformat 0AF5 getlab 0902 +getlet 06B9 getop 03C8 getop1 03CB getop2 03BF getsp 0F54 +getsy 0627 getsym 0602 getval 043B gotit 06A5 gotop 0F19 +grp1 0B33 grp10 0E3D grp11 0E65 grp12 0E6D grp13 0E97 +grp14 0EC1 grp16 0F3F grp17 0FB7 grp18 0FF0 grp19 101B +grp2 0C84 grp20 1082 grp21 1093 grp22 10AB grp23 10CC +grp3 0CB5 grp4 0D15 grp5 0D3B grp6 0DB5 grp7 0DC1 +grp8 0DE9 grp9 0DEF h3 16D0 h4 16D6 havdef 11DE +havmes 14F4 havndp 0A47 havop 09C3 havreg 0777 header 0102 +heap 2133 hex 0690 hex1 0695 hexadd 2142 hexbuf 215E +hexbufsiz 0046 hexbyt 156A hexcnt 2146 hexend 13B6 +hexfcb 2080 hexlen 2140 hexpnt 215A hidig 1318 i2 16DD +i3 16E6 i4 16FB id 20DF if 1101 ifend 2074 +ifflg 214A ifnest 207A imm 0B8C immed 0B5D integer 0020 +ix 2156 iy 2158 j2 1714 j3 173D j4 1793 +l0000 019C l0002 0242 l0003 05B6 l0004 0722 l0006 0B45 +l0008 0CED l0011 0F8D l0012 13AF l0014 1438 l3 17B8 +l4 17C8 l5 17E7 l6 1804 labchk 0928 label 092F +labpt 20CE lastad 2144 lead 12FD lenid 20DE letter 06FD +lhalf 1604 line 213E linflg 2148 list 133E listret 1367 +load 036B longj 0F29 longr 0F68 look 07EF lookit 087C +lookndp 0A00 lookret 0823 lookup 0878 loop 0229 lstbuf 21A4 +lstbufsiz 0400 lstdev 2152 lstfcb 20A5 lstpnt 215C +lstret 214E m3 1815 m4 1820 m5 182D make 0016 +makfil 027E maxflg 20D1 mem 03FF memop 0ADE memory 0018 +mode 0462 mop 0E1A moreid 06D7 mrerr 03BA mrops 02EC +mulop 04EB n3 183C ndpa 1964 ndpb 1972 ndpc 197C +ndpd 1995 ndpe 19B6 ndpf 19BB ndpi 19C1 ndpl 1A06 +ndpm 1A3A ndpn 1A48 ndpo 1A44 ndpop 09C8 ndpp 1A4D +ndpr 1A5E ndps 1A6C ndpt 1AA8 ndptab 1BD4 ndpw 1AAD +ndpx 1AB3 ndpy 1AC3 needop 0080 newlin 153E newloc 0DA3 +nexb 0616 nexbt 11B7 nexfact 0520 nexlin 025B +nexsymlin 148F nextchj 0624 nextchr 02B6 nexterm 04D0 +nextmes 14EE nilify 08E5 nocon 04DE node 1425 nodec 0F8F +noerr 1232 noext 14C6 nofil 1262 nofile 2014 noflg 071A +noind 048E nomem 1FFC nomod 02E4 nomore 06F1 none 160F +noopchk 0AB9 noops 0AC0 noprn 01BB norev 0ACD nospac 1FE4 +not1 091A notac 039F notlon 0F7B notrg 0EE4 noundef 0C43 +nowait 2155 nreg 03F7 nwait 0A55 o2 184C o3 1851 +o4 185C objbt 11C9 object 0100 oldpc 20CC one 0DF7 +onej 0E63 oneop 0DF3 onereg 0040 open 000F operate 04BA +operr 09BE operrj 0A1A optab 1AD0 org 0D9D out 1512 +out10 12F0 outa 1510 outlin 12AA outln 12CD p3 1869 +p4 1874 p5 1881 packreg 109E paren 0582 pc 20CA +phex 1384 phexb 1339 plsmns 04B0 pmem 0CA2 preg 07C3 +prerr 0276 pret 0C3F prev 2149 print 1504 +printmes 0009 prnchk 134F prnerr 14FE prtcnt 12D9 +put 0B9C putadd 0C5C putaddj 0F03 putbj 0B5A putbw 0C12 +putbyt 0BF2 putcd 0BE1 putchk 0C1A putchr 15D2 putinc 0BDD +putmem 0B13 putop 0D69 putreg 0AAA putwor 0BEB pxreg 0CAE +r3 1889 r4 18A8 r5 18B5 read 0014 readid 06D2 +real 0028 reg 0002 regchk 077C regtab 07E7 reloc 213A +reperr 14D5 retpt 2150 retstr 207D rightson 1497 +rngerr 120D rop 0E2D rr 0321 rr1 0325 s3 18C4 +s4 18FC s5 191B savcd 149F savdat 10F7 savflg 072E +savnflg 09DA savpt 137E scanb 060B scanreg 07D0 scant 060E +segchk 033C segtab 07EB setdma 001A sholin 1248 sij 056D +skipcd 110A skiplp 110E small 080F smput 0C39 spc 2154 +spcfun 1285 specialop 0A25 spend 127B srcbuf 25A6 +sreg 0004 st0dest 0AA6 stack 2AA6 stackop 0010 start 2AA6 +sterr 03B8 stimm 0B81 store 0361 strgdat 05C7 string 05A4 +strtlin 1329 supz 1325 sym 2130 symdmp 13DA symflg 2135 +symlin 2136 symmes 205D symsav 072A symwid 0005 system 1517 +t4 1938 tab 14BF tabval 146B term 04E8 testtyp 11C2 +try2xm1 0A1C twobt 0C7A u2 193F uhalf 15FC undef 20DC +undefid 0000 uval 0592 val 03DF val1 03E1 w4 1944 +wrend 115C wrtbuf 1369 wrterr 2027 wrthex 15B7 wrtsym 145F +x3 194B x4 1951 xm1 195E xreg 0003 xrg 037E +zerlen 05E8 +D: diff --git a/1_transcription/bundle_7 b/1_transcription/bundle_7 new file mode 100644 index 0000000..c651354 --- /dev/null +++ b/1_transcription/bundle_7 @@ -0,0 +1,613 @@ + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHHHHHHHHHHHHHH KKKKKKKKK DDD DDD SSSSSSSSS KKKKKKKKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK +CCC HHH HHH KKK KKK DDD DDD SSS KKK KKK + CCCCCCCCCCCC HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + СССССССССССС HHH HHH KKK KKK DDDDDDDDDDDD SSSSSSSSSSSS KKK KKK + + + + + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 + AAAAAAAAA 888888888 666666666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888 888 666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAA AAA 888888888 666666666666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAAAAAAAAAAAAAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888 888 666 666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 +AAA AAA 888888888 666666666 + + + + + *START* User ROS BASIC [500,500] Job 86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:CHKDSK.A86<055>[500,500] Created: 15-Jun-81 04:10:28 Printed: 16-Jun-81 15:32:54 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL + 00100 +00200 ; CHKDSK Version 1.0 03/10/81 +00300 +00400 ; Verifies and repairs 86-DOS disk directory. +00500 +00600 SETDRV: EQU 14 +00700 GETDRV: EQU 25 +00800 GETMAP: EQU 27 +00900 OPEN: EQU 15 +01000 CLOSE: EQU 16 +01100 DELETE: EQU 19 +01200 SETDMA: EQU 26 +01300 SRCHFST:EQU 17 +01400 SRCHNXT:EQU 18 +01500 OUTCH: EQU 2 +01600 BLKWRT: EQU 40 +01700 PRINTBUF:EQU 9 +01800 +01900 ORG 100H +02000 PUT 100H +02100 +02200 CHKDSK: +02205 MOV SP,STACK +02300 MOV AH,GETDRV +02400 INT 21H +02500 MOV [CURDRV],AL +02600 MOV DL,[5CH] +02700 OR DL,DL +02800 JZ DRVSET +02900 MOV AH,SETDRV +03000 DEC DL +03100 INT 21H +03110 CMP AL,DL +03120 JA DRVSET +03130 MOV DX,BADDRV +03135 ERROR: +03140 MOV AH,PRINTBUF +03150 INT 33 +03160 INT 32 +03170 +03175 BADDSK: +03177 MOV AX,CS +03178 MOV DS,AX +03180 MOV AH,SETDRV +03185 MOV DL,[CURDRV] +03190 INT 33 +03195 MOV DX,DIRBAD +03197 JP ERROR +03200 DRVSET: +03202 MOV B,[WRKDRV],DL ;Save drive indicator +03300 MOV AH,GETMAP +03400 INT 21H +03410 CMP B,[BX],0FEH ;Check for initialized disk +03420 JNE BADDSK +03500 PUSH DS +03600 PUSH ES +03700 POP DS +03800 MOV [DSKSIZ],DX ;Number of allocation units +03900 MOV [SECSIZ],CX ;Size of physical sector +04000 MOV AH,0 +04100 MOV [CLUSSIZ],AX ;Sectors per cluster +04200 MOV CX,DX +04300 MOV DI,MAP +04400 XOR AX,AX +04500 REP +04600 STOW ;Zero out allocation map +04700 MOV CX,AX +04800 MOV [ALLOC],AX ;Count of allocation units used +04900 MOV [FILECNT],AX ;Number of files found +05000 MOV [DELCNT],AX ;Number of files deleted due to error +05100 MOV BP,DI +05200 MOV [NAMTAB],BP ;First address of file list +05300 MOV DX,DI +05400 MOV AH,SETDMA +05500 INT 21H +05600 MOV AH,SRCHFST +05700 MOV DX,ALLFILE +05800 INT 21H +05900 INC AL +06000 POP ES ;ES:BX point to FAT +06100 JNZ GETFILES +06200 JMP COMPMAP +06300 GETFILES: +06400 INC CX ;Count number of files +06500 ADD DI,44 ;Separate in file in list by 44 bytes +06600 MOV DX,DI +06700 MOV AH,SETDMA +06800 INT 21H +06900 MOV AH,SRCHNXT +07000 MOV DX,ALLFILE +07100 INT 21H +07200 INC AL +07300 JNZ GETFILES ;Loop until all files are in list +07400 MOV [FILECNT],CX +07500 MOV CX,1 ;File number (position in list) +07600 MOV DX,[DSKSIZ] +07700 INC DX ;Maximum cluster number +07800 MOV [MAXCLUS],DX +07900 ADD BP,34 ;Point to "first cluster" entry +08000 EACHFIL: +08100 XOR AX,AX ;No. of clusters in file +08200 MOV SI,[BP] ;First cluster of file +08300 CMP SI,[MAXCLUS] ;Make sure it's legal +08400 MOV DI,BADDIR +08500 JA BADFIRST +08600 OR SI,SI ;Check for zero-length file +08700 JZ HAVENDJ +08800 SCANFAT: +08900 MOV DI,CX +09000 SHL SI +09100 XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. +09200 SHR SI +09300 OR DI,DI ;Should be zero for unallocated cluster +09400 JNZ CROSSLINK +09500 INC AX ;Count cluster as part of this file +09600 CALL UNPACK +09700 JZ FORCEND ;Make sure cluster knows it's allocated +09800 CMP DI,0FF8H ;Bigger than this means End of File +09900 HAVENDJ:JAE HAVEND +10000 CMP DI,[MAXCLUS] ;Make sure it's a legal value +10100 JA FORCEND +10200 MOV SI,DI +10300 JP SCANFAT ;Visit each cluster allocated to file +10400 +10500 BADFIRST: +10600 PUSH AX ;Because FILERR will pop it later +10700 MOV AX,CX +10800 MOV DX,44 +10900 DEC AX +11000 MUL AX,DX ;Get position in file name table +11100 MOV DX,AX +11200 ADD DX,[NAMTAB] +11300 MOV AH,DELETE +11400 INT 21H +11405 OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY +11450 JZ DISKOK +11452 JMP BADDSK +11454 DISKOK: +11500 INC [DELCNT] ;Count one deleted file +11600 MOV DX,BADDIR +11700 JP FILERR +11800 +11900 CROSSLINK: +12000 MOV DX,LINKED +12100 PUSH AX +12200 MOV AH,PRINTBUF +12300 INT 21H +12400 MOV AX,DI +12500 CALL PRINTNAM +12600 MOV DX,FILE2 +12700 MOV AH,PRINTBUF +12800 INT 33 +12900 MOV AX,CX +13000 CALL PRINTNAM +13100 MOV DX,CRLF +13200 MOV AH,PRINTBUF +13300 INT 33 +13400 POP AX +13500 ADD [ALLOC],AX +13600 JMP SIZSET1 +13700 +13800 FORCEND: +13900 ; Come here if a cluster allocated to a file contained an illegal +14000 ; link--either a zero (meaning unallocated), or a value larger than +14100 ; the maximum cluster number, but not End of File. Put an End of File +14200 ; mark there so the FAT will at least be well-formed. +14300 MOV DX,0FFFH +14400 CALL PACK +14500 MOV DX,BADCLUS +14600 PUSH AX +14700 +14800 FILERR: +14900 MOV AH,PRINTBUF +15000 INT 21H +15100 MOV AX,CX +15200 CALL PRINTNAM +15300 MOV DX,CRLF +15400 MOV AH,PRINTBUF +15500 INT 21H +15600 POP AX +15700 +15800 HAVEND: +15900 ADD [ALLOC],AX ;Total up allocated clusters +16000 MOV SI,AX +16100 MOV AX,[BP+2] +16200 MOV DX,[BP+4] ;AX:DX now have file length +16300 PUSH CX +16400 MOV CX,[CLUSSIZ] +16500 DEC CX +16600 ADD AX,CX +16700 ADC DX,0 +16800 INC CX +16900 SCALE: +17000 SHR CX +17100 JC SCALED +17200 SHR DX +17300 RCR AX +17400 JP SCALE +17500 SCALED: +17600 DIV AX,[SECSIZ] +17700 OR DX,DX +17800 JZ HAVSIZ +17900 INC AX +18000 HAVSIZ: +18100 CMP AX,SI ;See if file size corresponds with allocation +18200 JZ SIZSET +18300 XOR DI,DI +18400 MOV CX,[CLUSSIZ] +18500 CALL UNSCALE +18600 MOV [BP+6],SI +18700 MOV [BP+8],DI +18800 MOV DX,BP +18900 SUB DX,34 +19000 MOV AH,OPEN +19100 INT 21H +19110 OR AL,AL +19120 JZ DISKOK2 +19130 JMP BADDSK +19140 DISKOK2: +19200 MOV AX,[SECSIZ] +19300 MOV [BP-27+14],AX ;Make record size=sector size +19400 MOV CX,0 +19500 MOV AH,BLKWRT +19600 INT 21H +19700 MOV AH,CLOSE ;Write back corrected directory entry +19800 INT 21H +19900 MOV AH,GETMAP +20000 PUSH DS +20100 INT 33 ;Make sure FAT dirty bit is still set +20200 POP DS +20300 MOV DX,BADSIZ +20400 MOV AH,PRINTBUF +20500 INT 21H +20600 POP AX +20700 PUSH AX +20800 CALL PRINTNAM +20900 MOV DX,CRLF +21000 MOV AH,PRINTBUF +21100 INT 21H +21200 SIZSET: +21300 POP CX +21400 SIZSET1: +21500 ADD BP,44 ;Scan next file +21600 INC CX +21700 CMP CX,[FILECNT] +21800 JA COMPMAP +21900 JMP EACHFIL +22000 ; Now compare the allocation map we have made with the FAT. Any +22100 ; clusters not allocated in the map will be released. +22200 COMPMAP: +22300 XOR AX,AX ;Keep count of clusters released +22400 MOV BP,MAP +22500 MOV SI,2 ;First usable cluster number +22600 MOV CX,[DSKSIZ] +22700 RELCLUS: +22800 TEST [BP],-1 ;Allocated in our map? +22900 JNZ NXTCLUS ;If so, skip to next +23000 CALL UNPACK +23100 JZ NXTCLUS ;If not allocated, skip to next +23200 XOR DX,DX +23300 CALL PACK ;Change to "Free" status +23400 INC AX ;Count clusters released +23500 NXTCLUS: +23600 INC BP +23700 INC BP +23800 INC SI +23900 LOOP RELCLUS +24000 OR AX,AX ;Any clusters released? +24100 JZ REPORT ;If not, do final report +24200 MOV BX,FREED +24300 CALL DISPCLUS +24400 REPORT: +24500 ; Make status report. Include no. of files, total disk space, +24600 ; free space on disk, total memory, and free memory. +24610 SEG CS +24620 MOV DL,[CURDRV] +24630 MOV AH,SETDRV +24640 INT 21H +24700 MOV SI,[FILECNT] +24800 SUB SI,[DELCNT] +24900 XOR DI,DI +25000 MOV BX,NUMFIL +25100 CALL DISP32BITS +25200 MOV AX,[DSKSIZ] +25300 MOV BX,DSKSPC +25400 CALL DISPCLUS +25500 MOV AX,[DSKSIZ] +25600 SUB AX,[ALLOC] +25700 MOV BX,FRESPC +25800 CALL DISPCLUS +25900 MOV AX,[2] +26000 MOV DX,16 +26100 MUL AX,DX +26200 MOV SI,AX +26300 MOV DI,DX +26400 MOV BX,TOTMEM +26500 CALL DISP32BITS +26600 MOV AX,[2] +26700 MOV DX,CS +26800 SUB AX,DX +26900 MOV DX,16 +27000 MUL AX,DX +27100 MOV SI,AX +27200 MOV DI,DX +27300 MOV BX,FREMEM +27400 CALL DISP32BITS +27405 CALL WRTFRC ;Force all writes and handle write +27410 ;protect violation +27900 INT 20H ;All done +27902 +27904 WRTFRC: ;******************************************************** +27906 ; This code forces all writes by performing a disk +27908 ; reset (function 13). When the attempt to write +27910 ; the allocation table fails in the case of a write- +27912 ; protected diskette, this logic determines if the +27914 ; allocation table had changed and if no changes were +27916 ; made a normal termination will be forced +27918 ;********************************************************* +27919 MOV AX,DS +27920 PUSH DS ;Must first intercept INT 24H +27921 MOV ES,AX +27922 XOR AX,AX +27924 MOV DS,AX +27926 MOV SI,90H +27928 MOV DI,INT24 ;will move vector to local address +27930 MOV CX,2 +27931 CLD ;So move will increment +27932 REP +27934 MOVW ;Vector now locally stored +27936 MOV AL,24H ; +27938 MOV AH,37 +27940 MOV DX,WRTPRT ; +27942 POP DS ;Get local segment +27944 INT 21H ;Interrupt vector now set +27946 MOV AH,13 +27948 INT 21H +27953 PUSH ES ;Will now reset INT 24H vector +27955 XOR AX,AX +27957 MOV ES,AX +27959 CLD +27961 MOV DI,90H +27963 MOV SI,INT24 +27965 MOV CX,2 +27967 REP +27969 MOVW +27971 POP ES +27973 RET +27974 +27976 WRTPRT: ;********************************************************* +27978 ; This logic is designed to handle the case where +27980 ; CHKDSK found no problems and upon rewriting the +27982 ; allocation table (by the DOS) the disk was write- +27984 ; protected and an error thus occured. With no problems +27986 ; this code will cause normal termination, otherwise +27987 ; normal error handling will occur. +27988 ;********************************************************* +27990 EI ;Run with interrupts live +27992 AND DI,0FFH ;See if write-protect +27994 JNZ WRT100 ;Do normal error handling +27996 CMP AH,3 ;File allocation write? +27998 JNZ WRT100 ;If not do normal handling +27999 SEG CS +28000 CMP [WRKDRV],AL ;Correct drive? +28002 JNZ WRT100 ; +28003 SEG CS +28004 CMP B,[CHGCLS],1 ;Legitimate change? +28006 JZ WRT100 ;If so do normal handling +28007 XOR AL,AL ;Ignore the error +28008 IRET +28009 WRT100: SEG CS +28010 JMP L,[INT24] ;Normal error handling +28012 +28014 +28015 +28100 UNPACK: +28200 MOV DI,SI +28300 SHR DI +28400 ADD DI,SI +28500 SEG ES +28600 MOV DI,[DI+BX] +28700 TEST SI,1 +28800 JZ HAVCLUS +28900 SHR DI +29000 SHR DI +29100 SHR DI +29200 SHR DI +29300 HAVCLUS: +29400 AND DI,0FFFH +29500 RET +29600 +29700 PACK: +29705 ;************************************************************* +29710 ; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +29715 ; SI CLUSTER NUMBER TO BE PACKED +29720 ; DX POINTER TO BE PLACED IN CLUSTER (SI) +29725 ;************************************************************* +29730 MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED +29800 PUSH SI +29900 MOV DI,SI +30000 SHR SI +30100 ADD SI,BX +30200 ADD SI,DI +30300 SHR DI +30400 SEG ES +30500 MOV DI,[SI] +30600 JNC ALIGNED +30700 SHL DX +30800 SHL DX +30900 SHL DX +31000 SHL DX +31100 AND DI,0FH +31200 JP PACKIN +31300 ALIGNED: +31400 AND DI,0F000H +31500 PACKIN: +31600 OR DI,DX +31700 SEG ES +31800 MOV [SI],DI +31900 POP SI +32000 RET +32100 +32200 UNSCALE: +32300 SHR CX +32400 JC RET +32500 SHL SI +32600 RCL DI +32700 JP UNSCALE +32800 +32900 DISPCLUS: +33000 MUL AX,[SECSIZ] +33100 MOV CX,[CLUSSIZ] +33200 MOV SI,AX +33300 MOV DI,DX +33400 CALL UNSCALE +33500 DISP32BITS: +33600 PUSH BX +33700 XOR AX,AX +33800 MOV BX,AX +33900 MOV BP,AX +34000 MOV CX,32 +34100 CONVLP: +34200 SHL SI +34300 RCL DI +34400 XCHG AX,BP +34500 CALL CONVWRD +34600 XCHG AX,BP +34700 XCHG AX,BX +34800 CALL CONVWRD +34900 XCHG AX,BX +35000 ADC AL,0 +35100 LOOP CONVLP +35200 ; Conversion complete. Print 10-digit number with 2 leading blanks. +35300 MOV CX,1B10H +35400 CALL OUTWORD +35500 MOV AX,BX +35600 CALL OUTWORD +35700 MOV AX,BP +35800 CALL OUTWORD +35900 POP DX +36000 MOV AH,PRINTBUF +36100 INT 21H +36200 RET +36300 +36400 OUTWORD: +36500 PUSH AX +36600 MOV DL,AH +36700 CALL OUTBYTE +36800 POP DX +36900 OUTBYTE: +37000 MOV DH,DL +37100 SHR DL +37200 SHR DL +37300 SHR DL +37400 SHR DL +37500 CALL DIGIT +37600 MOV DL,DH +37700 DIGIT: +37800 AND DL,0FH +37900 JZ BLANKZER +38000 MOV CL,0 +38100 BLANKZER: +38200 DEC CH +38300 AND CL,CH +38400 OR DL,30H +38500 SUB DL,CL +38600 MOV AH,OUTCH +38700 INT 21H +38800 RET +38900 +39000 CONVWRD: +39100 ADC AL,AL +39200 DAA +39300 XCHG AL,AH +39400 ADC AL,AL +39500 DAA +39600 XCHG AL,AH +39700 RET +39800 +39900 PRINTNAM: +39910 PUSH CX +40000 DEC AX +40100 MOV CX,44 +40200 MUL AX,CX +40300 MOV SI,AX +40400 ADD SI,[NAMTAB] +40500 ADD SI,8 +40600 MOV CX,8 +40700 MOV AH,OUTCH +40800 CALL PRINTCNT +40900 MOV DL," " +41000 INT 21H +41100 MOV CL,3 +41110 CALL PRINTCNT +41120 POP CX +41130 RET +41140 +41200 PRINTCNT: +41300 LODB +41400 MOV DL,AL +41500 INT 21H +41700 LOOP PRINTCNT +41800 RET +41900 +41950 ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB +42000 DB 0,"???????????" +42100 DS 25 +42200 +42300 FILE2: DB " and $" +42305 BADDRV: DB "Invalid drive specification$" +42400 BADCLUS:DB "Allocation error for file $" +42500 BADDIR: DB "Directory error-file : $" +42600 LINKED: DB "Files cross-linked: " +42605 DB 13,10 +42610 DB " $" +42700 BADSIZ: DB "File size error for file $" +42705 DIRBAD: DB "Diskette not initialized $" +42800 FREED: DB " bytes disk space freed",13,10,13,10,"$" +42900 NUMFIL: DB " disk files",13,10,"$" +43000 DSKSPC: DB " bytes total disk space",13,10,"$" +43100 FRESPC: DB " bytes remain available",13,10,13,10,"$" +43200 TOTMEM: DB " bytes total memory",13,10,"$" +43300 FREMEM: DB " bytes free" +43400 CRLF: DB 13,10,"$" +43500 +43600 DSKSIZ: DS 2 +43700 SECSIZ: DS 2 +43800 CLUSSIZ:DS 2 +43805 CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +43810 WRKDRV: DB 0 +43815 INT24: DS 4 +43900 FILECNT:DS 2 +44000 NAMTAB: DS 2 +44100 ALLOC: DS 2 +44200 MAXCLUS:DS 2 +44300 DELCNT: DS 2 +44400 CURDRV: DS 1 +44405 DS 100H +44410 STACK: +44500 +44600 MAP: diff --git a/1_transcription/bundle_8 b/1_transcription/bundle_8 new file mode 100644 index 0000000..406ae70 --- /dev/null +++ b/1_transcription/bundle_8 @@ -0,0 +1,1863 @@ + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS +888 888 666 DDD DDD OOO OOO SSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS + 888888888 666666666666 DDD DDD OOO OOO SSSSSSSSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS +888 888 666 666 DDD DDD OOO OOO SSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + 888888888 666666666 DDDDDDDDDDDD OOOOOOOOO SSSSSSSSSSSS + + + + +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDDDDDDDDDDD IIIIIIIII FFFFFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFFFFFFFFFFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDD DDD III FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF +DDDDDDDDDDDD IIIIIIIII FFF + + + + + *START* User ROS BASIC [500,500] Job 86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START* +File: DSKC:86DOS.DIF<055>[500,500] Created: 16-Jun-81 15:11:47 Printed: 16-Jun-81 15:13:47 +QUEUE Switches: /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1)1 00230 SMALLDIR: EQU 1 ;1 to enable, 0 to disable +1) 00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +**** +2)1 00230 SMALLDIR: EQU 0 ;1 to enable, 0 to disable +2) 00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +************** +1)1 00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +1) 00330 ; Interrupt Entry Points: +**** +2)1 00300 DSKTEST: EQU 1 ;1 to enable, 0 to disable +2) 00330 ; Interrupt Entry Points: +************** +1)1 00460 MAXCOM: EQU 41 +1) 00470 ESCCH: EQU 1BH +1) 00480 INTBASE:EQU 80H +**** +2)1 00460 MAXCOM: EQU 45 +2) 00470 ESCCH: EQU 0 +2) 00480 INTBASE:EQU 80H +************** +1)1 00590 ; Field definition for FCBs +**** +2)1 00580 ;Date format +2) 00590 ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 +2) 00600 ; y y y y y y y m m m m d d d d d +2) 00610 ; +2) 00620 ;where y=year,m=month,d=day +2) 00640 ; Field definition for FCBs +************** +1)1 00790 ; +1) 00800 ; Location bytes Description +1) 00810 ; +1) 00820 ; 0 11 File name and extension ( 0E5H if empty) +1) 00830 ; 11 13 Zero field (for expansion) +1) 00840 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +**** +2)1 00850 ; Location bytes Description +2) 00870 ; 0 11 File name and extension ( 0E5H if empty) +2) 00880 ; 11 1 Attributes. Bits 1 or 2 make file hidden +2) 00890 ; 12 12 Zero field (for expansion) +2) 00900 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +************** +1)1 00870 ; +1) 00880 ; The File Allocation Table uses a 12-bit entry for each allocation unit on +1) 00890 ; the disk. These entries are packed, two for every three bytes. The contents +1) 00900 ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +1) 00910 ; to the base address of the Allocation Table; 3) fetching the 16-bit word at +1) 00920 ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +1) 00930 ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +1) 00940 ; zero is used as an end-of-file trap in the OS and as a flag for directory +1) 00950 ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The +1) 00960 ; first available allocation unit is assigned entry number two, and for Drive Parameter Block +1) 00980 ORG 0 +**** +2)1 00950 ; Field definition for Drive Parameter Block +2) 00970 ORG 0 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 01270 BIOSSEG: EQU 40H +1) 01280 ORG 0 +**** +2)1 01260 BIOSSEG: EQU 60H +2) 01270 ORG 0 +************** +1)1 01650 ESCTAB: +1) 01660 DB "SC" ;Copy one char +1) 01670 DB "VN" ;Skip one char +1) 01680 DB "TA" ;Copy to char +1) 01690 DB "WB" ;Skip to char +1) 01700 DB "UH" ;Copy line +1) 01710 DB "HH" ;Kill line (no change in template) +1) 01720 DB "RM" ;Reedit line (new template) +1) 01730 DB "DD" ;Backspace +1) 01740 DB "P@" ;Enter insert mode +1) 01750 DB "QL" ;Exit insert mode +1) 01760 DB ESCCH,ESCCH ;Escape character +1) 01770 DB ESCCH,ESCCH ;End of table +1) 01790 ESCTABLEN:EQU $-ESCTAB +1) 01810 HEADER: DB 13,10,"86-DOS version 1.00" +1) 01830 IF DSKTEST +1) 01840 DB "D" +1) 01850 ENDIF +1) 01870 DB 13,10 +1) 01880 DB "Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$" +1) 01900 QUIT: +**** +2)1 01630 ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +2) 01640 ESCTAB: +2) 01650 DB 77 ;Copy one char--RIGHT ARROW +2) 01660 DB 59 ;Copy one char--F1 +2) 01670 DB 83 ;Skip one char--DELETE +2) 01680 DB 60 ;Copy to char--F2 +2) 01690 DB 62 ;Skip to char--F4 +2) 01700 DB 61 ;Copy line--F3 +2) 01710 DB 64 ;Ctrl-Z--F6 +2) 01720 DB 63 ;Reedit line (new template)--F5 +2) 01730 DB 75 ;Backspace--LEFT ARROW +2) 01740 DB 82 ;Toggle insert mode--INSERT +2) 01750 DB 65 ;Escape character--F7 +2) 01760 DB 65 ;End of table +2) 01780 ESCTABLEN:EQU $-ESCTAB +2) 01810 QUIT: +************** +1)1 02420 MOV BP,SP +1) 02430 MOV BX,[BP+CSSAVE] +1) 02440 SEG CS +1) 02450 MOV [CSLOC],BX +1) 02460 MOV SP,CS +1) 02470 MOV SS,SP +1) 02480 MOV SP,STACK +1) 02490 EI ;Stack OK now +**** +2)1 02330 MOV SP,CS + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 02340 MOV SS,SP +2) 02350 REDISP: +2) 02360 MOV SP,IOSTACK +2) 02370 EI ;Stack OK now +************** +1)1 02570 IF DSKTEST +1) 02580 CMP AH,12 +1) 02590 JL SAMSTK +1) 02600 MOV SP,TESTSTK +1) 02610 SAMSTK: +1) 02620 ENDIF +1) 02640 SEG CS +**** +2)1 02440 CMP AH,12 +2) 02450 JLE SAMSTK +2) 02460 MOV SP,DSKSTACK +2) 02470 SAMSTK: +2) 02480 SEG CS +************** +1)1 02790 MOV [SPSA ENDIF +1) 02810 PBX +1) 02820 POP CX +**** +2)1 02630 MOV [SPSAVE],AX +2) 02640 SEG CS +2) 02650 MOV AX,[NSS] +2) 02660 SEG CS +2) 02670 MOV [SSSAVE],AX +2) 02680 ENDIF +2) 02700 POP AX +2) 02710 POP BX +2) 02720 POP CX +************** +1)1 02930 DW ABORT ;0 +1) 02940 DW CONIN +**** +2)1 02830 DW ABORT +2) 02840 DW CONIN +************** +1)1 02980 DW LIST ;5 +1) 02990 DW RAWIO +**** +2)1 02880 DW LIST +2) 02890 DW RAWIO +************** +1)1 03030 DW BUFIN ;10 +1) 03040 DW CONSTAT +1) 03050 DW VERSION +1) 03060 DW DSKRESET +1) 03070 DW SELDSK +1) 03080 DW OPEN ;15 +1) 03090 DW CLOSE +**** +2)1 02930 DW BUFIN +2) 02940 DW CONSTAT +2) 02950 DW FLUSHKB + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 02960 DW DSKRESET +2) 02970 DW SELDSK +2) 02980 DW OPEN +2) 02990 DW CLOSE +************** +1)1 03130 DW SEQRD ;20 +1) 03140 DW SEQWRT +**** +2)1 03030 DW SEQRD +2) 03040 DW SEQWRT +************** +1)1 03180 DW CURDRV ;25 +1) 03190 DW SETDMA +**** +2)1 03080 DW CURDRV +2) 03090 DW SETDMA +************** +1)1 03230 DW SETATTRIB ;30 +1) 03240 DW GETDSKPT +**** +2)1 03130 DW SETATTRIB +2) 03140 DW GETDSKPT +************** +1)1 03280 DW FILESIZE ;35 +1) 03290 DW SETRNDREC +**** +2)1 03180 DW FILESIZE +2) 03190 DW SETRNDREC +************** +1)1 03370 VERSION: +1) 03380 GETIO: +**** +2)1 03260 DW GETDATE +2) 03270 DW SETDATE +2) 03280 DW GETTIME +2) 03290 DW SETTIME ;45 +2) 03310 GETIO: +************** +1)1 03440 MOV AL,0 +1) 03450 RET +1) 03480 READER: +1) 03490 CALL BIOSAUXIN,BIOSSEG +**** +2)1 03370 INUSE: +2) 03380 GETDSKPT: +2) 03390 MOV AL,0 +2) 03400 RET +2) 03420 FLUSHKB: +2) 03430 XOR BX,BX +2) 03440 MOV ES,BX ;Select segment 0 +2) 03450 SEG ES +2) 03460 MOV B,[41AH],1EH ;Reset KB queue head pointer +2) 03470 SEG ES +2) 03480 MOV B,[41CH],1EH ;Reset tail pointer +2) 03490 MOV AH,AL +2) 03500 CMP AL,1 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 03510 JZ REDISPJ +2) 03520 CMP AL,7 +2) 03530 JZ REDISPJ +2) 03540 CMP AL,8 +2) 03550 JZ REDISPJ +2) 03560 CMP AL,10 +2) 03570 JZ REDISPJ +2) 03575 MOV AL,0 +2) 03580 RET +2) 03600 REDISPJ:JMP REDISP +2) 03620 READER: +2) 03630 AUXIN: +2) 03640 CALL STATCHK +2) 03650 CALL BIOSAUXIN,BIOSSEG +************** +1)1 03540 CALL BIOSAUXOUT,BIOSSEG +**** +2)1 03700 AUXOUT: +2) 03710 PUSH AX +2) 03720 CALL STATCHK +2) 03730 POP AX +2) 03740 CALL BIOSAUXOUT,BIOSSEG +************** +1)1 03860 MOV SI,BADMES +1) 03870 CALL OUTMES +1) 03880 JMP ERROR +1) 03910 PACK: +**** +2)1 04070 PUSH AX +2) 04080 MOV AH,80H +2) 04090 MOV DI,0FFFH +2) 04100 CALL FATAL +2) 04110 POP AX +2) 04120 RET +2) 04150 PACK: +************** +1)1 04230 IOCHK: +1) 04240 MOV CX,5 ;Check rest of name but not extension +1) 04250 CMP B,[DI],":" +1) 04260 JNZ NOCOL +1) 04270 INC DI ;Skip over colon +1) 04280 DEC CX +1) 04290 NOCOL: +1) 04300 MOV AL," " +**** +2)1 04454 DEVNAME: +2) 04455 MOV SI,IONAME ;List of I/O devices with file names +2) 04456 MOV BL,6 ;BL = number of device names +2) 04457 LOOKIO: +2) 04458 MOV DI,NAME1 +2) 04459 MOV CX,4 ;All device names are 4 letters +2) 04460 REPE +2) 04461 CMPB ;Check for name in list +2) 04462 JZ IOCHK ;If first 4 letters OK, check the rest +2) 04463 ADD SI,CX ;Point to next device name +2) 04464 DEC BL + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 04465 JNZ LOOKIO +2) 04466 CRET: +2) 04467 STC +2) 04468 RET +2) 04470 IOCHK: +2) 04480 MOV CX,4 ;Check rest of name but not extension +2) 04490 MOV AL," " +************** +1)1 04330 JNZ FILSRCH +1) 04340 DEC BL +1) 04350 RET +1) 04370 GETFILE: +1) 04390 ; Inputs: +**** +2)1 04520 JNZ CRET +2) 04530 MOV AL,BL +2) 04540 MOV BX,IONUM-1 +2) 04550 XLAT ;Translate to internal device number +2) 04560 MOV BL,AL +2) 04570 MOV BH,-1 +2) 04580 RET +2) 04600 GETFILE: +2) 04610 ; Same as GETNAME except ES:DI points to FCB on successful return +2) 04620 CALL MOVNAME +2) 04630 JC RET +2) 04640 PUSH DX +2) 04650 PUSH DS +2) 04660 CALL FINDNAME +2) 04670 POP ES +2) 04680 POP DI +2) 04690 RET +2) 04710 GETNAME: +2) 04730 ; Inputs: +************** +1)1 04480 ; BP = Base of drive parameters +**** +2)1 04820 ; Zero set if attributes match (always except when creating) +2) 04830 ; BP = Base of drive parameters +************** +1)1 04620 MOV SI,IONAME ;List of I/O devices with file names +1) 04630 MOV BX,0FF04H ;BL = number of devices +1) 04640 LOOKIO: +1) 04650 MOV DI,NAME1 +1) 04660 MOV CX,3 ;All device names are 3 letters +1) 04670 REPE +1) 04680 CMPB ;Check for name in list +1) 04690 JZ IOCHK ;If first 3 letters OK, check the rest +1) 04700 ADD SI,CX ;Point to next device name +1) 04710 DEC BL +1) 04720 JNZ LOOKIO +1) 04730 FILSRCH: ;Not a device name +1) 04740 CALL STARTSRCH +**** +2)1 04961 CALL DEVNAME +2) 04962 JNC RET +2) 05090 CALL STARTSRCH + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 05010 ADD SI,15 +1) 05020 RET +**** +2)1 05370 ;Check if attributes allow finding it +2) 05380 MOV AH,[ATTRIB] ;Attributes of search +2) 05390 NOT AH +2) 05400 AND AH,[SI] ;Compare with attributes of file +2) 05410 ADD SI,15 +2) 05420 AND AH,6 ;Only look at bits 1 and 2 +2) 05430 JZ RET +2) 05440 TEST B,[CREATING],-1 +2) 05450 JZ NEXTENT +2) 05460 RET +************** +1)1 05230 MOV [LASTENT],AX +**** +2)1 05670 GETENT: +2) 05680 MOV [LASTENT],AX +************** +1)1 05920 CALL GETFILE +1) 05930 JC ERRET +1) 05940 CMP BH,-1 ;Check if device name +1) 05950 JZ ERRET ;Can't delete I/O devices +1) 05960 DELFILE: +**** +2)1 06370 CALL GETNAME +2) 06375 MOV AL,-1 +2) 06380 JC RET +2) 06390 CMP BH,AL ;Check if device name +2) 06400 JZ RET ;Can't delete I/O devices +2) 06410 DELFILE: +************** +1)1 06180 CMP BH,-1 ;Check if I/O device name +1) 06190 JZ ERRET ;If so, can't rename it +1) 06200 ADD SI,5 +**** +2)1 06650 ADD SI,5 +************** +1)1 06250 RENFIL: +1) 06260 MOV B,[DIRTYDIR],-1 +1) 06270 MOV DI,BX +1) 06280 MOV SI,NAME2 +**** +2)1 06692 CMP BH,-1 ;Check if I/O device name +2) 06694 JZ ERRET ;If so, can't rename it +2) 06700 MOV SI,NAME1 +2) 06710 MOV DI,NAME3 +2) 06720 MOV CX,6 ;Include attribute byte +2) 06730 REP +2) 06740 MOVW ;Copy name to search for +2) 06750 RENFIL: +2) 06760 MOV DI,NAME1 +2) 06770 MOV SI,NAME2 +************** +1)1 06330 JZ NOCHG + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 06340 MOV [DI],AL +1) 06350 NOCHG: +1) 06360 INC DI +1) 06370 LOOP NEWNAM +1) 06380 CALL CONTSRCH +**** +2)1 06820 JNZ NOCHG +2) 06830 MOV AL,[BX] +2) 06840 NOCHG: +2) 06850 STOB +2) 06860 INC BX +2) 06870 LOOP NEWNAM +2) 06871 MOV B,[DI],6 ;Stop duplicates with any attributes +2) 06872 CALL DEVNAME ;Check if giving it a device name +2) 06874 JNC RENERR +2) 06890 PUSH [LASTENT] ;Save position of match +2) 06895 MOV [LASTENT],-1 ;Search entire dirctory for duplicate +2) 06900 CALL CONTSRCH ;See if new name already exists +2) 06910 POP AX +2) 06920 JNC RENERR ;Error if found +2) 06930 CALL GETENT ;Re-read matching entry +2) 06940 MOV DI,BX +2) 06950 MOV SI,NAME1 +2) 06960 MOV CX,11 +2) 06970 REP +2) 06980 MOVB ;Replace old name with new +2) 06990 MOV B,[DIRTYDIR],-1 ;Flag change in directory +2) 07000 MOV SI,NAME3 +2) 07010 MOV DI,NAME1 +2) 07020 MOV CX,6 ;Include attribute byte +2) 07030 REP +2) 07040 MOVW ;Copy name back into search buffer +2) 07050 CALL CONTSRCH +************** +1)1 06440 ERRET: +**** +2)1 07102 RENERR: +2) 07104 CALL CHKDIRWRITE +2) 07110 ERRET: +************** +1)1 06520 ; DS, DX point to FCB +1) 06530 ; Outputs: +1) 06540 ; ES = CS +**** +2)1 07190 ; DS, DX point to FCB or extended FCB +2) 07200 ; Outputs: +2) 07210 ; DS:DX point to normal FCB +2) 07220 ; ES = CS +************** +1)1 06610 MOV AX,CS +**** +2)1 07290 SEG CS +2) 07300 MOV B,[CREATING],0 +2) 07310 MOV AX,CS +************** +1)1 06660 CALL GETBP + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +**** +2)1 07360 SEG CS +2) 07370 MOV [EXTFCB],AL +2) 07380 MOV AH,0 +2) 07390 CMP AL,-1 +2) 07400 JNZ HAVATTRB +2) 07410 ADD DX,7 +2) 07420 ADD SI,6 +2) 07430 MOV AH,[SI-1] +2) 07440 LODB +2) 07450 HAVATTRB: +2) 07460 SEG CS +2) 07470 MOV [ATTRIB],AH +2) 07480 CALL GETBP +************** +1)1 06730 LODB +1) 06740 AND AL,7FH +1) 06750 CMP AL,60H +1) 06760 JLE CASEOK +1) 06770 AND AL,5FH +1) 06780 CASEOK: +1) 06790 CMP AL,20H +**** +2)1 07550 CALL GETLET +2) 07560 JNZ CTRLCHK ;Is it a delimiter? +2) 07570 CMP AL," " ;This is the only delimiter allowed +2) 07580 STC ;In case of error +2) 07590 JNZ RET +2) 07600 CTRLCHK: +2) 07610 CMP AL,20H +************** +1)1 06970 PUSH DX +1) 06980 PUSH DS +1) 06990 CALL GETFILE +**** +2)1 07790 CALL GETFILE +************** +1)1 07020 ; in directory. DS=ES=CS, BX points to directory +1) 07030 ; entry in DIRBUF, SI points to First Cluster field, and +1) 07040 ; the top of the stack has the address and segment +1) 07050 ; of the FCB to be opened. This entry point is used +1) 07060 ; by CREATE. +1) 07070 POP ES +1) 07080 POP DI +1) 07090 JC ERRET +**** +2)1 07820 ; in directory. DS=CS, BX points to directory +2) 07830 ; entry in DIRBUF, SI points to First Cluster field, and +2) 07840 ; ES:DI point to the FCB to be opened. This entry point +2) 07850 ; is used by CREATE. +2) 07860 JC ERRET +************** +1)1 07870 PUSH DX +1) 07880 PUSH CX +1) 07890 PUSH BX +1) 07900 PUSH AX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 07910 CALL DREAD +1) 07920 OR AL,AL +1) 07930 POP AX +1) 07940 POP BX +1) 07950 POP CX +1) 07960 POP DX +1) 07970 JNZ BADFAT +1) 07990 IF SMALLDIR +**** +2)1 08640 PUSH AX +2) 08650 CALL DSKREAD +2) 08660 POP AX +2) 08670 JC BADFAT +2) 08690 IF SMALLDIR +************** +1)1 08220 ADD DX,CX +**** +2)1 08920 MOV CX,DI +2) 08930 ADD DX,CX +************** +1)1 08250 POP BP +1) 08260 ;{Insert error code here. All FATs on drive are bad.} +1) 08270 MOV SI,BADFATMES +1) 08280 CALL HARDERR +1) 08290 JP FATREAD +1) 08310 OKRET1: +**** +2)1 08960 CALL FIGFAT ;Reset registers +2) 08970 JMP DREAD ;Try first FAT once more +2) 08990 OKRET1: +************** +1)1 08370 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +**** +2)1 09050 CMP B,[DI],-1 +2) 09060 JNZ NORMFCB3 +2) 09070 ADD DI,7 +2) 09080 NORMFCB3: +2) 09090 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +************** +1)1 08620 PUSH DX +1) 08630 PUSH DS +1) 08640 CALL GETFILE +1) 08650 POP ES +1) 08660 POP DI +1) 08670 BADCLOSEJ: +**** +2)1 09340 CALL GETFILE +2) 09350 BADCLOSEJ: +************** +1)1 09710 PUSH DX +**** +2)1 10390 SEG CS +2) 10400 MOV B,[CREATING],1 +2) 10410 PUSH DX +************** +1)1 09820 POP DS + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +**** +2)1 10520 ERRPOP: +2) 10530 POP DS +************** +1)1 09890 CMP BH,-1 ;Check if file is I/O device +1) 09900 JZ OPENJMP ;If so, no action +1) 09910 XOR CX,CX +1) 09920 MOV [SI+2],CX +1) 09930 MOV AX,[DATE] +1) 09950 IF SMALLDIR +1) 09960 MOV [SI+4],CL +1) 09970 CMP B,[BP+DIRSIZ],-1 +1) 09980 JZ SMLENT +1) 09990 MOV [SI+5],CL +1) 10000 MOV [SI-2],AX +1) 10010 SMLENT: +1) 10020 ENDIF +1) 10040 IF 1-SMALLDIR +1) 10050 MOV [SI+4],CX +1) 10060 MOV [SI-2],AX +1) 10070 ENDIF +1) 10090 XCHG CX,[SI] +1) 10100 PUSH SI +1) 10110 PUSH BX +1) 10120 JCXZ WRTBACK +1) 10130 CMP CX,[BP+MAXCLUS] +1) 10140 JA WRTBACK +1) 10150 MOV BX,CX +1) 10160 LEA SI,[BP+FAT] +1) 10170 CALL RELEASE +1) 10180 CALL FATWRT +1) 10190 JP WRTBACK +1) 10210 FREESPOT: +**** +2)1 10600 JNZ ERRPOP ;Error if attributes don't match +2) 10610 CMP BH,-1 ;Check if file is I/O device +2) 10620 JZ OPENJMP ;If so, no action +2) 10630 MOV CX,[SI] ;Get pointer to clusters +2) 10640 JCXZ FREESPOT +2) 10650 CMP CX,[BP+MAXCLUS] +2) 10660 JA FREESPOT +2) 10670 PUSH BX +2) 10680 MOV BX,CX +2) 10690 LEA SI,[BP+FAT] +2) 10700 CALL RELEASE ;Free any data already allocated +2) 10710 CALL FATWRT +2) 10720 POP BX +2) 10730 FREESPOT: +************** +1)1 10280 XOR AX,AX +1) 10300 IF SMALLDIR +**** +2)1 10810 IF SMALLDIR +************** +1)1 10350 JP SMALLENT +**** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2)1 10860 XOR AX,AX +2) 10870 JP SMALLENT +************** +1)1 10390 MOV CL,13 +1) 10400 REP +1) 10410 STOB +1) 10420 MOV AX,[DATE] +1) 10430 STOW +**** +2)1 10910 MOV AL,[ATTRIB] +2) 10920 STOB +2) 10930 XOR AX,AX +2) 10940 MOV CL,6 +2) 10950 REP +2) 10960 STOW +2) 10970 CALL DATE16 +2) 10980 STOW +************** +1)1 10510 WRTBACK: +1) 10520 CALL DIRWRITE +**** +2)1 11060 CALL DIRWRITE +************** +1)1 10570 JMP DOOPEN +**** +2)1 11110 POP ES +2) 11120 POP DI +2) 11130 JMP DOOPEN +************** +1)1 10940 ; Outputs: +1) 10950 ; AL = 0 if no error, otherwise non-zero +1) 10960 ; BP preserved. All other registers destroyed. +1) 10980 MOV AL,[BP+DRVNUM] +**** +2)1 11500 ; BP preserved. All other registers destroyed. +2) 11520 CALL DSKREAD +2) 11530 JNC RET +2) 11540 SEG CS +2) 11550 MOV B,[READOP],0 +2) 11560 CALL HARDERR +2) 11570 CMP AL,1 ;Check for retry +2) 11580 JZ DREAD +2) 11590 RET ;Ignore otherwise +2) 11610 HARDERR: +2) 11620 ;Hard disk error handler. Entry conditions: +2) 11630 ; DS:BX = Original disk transfer address +2) 11640 ; DX = Original logical sector number +2) 11650 ; CX = Number of sectors to go (first one gave the error) +2) 11660 ; AX = Hardware error code +2) 11670 ; DI = Original sector transfer count +2) 11680 ; BP = Base of drive parameters +2) 11690 ; [READOP] = 0 for read, 1 for write +2) 11710 XCHG AX,DI ;Error code in DI, count in AX +2) 11720 SUB AX,CX ;Number of sectors successfully transferred +2) 11730 ADD DX,AX ;First sector number to retry +2) 11740 PUSH DX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 11750 MUL AX,[BP+SECSIZ] ;Number of bytes transferred +2) 11760 POP DX +2) 11770 ADD BX,AX ;First address for retry +2) 11780 MOV AH,0 ;Flag disk section in error +2) 11790 CMP DX,[BP+FIRFAT] ;In reserved area? +2) 11800 JB ERRINT +2) 11810 INC AH ;Flag for FAT +2) 11820 CMP DX,[FIRDIR] ;In FAT? +2) 11830 JB ERRINT +2) 11840 INC AH +2) 11850 CMP DX,[FIRREC] ;In directory? +2) 11860 JB ERRINT +2) 11870 INC AH ;Must be in data area +2) 11880 ERRINT: +2) 11890 SHL AH ;Make room for read/write bit +2) 11900 SEG CS +2) 11910 OR AH,[READOP] +2) 11920 FATAL: +2) 11930 MOV AL,[BP+DRVNUM] ;Get drive number +2) 11940 PUSH BP ;The only thing we preserve +2) 11950 SEG CS +2) 11960 MOV [CONTSTK],SP +2) 11970 DI ;Prepare to play with stack +2) 11980 SEG CS +2) 11990 MOV SS,[SSSAVE] +2) 12000 SEG CS +2) 12010 MOV SP,[SPSAVE] ;User stack pointer restored +2) 12020 INT 24H ;Fatal error interrupt vector +2) 12030 SEG CS +2) 12040 MOV [SPSAVE],SP +2) 12050 SEG CS +2) 12060 MOV [SSSAVE],SS +2) 12070 MOV SP,CS +2) 12080 MOV SS,SP +2) 12090 SEG CS +2) 12100 MOV SP,[CONTSTK] +2) 12110 EI +2) 12120 POP BP +2) 12130 CMP AL,2 +2) 12140 JZ ERROR +2) 12150 RET +2) 12170 DSKREAD: +2) 12180 MOV AL,[BP+DRVNUM] +************** +1)1 11080 JC HARDREAD +1) 11090 XOR AL,AL +1) 11100 RET +1) 11120 HARDREAD: +1) 11130 MOV SI,RDERRMES +1) 11140 CALL HARDERR +1) 11150 JP DREAD +1) 11180 CHKDIRWRITE: +**** +2)1 12280 RET +2) 12310 CHKDIRWRITE: +************** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1)1 11490 ; Outputs: +1) 11500 ; AL = 0 if no error, otherwise non-zero +1) 11510 ; BP preserved. All other registers destroyed. +1) 11530 MOV AL,[BP+DRVNUM] +1) 11540 WRTDRV: +1) 11550 PUSH AX +1) 11560 PUSH BP +**** +2)1 12620 ; BP preserved. All other registers destroyed. +2) 12640 MOV AL,[BP+DRVNUM] +2) 12650 PUSH BP +************** +1)1 11650 POP AX +1) 11660 JC HARDWRITE +1) 11670 XOR AL,AL +1) 11680 RET +1) 11690 HARDWRITE: +1) 11700 MOV SI,WRTERRMES +1) 11710 CALL HARDERR +1) 11720 JP WRTDRV +1) 11750 HARDERR: +1) 11760 SUB DI,CX +1) 11770 ADD DX,DI +1) 11780 CALL SHFTDI7 +1) 11790 ADD BX,DI +1) 11800 MOV AH,AL ;Save drive number +1) 11810 CALL OUTMES +1) 11820 GETINSTR: +1) 11830 CALL IN +1) 11840 OR AL,20H +1) 11850 CMP AL,"a" +1) 11860 JZ ERROR +1) 11870 CMP AL,"r" +1) 11880 JZ RETRY +1) 11890 CMP AL,"i" +1) 11900 JZ IGNORE +1) 11910 CMP AL,"c" +1) 11920 JNZ GETINSTR +1) 11930 CONTINUE: +1) 11940 POP AX +1) 11950 MOV AL,1 +1) 11960 RET +1) 11970 IGNORE: +1) 11980 POP AX +1) 11990 MOV AL,0 +1) 12000 RET +1) 12010 RETRY: +1) 12020 MOV AL,AH ;Restore drive number +1) 12030 RET +**** +2)1 12740 JNC RET +2) 12750 SEG CS +2) 12760 MOV B,[READOP],1 +2) 12770 CALL HARDERR +2) 12780 CMP AL,1 ;Check for retry +2) 12790 JZ DWRITE + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 12800 RET +************** +1)1 12080 MOV DS,[CSLOC] +1) 12090 XOR AX,AX +**** +2)1 12840 LDS SI,[SPSAVE] +2) 12850 MOV DS,[SI+CSSAVE] +2) 12860 XOR AX,AX +************** +1)1 13120 MOV AX,[DI+RR] +**** +2)1 13890 CMP B,[DI],-1 +2) 13900 JNZ NORMFCB1 +2) 13910 ADD DI,7 +2) 13920 NORMFCB1: +2) 13930 MOV AX,[DI+RR] +************** +1)1 13180 MOV B,[DSKERR],-2 +1) 13190 POP BX +**** +2)1 13990 MOV B,[DSKERR],4 +2) 14000 POP BX +************** +1)1 13880 DIV AX,[BP+SECSIZ] +1) 13890 MOV [SECPOS],AX +**** +2)1 14690 MOV BX,[BP+SECSIZ] +2) 14700 CMP DX,BX ;See if divide will overflow +2) 14710 JNC EOFERR +2) 14720 DIV AX,BX +2) 14730 MOV [SECPOS],AX +************** +1)1 14020 JZ OK ;Must stay within 64K +1) 14030 MOV AX,[DMAADD] +1) 14040 NEG AX ;Amount of room left in segment +1) 14050 XOR DX,DX +1) 14060 DIV AX,SI ;How many records will fit? +1) 14070 MUL AX,SI ;Translate that back into bytes +**** +2)1 14860 JZ OK ;Must be less than 64K +2) 14870 MOV AX,[DMAADD] +2) 14880 NEG AX ;Amount of room left in segment +2) 14890 JNZ PARTSEG ;All 64K available? +2) 14900 DEC AX ;If so, reduce it by one +2) 14910 PARTSEG: +2) 14920 XOR DX,DX +2) 14930 DIV AX,SI ;How many records will fit? +2) 14940 MOV [RECCNT],AX +2) 14950 MUL AX,SI ;Translate that back into bytes +************** +1)1 15170 OR AL,AL +1) 15180 JNZ SETBUF +1) 15190 CMP DX,[BUFSECNO] +**** +2)1 16050 MOV [PREREAD],AL +2) 16060 CMP DX,[BUFSECNO] + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 15280 MOV AL,[BUFDRVNO] +1) 15290 MOV BX,[BUFFER] +**** +2)1 16150 PUSH BP +2) 16160 MOV BP,[BUFDRVBP] +2) 16170 MOV BX,[BUFFER] +************** +1)1 15320 CALL WRTDRV +1) 15330 POP DX +1) 15340 RDSEC: +1) 15350 MOV BX,[BUFFER] +**** +2)1 16200 CALL DWRITE +2) 16210 POP BP +2) 16220 POP DX +2) 16230 RDSEC: +2) 16240 TEST B,[PREREAD],-1 +2) 16250 JNZ SETBUF +2) 16260 MOV BX,[BUFFER] +************** +1)1 15450 FINBUF: +**** +2)1 16360 MOV [BUFDRVBP],BP +2) 16370 FINBUF: +************** +1)1 16560 CALL BIOSAUXIN,BIOSSEG +1) 16570 STOB +**** +2)1 17480 CALL AUXIN +2) 17490 STOB +************** +1)1 18310 WRTLST: +**** +2)1 19230 DEC BL +2) 19240 JNZ ENDWRDEV ;Done if device is NUL +2) 19250 WRTLST: +************** +1)1 18350 CALL BIOSPRINT,BIOSSEG +1) 18360 LOOP WRTLST +**** +2)1 19290 CALL LISTOUT +2) 19300 LOOP WRTLST +************** +1)1 18410 CALL BIOSAUXOUT,BIOSSEG +1) 18420 CMP AL,1AH +**** +2)1 19350 CALL AUXOUT +2) 19360 CMP AL,1AH +************** +1)1 18900 SEG CS +1) 18910 MOV BX,[DATE] +1) 18920 MOV [DI+FDATE],BX +1) 18930 CALL SETUP +1) 18940 SEG ES +**** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2)1 19840 CALL SETUP +2) 19850 CALL DATE16 +2) 19860 SEG ES +2) 19870 MOV [DI+FDATE],AX +2) 19880 SEG ES +************** +1)1 19120 MOV DX,[DI+FILSIZ] +1) 19130 DIV AX,[BP+SECSIZ] +**** +2)1 20060 MOV DX,[DI+FILSIZ+2] +2) 20070 DIV AX,[BP+SECSIZ] +************** +1)1 19260 JCXZ HAVSTART +1) 19270 PUSH CX ;No. of clusters short of first +**** +2)1 20200 JCXZ HAVSTART ;See if no more data +2) 20210 PUSH CX ;No. of clusters short of first +************** +1)1 21460 MOV CX,1 +**** +2)1 22400 CMP B,[DI],-1 +2) 22410 JNZ NORMFCB2 +2) 22420 ADD DI,7 +2) 22430 NORMFCB2: +2) 22440 MOV CX,1 +************** +1)1 22920 PUSH DX +1) 22930 PUSH DS +1) 22940 CALL GETFILE +**** +2)1 23900 CALL GETFILE +************** +1)1 22980 POP ES +1) 22990 POP DI +1) 23000 JC KILLSRCH +**** +2)1 23940 JC KILLSRCH +************** +1)1 23100 MOV AL,[BP+DRVNUM] +**** +2)1 24040 MOV AX,00FFH +2) 24050 CMP AL,[EXTFCB] +2) 24060 JNZ NORMFCB +2) 24070 STOW +2) 24080 INC AL +2) 24090 STOW +2) 24100 STOW +2) 24110 MOV AL,[ATTRIB] +2) 24120 STOB +2) 24130 NORMFCB: +2) 24140 MOV AL,[BP+DRVNUM] +************** +1)1 23530 SUB SI,3 ;Point to device name +1) 23540 MOVW +1) 23550 MOVB +1) 23560 MOV AX,2020H + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 23570 MOV CX,4 +1) 23580 REP +1) 23590 STOW ;Fill with 8 blanks +1) 23600 XOR AX,AX +**** +2)1 24570 SUB SI,4 ;Point to device name +2) 24580 MOVW +2) 24590 MOVW +2) 24600 MOV AX,2020H +2) 24610 MOV CX,3 +2) 24620 REP +2) 24630 STOW ;Fill with 6 blanks +2) 24640 STOB ;And a 7th +2) 24650 XOR AX,AX +************** +1)1 23780 JMP SAVPLCE +1) 23810 FILESIZE: ;System call 35 +1) 23820 PUSH DS +1) 23830 PUSH DX +1) 23840 CALL GETFILE +1) 23850 POP DI +1) 23860 POP ES +1) 23870 MOV AL,-1 +**** +2)1 24830 POP ES +2) 24840 POP DI +2) 24850 JMP SAVPLCE +2) 24880 FILESIZE: ;System call 35 +2) 24890 CALL GETFILE +2) 24900 MOV AL,-1 +************** +1)1 24610 GETDSKPT: ;System call 31 +1) 24620 SEG CS +1) 24630 MOV BX,[CURDRVPT] +1) 24640 SEG CS +1) 24650 LDS SI,[SPSAVE] +1) 24660 MOV [SI+BXSAVE],BX +1) 24670 MOV [SI+DSSAVE],CS +1) 24680 RET +1) 24710 DSKRESET: ;System call 13 +**** +2)1 25640 DSKRESET: ;System call 13 +************** +1)1 24810 MOV CL,[NUMDRV] +**** +2)1 25740 MOV AX,[BUFDRVNO] +2) 25750 OR AH,AH +2) 25760 JZ NOBUF +2) 25770 CBW +2) 25780 MOV BX,AX +2) 25790 SHL BX +2) 25800 MOV BP,[BX+DRVTAB] +2) 25810 MOV B,[DIRTYBUF],0 +2) 25820 MOV DX,[BUFSECNO] +2) 25830 MOV BX,BUFFER +2) 25840 MOV CX,1 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 25850 CALL DWRITE +2) 25860 NOBUF: +2) 25870 MOV CL,[NUMDRV] +************** +1)1 24930 MOV AX,[BUFDRVNO] +1) 24940 OR AH,AH +1) 24950 JZ RET +1) 24960 CBW +1) 24970 MOV BX,AX +1) 24980 SHL BX +1) 24990 MOV BP,[BX+DRVTAB] +1) 25000 MOV B,[DIRTYBUF],0 +1) 25010 MOV DX,[BUFSECNO] +1) 25020 MOV BX,BUFFER +1) 25030 MOV CX,1 +1) 25040 JMP DWRITE +1) 25070 CURDRV: ;System call 25 +**** +2)1 25990 RET +2) 26020 CURDRV: ;System call 25 +************** +1)1 25140 INUSE: ;System call 24 +1) 25150 MOV AX,CS +1) 25160 MOV DS,AX +1) 25170 MOV CL,[NUMDRV] +1) 25180 MOV CH,0 +1) 25190 MOV SI,CX +1) 25200 SHL SI +1) 25210 ADD SI,CURDRVPT +1) 25220 MOV BX,0 +1) 25230 DOWN +1) 25240 CHKUSE: +1) 25250 LODW +1) 25260 MOV BP,AX +1) 25270 CMP B,[BP+DIRTYFAT],-1 ;Carry set if not equal +1) 25280 RCL BX +1) 25290 LOOP CHKUSE +1) 25300 MOV AL,BL +1) 25310 RET +1) 25340 SETRNDREC: ;System call 36 +**** +2)1 26090 SETRNDREC: ;System call 36 +************** +1)1 25380 RET +**** +2)1 26130 CMP [DI+RECSIZ],64 +2) 26140 JAE RET +2) 26150 MOV [DI+36],DH ;Set 4th byte only if record size < 64 +2) 26160 RET +************** +1)1 25870 JZ BACKSP +1) 25880 CMP AL,8 +1) 25890 JZ BACKSP +1) 25900 CMP AL,13 +**** +2)1 26650 JZ BACKSPJ + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 26660 CMP AL,8 +2) 26670 JZ BACKSPJ +2) 26680 CMP AL,13 +************** +1)1 25960 CMP AL,ESCCH +**** +2)1 26740 CMP AL,1BH +2) 26750 JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X +2) 26760 CMP AL,ESCCH +************** +1)1 26000 JAE GETCH +1) 26010 STOB +**** +2)1 26800 JAE BELL +2) 26810 STOB +************** +1)1 26120 ESC: +1) 26130 CALL IN +1) 26140 MOV CL,ESCTABLEN +1) 26150 PUSH DI +1) 26160 MOV DI,ESCTAB +**** +2)1 26920 BELL: +2) 26930 MOV AL,7 +2) 26940 CALL OUTCH +2) 26950 JP GETCH +2) 26970 BACKSPJ:JP BACKSP +2) 26990 ESC: +2) 27000 CALL IN +2) 27010 PUSH DI +2) 27020 MOV CL,ESCTABLEN +2) 27030 MOV DI,ESCTAB +************** +1)1 26200 AND CL,0FEH +1) 26210 MOV BP,CX +1) 26220 SEG CS ;To work in init +**** +2)1 27070 MOV BP,CX +2) 27080 SHL BP +2) 27090 SEG CS ;To work in init +************** +1)1 27420 CMP DH,DL +**** +2)1 28290 MOV AH,0 ;Turn off insert mode when copying +2) 28300 CMP DH,DL +************** +1)1 28080 ENTERINS: +1) 28090 MOV AH,-1 +1) 28100 JMP GETCH +1) 28120 EXITINS: +1) 28130 MOV AH,0 +1) 28140 JMP GETCH +1) 28160 ESCFUNC: +**** +2)1 28960 TOGGLINS: +2) 28970 NOT AH + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 28980 JMP GETCH +2) 29000 CTRLZ: +2) 29010 MOV AL,1AH +2) 29020 JMP SAVCH +2) 29040 ESCFUNC: +************** +1)1 28190 DW EXITINS +1) 28200 DW ENTERINS +1) 28210 DW BACKSP +1) 28220 DW REEDIT +1) 28230 DW KILNEW +1) 28240 DW COPYLIN +**** +2)1 29070 DW TOGGLINS +2) 29080 DW BACKSP +2) 29090 DW REEDIT +2) 29100 DW CTRLZ +2) 29110 DW COPYLIN +************** +1)1 28300 BUFOUT: +**** +2)1 29160 DW COPYONE +2) 29180 BUFOUT: +************** +1)1 28520 CALL BIOSOUT,BIOSSEG +**** +2)1 29400 PUSH AX +2) 29410 CALL STATCHK +2) 29420 POP AX +2) 29430 CALL BIOSOUT,BIOSSEG +************** +1)1 28550 JZ STATCHK +1) 28560 CALL BIOSPRINT,BIOSSEG +1) 28570 STATCHK: +**** +2)1 29460 JZ RET +2) 29470 CALL BIOSPRINT,BIOSSEG +2) 29480 RET +2) 29500 NOSTOP: +2) 29510 CMP AL,"P"-"@" +2) 29520 JZ INCHK +2) 29530 CMP AL,"C"-"@" +2) 29540 JZ INCHK +2) 29550 RET +2) 29570 STATCHK: +************** +1)1 28600 INCHK: +1) 28610 CALL BIOSIN,BIOSSEG +1) 28620 CMP AL,'S'-'@' +1) 28630 JNZ NOSTOP +1) 28640 CALL BIOSIN,BIOSSEG +1) 28650 NOSTOP: +1) 28660 CMP AL,'P'-'@' +1) 28670 JZ PRINTON +1) 28680 CMP AL,'N'-'@' +1) 28690 JZ PRINTOFF + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 28700 CMP AL,'C'-'@' +**** +2)1 29600 CMP AL,'S'-'@' +2) 29610 JNZ NOSTOP +2) 29620 CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +2) 29630 INCHK: +2) 29640 CALL BIOSIN,BIOSSEG +2) 29650 CMP AL,'P'-'@' +2) 29660 JZ PRINTOGL +2) 29670 CMP AL,'C'-'@' +************** +1)1 28810 ; repeated, except for console output (function 2), which has already output +1) 28820 ; its character before the interrupt. +1) 28830 SEG CS +**** +2)1 29780 ; repeated. +2) 29790 SEG CS +************** +1)1 29090 CMP AH,2 ;Check if function was console output +1) 29100 JZ SETAL +1) 29110 JMP COMMAND ;Repeat command otherwise +1) 29120 SETAL: +1) 29130 MOV AL,DL +1) 29140 IRET ;Return to user program +1) 29160 PRINTON: +1) 29170 SEG CS +1) 29180 MOV B,[PFLAG],1 +1) 29190 RET +1) 29200 PRINTOFF: +1) 29210 SEG CS +1) 29220 MOV B,[PFLAG],0 +1) 29230 RET +**** +2)1 30050 JMP COMMAND ;Repeat command otherwise +2) 30070 PRINTOGL: +2) 30080 SEG CS +2) 30090 XOR B,[PFLAG],1 +2) 30100 XOR AL,AL ;Set zero flag--character not received +2) 30110 RET +************** +1)1 29590 JZ RET +**** +2)1 30470 MOV AL,0 +2) 30480 JZ RET +************** +1)1 29820 JZ RET +**** +2)1 30710 MOV AL,0 +2) 30720 JZ RET +************** +1)1 29920 CALL BIOSPRINT,BIOSSEG +**** +2)1 30820 LISTOUT: +2) 30830 PUSH AX +2) 30840 CALL STATCHK +2) 30850 POP AX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 30860 CALL BIOSPRINT,BIOSSEG +************** +1)1 30220 CMP B,[SI+1],":" ;Check for potential drive specifier +1) 30230 JNZ DEFAULT +1) 30240 CALL GETLET +1) 30250 SUB AL,"@" ;Convert drive letter to binary drive number +1) 30260 JZ NODRV ;Valid drive numbers are 1-15 +1) 30270 INCcifier--back up pointer +1) 30280 DEFAULT: +1) 30290 XOR AL,AL +1) 30300 HAVDRV: +**** +2)1 31160 MOV AL,0 +2) 31170 CMP B,[SI],20H ;Check for termination character +2) 31180 JB HAVDRV +2) 31190 CMP B,[SI+1],":" ;Check for potential drive specifier +2) 31200 JNZ HAVDRV +2) 31210 CALL GETLET +2) 31220 SUB AL,"@" ;Convert drive letter to binary drive number +2) 31230 JBE BADDRV ;Valid drive numbers are 1-15 +2) 31240 SEG CS +2) 31250 CMP AL,[NUMDRV] +2) 31260 JA BADDRV +2) 31270 INC SI ;Skip over colon +2) 31280 HAVDRV: +************** +1)1 30490 GETWORD: +**** +2)1 31470 BADDRV: +2) 31480 MOV AL,-1 +2) 31490 RET +2) 31510 GETWORD: +************** +1)1 30780 CMP AL,"a" +**** +2)1 31800 AND AL,7FH +2) 31810 CMP AL,"a" +************** +1)1 30960 CMP AL,9 ;Filter out TABs too +**** +2)1 31990 CMP AL,'"' +2) 32000 JZ RET +2) 32010 CMP AL,"+" +2) 32020 JZ RET +2) 32030 CMP AL,"/" +2) 32040 JZ RET +2) 32050 CMP AL,"[" +2) 32060 JZ RET +2) 32070 CMP AL,"]" +2) 32080 JZ RET +2) 32090 CMP AL,9 ;Filter out TABs too +************** +1)1 31160 MOV DS,[CSLOC] +1) 31170 XOR SI,SI +**** +2)1 32290 LDS SI,[SPSAVE] + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 32300 MOV DS,[SI+CSSAVE] +2) 32310 XOR SI,SI +************** +1)1 31830 ; Default handler for division overflow trap +1) 31840 DIVOV: +1) 31850 XOR DX,DX ;Say no remainder +1) 31860 MOV AX,-1 ;But large quotient +1) 31870 IRET +1) 31900 ;***** DATA AREA ***** +1) 31920 BADMES: DB 13,10,"Bad FAT",13,10,"$" +1) 31930 BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$" +1) 31940 RDERRMES:DB 13,10,"Disk read error",13,10,"$" +1) 31950 WRTERRMES:DB 13,10,"Disk write error",13,10,"$" +1) 31960 IONAME: DB "PRN","LST","AUX","CON" +1) 31980 CARPOS: DB 0 +1) 31990 STARTPOS:DB 0 +1) 32000 PFLAG: DB 0 +1) 32010 DIRTYDIR:DB 0 ;Dirty buffer flag +**** +2)1 32960 DATE16: +2) 32970 PUSH CX +2) 32980 PUSH DX +2) 32990 PUSH BX +2) 33000 CALL READTIME +2) 33010 POP BX +2) 33020 POP DX +2) 33030 POP CX +2) 33040 MOV AX,[MONTH] ;Fetch month and year +2) 33050 SHL AL ;Push month to left to make room for day +2) 33060 SHL AL +2) 33070 SHL AL +2) 33080 SHL AL +2) 33090 SHL AX +2) 33100 OR AL,[DAY] +2) 33110 RET +2) 33130 READTIME: +2) 33140 ;Gets tick count in CX:DX. Causes date rollover if new day has started +2) 33150 ;since last call. Destroys AX, BX. +2) 33160 MOV AH,0 ;Request get time +2) 33170 INT 1AH ;Time-of-day interrupt +2) 33180 OR AL,AL ;See if day has changed +2) 33190 JZ RET +2) 33200 ADD AL,[DAY] +2) 33210 MOV [DAY],AL +2) 33220 MOV AH,AL +2) 33230 MOV AL,[MONTH] +2) 33240 MOV BX,DAYTAB-1 ;Table of days in each month +2) 33250 XLAT ;Get number of days in current month +2) 33260 SUB AH,AL ;Have we rolled into next month? +2) 33270 JBE RET +2) 33280 MOV [DAY],AH ;Yes-store day of new month +2) 33290 MOV AL,[MONTH] +2) 33300 INC AL +2) 33310 MOV [MONTH],AL +2) 33320 CMP AL,12 ;Have we rolled into next year? +2) 33330 JBE RET + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 33340 MOV B,[MONTH],1 ;Set first month to January +2) 33350 MOV AL,[YEAR] +2) 33360 INC AL +2) 33370 SETYEAR: +2) 33380 ;Set year with value in AL. Adjust length of February for this year. +2) 33390 MOV [YEAR],AL +2) 33400 AND AL,3 ;Check for leap year +2) 33410 MOV AL,28 +2) 33420 JNZ SAVFEB ;28 days if no leap year +2) 33430 INC AL ;Add leap day +2) 33440 SAVFEB: +2) 33450 MOV [DAYTAB+1],AL ;Store for February +2) 33460 RET +2) 33480 DAYTAB: ;Days of each month +2) 33490 DB 31 ;January +2) 33500 DB 28 ;February--reset each time year changes +2) 33510 DB 31 ;March +2) 33520 DB 30 ;April +2) 33530 DB 31 ;May +2) 33540 DB 30 ;June +2) 33550 DB 31 ;July +2) 33560 DB 31 ;August +2) 33570 DB 30 ;September +2) 33580 DB 31 ;October +2) 33590 DB 30 ;November +2) 33600 DB 31 ;December +2) 33620 GETDATE: ;Function call 42 +2) 33630 PUSH CS +2) 33640 POP DS +2) 33650 CALL READTIME ;Check for rollover to next day +2) 33660 MOV AX,[YEAR] +2) 33670 MOV BX,[DAY] +2) 33680 LDS SI,[SPSAVE] ;Get pointer to user registers +2) 33690 MOV [SI+DXSAVE],BX ;DH=month, DL=day +2) 33700 ADD AX,1980 ;Put bias back +2) 33710 MOV [SI+CXSAVE],AX ;CX=year +2) 33720 XOR AL,AL +2) 33730 RET +2) 33750 SETDATE: ;Function call 43 +2) 33760 MOV AL,-1 ;Be ready to flag an error +2) 33770 SUB CX,1980 ;Fix bias in year +2) 33780 JC RET ;Error if not big enough +2) 33790 CMP CX,119 ;Year must be less than 2100 +2) 33800 JA RET +2) 33810 OR DH,DH +2) 33820 JZ RET +2) 33830 OR DL,DL +2) 33840 JZ RET ;Error if either month or day is 0 +2) 33850 CMP DH,12 ;Check against max. month +2) 33860 JA RET +2) 33870 PUSH CS +2) 33880 POP DS +2) 33890 CMP DH,2 ;Check for Feb.--needs special handling +2) 33900 JNE DAYCHK +2) 33910 CMP DL,29 +2) 33920 JA RET ;Max 29 days in Feb. + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 33930 JB DAYOK ;If 28 or less, definitely OK +2) 33940 TEST CL,3 ;Check for leap year +2) 33950 JZ DAYOK ;If it is, 29 days OK +2) 33960 RET ;Error if it's not +2) 33970 DAYCHK: +2) 33980 MOV AL,DH +2) 33990 MOV BX,DAYTAB-1 +2) 34000 XLAT ;Look up days in month +2) 34010 CMP AL,DL +2) 34020 MOV AL,-1 ;Restore error flag, just in case +2) 34030 JB RET ;Error if too many days +2) 34040 DAYOK: +2) 34050 PUSH DX +2) 34060 PUSH CX +2) 34070 MOV AH,0 +2) 34080 INT 1AH ;Read time to clear day overflow +2) 34090 POP AX ;Year +2) 34100 CALL SETYEAR +2) 34110 POP [DAY] ;Set both day and month +2) 34120 XOR AL,AL ;Flag OK +2) 34130 RET +2) 34150 ;*************************************** +2) 34160 ; Time Functions +2) 34170 ; +2) 34180 ; Uses clock with 1,193,180/65536 ticks per second. User sees only +2) 34190 ; time in hours, minutes, seconds, and 1/100 second, in registers +2) 34200 ; CH, CL, DH, DL respectively. (Each is a binary number.) To +2) 34210 ; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +2) 34220 ; reciprocal of the tick rate. To convert the other way, 1/100 secs +2) 34230 ; is multiplied by 59659/(5 * 2**16). +2) 34250 GETTIME: ;Function call 44 +2) 34260 PUSH CS +2) 34270 POP DS +2) 34280 CALL READTIME ;Get tick count in CX:DX +2) 34290 ;First multiply by 5 +2) 34300 MOV AX,CX +2) 34310 MOV BX,DX +2) 34320 SHL DX +2) 34330 RCL CX ;Times 2 +2) 34340 SHL DX +2) 34350 RCL CX ;Times 4 +2) 34360 ADD DX,BX +2) 34370 ADC AX,CX ;Times 5 +2) 34380 XCHG AX,DX +2) 34390 MOV CX,59659 +2) 34400 DIV AX,CX +2) 34410 MOV BX,AX ;Save quotient +2) 34420 XOR AX,AX ;Extend precision +2) 34430 DIV AX,CX +2) 34440 ;Rounding based on the remainder may be added here +2) 34450 ;The result in BX:AX is time in 1/100 second. +2) 34460 MOV DX,BX +2) 34470 MOV CX,200 ;Extract 1/100's +2) 34480 ;Division by 200 is necessary to ensure no overflow--max result +2) 34490 ;is number of seconds in a day/2 = 43200. +2) 34500 DIV AX,CX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 34510 CMP DL,100 ;Remainder over 100? +2) 34520 JB NOADJ +2) 34530 SUB DL,100 ;Keep 1/100's less than 100 +2) 34540 NOADJ: +2) 34550 CMC ;If we subtracted 100, carry is now set +2) 34560 MOV BL,DL ;Save 1/100's +2) 34570 ;To compensate for dividing by 200 instead of 100, we now multiply +2) 34580 ;by two, shifting a one in if the remainder had exceeded 100. +2) 34590 RCL AX +2) 34600 MOV DL,0 +2) 34610 RCL DX +2) 34620 MOV CX,60 ;Divide out seconds +2) 34630 DIV AX,CX +2) 34640 MOV BH,DL ;Save the seconds +2) 34650 DIV AL,CL ;Break into hours and minutes +2) 34660 XCHG AL,AH +2) 34670 ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) +2) 34680 LDS SI,[SPSAVE] ;Get pointer to user registers +2) 34690 MOV [SI+DXSAVE],BX +2) 34700 MOV [SI+CXSAVE],AX +2) 34710 XOR AL,AL +2) 34720 RET +2) 34740 SETTIME: ;Function call 45 +2) 34750 ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec +2) 34760 MOV AL,-1 ;Flag in case of error +2) 34770 CMP CH,24 ;Check hours +2) 34780 JAE RET +2) 34790 CMP CL,60 ;Check minutes +2) 34800 JAE RET +2) 34810 CMP DH,60 ;Check seconds +2) 34820 JAE RET +2) 34830 CMP DL,100 ;Check 1/100's +2) 34840 JAE RET +2) 34850 MOV AL,60 +2) 34860 MUL AL,CH ;Hours to minutes +2) 34870 MOV CH,0 +2) 34880 ADD AX,CX ;Total minutes +2) 34890 MOV CX,6000 ;60*100 +2) 34900 MOV BX,DX ;Get out of the way of the multiply +2) 34910 MUL AX,CX ;Convert to 1/100 sec +2) 34920 MOV CX,AX +2) 34930 MOV AL,100 +2) 34940 MUL AL,BH ;Convert seconds to 1/100 sec +2) 34950 ADD CX,AX ;Combine seconds with hours and min. +2) 34960 ADC DX,0 ;Ripple carry +2) 34970 MOV BH,0 +2) 34980 ADD CX,BX ;Combine 1/100 sec +2) 34990 ADC DX,0 +2) 35000 ;DX:CX is time in 1/100 sec +2) 35010 XCHG AX,DX +2) 35020 XCHG AX,CX ;Now time is in CX:AX +2) 35030 MOV BX,59659 +2) 35040 MUL AX,BX ;Multiply low half +2) 35050 XCHG DX,CX +2) 35060 XCHG AX,DX ;CX->AX, AX->DX, DX->CX +2) 35070 MUL AX,BX ;Multiply high half + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 35080 ADD AX,CX ;Combine overlapping products +2) 35090 ADC DX,0 +2) 35100 XCHG AX,DX ;AX:DX=time*59659 +2) 35110 MOV BX,5 +2) 35120 DIV AL,BL ;Divide high half by 5 +2) 35130 MOV CL,AL +2) 35140 MOV CH,0 +2) 35150 MOV AL,AH ;Remainder of divide-by-5 +2) 35160 CBW +2) 35170 XCHG AX,DX ;Use it to extend low half +2) 35180 DIV AX,BX ;Divde low half by 5 +2) 35190 MOV DX,AX +2) 35200 ;CX:DX now has time in ticks +2) 35210 MOV AH,1 +2) 35220 INT 1AH ;Set clock +2) 35230 XOR AL,AL ;Return no error +2) 35240 RET +2) 35260 ;***** DATA AREA ***** +2) 35280 ;Device number mapping +2) 35290 ;0,1 = CON, AUX (Bidirectional devices) +2) 35300 ;2,3 = Printer, bit bucket (output only) +2) 35320 IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +2) 35330 IONUM: DB 3,0,1,1,2,2 +2) 35350 CARPOS: DB 0 +2) 35360 INSFLG: DB 0 +2) 35370 STARTPOS:DB 0 +2) 35380 PFLAG: DB 0 +2) 35390 DAY: DB 0 +2) 35400 MONTH: DB 0 +2) 35410 YEAR: DW 0 +2) 35420 DIRTYDIR:DB 0 ;Dirty buffer flag +************** +1)1 32120 DIRBUFID:DW -1 +1) 32130 DATE: DS 2 +1) 32140 CURDRVPT:DS 2 +**** +2)1 35530 BUFDRVBP:DS 2 +2) 35540 DIRBUFID:DW -1 +2) 35550 CURDRVPT:DS 2 +************** +1)1 32290 NAME2: DS 11 +1) 32300 TEMP: +1) 32310 CSLOC: DS 2 +1) 32320 SPSAVE: DS 2 +1) 32330 SSSAVE: DS 2 +1) 32340 SECCLUSPOS:DS 1 ;Position of first sector within cluster +**** +2)1 35700 ATTRIB: DS 1 ;Search attributes +2) 35710 NAME2: DS 11 +2) 35715 NAME3: DS 12 +2) 35720 EXTFCB: DS 1 +2) 35730 CREATING:DS 1 +2) 35740 TEMP: +2) 35750 SPSAVE: DS 2 +2) 35760 SSSAVE: DS 2 +2) 35770 CONTSTK:DS 2 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 35780 SECCLUSPOS:DS 1 ;Position of first sector within cluster +************** +1)1 32380 ALIGN +**** +2)1 35810 PREREAD:DS 1 ;0 means must preread; 1 means optional +2) 35820 READOP: DS 1 +2) 35840 ALIGN +************** +1)1 32490 BYTCNT1:DS 2 ;No. of bytes in first sector +1) 32500 BYTCNT2:DS 2 ;No. of bytes in last sector +1) 32510 SECCNT: DS 2 ;No. of whole sectors +1) 32530 DS 60 ;Stack space +1) 32540 STACK: +1) 32560 IF DSKTEST +**** +2)1 35950 BYTCNT1:DS 2 ;No. of bytes in first sector +2) 35960 BYTCNT2:DS 2 ;No. of bytes in last sector +2) 35970 SECCNT: DS 2 ;No. of whole sectors +2) 35990 DS 100H ;Stack space +2) 36000 IOSTACK: +2) 36010 DS 100H +2) 36020 DSKSTACK: +2) 36040 IF DSKTEST +************** +1)1 32590 DS 60 +1) 32600 TESTSTK: +1) 32610 ENDIF +**** +2)1 36070 ENDIF +************** +1)1 33840 ADD AX,[BP+DIRSEC] ;Add number of dir. sectores for 32-byte entry +1) 33850 STOW ;FIRREC2 +**** +2)1 37300 ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry +2) 37310 STOW ;FIRREC2 +************** +1)1 34330 MOV [0],DIVOV ;Set default divide trap address +1) 34340 MOV [2],AX +1) 34350 MOV CX,9 +**** +2)1 37790 MOV CX,9 +************** +1)1 34550 MOV CX,DX +1) 34560 MOV BX,0FH +1) 34570 MEMSCAN: +1) 34580 INC CX +1) 34590 JZ HAVMEM +1) 34600 MOV DS,CX +1) 34610 MOV AL,[BX] +1) 34620 NOT AL +1) 34630 MOV [BX],AL +1) 34640 CMP AL,[BX] +1) 34650 NOT AL +1) 34660 MOV [BX],AL +1) 34670 JZ MEMSCAN +1) 34680 HAVMEM: + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 34690 SEG CS +1) 34700 MOV [ENDMEM],CX +1) 34710 XOR CX,CX +**** +2)1 37990 INT 12H ;Get memory size--1K blocks in AX +2) 38000 MOV CL,6 +2) 38010 SHL AX,CL ;Convert to 16-byte blocks (segment no.) +2) 38020 SEG CS +2) 38030 MOV [ENDMEM],AX +2) 38040 XOR CX,CX +************** +1)1 34750 MOV SI,HEADER +1) 34760 CALL OUTMES +1) 34770 PUSH CS +**** +2)1 38080 PUSH CS +************** +1)1 34810 PUSH DX +1) 34820 GETDAT: +1) 34830 MOV SI,DATMES +1) 34840 CALL OUTMES +1) 34850 MOV DX,DATBUF +1) 34860 CALL BUFIN +1) 34870 CALL CRLF +1) 34880 MOV SI,DATBUF+2 +1) 34890 MOV DX,12 +1) 34900 CALL MYD +1) 34910 JC GETDAT +1) 34920 MOV CL,5 +1) 34930 SHL AX,CL +1) 34940 MOV [DATE],AX +1) 34950 MOV DX,31 +1) 34960 CALL MYD +1) 34970 JC GETDAT +1) 34980 OR [DATE],AL +1) 34990 MOV DX,2100 +1) 35000 CALL MYD +1) 35010 JC GETDAT +1) 35020 SUB AX,80 +1) 35030 JC GETDAT +1) 35040 CMP AX,19 +1) 35050 JBE SAVYR +1) 35060 SUB AX,1900 +1) 35070 JC GETDAT +1) 35080 SAVYR: +1) 35090 SHL AL +1) 35100 OR [DATE+1],AL +1) 35110 ;Move the FATs into position and adjust the drive pointer table +1) 35120 POP DX +1) 35130 POP SI +**** +2)1 38120 MOV [ENDDOS],DX +2) 38130 ;Move FATs into position. Segment of COMMAND still in DX. +2) 38140 POP SI +************** +1)1 35700 MYD: + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 35710 ;SI points to input buffer. Get decimal number < DX and return it +1) 35720 ;in AX. Carry set on error. +1) 35730 XOR BX,BX +1) 35740 MOV AH,0 +1) 35750 GETDIG: +1) 35760 LODB +1) 35770 SUB AL,"0" +1) 35780 JC CHKRET +1) 35790 CMP AL,10 +1) 35800 JNC CHKRET +1) 35810 SHL BX +1) 35820 MOV CX,BX +1) 35830 SHL BX +1) 35840 SHL BX +1) 35850 ADD BX,CX +1) 35860 ADD BX,AX +1) 35870 JP GETDIG +1) 35880 CHKRET: +1) 35890 MOV AX,BX +1) 35900 OR AX,AX +1) 35910 STC +1) 35920 JZ RET +1) 35930 CMP DX,AX +1) 35940 RET +1) 35960 DRVCNT: DB 0 +1) 35980 DATMES: DB "Enter today's date (m-d-y): $" +1) 35990 DATBUF: DB 12,8,"04-28-81",13 +1) 36000 DS 5 +1) 36020 SDIRSEC:DS 2 +1) 36040 MEMSTRT: +1) 36050 ADJFAC: EQU DIRBUF-MEMSTRT +**** +2)1 38710 DRVCNT: DB 0 +2) 38720 SDIRSEC:DS 1 +2) 38740 MEMSTRT: +2) 38750 ADJFAC: EQU DIRBUF-MEMSTRT +************** diff --git a/2_printed_files/bundle_01/MSDOS.LST b/2_printed_files/bundle_01/MSDOS.LST new file mode 100644 index 0000000..bc85982 --- /dev/null +++ b/2_printed_files/bundle_01/MSDOS.LST @@ -0,0 +1,5013 @@ +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-1 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + TITLE MS-DOS version 1.25 by Tim Pate + rson March 3, 1982 + PAGE 60,132 + ; Use the following booleans to set the switches + = 0000 FALSE EQU 0 + = FFFF TRUE EQU NOT FALSE + + ; Use the switches below to produce the standard Microsoft version of the IBM + ; version of the operating system + = MSVER EQU TRUE + = IBM EQU FALSE + + ; Set this switch to cause DOS to move itself to the end of memory + = HIGHMEM EQU FALSE + + ; Turn on switch below to allow testing disk code with DEBUG. It sets + ; up a different stack for disk I/O (functions > 11) than that used for + ; character I/O which effectively makes the DOS re-entrant. + + = DSKTEST EQU FALSE + + C INCLUDE MSDOS.ASM + C ; 86-DOS High-performance operating system for the 8086 version 1.25 + C ; by Tim Paterson + C + C + C ; ****************** Revision History ************************* + C ; >> EVERY change must noted below!! << + C ; + C ; 0.34 12/29/80 General release, updating all past customers + C ; 0.42 02/25/81 32-byte directory entries added + C ; 0.56 03/23/81 Variable record and sector sizes + C ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack + C ; 0.74 04/15/81 Recognize I/O devices with file names + C ; 0.75 04/17/81 Improve and correct buffer handling + C ; 0.76 04/23/81 Correct directory size when not 2^N entries + C ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 + C ; 1.00 04/28/81 Renumber for general release + C ; 1.01 05/12/81 Fix bug in `STORE' + C ; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time, + C ; RENAME fix, general cleanup + C ; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE + C ; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't) + C ; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling + C ; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; + C ; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; + C ; Lots of smaller improvements + C ; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory + C ; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write + C ; 1.23 02/11/82 Add defaulting to parser; use variable escape character + C ; Don't zero extent field in IBM version (back to 1.01!) + C ; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28 + C ; 1.25 03/03/82 Put marker (00) at end of directory to speed searches + C ; + C ; ************************************************************* +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-2 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + C + C ; Interrupt Entry Points: + C + C ; INTBASE: ABORT + C ; INTBASE+4: COMMAND + C ; INTBASE+8: BASE EXIT ADDRESS + C ; INTBASE+C: CONTROL-C ABORT + C ; INTBASE+10H: FATAL ERROR ABORT + C ; INTBASE+14H: BIOS DISK READ + C ; INTBASE+18H: BIOS DISK WRITE + C ; INTBASE+40H: Long jump to CALL entry point + C + C ELSE + = 001B C ESCCH EQU 1BH + = 0018 C CANCEL EQU "X"-"@" ;Cancel with Ctrl-X + = C TOGLINS EQU FALSE ;Separate keys for insert mode on and off + = C TOGLPRN EQU FALSE ;Separate keys for printer echo on and off + = 0005 C NUMDEV EQU 5 ;Number of I/O device names + = C ZEROEXT EQU FALSE + C ENDIF + C + = 0024 C MAXCALL EQU 36 + = 002E C MAXCOM EQU 46 + = 0080 C INTBASE EQU 80H + = 0020 C INTTAB EQU 20H + = 000C C ENTRYPOINTSEG EQU 0CH + = 00C0 C ENTRYPOINT EQU INTBASE+40H + = 0023 C CONTC EQU INTTAB+3 + = 0088 C EXIT EQU INTBASE+8 + = 00EA C LONGJUMP EQU 0EAH + = 009A C LONGCALL EQU 9AH + = 0FFF C MAXDIF EQU 0FFFH + = 000A C SAVEXIT EQU 10 + C + C ; Field definition for FCBs + C + C FCBLOCK STRUC + 0000 0C [ C DB 12 DUP (?) ;Drive code and name + ?? C + ] C + C + 000C ???? C EXTENT DW ? + 000E ???? C RECSIZ DW ? ;Size of record (user settable) + 0010 ???? C FILSIZ DW ? ;Size of file in bytes + 0012 ???? C DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT + 0014 ???? C FDATE DW ? ;Date of last writing + 0016 ???? C FTIME DW ? ;Time of last writing + 0018 ?? C DEVID DB ? ;Device ID number, bits 0-5 + C ;bit 7=0 for file, bit 7=1 for I/O device + C ;If file, bit 6=0 if dirty + C ;If I/O device, bit 6=0 if EOF (input) + 0019 ???? C FIRCLUS DW ? ;First cluster of file + 001B ???? C LSTCLUS DW ? ;Last cluster accessed + 001D ???? C CLUSPOS DW ? ;Position of last cluster accessed +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-3 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 001F ?? C DB ? ;Forces NR to offset 32 + 0020 ?? C NR DB ? ;Next record + 0021 03 [ C RR DB 3 DUP (?) ;Random record + ?? C + ] C + C + 0024 C FCBLOCK ENDS + = 0010 C FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT + C + C ; Description of 32-byte directory entry (same as returned by SEARCH FIRST + C ; and SEARCH NEXT, functions 17 and 18). + C ; + C ; Location bytes Description + C ; + C ; 0 11 File name and extension ( 0E5H if empty) + C ; 11 1 Attributes. Bits 1 or 2 make file hidden + C ; 12 10 Zero field (for expansion) + C ; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour + C ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 + C ; 26 2 First allocation unit ( < 4080 ) + C ; 28 4 File size, in bytes (LSB first, 30 bits max.) + C ; + C ; The File Allocation Table uses a 12-bit entry for each allocation unit on + C ; the disk. These entries are packed, two for every three bytes. The contents + C ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result + C ; to the base address of the Allocation Table; 3) fetching the 16-bit word at + C ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the + C ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number + C ; zero is used as an end-of-file trap in the OS and as a flag for directory + C ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The + C ; first available allocation unit is assigned entry number two, and even + C ; though it is the first, is called cluster 2. Entries greater than 0FF8H are + C ; end of file marks; entries of zero are unallocated. Otherwise, the contents + C ; of a FAT entry is the number of the next cluster in the file. + C + C + C ; Field definition for Drive Parameter Block + C + C DPBLOCK STRUC + 0000 ?? C DEVNUM DB ? ;I/O driver number + 0001 ?? C DRVNUM DB ? ;Physical Unit number + 0002 ???? C SECSIZ DW ? ;Size of physical sector in bytes + 0004 ?? C CLUSMSK DB ? ;Sectors/cluster - 1 + 0005 ?? C CLUSSHFT DB ? ;Log2 of sectors/cluster + 0006 ???? C FIRFAT DW ? ;Starting record of FATs + 0008 ?? C FATCNT DB ? ;Number of FATs for this drive + 0009 ???? C MAXENT DW ? ;Number of directory entries + 000B ???? C FIRREC DW ? ;First sector of first cluster + 000D ???? C MAXCLUS DW ? ;Number of clusters on drive + 1 + 000F ?? C FATSIZ DB ? ;Number of records occupied by FAT + 0010 ???? C FIRDIR DW ? ;Starting record of directory + 0012 ???? C FAT DW ? ;Pointer to start of FAT + 0014 C DPBLOCK ENDS + C + = 0014 C DPBSIZ EQU 20 ;Size of the structure in bytes +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-4 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + = 000B C DIRSEC = FIRREC ;Number of dir. sectors (init temporary) + = 000D C DSKSIZ = MAXCLUS ;Size of disk (temp used during init only) + C + C ;The following are all of the segments used + C ;They are declared in the order that they should be placed in the executable + C + 0000 C CODE SEGMENT + 0000 C CODE ENDS + C + 0000 C CONSTANTS SEGMENT BYTE + 0000 C CONSTANTS ENDS + C + 0000 C DATA SEGMENT WORD + 0000 C DATA ENDS + C + C DOSGROUP GROUP CODE,CONSTANTS,DATA + C + 0000 C SEGBIOS SEGMENT + 0000 C SEGBIOS ENDS + C + C + C ; BOIS entry point definitions + C + C ENDIF + C IF NOT IBM + = 0040 C BIOSSEG EQU 40H + C ENDIF + C + 0000 C SEGBIOS SEGMENT AT BIOSSEG + 0000 C ORG 0 + 0000 03 [ C DB 3 DUP (?) ;Reserve room for jump to init code + ?? C + ] C + C + 0003 03 [ C BIOSSTAT DB 3 DUP (?) ;Console input status check + ?? C + ] C + C + 0006 03 [ C BIOSIN DB 3 DUP (?) ;Get console character + ?? C + ] C + C + 0009 03 [ C BIOSOUT DB 3 DUP (?) ;Output console character + ?? C + ] C + C + 000C 03 [ C BIOSPRINT DB 3 DUP (?) ;Output to printer + ?? C + ] C + C + 000F 03 [ C BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary + ?? C + ] C + C + 0012 03 [ C BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-5 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + ?? C + ] C + C + 0015 03 [ C BIOSREAD DB 3 DUP (?) ;Disk read + ?? C + ] C + C + 0018 03 [ C BIOSWRITE DB 3 DUP (?) ;Disk write + ?? C + ] C + C + 001B 03 [ C BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status + ?? C + ] C + C + 001E 03 [ C BIOSSETDATE DB 3 DUP (?) ;Set date + ?? C + ] C + C + 0021 03 [ C BIOSSETTIME DB 3 DUP (?) ;Set time + ?? C + ] C + C + 0024 03 [ C BIOSGETTIME DB 3 DUP (?) ;Get time and date + ?? C + ] C + C + 0027 03 [ C BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer + ?? C + ] C + C + 002A 03 [ C BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper + ?? C + ] C + C + C + 002D C SEGBIOS ENDS + C ; Location of user registers relative user stack pointer + C + C STKPTRS STRUC + 0000 ???? C AXSAVE DW ? + 0002 ???? C BXSAVE DW ? + 0004 ???? C CXSAVE DW ? + 0006 ???? C DXSAVE DW ? + 0008 ???? C SISAVE DW ? + 000A ???? C DISAVE DW ? + 000C ???? C BPSAVE DW ? + 000E ???? C DSSAVE DW ? + 0010 ???? C ESSAVE DW ? + 0012 ???? C IPSAVE DW ? + 0014 ???? C CSSAVE DW ? + 0016 ???? C FSAVE DW ? + 0018 C STKPTRS ENDS + C + C ; Start of code +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-6 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0000 C CODE SEGMENT + C ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP + C + 0000 C ORG 0 + = 0000 C CODSTRT EQU $ + 0000 E9 0024 R C JMP DOSINIT + C + 0003 1B C ESCCHAR DB ESCCH ;Lead-in character for escape sequences + 0004 C ESCTAB: + C IF NOT IBM + 0004 53 C DB "S" ;Copy one char + 0005 56 C DB "V" ;Skip one char + 0006 54 C DB "T" ;Copy to char + 0007 57 C DB "W" ;Skip to char + 0008 55 C DB "U" ;Copy line + 0009 45 C DB "E" ;Kill line (no change in template) + 000A 4A C DB "J" ;Reedit line (new template) + 000B 44 C DB "D" ;Backspace + 000C 50 C DB "P" ;Enter insert mode + 000D 51 C DB "Q" ;Exit insert mode + 000E 52 C DB "R" ;Escape character + 000F 52 C DB "R" ;End of table + C ENDIF + C ENDIF + C + = 000C C ESCTABLEN EQU $-ESCTAB + C IF NOT IBM + 0010 0D 0A 4D 53 2D 44 C HEADER DB 13,10,"MS-DOS version 1.25" + 4F 53 20 76 65 72 C + 73 69 6F 6E 20 31 C + 2E 32 35 C + C ENDIF + C ENDIF + C + 0025 0D 0A C DB 13,10 + 0027 43 6F 70 79 72 69 C DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$" + 67 68 74 20 31 39 C + 38 31 2C 38 32 20 C + 4D 69 63 72 6F 73 C + 6F 66 74 2C 20 49 C + 6E 63 2E 0D 0A 24 C + C ENDIF + C + 004B C QUIT: + 004B B4 00 C MOV AH,0 + 004D EB 1E C JMP SHORT SAVREGS + C + 004F C COMMAND: ;Interrupt call entry point + 004F 80 FC 2E C CMP AH,MAXCOM + 0052 76 19 C JBE SAVREGS + 0054 C BADCALL: + 0054 B0 00 C MOV AL,0 + 0056 CF C IRET: IRET + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-7 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0057 C ENTRY: ;System call entry point and dispatcher + 0057 58 C POP AX ;IP from the long call at 5 + 0058 58 C POP AX ;Segment from the long call at 5 + 0059 2E: 8F 06 0131 R C POP CS:[TEMP] ;IP from the CALL 5 + 005E 9C C PUSHF ;Start re-ordering the stack + 005F FA C CLI + 0060 50 C PUSH AX ;Save segment + 0061 2E: FF 36 0131 R C PUSH CS:[TEMP] ;Stack now ordered as if INT had been used + 0066 80 F9 24 C CMP CL,MAXCALL ;This entry point doesn't get as many calls + 0069 77 E9 C JA BADCALL + 006B 8A E1 C MOV AH,CL + 006D C SAVREGS: + 006D 06 C PUSH ES + 006E 1E C PUSH DS + 006F 55 C PUSH BP + 0070 57 C PUSH DI + 0071 56 C PUSH SI + 0072 52 C PUSH DX + 0073 51 C PUSH CX + 0074 53 C PUSH BX + 0075 50 C PUSH AX + C + C ENDIF + C + 0076 2E: 89 26 0131 R C MOV CS:[SPSAVE],SP + 007B 2E: 8C 16 0133 R C MOV CS:[SSSAVE],SS + 0080 8C CC C MOV SP,CS + 0082 8E D4 C MOV SS,SP + 0084 C REDISP: + 0084 BC 01DE R C MOV SP,OFFSET DOSGROUP:IOSTACK + 0087 FB C STI ;Stack OK now + 0088 8A DC C MOV BL,AH + 008A B7 00 C MOV BH,0 + 008C D1 E3 C SHL BX,1 + 008E FC C CLD + 008F 80 FC 0C C CMP AH,12 + 0092 7E 03 C JLE SAMSTK + 0094 BC 025E R C MOV SP,OFFSET DOSGROUP:DSKSTACK + 0097 C SAMSTK: + 0097 2E: FF 97 00B6 R C CALL CS:[BX+DISPATCH] + 009C C LEAVE: + 009C FA C CLI + 009D 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] + 00A2 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 00A7 8B EC C MOV BP,SP + 00A9 88 46 00 C MOV BYTE PTR [BP.AXSAVE],AL + C + C ENDIF + C + 00AC 58 C POP AX + 00AD 5B C POP BX + 00AE 59 C POP CX + 00AF 5A C POP DX + 00B0 5E C POP SI + 00B1 5F C POP DI +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-8 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 00B2 5D C POP BP + 00B3 1F C POP DS + 00B4 07 C POP ES + 00B5 CF C IRET + C ; Standard Functions + 00B6 06B1 R C DISPATCH DW ABORT ;0 + 00B8 1253 R C DW CONIN + 00BA 119D R C DW CONOUT + 00BC 0141 R C DW READER + 00BE 014A R C DW PUNCH + 00C0 128B R C DW LIST ;5 + 00C2 1262 R C DW RAWIO + 00C4 127F R C DW RAWINP + 00C6 125C R C DW IN + 00C8 1298 R C DW PRTBUF + 00CA 0FBD R C DW BUFIN ;10 + 00CC 1249 R C DW CONSTAT + 00CE 011E R C DW FLUSHKB + 00D0 0F64 R C DW DSKRESET + 00D2 0FAF R C DW SELDSK + 00D4 03CD R C DW OPEN ;15 + 00D6 04BB R C DW CLOSE + 00D8 0E50 R C DW SRCHFRST + 00DA 0EB3 R C DW SRCHNXT + 00DC 029B R C DW DELETE + 00DE 06F6 R C DW SEQRD ;20 + 00E0 06FE R C DW SEQWRT + 00E2 056D R C DW CREATE + 00E4 02F3 R C DW RENAME + 00E6 0114 R C DW INUSE + 00E8 0F97 R C DW GETDRV ;25 + 00EA 0F12 R C DW SETDMA + 00EC 0F20 R C DW GETFATPT + 00EE 0F22 R C DW GETFATPTDL + 00F0 0114 R C DW GETRDONLY + 00F2 0114 R C DW SETATTRIB ;30 + 00F4 0F4E R C DW GETDSKPT + 00F6 0114 R C DW USERCODE + 00F8 070E R C DW RNDRD + 00FA 0716 R C DW RNDWRT + 00FC 0ED2 R C DW FILESIZE ;35 + 00FE 0F9C R C DW SETRNDREC + C ; Extended Functions + 0100 1396 R C DW SETVECT + 0102 13A8 R C DW NEWBASE + 0104 071E R C DW BLKRD + 0106 0726 R C DW BLKWRT ;40 + 0108 12AF R C DW MAKEFCB + 010A 14A6 R C DW GETDATE + 010C 14C4 R C DW SETDATE + 010E 1546 R C DW GETTIME + 0110 1558 R C DW SETTIME ;45 + 0112 0117 R C DW VERIFY + C + 0114 C INUSE: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-9 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0114 C GETIO: + 0114 C SETIO: + 0114 C GETRDONLY: + 0114 C SETATTRIB: + 0114 C USERCODE: + 0114 B0 00 C MOV AL,0 + 0116 C3 C RET + C + 0117 C VERIFY: + 0117 24 01 C AND AL,1 + 0119 2E: A2 002E R C MOV CS:VERFLG,AL + 011D C3 C RET + C + 011E C FLUSHKB: + 011E 50 C PUSH AX + 011F 9A 0027 ---- R C CALL FAR PTR BIOSFLUSH + 0124 58 C POP AX + 0125 8A E0 C MOV AH,AL + 0127 3C 01 C CMP AL,1 + 0129 74 13 C JZ REDISPJ + 012B 3C 06 C CMP AL,6 + 012D 74 0F C JZ REDISPJ + 012F 3C 07 C CMP AL,7 + 0131 74 0B C JZ REDISPJ + 0133 3C 08 C CMP AL,8 + 0135 74 07 C JZ REDISPJ + 0137 3C 0A C CMP AL,10 + 0139 74 03 C JZ REDISPJ + 013B B0 00 C MOV AL,0 + 013D C3 C RET + C + 013E E9 0084 R C REDISPJ:JMP REDISP + C + 0141 C READER: + 0141 C AUXIN: + 0141 E8 11C4 R C CALL STATCHK + 0144 9A 000F ---- R C CALL FAR PTR BIOSAUXIN + 0149 C3 C RET + C + 014A C PUNCH: + 014A 8A C2 C MOV AL,DL + 014C C AUXOUT: + 014C 50 C PUSH AX + 014D E8 11C4 R C CALL STATCHK + 0150 58 C POP AX + 0151 9A 0012 ---- R C CALL FAR PTR BIOSAUXOUT + 0156 C3 C RET + C + C + 0157 C UNPACK: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster number + C ; BP = Base of drive parameters +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-10 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; SI = Pointer to drive FAT + C ; Outputs: + C ; DI = Contents of FAT for given cluster + C ; Zero set means DI=0 (free cluster) + C ; No other registers affected. Fatal error if cluster too big. + C + 0157 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 015A 77 18 C JA HURTFAT + 015C 8D 38 C LEA DI,[SI+BX] + 015E D1 EB C SHR BX,1 + 0160 8B 39 C MOV DI,[DI+BX] + 0162 73 09 C JNC HAVCLUS + 0164 D1 EF C SHR DI,1 + 0166 D1 EF C SHR DI,1 + 0168 D1 EF C SHR DI,1 + 016A D1 EF C SHR DI,1 + 016C F9 C STC + 016D C HAVCLUS: + 016D D1 D3 C RCL BX,1 + 016F 81 E7 0FFF C AND DI,0FFFH + 0173 C3 C RET + 0174 C HURTFAT: + 0174 50 C PUSH AX + 0175 B4 80 C MOV AH,80H ;Signal Bad FAT to INT 24H handler + 0177 BF 0FFF C MOV DI,0FFFH ;In case INT 24H returns (it shouldn't) + 017A E8 0639 R C CALL FATAL + 017D 58 C POP AX ;Try to ignore bad FAT + 017E C3 C RET + C + C + 017F C PACK: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster number + C ; DX = Data + C ; SI = Pointer to drive FAT + C ; Outputs: + C ; The data is stored in the FAT at the given cluster. + C ; BX,DX,DI all destroyed + C ; No other registers affected + C + 017F 8B FB C MOV DI,BX + 0181 D1 EB C SHR BX,1 + 0183 03 DE C ADD BX,SI + 0185 03 DF C ADD BX,DI + 0187 D1 EF C SHR DI,1 + 0189 8B 3F C MOV DI,[BX] + 018B 73 0E C JNC ALIGNED + 018D D1 E2 C SHL DX,1 + 018F D1 E2 C SHL DX,1 + 0191 D1 E2 C SHL DX,1 + 0193 D1 E2 C SHL DX,1 + 0195 81 E7 000F C AND DI,0FH + 0199 EB 04 C JMP SHORT PACKIN +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-11 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 019B C ALIGNED: + 019B 81 E7 F000 C AND DI,0F000H + 019F C PACKIN: + 019F 0B FA C OR DI,DX + 01A1 89 3F C MOV [BX],DI + 01A3 C3 C RET + C + 01A4 C DEVNAME: + 01A4 BE 0000 R C MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names + 01A7 B7 05 C MOV BH,NUMDEV ;BH = number of device names + 01A9 C LOOKIO: + 01A9 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 01AC B9 0004 C MOV CX,4 ;All devices are 4 letters + 01AF F3/ A6 C REPE CMPSB ;Check for name in list + 01B1 74 08 C JZ IOCHK ;If first 3 letters OK, check for the rest + 01B3 03 F1 C ADD SI,CX ;Point to next device name + 01B5 FE CF C DEC BH + 01B7 75 F0 C JNZ LOOKIO + 01B9 C CRET: + 01B9 F9 C STC ;Not found + 01BA C3 C RET + C + 01BB C IOCHK: + C ENDIF + 01BB F6 DF C NEG BH + 01BD B9 0002 C MOV CX,2 ;Check rest of name but not extension + 01C0 B8 2020 C MOV AX,2020H + 01C3 F3/ AF C REPE SCASW ;Make sure rest of name is blanks + 01C5 75 F2 C JNZ CRET + 01C7 C3 C RET1: RET ;Zero set so CREATE works + C + 01C8 C GETFILE: + C ; Same as GETNAME except ES:DI points to FCB on successful return + 01C8 E8 0372 R C CALL MOVNAME + 01CB 72 FA C JC RET1 + 01CD 52 C PUSH DX + 01CE 1E C PUSH DS + 01CF E8 01DA R C CALL FINDNAME + 01D2 07 C POP ES + 01D3 5F C POP DI + 01D4 C3 C RET2: RET + C + C + 01D5 C GETNAME: + C + C ; Inputs: + C ; DS,DX point to FCB + C ; Function: + C ; Find file name in disk directory. First byte is + C ; drive number (0=current disk). "?" matches any + C ; character. + C ; Outputs: + C ; Carry set if file not found + C ; ELSE + C ; Zero set if attributes match (always except when creating) +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-12 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; BP = Base of drive parameters + C ; DS = CS + C ; ES = CS + C ; BX = Pointer into directory buffer + C ; SI = Pointer to First Cluster field in directory entry + C ; [DIRBUF] has directory record with match + C ; [NAME1] has file name + C ; All other registers destroyed. + C + 01D5 E8 0372 R C CALL MOVNAME + 01D8 72 FA C JC RET2 ;Bad file name? + 01DA C FINDNAME: + 01DA 8C C8 C MOV AX,CS + 01DC 8E D8 C MOV DS,AX + 01DE E8 01A4 R C CALL DEVNAME + 01E1 73 F1 C JNC RET2 + 01E3 E8 0423 R C CALL STARTSRCH + 01E6 C CONTSRCH: + 01E6 E8 023E R C CALL GETENTRY + 01E9 72 E9 C JC RET2 + 01EB C SRCH: + 01EB 8A 27 C MOV AH,BYTE PTR [BX] + 01ED 0A E4 C OR AH,AH ;End of directory? + 01EF 74 1E C JZ FREE + 01F1 3A 26 0130 R C CMP AH,[DELALL] ;Free entry? + 01F5 74 18 C JZ FREE + 01F7 8B F3 C MOV SI,BX + 01F9 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 01FC B9 000B C MOV CX,11 + 01FF C WILDCRD: + 01FF F3/ A6 C REPE CMPSB + 0201 74 23 C JZ FOUND + 0203 80 7D FF 3F C CMP BYTE PTR [DI-1],"?" + 0207 74 F6 C JZ WILDCRD + 0209 C NEXTENT: + 0209 E8 0275 R C CALL NEXTENTRY + 020C 73 DD C JNC SRCH + 020E C3 C RET3: RET + C + 020F C FREE: + 020F 83 3E 015C R FF C CMP [ENTFREE],-1 ;Found a free entry before? + 0214 75 08 C JNZ TSTALL ;If so, ignore this one + 0216 8B 0E 0103 R C MOV CX,[LASTENT] + 021A 89 0E 015C R C MOV [ENTFREE],CX + 021E C TSTALL: + 021E 3A 26 0130 R C CMP AH,[DELALL] ;At end of directory? + 0222 74 E5 C JZ NEXTENT ;No - continue search + 0224 F9 C STC ;Report not found + 0225 C3 C RET + C + 0226 C FOUND: + C ;Check if attributes allow finding it + 0226 8A 26 0116 R C MOV AH,[ATTRIB] ;Attributes of search + 022A F6 D4 C NOT AH + 022C 22 24 C AND AH,[SI] ;Compare with attributes of file +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-13 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 022E 83 C6 0F C ADD SI,15 + 0231 80 E4 06 C AND AH,6 ;Only look at bits 1 and 2 + 0234 74 D8 C JZ RET3 + 0236 F6 06 012F R FF C TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating + 023B 74 CC C JZ NEXTENT ;Otherwise continue searching + 023D C3 C RET + C + C + 023E C GETENTRY: + C + C ; Inputs: + C ; [LASTENT] has previously searched directory entry + C ; Function: + C ; Locates next sequential directory entry in preparation for search + C ; Outputs: + C ; Carry set if none + C ; ELSE + C ; AL = Current directory block + C ; BX = Pointer to next directory entry in [DIRBUF] + C ; DX = Pointer to first byte after end of DIRBUF + C ; [LASTENT] = New directory entry number + C + 023E A1 0103 R C MOV AX,[LASTENT] + 0241 40 C INC AX ;Start with next entry + 0242 3B 46 09 C CMP AX,[BP.MAXENT] + 0245 73 4F C JAE NONE + 0247 C GETENT: + 0247 A3 0103 R C MOV [LASTENT],AX + 024A B1 04 C MOV CL,4 + 024C D3 E0 C SHL AX,CL + 024E 33 D2 C XOR DX,DX + 0250 D1 E0 C SHL AX,1 + 0252 D1 D2 C RCL DX,1 ;Account for overflow in last shift + 0254 8B 5E 02 C MOV BX,[BP.SECSIZ] + 0257 80 E3 E0 C AND BL,255-31 ;Must be multiple of 32 + 025A F7 F3 C DIV BX + 025C 8B DA C MOV BX,DX ;Position within sector + 025E 8A 66 00 C MOV AH,[BP.DEVNUM] ;AL=Directory sector no. + 0261 3B 06 0041 R C CMP AX,[DIRBUFID] + 0265 74 05 C JZ HAVDIRBUF + 0267 53 C PUSH BX + 0268 E8 05E8 R C CALL DIRREAD + 026B 5B C POP BX + 026C C HAVDIRBUF: + 026C BA 025E R C MOV DX,OFFSET DOSGROUP:DIRBUF + 026F 03 DA C ADD BX,DX + 0271 03 56 02 C ADD DX,[BP.SECSIZ] + 0274 C3 C RET + C + 0275 C NEXTENTRY: + C + C ; Inputs: + C ; Same as outputs of GETENTRY, above + C ; Function: + C ; Update AL, BX, and [LASTENT] for next directory entry. +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-14 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; Carry set if no more. + C + 0275 8B 3E 0103 R C MOV DI,[LASTENT] + 0279 47 C INC DI + 027A 3B 7E 09 C CMP DI,[BP.MAXENT] + 027D 73 17 C JAE NONE + 027F 89 3E 0103 R C MOV [LASTENT],DI + 0283 83 C3 20 C ADD BX,32 + 0286 3B DA C CMP BX,DX + 0288 72 0A C JB HAVIT + 028A FE C0 C INC AL ;Next directory sector + 028C 52 C PUSH DX ;Save limit + 028D E8 05E8 R C CALL DIRREAD + 0290 5A C POP DX + 0291 BB 025E R C MOV BX,OFFSET DOSGROUP:DIRBUF + 0294 C HAVIT: + 0294 F8 C CLC + 0295 C3 C RET + C + 0296 C NONE: + 0296 E8 067A R C CALL CHKDIRWRITE + 0299 F9 C STC + 029A C3 C RET4: RET + C + C + 029B C DELETE: ; System call 19 + 029B E8 0372 R C CALL MOVNAME + 029E B0 FF C MOV AL,-1 + 02A0 72 F8 C JC RET4 + 02A2 2E: A0 0116 R C MOV AL,CS:[ATTRIB] + 02A6 24 06 C AND AL,6 ;Look only at hidden bits + 02A8 3C 06 C CMP AL,6 ;Both must be set + 02AA 75 12 C JNZ NOTALL + 02AC B9 000B C MOV CX,11 + 02AF B0 3F C MOV AL,"?" + 02B1 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 02B4 F3/ AE C REPE SCASB ;See if name is *.* + 02B6 75 06 C JNZ NOTALL + 02B8 2E: C6 06 0130 R 00 C MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all + 02BE C NOTALL: + 02BE E8 01DA R C CALL FINDNAME + 02C1 B0 FF C MOV AL,-1 + 02C3 72 D5 C JC RET4 + 02C5 0A FF C OR BH,BH ;Check if device name + 02C7 78 D1 C JS RET4 ;Can't delete I/O devices + 02C9 C DELFILE: + 02C9 C6 06 002B R FF C MOV BYTE PTR [DIRTYDIR],-1 + 02CE 8A 26 0130 R C MOV AH,[DELALL] + 02D2 88 27 C MOV BYTE PTR [BX],AH + 02D4 8B 1C C MOV BX,[SI] + 02D6 8B 76 12 C MOV SI,[BP.FAT] + 02D9 0B DB C OR BX,BX + 02DB 74 08 C JZ DELNXT + 02DD 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 02E0 77 03 C JA DELNXT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-15 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 02E2 E8 0E2F R C CALL RELEASE + 02E5 C DELNXT: + 02E5 E8 01E6 R C CALL CONTSRCH + 02E8 73 DF C JNC DELFILE + 02EA E8 052C R C CALL FATWRT + 02ED E8 067A R C CALL CHKDIRWRITE + 02F0 32 C0 C XOR AL,AL + 02F2 C3 C RET + C + C + 02F3 C RENAME: ;System call 23 + 02F3 E8 0372 R C CALL MOVNAME + 02F6 72 77 C JC ERRET + 02F8 83 C6 05 C ADD SI,5 + 02FB BF 0117 R C MOV DI,OFFSET DOSGROUP:NAME2 + 02FE E8 039F R C CALL LODNAME + 0301 72 6C C JC ERRET ;Report error if second name invalid + 0303 E8 01DA R C CALL FINDNAME + 0306 72 67 C JC ERRET + 0308 0A FF C OR BH,BH ;Check if I/O device name + 030A 78 63 C JS ERRET ;If so, can't rename it + 030C BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 030F BF 0122 R C MOV DI,OFFSET DOSGROUP:NAME3 + 0312 B9 0006 C MOV CX,6 ;6 words (12 bytes)--include attribute byte + 0315 F3/ A5 C REP MOVSW ;Copy name to search for + 0317 C RENFIL: + 0317 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 031A BE 0117 R C MOV SI,OFFSET DOSGROUP:NAME2 + 031D B9 000B C MOV CX,11 + 0320 C NEWNAM: + 0320 AC C LODSB + 0321 3C 3F C CMP AL,"?" + 0323 75 02 C JNZ NOCHG + 0325 8A 07 C MOV AL,[BX] + 0327 C NOCHG: + 0327 AA C STOSB + 0328 43 C INC BX + 0329 E2 F5 C LOOP NEWNAM + 032B C6 05 06 C MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes + 032E E8 01A4 R C CALL DEVNAME ;Check if giving it a device name + 0331 73 39 C JNC RENERR + 0333 FF 36 0103 R C PUSH [LASTENT] ;Save position of match + 0337 C7 06 0103 R FFFF C MOV [LASTENT],-1 ;Search entire directory for duplicate + 033D E8 01E6 R C CALL CONTSRCH ;See if new name already exists + 0340 58 C POP AX + 0341 73 29 C JNC RENERR ;Error if found + 0343 E8 0247 R C CALL GETENT ;Re-read matching entry + 0346 8B FB C MOV DI,BX + 0348 BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 034B B9 0005 C MOV CX,5 + 034E A4 C MOVSB + 034F F3/ A5 C REP MOVSW ;Replace old name with new one + 0351 C6 06 002B R FF C MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory + 0356 BE 0122 R C MOV SI,OFFSET DOSGROUP:NAME3 + 0359 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-16 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 035C B9 0006 C MOV CX,6 ;Include attribute byte + 035F F3/ A5 C REP MOVSW ;Copy name back into search buffer + 0361 E8 01E6 R C CALL CONTSRCH + 0364 73 B1 C JNC RENFIL + 0366 E8 067A R C CALL CHKDIRWRITE + 0369 32 C0 C XOR AL,AL + 036B C3 C RET + C + 036C C RENERR: + 036C E8 067A R C CALL CHKDIRWRITE + 036F C ERRET: + 036F B0 FF C MOV AL,-1 + 0371 C3 C RET5: RET + C + C + 0372 C MOVNAME: + C + C ; Inputs: + C ; DS, DX point to FCB or extended FCB + C ; Outputs: + C ; DS:DX point to normal FCB + C ; ES = CS + C ; If file name OK: + C ; BP has base of driver parameters + C ; [NAME1] has name in upper case + C ; All registers except DX destroyed + C ; Carry set if bad file name or drive + C + 0372 2E: C7 06 012F R E500 C MOV CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.* + 0379 8C C8 C MOV AX,CS + 037B 8E C0 C MOV ES,AX + 037D BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 0380 8B F2 C MOV SI,DX + 0382 AC C LODSB + 0383 2E: A2 012E R C MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use + 0387 B4 00 C MOV AH,0 ;Set default attributes + 0389 3C FF C CMP AL,-1 ;Is it an extended FCB? + 038B 75 0A C JNZ HAVATTRB + 038D 83 C2 07 C ADD DX,7 ;Adjust to point to normal FCB + 0390 83 C6 06 C ADD SI,6 ;Point to drive select byte + 0393 8A 64 FF C MOV AH,[SI-1] ;Get attribute byte + 0396 AC C LODSB ;Get drive select byte + 0397 C HAVATTRB: + 0397 2E: 88 26 0116 R C MOV CS:[ATTRIB],AH ;Save attributes + 039C E8 03B9 R C CALL GETTHISDRV + 039F C LODNAME: + C ; This entry point copies a file name from DS,SI + C ; to ES,DI converting to upper case. + 039F 80 3C 20 C CMP BYTE PTR [SI]," " ;Don't allow blank as first letter + 03A2 F9 C STC ;In case of error + 03A3 74 CC C JZ RET5 + 03A5 B9 000B C MOV CX,11 + 03A8 C MOVCHK: + 03A8 E8 135A R C CALL GETLET + 03AB 72 C4 C JB RET5 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-17 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 03AD 75 05 C JNZ STOLET ;Is it a delimiter? + 03AF 3C 20 C CMP AL," " ;This is the only delimiter allowed + 03B1 F9 C STC ;In case of error + 03B2 75 BD C JNZ RET5 + 03B4 C STOLET: + 03B4 AA C STOSB + 03B5 E2 F1 C LOOP MOVCHK + 03B7 F8 C CLC ;Got through whole name - no error + 03B8 C3 C RET6: RET + C + 03B9 C GETTHISDRV: + 03B9 2E: 38 06 002C R C CMP CS:[NUMDRV],AL + 03BE 72 F8 C JC RET6 + 03C0 FE C8 C DEC AL + 03C2 79 04 C JNS PHYDRV + 03C4 2E: A0 004A R C MOV AL,CS:[CURDRV] + 03C8 C PHYDRV: + 03C8 2E: A2 013C R C MOV CS:[THISDRV],AL + 03CC C3 C RET + C + C + 03CD C OPEN: ;System call 15 + 03CD E8 01C8 R C CALL GETFILE + 03D0 C DOOPEN: + C ; Enter here to perform OPEN on file already found + C ; in directory. DS=CS, BX points to directory + C ; entry in DIRBUF, SI points to First Cluster field, and + C ; ES:DI point to the FCB to be opened. This entry point + C ; is used by CREATE. + 03D0 72 9D C JC ERRET + 03D2 0A FF C OR BH,BH ;Check if file is I/O device + 03D4 78 29 C JS OPENDEV ;Special handler if so + 03D6 A0 013C R C MOV AL,[THISDRV] + 03D9 40 C INC AX + 03DA AA C STOSB + 03DB 33 C0 C XOR AX,AX + C ENDIF + C IF NOT ZEROEXT + 03DD 83 C7 0C C ADD DI,12 ;Point to high half of CURRENT BLOCK field + 03E0 AA C STOSB ;Set it to zero (CP/M programs set low byte) + C ENDIF + 03E1 B0 80 C MOV AL,128 ;Default record size + 03E3 AB C STOSW ;Set record size + 03E4 AD C LODSW ;Get starting cluster + 03E5 8B D0 C MOV DX,AX ;Save it for the moment + 03E7 A5 C MOVSW ;Transfer size to FCB + 03E8 A5 C MOVSW + 03E9 8B 44 F8 C MOV AX,[SI-8] ;Get date + 03EC AB C STOSW ;Save date in FCB + 03ED 8B 44 F6 C MOV AX,[SI-10] ;Get time + 03F0 AB C STOSW ;Save it in FCB + 03F1 8A 46 00 C MOV AL,[BP.DEVNUM] + 03F4 0C 40 C OR AL,40H + 03F6 AA C STOSB + 03F7 8B C2 C MOV AX,DX ;Restore starting cluster +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-18 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 03F9 AB C STOSW ; first cluster + 03FA AB C STOSW ; last cluster accessed + 03FB 33 C0 C XOR AX,AX + 03FD AB C STOSW ; position of last cluster + 03FE C3 C RET + C + C + 03FF C OPENDEV: + 03FF 83 C7 0D C ADD DI,13 ;point to 2nd half of extent field + 0402 33 C0 C XOR AX,AX + 0404 AA C STOSB ;Set it to zero + 0405 B0 80 C MOV AL,128 + 0407 AB C STOSW ;Set record size to 128 + 0408 33 C0 C XOR AX,AX + 040A AB C STOSW + 040B AB C STOSW ;Set current size to zero + 040C E8 1400 R C CALL DATE16 + 040F AB C STOSW ;Date is todays + 0410 92 C XCHG AX,DX + 0411 AB C STOSW ;Use current time + 0412 8A C7 C MOV AL,BH ;Get device number + 0414 AA C STOSB + 0415 32 C0 C XOR AL,AL ;No error + 0417 C3 C RET + 0418 C FATERR: + 0418 97 C XCHG AX,DI ;Put error code in DI + 0419 B4 02 C MOV AH,2 ;While trying to read FAT + 041B A0 013C R C MOV AL,[THISDRV] ;Tell which drive + 041E E8 063C R C CALL FATAL1 + 0421 EB 09 C JMP SHORT FATREAD + 0423 C STARTSRCH: + 0423 B8 FFFF C MOV AX,-1 + 0426 A3 0103 R C MOV [LASTENT],AX + 0429 A3 015C R C MOV [ENTFREE],AX + 042C C FATREAD: + C + C ; Inputs: + C ; DS = CS + C ; Function: + C ; If disk may have been changed, FAT is read in and buffers are + C ; flagged invalid. If not, no action is taken. + C ; Outputs: + C ; BP = Base of drive parameters + C ; Carry set if invalid drive returned by MAPDEV + C ; All other registers destroyed + C + 042C A0 013C R C MOV AL,[THISDRV] + 042F 32 E4 C XOR AH,AH ;Set default response to zero & clear carry + 0431 9A 001B ---- R C CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say + 0436 72 E0 C JC FATERR + 0438 E8 0492 R C CALL GETBP + 043B A0 013C R C MOV AL,[THISDRV] ;Use physical unit number + 043E 8B 76 12 C MOV SI,[BP.FAT] + 0441 0A 64 FF C OR AH,[SI-1] ;Dirty byte for FAT + 0444 78 0A C JS NEWDSK ;If either say new disk, then it's so +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-19 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0446 75 47 C JNZ MAPDRV + 0448 B4 01 C MOV AH,1 + 044A 3B 06 003D R C CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive? + 044E 74 3F C JZ MAPDRV + 0450 C NEWDSK: + 0450 3A 06 003D R C CMP AL,[BUFDRVNO] ;See if buffer is for this drive + 0454 75 0C C JNZ BUFOK ;If not, don't touch it + 0456 C7 06 003B R 0000 C MOV [BUFSECNO],0 ;Flag buffers invalid + 045C C7 06 003D R 00FF C MOV WORD PTR [BUFDRVNO],00FFH + 0462 C BUFOK: + 0462 C7 06 0041 R FFFF C MOV [DIRBUFID],-1 + 0468 E8 0551 R C CALL FIGFAT + 046B C NEXTFAT: + 046B 50 C PUSH AX + 046C E8 0669 R C CALL DSKREAD + 046F 58 C POP AX + 0470 72 36 C JC BADFAT + 0472 2A 46 08 C SUB AL,[BP.FATCNT] + 0475 74 03 C JZ NEWFAT + 0477 E8 052C R C CALL FATWRT + 047A C NEWFAT: + 047A 8B 76 12 C MOV SI,[BP.FAT] + 047D 8A 46 00 C MOV AL,[BP.DEVNUM] + 0480 8A 24 C MOV AH,[SI] ;Get first byte of FAT + 0482 80 CC F8 C OR AH,0F8H ;Put in range + 0485 9A 002A ---- R C CALL FAR PTR BIOSMAPDEV + 048A B4 00 C MOV AH,0 + 048C 89 44 FE C MOV [SI-2],AX ;Set device no. and reset dirty bit + 048F C MAPDRV: + 048F 8A 44 FE C MOV AL,[SI-2] ;Get device number + 0492 C GETBP: + 0492 8B 2E 004B R C MOV BP,[DRVTAB] ;Just in case drive isn't valid + 0496 24 3F C AND AL,3FH ;Mask out dirty bit + 0498 3A 06 002D R C CMP AL,[NUMIO] + 049C F5 C CMC + 049D 72 08 C JC RET7 + 049F 50 C PUSH AX + 04A0 B4 14 C MOV AH,DPBSIZ + 04A2 F6 E4 C MUL AH + 04A4 03 E8 C ADD BP,AX + 04A6 58 C POP AX + 04A7 C3 C RET7: RET + C + 04A8 C BADFAT: + 04A8 8B CF C MOV CX,DI + 04AA 03 D1 C ADD DX,CX + 04AC FE C8 C DEC AL + 04AE 75 BB C JNZ NEXTFAT + 04B0 E8 0551 R C CALL FIGFAT ;Reset registers + 04B3 E8 05FC R C CALL DREAD ;Try first FAT once more + 04B6 EB C2 C JMP SHORT NEWFAT + C + 04B8 C OKRET1: + 04B8 B0 00 C MOV AL,0 + 04BA C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-20 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 04BB C CLOSE: ;System call 16 + 04BB 8B FA C MOV DI,DX + 04BD 80 3D FF C CMP BYTE PTR [DI],-1 ;Check for extended FCB + 04C0 75 03 C JNZ NORMFCB3 + 04C2 83 C7 07 C ADD DI,7 + 04C5 C NORMFCB3: + 04C5 F6 45 18 C0 C TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files + 04C9 75 ED C JNZ OKRET1 ;can't close if I/O device, or not writen + 04CB 8A 05 C MOV AL,[DI] ;Get physical unit number + 04CD FE C8 C DEC AL ;Make zero = drive A + 04CF B4 01 C MOV AH,1 ;Look for dirty buffer + 04D1 2E: 3B 06 003D R C CMP AX,CS:WORD PTR [BUFDRVNO] + 04D6 75 1D C JNZ FNDDIR + C ;Write back dirty buffer if on same drive + 04D8 52 C PUSH DX + 04D9 1E C PUSH DS + 04DA 0E C PUSH CS + 04DB 1F C POP DS + 04DC C6 06 003E R 00 C MOV BYTE PTR [DIRTYBUF],0 + 04E1 8B 1E 0039 R C MOV BX,[BUFFER] + 04E5 B9 0001 C MOV CX,1 + 04E8 8B 16 003B R C MOV DX,[BUFSECNO] + 04EC 8B 2E 003F R C MOV BP,[BUFDRVBP] + 04F0 E8 068C R C CALL DWRITE + 04F3 1F C POP DS + 04F4 5A C POP DX + 04F5 C FNDDIR: + 04F5 E8 01C8 R C CALL GETFILE + 04F8 C BADCLOSEJ: + 04F8 72 4D C JC BADCLOSE + 04FA 26: 8B 4D 19 C MOV CX,ES:[DI.FIRCLUS] + 04FE 89 0C C MOV [SI],CX + 0500 26: 8B 55 10 C MOV DX,ES:WORD PTR [DI.FILSIZ] + 0504 89 54 02 C MOV [SI+2],DX + 0507 26: 8B 55 12 C MOV DX,ES:WORD PTR [DI.FILSIZ+2] + 050B 89 54 04 C MOV [SI+4],DX + 050E 26: 8B 55 14 C MOV DX,ES:[DI.FDATE] + 0512 89 54 FE C MOV [SI-2],DX + 0515 26: 8B 55 16 C MOV DX,ES:[DI.FTIME] + 0519 89 54 FC C MOV [SI-4],DX + 051C E8 0681 R C CALL DIRWRITE + C + 051F C CHKFATWRT: + C ; Do FATWRT only if FAT is dirty and uses same I/O driver + 051F 8B 76 12 C MOV SI,[BP.FAT] + 0522 8A 46 00 C MOV AL,[BP.DEVNUM] + 0525 B4 01 C MOV AH,1 + 0527 39 44 FE C CMP [SI-2],AX ;See if FAT dirty and uses same driver + 052A 75 18 C JNZ OKRET + C + 052C C FATWRT: + C + C ; Inputs: + C ; DS = CS +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-21 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; BP = Base of drive parameter table + C ; Function: + C ; Write the FAT back to disk and reset FAT + C ; dirty bit. + C ; Outputs: + C ; AL = 0 + C ; BP unchanged + C ; All other registers destroyed + C + 052C E8 0551 R C CALL FIGFAT + 052F C6 47 FF 00 C MOV BYTE PTR [BX-1],0 + 0533 C EACHFAT: + 0533 52 C PUSH DX + 0534 51 C PUSH CX + 0535 53 C PUSH BX + 0536 50 C PUSH AX + 0537 E8 068C R C CALL DWRITE + 053A 58 C POP AX + 053B 5B C POP BX + 053C 59 C POP CX + 053D 5A C POP DX + 053E 03 D1 C ADD DX,CX + 0540 FE C8 C DEC AL + 0542 75 EF C JNZ EACHFAT + 0544 C OKRET: + 0544 B0 00 C MOV AL,0 + 0546 C3 C RET + C + 0547 C BADCLOSE: + 0547 8B 76 12 C MOV SI,[BP.FAT] + 054A C6 44 FF 00 C MOV BYTE PTR [SI-1],0 + 054E B0 FF C MOV AL,-1 + 0550 C3 C RET + C + C + 0551 C FIGFAT: + C ; Loads registers with values needed to read or + C ; write a FAT. + 0551 8A 46 08 C MOV AL,[BP.FATCNT] + 0554 8B 5E 12 C MOV BX,[BP.FAT] + 0557 8A 4E 0F C MOV CL,[BP.FATSIZ] ;No. of records occupied by FAT + 055A B5 00 C MOV CH,0 + 055C 8B 56 06 C MOV DX,[BP.FIRFAT] ;Record number of start of FATs + 055F C3 C RET + C + C + 0560 C DIRCOMP: + C ; Prepare registers for directory read or write + 0560 98 C CBW + 0561 03 46 10 C ADD AX,[BP.FIRDIR] + 0564 8B D0 C MOV DX,AX + 0566 BB 025E R C MOV BX,OFFSET DOSGROUP:DIRBUF + 0569 B9 0001 C MOV CX,1 + 056C C3 C RET + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-22 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 056D C CREATE: ;System call 22 + 056D E8 0372 R C CALL MOVNAME + 0570 72 28 C JC ERRET3 + 0572 BF 010B R C MOV DI,OFFSET DOSGROUP:NAME1 + 0575 B9 000B C MOV CX,11 + 0578 B0 3F C MOV AL,"?" + 057A F2/ AE C REPNE SCASB + 057C 74 1C C JZ ERRET3 + 057E 2E: C6 06 012F R FF C MOV CS:BYTE PTR [CREATING],-1 + 0584 52 C PUSH DX + 0585 1E C PUSH DS + 0586 E8 01DA R C CALL FINDNAME + 0589 73 12 C JNC EXISTENT + 058B A1 015C R C MOV AX,[ENTFREE] ;First free entry found in FINDNAME + 058E 3D FFFF C CMP AX,-1 + 0591 74 05 C JZ ERRPOP + 0593 E8 0247 R C CALL GETENT ;Point at that free entry + 0596 EB 21 C JMP SHORT FREESPOT + 0598 C ERRPOP: + 0598 1F C POP DS + 0599 5A C POP DX + 059A C ERRET3: + 059A B0 FF C MOV AL,-1 + 059C C3 C RET + C + 059D C EXISTENT: + 059D 75 F9 C JNZ ERRPOP ;Error if attributes don't match + 059F 0A FF C OR BH,BH ;Check if file is I/O device + 05A1 78 3F C JS OPENJMP ;If so, no action + 05A3 8B 0C C MOV CX,[SI] ;Get pointer to clusters + 05A5 E3 12 C JCXZ FREESPOT + 05A7 3B 4E 0D C CMP CX,[BP.MAXCLUS] + 05AA 77 0D C JA FREESPOT + 05AC 53 C PUSH BX + 05AD 8B D9 C MOV BX,CX + 05AF 8B 76 12 C MOV SI,[BP.FAT] + 05B2 E8 0E2F R C CALL RELEASE ;Free any data already allocated + 05B5 E8 052C R C CALL FATWRT + 05B8 5B C POP BX + 05B9 C FREESPOT: + 05B9 8B FB C MOV DI,BX + 05BB BE 010B R C MOV SI,OFFSET DOSGROUP:NAME1 + 05BE B9 0005 C MOV CX,5 + 05C1 A4 C MOVSB + 05C2 F3/ A5 C REP MOVSW + 05C4 A0 0116 R C MOV AL,[ATTRIB] + 05C7 AA C STOSB + 05C8 33 C0 C XOR AX,AX + 05CA B1 05 C MOV CL,5 + 05CC F3/ AB C REP STOSW + 05CE E8 1400 R C CALL DATE16 + 05D1 92 C XCHG AX,DX + 05D2 AB C STOSW + 05D3 92 C XCHG AX,DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-23 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 05D4 AB C STOSW + 05D5 33 C0 C XOR AX,AX + 05D7 57 C PUSH DI + 05D8 B1 06 C MOV CL,6 + 05DA C SMALLENT: + 05DA F3/ AA C REP STOSB + 05DC 53 C PUSH BX + 05DD E8 0681 R C CALL DIRWRITE + 05E0 5B C POP BX + 05E1 5E C POP SI + 05E2 C OPENJMP: + 05E2 F8 C CLC ;Clear carry so OPEN won't fail + 05E3 07 C POP ES + 05E4 5F C POP DI + 05E5 E9 03D0 R C JMP DOOPEN + C + C + 05E8 C DIRREAD: + C + C ; Inputs: + C ; DS = CS + C ; AL = Directory block number + C ; BP = Base of drive parameters + C ; Function: + C ; Read the directory block into DIRBUF. + C ; Outputs: + C ; AX,BP unchanged + C ; All other registers destroyed. + C + 05E8 50 C PUSH AX + 05E9 E8 067A R C CALL CHKDIRWRITE + 05EC 58 C POP AX + 05ED 50 C PUSH AX + 05EE 8A 66 00 C MOV AH,[BP.DEVNUM] + 05F1 A3 0041 R C MOV [DIRBUFID],AX + 05F4 E8 0560 R C CALL DIRCOMP + 05F7 E8 05FC R C CALL DREAD + 05FA 58 C POP AX + 05FB C3 C RET8: RET + C + C + 05FC C DREAD: + C + C ; Inputs: + C ; BX,DS = Transfer address + C ; CX = Number of sectors + C ; DX = Absolute record number + C ; BP = Base of drive parameters + C ; Function: + C ; Calls BIOS to perform disk read. If BIOS reports + C ; errors, will call HARDERR for further action. + C ; BP preserved. All other registers destroyed. + C + 05FC E8 0669 R C CALL DSKREAD + 05FF 73 FA C JNC RET8 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-24 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0601 2E: C6 06 013B R 00 C MOV CS:BYTE PTR [READOP],0 + 0607 E8 060F R C CALL HARDERR + 060A 3C 01 C CMP AL,1 ;Check for retry + 060C 74 EE C JZ DREAD + 060E C3 C RET ;Ignore otherwise + C + C + 060F C HARDERR: + C + C ;Hard disk error handler. Entry conditions: + C ; DS:BX = Original disk transfer address + C ; DX = Original logical sector number + C ; CX = Number of sectors to go (first one gave the error) + C ; AX = Hardware error code + C ; DI = Original sector transfer count + C ; BP = Base of drive parameters + C ; [READOP] = 0 for read, 1 for write + C + 060F 97 C XCHG AX,DI ;Error code in DI, count in AX + 0610 2B C1 C SUB AX,CX ;Number of sectors successfully transferred + 0612 03 D0 C ADD DX,AX ;First sector number to retry + 0614 52 C PUSH DX + 0615 F7 66 02 C MUL [BP.SECSIZ] ;Number of bytes transferred + 0618 5A C POP DX + 0619 03 D8 C ADD BX,AX ;First address for retry + 061B B4 00 C MOV AH,0 ;Flag disk section in error + 061D 3B 56 06 C CMP DX,[BP.FIRFAT] ;In reserved area? + 0620 72 10 C JB ERRINT + 0622 FE C4 C INC AH ;Flag for FAT + 0624 3B 56 10 C CMP DX,[BP.FIRDIR] ;In FAT? + 0627 72 09 C JB ERRINT + 0629 FE C4 C INC AH + 062B 3B 56 0B C CMP DX,[BP.FIRREC] ;In directory? + 062E 72 02 C JB ERRINT + 0630 FE C4 C INC AH ;Must be in data area + 0632 C ERRINT: + 0632 D0 E4 C SHL AH,1 ;Make room for read/write bit + 0634 2E: 0A 26 013B R C OR AH,CS:[READOP] + 0639 C FATAL: + 0639 8A 46 01 C MOV AL,[BP.DRVNUM] ;Get drive number + 063C C FATAL1: + 063C 55 C PUSH BP ;The only thing we preserve + 063D 2E: 89 26 0135 R C MOV CS:[CONTSTK],SP + 0642 FA C CLI ;Prepare to play with stack + 0643 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 0648 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] ;User stack pointer restored + 064D CD 24 C INT 24H ;Fatal error interrupt vector + 064F 2E: 89 26 0131 R C MOV CS:[SPSAVE],SP + 0654 2E: 8C 16 0133 R C MOV CS:[SSSAVE],SS + 0659 8C CC C MOV SP,CS + 065B 8E D4 C MOV SS,SP + 065D 2E: 8B 26 0135 R C MOV SP,CS:[CONTSTK] + 0662 FB C STI + 0663 5D C POP BP + 0664 3C 02 C CMP AL,2 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-25 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0666 74 61 C JZ ERROR + 0668 C3 C RET + C + 0669 C DSKREAD: + 0669 8A 46 00 C MOV AL,[BP.DEVNUM] + 066C 55 C PUSH BP + 066D 53 C PUSH BX + 066E 51 C PUSH CX + 066F 52 C PUSH DX + 0670 9A 0015 ---- R C CALL FAR PTR BIOSREAD + 0675 5A C POP DX + 0676 5F C POP DI + 0677 5B C POP BX + 0678 5D C POP BP + 0679 C3 C RET9: RET + C + C + 067A C CHKDIRWRITE: + 067A F6 06 002B R FF C TEST BYTE PTR [DIRTYDIR],-1 + 067F 74 F8 C JZ RET9 + C + 0681 C DIRWRITE: + C + C ; Inputs: + C ; DS = CS + C ; AL = Directory block number + C ; BP = Base of drive parameters + C ; Function: + C ; Write the directory block into DIRBUF. + C ; Outputs: + C ; BP unchanged + C ; All other registers destroyed. + C + 0681 C6 06 002B R 00 C MOV BYTE PTR [DIRTYDIR],0 + 0686 A0 0041 R C MOV AL,BYTE PTR [DIRBUFID] + 0689 E8 0560 R C CALL DIRCOMP + C + C + 068C C DWRITE: + C + C ; Inputs: + C ; BX,DS = Transfer address + C ; CX = Number of sectors + C ; DX = Absolute record number + C ; BP = Base of drive parameters + C ; Function: + C ; Calls BIOS to perform disk write. If BIOS reports + C ; errors, will call HARDERR for further action. + C ; BP preserved. All other registers destroyed. + C + 068C 8A 46 00 C MOV AL,[BP.DEVNUM] + 068F 2E: 8A 26 002E R C MOV AH,CS:VERFLG + 0694 55 C PUSH BP + 0695 53 C PUSH BX + 0696 51 C PUSH CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-26 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0697 52 C PUSH DX + 0698 9A 0018 ---- R C CALL FAR PTR BIOSWRITE + 069D 5A C POP DX + 069E 5F C POP DI + 069F 5B C POP BX + 06A0 5D C POP BP + 06A1 73 D6 C JNC RET9 + 06A3 2E: C6 06 013B R 01 C MOV CS:BYTE PTR [READOP],1 + 06A9 E8 060F R C CALL HARDERR + 06AC 3C 01 C CMP AL,1 ;Check for retry + 06AE 74 DC C JZ DWRITE + 06B0 C3 C RET + C + C + 06B1 C ABORT: + 06B1 2E: C5 36 0131 R C LDS SI,CS:DWORD PTR [SPSAVE] + 06B6 8E 5C 14 C MOV DS,[SI.CSSAVE] + 06B9 33 C0 C XOR AX,AX + 06BB 8E C0 C MOV ES,AX + 06BD BE 000A C MOV SI,SAVEXIT + 06C0 BF 0088 C MOV DI,EXIT + 06C3 A5 C MOVSW + 06C4 A5 C MOVSW + 06C5 A5 C MOVSW + 06C6 A5 C MOVSW + 06C7 A5 C MOVSW + 06C8 A5 C MOVSW + 06C9 C ERROR: + 06C9 8C C8 C MOV AX,CS + 06CB 8E D8 C MOV DS,AX + 06CD 8E C0 C MOV ES,AX + 06CF E8 0F66 R C CALL WRTFATS + 06D2 33 C0 C XOR AX,AX + 06D4 FA C CLI + 06D5 8E 16 0133 R C MOV SS,[SSSAVE] + 06D9 8B 26 0131 R C MOV SP,[SPSAVE] + 06DD 8E D8 C MOV DS,AX + 06DF BE 0088 C MOV SI,EXIT + 06E2 BF 0105 R C MOV DI,OFFSET DOSGROUP:EXITHOLD + 06E5 A5 C MOVSW + 06E6 A5 C MOVSW + 06E7 58 C POP AX + 06E8 5B C POP BX + 06E9 59 C POP CX + 06EA 5A C POP DX + 06EB 5E C POP SI + 06EC 5F C POP DI + 06ED 5D C POP BP + 06EE 1F C POP DS + 06EF 07 C POP ES + 06F0 FB C STI ;Stack OK now + 06F1 2E: FF 2E 0105 R C JMP CS:DWORD PTR [EXITHOLD] + C + C + 06F6 C SEQRD: ;System call 20 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-27 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 06F6 E8 0D9A R C CALL GETREC + 06F9 E8 0A1E R C CALL LOAD + 06FC EB 06 C JMP SHORT FINSEQ + C + 06FE C SEQWRT: ;System call 21 + 06FE E8 0D9A R C CALL GETREC + 0701 E8 0BA9 R C CALL STORE + 0704 C FINSEQ: + 0704 E3 45 C JCXZ SETNREX + 0706 05 0001 C ADD AX,1 + 0709 83 D2 00 C ADC DX,0 + 070C EB 3D C JMP SHORT SETNREX + C + 070E C RNDRD: ;System call 33 + 070E E8 0767 R C CALL GETRRPOS1 + 0711 E8 0A1E R C CALL LOAD + 0714 EB 25 C JMP SHORT FINRND + C + 0716 C RNDWRT: ;System call 34 + 0716 E8 0767 R C CALL GETRRPOS1 + 0719 E8 0BA9 R C CALL STORE + 071C EB 1D C JMP SHORT FINRND + C + 071E C BLKRD: ;System call 39 + 071E E8 076A R C CALL GETRRPOS + 0721 E8 0A1E R C CALL LOAD + 0724 EB 06 C JMP SHORT FINBLK + C + 0726 C BLKWRT: ;System call 40 + 0726 E8 076A R C CALL GETRRPOS + 0729 E8 0BA9 R C CALL STORE + 072C C FINBLK: + 072C C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0730 89 4C 04 C MOV [SI.CXSAVE],CX + 0733 E3 06 C JCXZ FINRND + 0735 05 0001 C ADD AX,1 + 0738 83 D2 00 C ADC DX,0 + 073B C FINRND: + 073B 26: 89 45 21 C MOV ES:WORD PTR [DI.RR],AX + 073F 26: 88 55 23 C MOV ES:[DI.RR+2],DL + 0743 0A F6 C OR DH,DH + 0745 74 04 C JZ SETNREX + 0747 26: 88 75 24 C MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant + 074B C SETNREX: + 074B 8B C8 C MOV CX,AX + 074D 24 7F C AND AL,7FH + 074F 26: 88 45 20 C MOV ES:[DI.NR],AL + 0753 80 E1 80 C AND CL,80H + 0756 D1 E1 C SHL CX,1 + 0758 D1 D2 C RCL DX,1 + 075A 8A C5 C MOV AL,CH + 075C 8A E2 C MOV AH,DL + 075E 26: 89 45 0C C MOV ES:[DI.EXTENT],AX + 0762 2E: A0 0138 R C MOV AL,CS:[DSKERR] + 0766 C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-28 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0767 C GETRRPOS1: + 0767 B9 0001 C MOV CX,1 + 076A C GETRRPOS: + 076A 8B FA C MOV DI,DX + 076C 80 3D FF C CMP BYTE PTR [DI],-1 + 076F 75 03 C JNZ NORMFCB1 + 0771 83 C7 07 C ADD DI,7 + 0774 C NORMFCB1: + 0774 8B 45 21 C MOV AX,WORD PTR [DI.RR] + 0777 8B 55 23 C MOV DX,WORD PTR [DI.RR+2] + 077A C3 C RET + C + 077B C NOFILERR: + 077B 33 C9 C XOR CX,CX + 077D C6 06 0138 R 04 C MOV BYTE PTR [DSKERR],4 + 0782 5B C POP BX + 0783 C3 C RET + C + 0784 C SETUP: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Record position in file of disk transfer + C ; CX = Record count + C ; Outputs: + C ; DS = CS + C ; ES:DI point to FCB + C ; BL = DEVID from FCB + C ; CX = No. of bytes to transfer + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; [RECCNT] = Record count + C ; [RECPOS] = Record position in file + C ; [FCB] = DI + C ; [NEXTADD] = Displacement of disk transfer within segment + C ; [SECPOS] = Position of first sector + C ; [BYTPOS] = Byte position in file + C ; [BYTSECPOS] = Byte position in first sector + C ; [CLUSNUM] = First cluster + C ; [SECCLUSPOS] = Sector within first cluster + C ; [DSKERR] = 0 (no errors yet) + C ; [TRANS] = 0 (No transfers yet) + C ; [THISDRV] = Physical drive unit number + C ; If SETUP detects no records will be transfered, it returns 1 level up + C ; with CX = 0. + C + 0784 50 C PUSH AX + 0785 8A 05 C MOV AL,[DI] + 0787 FE C8 C DEC AL + 0789 2E: A2 013C R C MOV CS:[THISDRV],AL + 078D 8A 45 18 C MOV AL,[DI.DEVID] + 0790 8B 75 0E C MOV SI,[DI.RECSIZ] + 0793 0B F6 C OR SI,SI + 0795 75 06 C JNZ HAVRECSIZ +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-29 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0797 BE 0080 C MOV SI,128 + 079A 89 75 0E C MOV [DI.RECSIZ],SI + 079D C HAVRECSIZ: + 079D 1E C PUSH DS + 079E 07 C POP ES ;Set ES to DS + 079F 0E C PUSH CS + 07A0 1F C POP DS ;Set DS to CS + 07A1 0A C0 C OR AL,AL ;Is it a device? + 07A3 79 02 C JNS NOTDEVICE + 07A5 B0 00 C MOV AL,0 ;Fake in drive 0 so we can get SP + 07A7 C NOTDEVICE: + 07A7 E8 0492 R C CALL GETBP + 07AA 58 C POP AX + 07AB 72 CE C JC NOFILERR + 07AD 83 FE 40 C CMP SI,64 ;Check if highest byte of RECPOS is significant + 07B0 72 02 C JB SMALREC + 07B2 B6 00 C MOV DH,0 ;Ignore MSB if record >= 64 bytes + 07B4 C SMALREC: + 07B4 89 0E 0146 R C MOV [RECCNT],CX + 07B8 A3 0142 R C MOV WORD PTR [RECPOS],AX + 07BB 89 16 0144 R C MOV WORD PTR [RECPOS+2],DX + 07BF 89 3E 013E R C MOV [FCB],DI + 07C3 8B 1E 0031 R C MOV BX,[DMAADD] + 07C7 89 1E 0140 R C MOV [NEXTADD],BX + 07CB C6 06 0138 R 00 C MOV BYTE PTR [DSKERR],0 + 07D0 C6 06 0139 R 00 C MOV BYTE PTR [TRANS],0 + 07D5 8B DA C MOV BX,DX + 07D7 F7 E6 C MUL SI + 07D9 A3 0152 R C MOV WORD PTR [BYTPOS],AX + 07DC 52 C PUSH DX + 07DD 8B C3 C MOV AX,BX + 07DF F7 E6 C MUL SI + 07E1 5B C POP BX + 07E2 03 C3 C ADD AX,BX + 07E4 83 D2 00 C ADC DX,0 ;Ripple carry + 07E7 75 5A C JNZ EOFERR + 07E9 A3 0154 R C MOV WORD PTR [BYTPOS+2],AX + 07EC 8B D0 C MOV DX,AX + 07EE A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 07F1 8B 5E 02 C MOV BX,[BP.SECSIZ] + 07F4 3B D3 C CMP DX,BX ;See if divide will overflow + 07F6 73 4B C JNC EOFERR + 07F8 F7 F3 C DIV BX + 07FA A3 014C R C MOV [SECPOS],AX + 07FD 89 16 0150 R C MOV [BYTSECPOS],DX + 0801 8B D0 C MOV DX,AX + 0803 22 46 04 C AND AL,[BP.CLUSMSK] + 0806 A2 0137 R C MOV [SECCLUSPOS],AL + 0809 8B C1 C MOV AX,CX ;Record count + 080B 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 080E D3 EA C SHR DX,CL + 0810 89 16 014A R C MOV [CLUSNUM],DX + 0814 F7 E6 C MUL SI ;Multiply by bytes per record + 0816 8B C8 C MOV CX,AX + 0818 03 06 0031 R C ADD AX,[DMAADD] ;See if it will fit in one segment +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-30 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 081C 83 D2 00 C ADC DX,0 + 081F 74 1A C JZ OK ;Must be less than 64K + 0821 A1 0031 R C MOV AX,[DMAADD] + 0824 F7 D8 C NEG AX ;Amount of room left in segment + 0826 75 01 C JNZ PARTSEG ;All 64K available? + 0828 48 C DEC AX ;If so, reduce by one + 0829 C PARTSEG: + 0829 33 D2 C XOR DX,DX + 082B F7 F6 C DIV SI ;How many records will fit? + 082D A3 0146 R C MOV [RECCNT],AX + 0830 F7 E6 C MUL SI ;Translate that back into bytes + 0832 C6 06 0138 R 02 C MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place + 0837 8B C8 C MOV CX,AX + 0839 E3 0F C JCXZ NOROOM + 083B C OK: + 083B 26: 8A 5D 18 C MOV BL,ES:[DI.DEVID] + 083F 8B 76 12 C MOV SI,[BP.FAT] + 0842 C3 C RET + C + 0843 C EOFERR: + 0843 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0848 33 C9 C XOR CX,CX + 084A C NOROOM: + 084A 5B C POP BX ;Kill return address + 084B C3 C RET + C + 084C C BREAKDOWN: + C + C ;Inputs: + C ; DS = CS + C ; CX = Length of disk transfer in bytes + C ; BP = Base of drive parameters + C ; [BYTSECPOS] = Byte position witin first sector + C ;Outputs: + C ; [BYTCNT1] = Bytes to transfer in first sector + C ; [SECCNT] = No. of whole sectors to transfer + C ; [BYTCNT2] = Bytes to transfer in last sector + C ;AX, BX, DX destroyed. No other registers affected. + C + 084C A1 0150 R C MOV AX,[BYTSECPOS] + 084F 8B D9 C MOV BX,CX + 0851 0B C0 C OR AX,AX + 0853 74 0D C JZ SAVFIR ;Partial first sector? + 0855 2B 46 02 C SUB AX,[BP.SECSIZ] + 0858 F7 D8 C NEG AX ;Max number of bytes left in first sector + 085A 2B D8 C SUB BX,AX ;Subtract from total length + 085C 73 04 C JAE SAVFIR + 085E 03 C3 C ADD AX,BX ;Don't use all of the rest of the sector + 0860 33 DB C XOR BX,BX ;And no bytes are left + 0862 C SAVFIR: + 0862 A3 0156 R C MOV [BYTCNT1],AX + 0865 8B C3 C MOV AX,BX + 0867 33 D2 C XOR DX,DX + 0869 F7 76 02 C DIV [BP.SECSIZ] ;How many whole sectors? + 086C A3 015A R C MOV [SECCNT],AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-31 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 086F 89 16 0158 R C MOV [BYTCNT2],DX ;Bytes remaining for last sector + 0873 C3 C RET10: RET + C + C + 0874 C FNDCLUS: + C + C ; Inputs: + C ; DS = CS + C ; CX = No. of clusters to skip + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; ES:DI point to FCB + C ; Outputs: + C ; BX = Last cluster skipped to + C ; CX = No. of clusters remaining (0 unless EOF) + C ; DX = Position of last cluster + C ; DI destroyed. No other registers affected. + C + 0874 26: 8B 5D 1B C MOV BX,ES:[DI.LSTCLUS] + 0878 26: 8B 55 1D C MOV DX,ES:[DI.CLUSPOS] + 087C 0B DB C OR BX,BX + 087E 74 1D C JZ NOCLUS + 0880 2B CA C SUB CX,DX + 0882 73 08 C JNB FINDIT + 0884 03 CA C ADD CX,DX + 0886 33 D2 C XOR DX,DX + 0888 26: 8B 5D 19 C MOV BX,ES:[DI.FIRCLUS] + 088C C FINDIT: + 088C E3 E5 C JCXZ RET10 + 088E C SKPCLP: + 088E E8 0157 R C CALL UNPACK + 0891 81 FF 0FF8 C CMP DI,0FF8H + 0895 73 DC C JAE RET10 + 0897 87 DF C XCHG BX,DI + 0899 42 C INC DX + 089A E2 F2 C LOOP SKPCLP + 089C C3 C RET + 089D C NOCLUS: + 089D 41 C INC CX + 089E 4A C DEC DX + 089F C3 C RET + C + C + 08A0 C BUFSEC: + C ; Inputs: + C ; AL = 0 if buffer must be read, 1 if no pre-read needed + C ; BP = Base of drive parameters + C ; [CLUSNUM] = Physical cluster number + C ; [SECCLUSPOS] = Sector position of transfer within cluster + C ; [BYTCNT1] = Size of transfer + C ; Function: + C ; Insure specified sector is in buffer, flushing buffer before + C ; read if necessary. + C ; Outputs: + C ; SI = Pointer to buffer +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-32 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; DI = Pointer to transfer address + C ; CX = Number of bytes + C ; [NEXTADD] updated + C ; [TRANS] set to indicate a transfer will occur + C + 08A0 8B 16 014A R C MOV DX,[CLUSNUM] + 08A4 8A 1E 0137 R C MOV BL,[SECCLUSPOS] + 08A8 E8 0D8B R C CALL FIGREC + 08AB A2 013A R C MOV [PREREAD],AL + 08AE 3B 16 003B R C CMP DX,[BUFSECNO] + 08B2 75 09 C JNZ GETSEC + 08B4 A0 003D R C MOV AL,[BUFDRVNO] + 08B7 3A 06 013C R C CMP AL,[THISDRV] + 08BB 74 4A C JZ FINBUF ;Already have it? + 08BD C GETSEC: + 08BD 32 C0 C XOR AL,AL + 08BF 86 06 003E R C XCHG [DIRTYBUF],AL ;Read dirty flag and reset it + 08C3 0A C0 C OR AL,AL + 08C5 74 16 C JZ RDSEC + 08C7 52 C PUSH DX + 08C8 55 C PUSH BP + 08C9 8B 2E 003F R C MOV BP,[BUFDRVBP] + 08CD 8B 1E 0039 R C MOV BX,[BUFFER] + 08D1 B9 0001 C MOV CX,1 + 08D4 8B 16 003B R C MOV DX,[BUFSECNO] + 08D8 E8 068C R C CALL DWRITE + 08DB 5D C POP BP + 08DC 5A C POP DX + 08DD C RDSEC: + 08DD F6 06 013A R FF C TEST BYTE PTR [PREREAD],-1 + 08E2 75 15 C JNZ SETBUF + 08E4 33 C0 C XOR AX,AX + 08E6 A3 003B R C MOV [BUFSECNO],AX ;Set buffer valid in case of disk error + 08E9 48 C DEC AX + 08EA A2 003D R C MOV [BUFDRVNO],AL + 08ED 8B 1E 0039 R C MOV BX,[BUFFER] + 08F1 B9 0001 C MOV CX,1 + 08F4 52 C PUSH DX + 08F5 E8 05FC R C CALL DREAD + 08F8 5A C POP DX + 08F9 C SETBUF: + 08F9 89 16 003B R C MOV [BUFSECNO],DX + 08FD A0 013C R C MOV AL,[THISDRV] + 0900 A2 003D R C MOV [BUFDRVNO],AL + 0903 89 2E 003F R C MOV [BUFDRVBP],BP + 0907 C FINBUF: + 0907 C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 090C 8B 3E 0140 R C MOV DI,[NEXTADD] + 0910 8B F7 C MOV SI,DI + 0912 8B 0E 0156 R C MOV CX,[BYTCNT1] + 0916 03 F1 C ADD SI,CX + 0918 89 36 0140 R C MOV [NEXTADD],SI + 091C 8B 36 0039 R C MOV SI,[BUFFER] + 0920 03 36 0150 R C ADD SI,[BYTSECPOS] + 0924 C3 C RET +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-33 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0925 C BUFRD: + 0925 32 C0 C XOR AL,AL ;Pre-read necessary + 0927 E8 08A0 R C CALL BUFSEC + 092A 06 C PUSH ES + 092B 8E 06 0033 R C MOV ES,[DMAADD+2] + 092F D1 E9 C SHR CX,1 + 0931 73 01 C JNC EVENRD + 0933 A4 C MOVSB + 0934 C EVENRD: + 0934 F3/ A5 C REP MOVSW + 0936 07 C POP ES + 0937 C3 C RET + C + 0938 C BUFWRT: + 0938 A1 014C R C MOV AX,[SECPOS] + 093B 40 C INC AX ;Set for next sector + 093C A3 014C R C MOV [SECPOS],AX + 093F 3B 06 014E R C CMP AX,[VALSEC] ;Has sector been written before? + 0943 B0 01 C MOV AL,1 + 0945 77 02 C JA NOREAD ;Skip preread if SECPOS>VALSEC + 0947 B0 00 C MOV AL,0 + 0949 C NOREAD: + 0949 E8 08A0 R C CALL BUFSEC + 094C 87 FE C XCHG DI,SI + 094E 1E C PUSH DS + 094F 06 C PUSH ES + 0950 0E C PUSH CS + 0951 07 C POP ES + 0952 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0956 D1 E9 C SHR CX,1 + 0958 73 01 C JNC EVENWRT + 095A A4 C MOVSB + 095B C EVENWRT: + 095B F3/ A5 C REP MOVSW + 095D 07 C POP ES + 095E 1F C POP DS + 095F C6 06 003E R 01 C MOV BYTE PTR [DIRTYBUF],1 + 0964 C3 C RET + C + 0965 C NEXTSEC: + 0965 F6 06 0139 R FF C TEST BYTE PTR [TRANS],-1 + 096A 74 27 C JZ CLRET + 096C A0 0137 R C MOV AL,[SECCLUSPOS] + 096F FE C0 C INC AL + 0971 3A 46 04 C CMP AL,[BP.CLUSMSK] + 0974 76 1A C JBE SAVPOS + 0976 8B 1E 014A R C MOV BX,[CLUSNUM] + 097A 81 FB 0FF8 C CMP BX,0FF8H + 097E 73 15 C JAE NONEXT + 0980 8B 76 12 C MOV SI,[BP.FAT] + 0983 E8 0157 R C CALL UNPACK + 0986 89 3E 014A R C MOV [CLUSNUM],DI + 098A FF 06 0148 R C INC [LASTPOS] + 098E B0 00 C MOV AL,0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-34 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0990 C SAVPOS: + 0990 A2 0137 R C MOV [SECCLUSPOS],AL + 0993 C CLRET: + 0993 F8 C CLC + 0994 C3 C RET + 0995 C NONEXT: + 0995 F9 C STC + 0996 C3 C RET + C + 0997 C TRANBUF: + 0997 AC C LODSB + 0998 AA C STOSB + 0999 3C 0D C CMP AL,13 ;Check for carriage return + 099B 75 03 C JNZ NORMCH + 099D C6 04 0A C MOV BYTE PTR [SI],10 + 09A0 C NORMCH: + 09A0 3C 0A C CMP AL,10 + 09A2 E0 F3 C LOOPNZ TRANBUF + 09A4 75 0B C JNZ ENDRDCON + 09A6 E8 119F R C CALL OUT ;Transmit linefeed + 09A9 33 F6 C XOR SI,SI + 09AB 0B C9 C OR CX,CX + 09AD 75 47 C JNZ GETBUF + 09AF 0C 01 C OR AL,1 ;Clear zero flag--not end of file + 09B1 C ENDRDCON: + 09B1 89 36 002F R C MOV [CONTPOS],SI + 09B5 C ENDRDDEV: + 09B5 89 3E 0140 R C MOV [NEXTADD],DI + 09B9 07 C POP ES + 09BA 75 09 C JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + 09BC 8B 3E 013E R C MOV DI,[FCB] + 09C0 26: 80 65 18 BF C AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available + 09C5 C SETFCBJ: + 09C5 E9 0ACD R C JMP SETFCB + C + 09C8 C READDEV: + 09C8 06 C PUSH ES + 09C9 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 09CD FE C3 C INC BL + 09CF 74 0E C JZ READCON + 09D1 FE C3 C INC BL + 09D3 75 E0 C JNZ ENDRDDEV + 09D5 C READAUX: + 09D5 E8 0141 R C CALL AUXIN + 09D8 AA C STOSB + 09D9 3C 1A C CMP AL,1AH + 09DB E0 F8 C LOOPNZ READAUX + 09DD EB D6 C JMP SHORT ENDRDDEV + C + 09DF C READCON: + 09DF 0E C PUSH CS + 09E0 1F C POP DS + 09E1 8B 36 002F R C MOV SI,[CONTPOS] + 09E5 0B F6 C OR SI,SI + 09E7 75 AE C JNZ TRANBUF +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-35 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 09E9 80 3E 0080 R 80 C CMP BYTE PTR [CONBUF],128 + 09EE 74 06 C JZ GETBUF + 09F0 C7 06 0080 R FF80 C MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template + 09F6 C GETBUF: + 09F6 51 C PUSH CX + 09F7 06 C PUSH ES + 09F8 57 C PUSH DI + 09F9 BA 0080 R C MOV DX,OFFSET DOSGROUP:CONBUF + 09FC E8 0FBD R C CALL BUFIN ;Get input buffer + 09FF 5F C POP DI + 0A00 07 C POP ES + 0A01 59 C POP CX + 0A02 BE 0082 R C MOV SI,2 + OFFSET DOSGROUP:CONBUF + 0A05 80 3C 1A C CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character + 0A08 75 8D C JNZ TRANBUF + 0A0A B0 1A C MOV AL,1AH + 0A0C AA C STOSB + 0A0D B0 0A C MOV AL,10 + 0A0F E8 119F R C CALL OUT ;Send linefeed + 0A12 33 F6 C XOR SI,SI + 0A14 EB 9B C JMP SHORT ENDRDCON + C + 0A16 C RDERR: + 0A16 33 C9 C XOR CX,CX + 0A18 E9 0B92 R C JMP WRTERR + C + 0A1B E9 0B2D R C RDLASTJ:JMP RDLAST + C + 0A1E C LOAD: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Position in file to read + C ; CX = No. of records to read + C ; Outputs: + C ; DX:AX = Position of last record read + C ; CX = No. of bytes read + C ; ES:DI point to FCB + C ; LSTCLUS, CLUSPOS fields in FCB set + C + 0A1E E8 0784 R C CALL SETUP + 0A21 0A DB C OR BL,BL ;Check for named device I/O + 0A23 78 A3 C JS READDEV + 0A25 26: 8B 45 10 C MOV AX,ES:WORD PTR [DI.FILSIZ] + 0A29 26: 8B 5D 12 C MOV BX,ES:WORD PTR [DI.FILSIZ+2] + 0A2D 2B 06 0152 R C SUB AX,WORD PTR [BYTPOS] + 0A31 1B 1E 0154 R C SBB BX,WORD PTR [BYTPOS+2] + 0A35 72 DF C JB RDERR + 0A37 75 0A C JNZ ENUF + 0A39 0B C0 C OR AX,AX + 0A3B 74 D9 C JZ RDERR + 0A3D 3B C1 C CMP AX,CX + 0A3F 73 02 C JAE ENUF + 0A41 8B C8 C MOV CX,AX + 0A43 C ENUF: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-36 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0A43 E8 084C R C CALL BREAKDOWN + 0A46 8B 0E 014A R C MOV CX,[CLUSNUM] + 0A4A E8 0874 R C CALL FNDCLUS + 0A4D 0B C9 C OR CX,CX + 0A4F 75 C5 C JNZ RDERR + 0A51 89 16 0148 R C MOV [LASTPOS],DX + 0A55 89 1E 014A R C MOV [CLUSNUM],BX + 0A59 83 3E 0156 R 00 C CMP [BYTCNT1],0 + 0A5E 74 03 C JZ RDMID + 0A60 E8 0925 R C CALL BUFRD + 0A63 C RDMID: + 0A63 83 3E 015A R 00 C CMP [SECCNT],0 + 0A68 74 B1 C JZ RDLASTJ + 0A6A E8 0965 R C CALL NEXTSEC + 0A6D 72 5E C JC SETFCB + 0A6F C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 0A74 C ONSEC: + 0A74 8A 16 0137 R C MOV DL,[SECCLUSPOS] + 0A78 8B 0E 015A R C MOV CX,[SECCNT] + 0A7C 8B 1E 014A R C MOV BX,[CLUSNUM] + 0A80 C RDLP: + 0A80 E8 0D15 R C CALL OPTIMIZE + 0A83 57 C PUSH DI + 0A84 50 C PUSH AX + 0A85 1E C PUSH DS + 0A86 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0A8A 52 C PUSH DX + 0A8B 53 C PUSH BX + 0A8C 9C C PUSHF ;Save carry flag + 0A8D E8 05FC R C CALL DREAD + 0A90 9D C POPF ;Restore carry flag + 0A91 5F C POP DI ;Initial transfer address + 0A92 58 C POP AX ;First sector transfered + 0A93 1F C POP DS + 0A94 72 25 C JC NOTBUFFED ;Was one of those sectors in the buffer? + 0A96 80 3E 003E R 00 C CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty? + 0A9B 74 1E C JZ NOTBUFFED ;If not no problem + C ;We have transfered in a sector from disk when a dirty copy of it is in the buffer. + C ;We must transfer the sector from the buffer to correct memory address + 0A9D 2B 06 003B R C SUB AX,[BUFSECNO] ;How many sectors into the transfer? + 0AA1 F7 D8 C NEG AX + 0AA3 8B 4E 02 C MOV CX,[BP.SECSIZ] + 0AA6 F7 E1 C MUL CX ;How many bytes into the transfer? + 0AA8 03 F8 C ADD DI,AX + 0AAA 8B 36 0039 R C MOV SI,[BUFFER] + 0AAE 06 C PUSH ES + 0AAF 8E 06 0033 R C MOV ES,[DMAADD+2] ;Get disk transfer segment + 0AB3 D1 E9 C SHR CX,1 + 0AB5 F3/ A5 C REP MOVSW + 0AB7 73 01 C JNC EVENMOV + 0AB9 A4 C MOVSB + 0ABA C EVENMOV: + 0ABA 07 C POP ES + 0ABB C NOTBUFFED: + 0ABB 59 C POP CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-37 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0ABC 5B C POP BX + 0ABD E3 6E C JCXZ RDLAST + 0ABF 81 FB 0FF8 C CMP BX,0FF8H + 0AC3 73 08 C JAE SETFCB + 0AC5 B2 00 C MOV DL,0 + 0AC7 FF 06 0148 R C INC [LASTPOS] ;We'll be using next cluster + 0ACB EB B3 C JMP SHORT RDLP + C + 0ACD C SETFCB: + 0ACD 8B 36 013E R C MOV SI,[FCB] + 0AD1 A1 0140 R C MOV AX,[NEXTADD] + 0AD4 8B F8 C MOV DI,AX + 0AD6 2B 06 0031 R C SUB AX,[DMAADD] ;Number of bytes transfered + 0ADA 33 D2 C XOR DX,DX + 0ADC 26: 8B 4C 0E C MOV CX,ES:[SI.RECSIZ] + 0AE0 F7 F1 C DIV CX ;Number of records + 0AE2 3B 06 0146 R C CMP AX,[RECCNT] ;Check if all records transferred + 0AE6 74 22 C JZ FULLREC + 0AE8 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0AED 0B D2 C OR DX,DX + 0AEF 74 19 C JZ FULLREC ;If remainder 0, then full record transfered + 0AF1 C6 06 0138 R 03 C MOV BYTE PTR [DSKERR],3 ;Flag partial last record + 0AF6 2B CA C SUB CX,DX ;Bytes left in last record + 0AF8 06 C PUSH ES + 0AF9 8E 06 0033 R C MOV ES,[DMAADD+2] + 0AFD 93 C XCHG AX,BX ;Save the record count temporarily + 0AFE 33 C0 C XOR AX,AX ;Fill with zeros + 0B00 D1 E9 C SHR CX,1 + 0B02 73 01 C JNC EVENFIL + 0B04 AA C STOSB + 0B05 C EVENFIL: + 0B05 F3/ AB C REP STOSW + 0B07 93 C XCHG AX,BX ;Restore record count to AX + 0B08 07 C POP ES + 0B09 40 C INC AX ;Add last (partial) record to total + 0B0A C FULLREC: + 0B0A 8B C8 C MOV CX,AX + 0B0C 8B FE C MOV DI,SI ;ES:DI point to FCB + 0B0E C SETCLUS: + 0B0E A1 014A R C MOV AX,[CLUSNUM] + 0B11 26: 89 45 1B C MOV ES:[DI.LSTCLUS],AX + 0B15 A1 0148 R C MOV AX,[LASTPOS] + 0B18 26: 89 45 1D C MOV ES:[DI.CLUSPOS],AX + 0B1C C ADDREC: + 0B1C A1 0142 R C MOV AX,WORD PTR [RECPOS] + 0B1F 8B 16 0144 R C MOV DX,WORD PTR [RECPOS+2] + 0B23 E3 07 C JCXZ RET28 ;If no records read, don't change position + 0B25 49 C DEC CX + 0B26 03 C1 C ADD AX,CX ;Update current record position + 0B28 83 D2 00 C ADC DX,0 + 0B2B 41 C INC CX + 0B2C C3 C RET28: RET + C + 0B2D C RDLAST: + 0B2D A1 0158 R C MOV AX,[BYTCNT2] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-38 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0B30 0B C0 C OR AX,AX + 0B32 74 99 C JZ SETFCB + 0B34 A3 0156 R C MOV [BYTCNT1],AX + 0B37 E8 0965 R C CALL NEXTSEC + 0B3A 72 91 C JC SETFCB + 0B3C C7 06 0150 R 0000 C MOV [BYTSECPOS],0 + 0B42 E8 0925 R C CALL BUFRD + 0B45 EB 86 C JMP SHORT SETFCB + C + 0B47 C WRTDEV: + 0B47 1E C PUSH DS + 0B48 C5 36 0031 R C LDS SI,DWORD PTR [DMAADD] + 0B4C 80 CB 40 C OR BL,40H + 0B4F FE C3 C INC BL + 0B51 74 1E C JZ WRTCON + 0B53 FE C3 C INC BL + 0B55 74 10 C JZ WRTAUX + 0B57 FE C3 C INC BL + 0B59 74 20 C JZ ENDWRDEV ;Done if device is NUL + 0B5B C WRTLST: + 0B5B AC C LODSB + 0B5C 3C 1A C CMP AL,1AH + 0B5E 74 1B C JZ ENDWRDEV + 0B60 E8 128D R C CALL LISTOUT + 0B63 E2 F6 C LOOP WRTLST + 0B65 EB 14 C JMP SHORT ENDWRDEV + C + 0B67 C WRTAUX: + 0B67 AC C LODSB + 0B68 E8 014C R C CALL AUXOUT + 0B6B 3C 1A C CMP AL,1AH + 0B6D E0 F8 C LOOPNZ WRTAUX + 0B6F EB 0A C JMP SHORT ENDWRDEV + C + 0B71 C WRTCON: + 0B71 AC C LODSB + 0B72 3C 1A C CMP AL,1AH + 0B74 74 05 C JZ ENDWRDEV + 0B76 E8 119F R C CALL OUT + 0B79 E2 F6 C LOOP WRTCON + 0B7B C ENDWRDEV: + 0B7B 1F C POP DS + 0B7C 8B 0E 0146 R C MOV CX,[RECCNT] + 0B80 8B 3E 013E R C MOV DI,[FCB] + 0B84 EB 96 C JMP SHORT ADDREC + C + 0B86 C HAVSTART: + 0B86 8B C8 C MOV CX,AX + 0B88 E8 088E R C CALL SKPCLP + 0B8B E3 16 C JCXZ DOWRTJ + 0B8D E8 0DBA R C CALL ALLOCATE + 0B90 73 11 C JNC DOWRTJ + 0B92 C WRTERR: + 0B92 C6 06 0138 R 01 C MOV BYTE PTR [DSKERR],1 + 0B97 C LVDSK: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-39 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0B97 A1 0142 R C MOV AX,WORD PTR [RECPOS] + 0B9A 8B 16 0144 R C MOV DX,WORD PTR [RECPOS+2] + 0B9E 8B 3E 013E R C MOV DI,[FCB] + 0BA2 C3 C RET + C + 0BA3 EB 7F 90 C DOWRTJ: JMP DOWRT + C + 0BA6 C WRTEOFJ: + 0BA6 E9 0CC3 R C JMP WRTEOF + C + 0BA9 C STORE: + C + C ; Inputs: + C ; DS:DI point to FCB + C ; DX:AX = Position in file of disk transfer + C ; CX = Record count + C ; Outputs: + C ; DX:AX = Position of last record written + C ; CX = No. of records written + C ; ES:DI point to FCB + C ; LSTCLUS, CLUSPOS fields in FCB set + C + 0BA9 E8 0784 R C CALL SETUP + 0BAC E8 1400 R C CALL DATE16 + 0BAF 26: 89 45 14 C MOV ES:[DI.FDATE],AX + 0BB3 26: 89 55 16 C MOV ES:[DI.FTIME],DX + 0BB7 0A DB C OR BL,BL + 0BB9 78 8C C JS WRTDEV + 0BBB 80 E3 3F C AND BL,3FH ;Mark file as dirty + 0BBE 26: 88 5D 18 C MOV ES:[DI.DEVID],BL + 0BC2 E8 084C R C CALL BREAKDOWN + 0BC5 A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 0BC8 8B 16 0154 R C MOV DX,WORD PTR [BYTPOS+2] + 0BCC E3 D8 C JCXZ WRTEOFJ + 0BCE 49 C DEC CX + 0BCF 03 C1 C ADD AX,CX + 0BD1 83 D2 00 C ADC DX,0 ;AX:DX=last byte accessed + 0BD4 F7 76 02 C DIV [BP.SECSIZ] ;AX=last sector accessed + 0BD7 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0BDA D3 E8 C SHR AX,CL ;Last cluster to be accessed + 0BDC 50 C PUSH AX + 0BDD 26: 8B 45 10 C MOV AX,ES:WORD PTR [DI.FILSIZ] + 0BE1 26: 8B 55 12 C MOV DX,ES:WORD PTR [DI.FILSIZ+2] + 0BE5 F7 76 02 C DIV [BP.SECSIZ] + 0BE8 0B D2 C OR DX,DX + 0BEA 74 01 C JZ NORNDUP + 0BEC 40 C INC AX ;Round up if any remainder + 0BED C NORNDUP: + 0BED A3 014E R C MOV [VALSEC],AX ;Number of sectors that have been written + 0BF0 58 C POP AX + 0BF1 8B 0E 014A R C MOV CX,[CLUSNUM] ;First cluster accessed + 0BF5 E8 0874 R C CALL FNDCLUS + 0BF8 89 1E 014A R C MOV [CLUSNUM],BX + 0BFC 89 16 0148 R C MOV [LASTPOS],DX + 0C00 2B C2 C SUB AX,DX ;Last cluster minus current cluster +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-40 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0C02 74 20 C JZ DOWRT ;If we have last clus, we must have first + 0C04 E3 80 C JCXZ HAVSTART ;See if no more data + 0C06 51 C PUSH CX ;No. of clusters short of first + 0C07 8B C8 C MOV CX,AX + 0C09 E8 0DBA R C CALL ALLOCATE + 0C0C 58 C POP AX + 0C0D 72 83 C JC WRTERR + 0C0F 8B C8 C MOV CX,AX + 0C11 8B 16 0148 R C MOV DX,[LASTPOS] + 0C15 42 C INC DX + 0C16 49 C DEC CX + 0C17 74 03 C JZ NOSKIP + 0C19 E8 088E R C CALL SKPCLP + 0C1C C NOSKIP: + 0C1C 89 1E 014A R C MOV [CLUSNUM],BX + 0C20 89 16 0148 R C MOV [LASTPOS],DX + 0C24 C DOWRT: + 0C24 83 3E 0156 R 00 C CMP [BYTCNT1],0 + 0C29 74 07 C JZ WRTMID + 0C2B 8B 1E 014A R C MOV BX,[CLUSNUM] + 0C2F E8 0938 R C CALL BUFWRT + 0C32 C WRTMID: + 0C32 A1 015A R C MOV AX,[SECCNT] + 0C35 0B C0 C OR AX,AX + 0C37 74 40 C JZ WRTLAST + 0C39 01 06 014C R C ADD [SECPOS],AX + 0C3D E8 0965 R C CALL NEXTSEC + 0C40 C6 06 0139 R 01 C MOV BYTE PTR [TRANS],1 ;A transfer is taking place + 0C45 8A 16 0137 R C MOV DL,[SECCLUSPOS] + 0C49 8B 1E 014A R C MOV BX,[CLUSNUM] + 0C4D 8B 0E 015A R C MOV CX,[SECCNT] + 0C51 C WRTLP: + 0C51 E8 0D15 R C CALL OPTIMIZE + 0C54 72 0C C JC NOTINBUF ;Is one of the sectors buffered? + 0C56 C7 06 003B R 0000 C MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're + 0C5C C7 06 003D R 00FF C MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it + 0C62 C NOTINBUF: + 0C62 57 C PUSH DI + 0C63 50 C PUSH AX + 0C64 1E C PUSH DS + 0C65 8E 1E 0033 R C MOV DS,[DMAADD+2] + 0C69 E8 068C R C CALL DWRITE + 0C6C 1F C POP DS + 0C6D 59 C POP CX + 0C6E 5B C POP BX + 0C6F E3 08 C JCXZ WRTLAST + 0C71 B2 00 C MOV DL,0 + 0C73 FF 06 0148 R C INC [LASTPOS] ;We'll be using next cluster + 0C77 EB D8 C JMP SHORT WRTLP + 0C79 C WRTLAST: + 0C79 A1 0158 R C MOV AX,[BYTCNT2] + 0C7C 0B C0 C OR AX,AX + 0C7E 74 0F C JZ FINWRT + 0C80 A3 0156 R C MOV [BYTCNT1],AX + 0C83 E8 0965 R C CALL NEXTSEC +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-41 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0C86 C7 06 0150 R 0000 C MOV [BYTSECPOS],0 + 0C8C E8 0938 R C CALL BUFWRT + 0C8F C FINWRT: + 0C8F A1 0140 R C MOV AX,[NEXTADD] + 0C92 2B 06 0031 R C SUB AX,[DMAADD] + 0C96 03 06 0152 R C ADD AX,WORD PTR [BYTPOS] + 0C9A 8B 16 0154 R C MOV DX,WORD PTR [BYTPOS+2] + 0C9E 83 D2 00 C ADC DX,0 + 0CA1 8B CA C MOV CX,DX + 0CA3 8B 3E 013E R C MOV DI,[FCB] + 0CA7 26: 3B 45 10 C CMP AX,ES:WORD PTR [DI.FILSIZ] + 0CAB 26: 1B 4D 12 C SBB CX,ES:WORD PTR [DI.FILSIZ+2] + 0CAF 72 08 C JB SAMSIZ + 0CB1 26: 89 45 10 C MOV ES:WORD PTR [DI.FILSIZ],AX + 0CB5 26: 89 55 12 C MOV ES:WORD PTR [DI.FILSIZ+2],DX + 0CB9 C SAMSIZ: + 0CB9 8B 0E 0146 R C MOV CX,[RECCNT] + 0CBD E9 0B0E R C JMP SETCLUS + C + C + 0CC0 E9 0B92 R C WRTERRJ:JMP WRTERR + C + 0CC3 C WRTEOF: + 0CC3 8B C8 C MOV CX,AX + 0CC5 0B CA C OR CX,DX + 0CC7 74 3D C JZ KILLFIL + 0CC9 2D 0001 C SUB AX,1 + 0CCC 83 DA 00 C SBB DX,0 + 0CCF F7 76 02 C DIV [BP.SECSIZ] + 0CD2 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0CD5 D3 E8 C SHR AX,CL + 0CD7 8B C8 C MOV CX,AX + 0CD9 E8 0874 R C CALL FNDCLUS + 0CDC E3 1C C JCXZ RELFILE + 0CDE E8 0DBA R C CALL ALLOCATE + 0CE1 72 DD C JC WRTERRJ + 0CE3 C UPDATE: + 0CE3 8B 3E 013E R C MOV DI,[FCB] + 0CE7 A1 0152 R C MOV AX,WORD PTR [BYTPOS] + 0CEA 26: 89 45 10 C MOV ES:WORD PTR [DI.FILSIZ],AX + 0CEE A1 0154 R C MOV AX,WORD PTR [BYTPOS+2] + 0CF1 26: 89 45 12 C MOV ES:WORD PTR [DI.FILSIZ+2],AX + 0CF5 33 C9 C XOR CX,CX + 0CF7 E9 0B1C R C JMP ADDREC + C + 0CFA C RELFILE: + 0CFA BA 0FFF C MOV DX,0FFFH + 0CFD E8 0E31 R C CALL RELBLKS + 0D00 C SETDIRT: + 0D00 C6 44 FF 01 C MOV BYTE PTR [SI-1],1 + 0D04 EB DD C JMP SHORT UPDATE + C + 0D06 C KILLFIL: + 0D06 33 DB C XOR BX,BX + 0D08 26: 87 5D 19 C XCHG BX,ES:[DI.FIRCLUS] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-42 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D0C 0B DB C OR BX,BX + 0D0E 74 D3 C JZ UPDATE + 0D10 E8 0E2F R C CALL RELEASE + 0D13 EB EB C JMP SHORT SETDIRT + C + C + 0D15 C OPTIMIZE: + C + C ; Inputs: + C ; DS = CS + C ; BX = Physical cluster + C ; CX = No. of records + C ; DL = sector within cluster + C ; BP = Base of drives parameters + C ; [NEXTADD] = transfer address + C ; Outputs: + C ; AX = No. of records remaining + C ; BX = Transfer address + C ; CX = No. or records to be transferred + C ; DX = Physical sector address + C ; DI = Next cluster + C ; Carry clear if a sector to transfer is in the buffer + C ; Carry set otherwise + C ; [CLUSNUM] = Last cluster accessed + C ; [NEXTADD] updated + C ; BP unchanged. Note that segment of transfer not set. + C + 0D15 52 C PUSH DX + 0D16 53 C PUSH BX + 0D17 8A 46 04 C MOV AL,[BP.CLUSMSK] + 0D1A FE C0 C INC AL ;Number of sectors per cluster + 0D1C 8A E0 C MOV AH,AL + 0D1E 2A C2 C SUB AL,DL ;AL = Number of sectors left in first cluster + 0D20 8B D1 C MOV DX,CX + 0D22 8B 76 12 C MOV SI,[BP.FAT] + 0D25 B9 0000 C MOV CX,0 + 0D28 C OPTCLUS: + C ;AL has number of sectors available in current cluster + C ;AH has number of sectors available in next cluster + C ;BX has current physical cluster + C ;CX has number of sequential sectors found so far + C ;DX has number of sectors left to transfer + C ;SI has FAT pointer + 0D28 E8 0157 R C CALL UNPACK + 0D2B 02 C8 C ADD CL,AL + 0D2D 80 D5 00 C ADC CH,0 + 0D30 3B CA C CMP CX,DX + 0D32 73 49 C JAE BLKDON + 0D34 8A C4 C MOV AL,AH + 0D36 43 C INC BX + 0D37 3B FB C CMP DI,BX + 0D39 74 ED C JZ OPTCLUS + 0D3B 4B C DEC BX + 0D3C C FINCLUS: + 0D3C 89 1E 014A R C MOV [CLUSNUM],BX ;Last cluster accessed +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-43 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D40 2B D1 C SUB DX,CX ;Number of sectors still needed + 0D42 52 C PUSH DX + 0D43 8B C1 C MOV AX,CX + 0D45 F7 66 02 C MUL [BP.SECSIZ] ;Number of sectors times sector size + 0D48 8B 36 0140 R C MOV SI,[NEXTADD] + 0D4C 03 C6 C ADD AX,SI ;Adjust by size of transfer + 0D4E A3 0140 R C MOV [NEXTADD],AX + 0D51 58 C POP AX ;Number of sectors still needed + 0D52 5A C POP DX ;Starting cluster + 0D53 2B DA C SUB BX,DX ;Number of new clusters accessed + 0D55 01 1E 0148 R C ADD [LASTPOS],BX + 0D59 5B C POP BX ;BL = sector postion within cluster + 0D5A E8 0D8B R C CALL FIGREC + 0D5D 8B DE C MOV BX,SI + C ;Now let's see if any of these sectors are already in the buffer + 0D5F 39 16 003B R C CMP [BUFSECNO],DX + 0D63 72 17 C JC RET100 ;If DX > [BUFSECNO] then not in buffer + 0D65 8B F2 C MOV SI,DX + 0D67 03 F1 C ADD SI,CX ;Last sector + 1 + 0D69 39 36 003B R C CMP [BUFSECNO],SI + 0D6D F5 C CMC + 0D6E 72 0C C JC RET100 ;If SI <= [BUFSECNO] then not in buffer + 0D70 50 C PUSH AX + 0D71 8A 46 00 C MOV AL,[BP.DEVNUM] + 0D74 3A 06 003D R C CMP AL,[BUFDRVNO] ;Is buffer for this drive? + 0D78 58 C POP AX + 0D79 74 01 C JZ RET100 ;If so, then we match + 0D7B F9 C STC ;No match + 0D7C C3 C RET100: RET + 0D7D C BLKDON: + 0D7D 2B CA C SUB CX,DX ;Number of sectors in cluster we don't want + 0D7F 2A E1 C SUB AH,CL ;Number of sectors in cluster we accepted + 0D81 FE CC C DEC AH ;Adjust to mean position within cluster + 0D83 88 26 0137 R C MOV [SECCLUSPOS],AH + 0D87 8B CA C MOV CX,DX ;Anyway, make the total equal to the request + 0D89 EB B1 C JMP SHORT FINCLUS + C + C + 0D8B C FIGREC: + C + C ;Inputs: + C ; DX = Physical cluster number + C ; BL = Sector postion within cluster + C ; BP = Base of drive parameters + C ;Outputs: + C ; DX = physical sector number + C ;No other registers affected. + C + 0D8B 51 C PUSH CX + 0D8C 8A 4E 05 C MOV CL,[BP.CLUSSHFT] + 0D8F 4A C DEC DX + 0D90 4A C DEC DX + 0D91 D3 E2 C SHL DX,CL + 0D93 0A D3 C OR DL,BL + 0D95 03 56 0B C ADD DX,[BP.FIRREC] +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-44 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0D98 59 C POP CX + 0D99 C3 C RET + C + 0D9A C GETREC: + C + C ; Inputs: + C ; DS:DX point to FCB + C ; Outputs: + C ; CX = 1 + C ; DX:AX = Record number determined by EXTENT and NR fields + C ; DS:DI point to FCB + C ; No other registers affected. + C + 0D9A 8B FA C MOV DI,DX + 0D9C 80 3D FF C CMP BYTE PTR [DI],-1 ;Check for extended FCB + 0D9F 75 03 C JNZ NORMFCB2 + 0DA1 83 C7 07 C ADD DI,7 + 0DA4 C NORMFCB2: + 0DA4 B9 0001 C MOV CX,1 + 0DA7 8A 45 20 C MOV AL,[DI.NR] + 0DAA 8B 55 0C C MOV DX,[DI.EXTENT] + 0DAD D0 E0 C SHL AL,1 + 0DAF D1 EA C SHR DX,1 + 0DB1 D0 D8 C RCR AL,1 + 0DB3 8A E2 C MOV AH,DL + 0DB5 8A D6 C MOV DL,DH + 0DB7 B6 00 C MOV DH,0 + 0DB9 C3 C RET + C + C + 0DBA C ALLOCATE: + C + C ; Inputs: + C ; DS = CS + C ; ES = Segment of FCB + C ; BX = Last cluster of file (0 if null file) + C ; CX = No. of clusters to allocate + C ; DX = Position of cluster BX + C ; BP = Base of drive parameters + C ; SI = FAT pointer + C ; [FCB] = Displacement of FCB within segment + C ; Outputs: + C ; IF insufficient space + C ; THEN + C ; Carry set + C ; CX = max. no. of records that could be added to file + C ; ELSE + C ; Carry clear + C ; BX = First cluster allocated + C ; FAT is fully updated including dirty bit + C ; FIRCLUS field of FCB set if file was null + C ; SI,BP unchanged. All other registers destroyed. + C + 0DBA FF 34 C PUSH [SI] + 0DBC 52 C PUSH DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-45 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0DBD 51 C PUSH CX + 0DBE 53 C PUSH BX + 0DBF 8B C3 C MOV AX,BX + 0DC1 C ALLOC: + 0DC1 8B D3 C MOV DX,BX + 0DC3 C FINDFRE: + 0DC3 43 C INC BX + 0DC4 3B 5E 0D C CMP BX,[BP.MAXCLUS] + 0DC7 7E 29 C JLE TRYOUT + 0DC9 3D 0001 C CMP AX,1 + 0DCC 7F 29 C JG TRYIN + 0DCE 5B C POP BX + 0DCF BA 0FFF C MOV DX,0FFFH + 0DD2 E8 0E31 R C CALL RELBLKS + 0DD5 58 C POP AX ;No. of clusters requested + 0DD6 2B C1 C SUB AX,CX ;AX=No. of clusters allocated + 0DD8 5A C POP DX + 0DD9 8F 04 C POP [SI] + 0DDB 42 C INC DX ;Position of first cluster allocated + 0DDC 03 C2 C ADD AX,DX ;AX=max no. of cluster in file + 0DDE 8A 56 04 C MOV DL,[BP.CLUSMSK] + 0DE1 B6 00 C MOV DH,0 + 0DE3 42 C INC DX ;DX=records/cluster + 0DE4 F7 E2 C MUL DX ;AX=max no. of records in file + 0DE6 8B C8 C MOV CX,AX + 0DE8 2B 0E 0142 R C SUB CX,WORD PTR [RECPOS] ;CX=max no. of records that could be written + 0DEC 77 02 C JA MAXREC + 0DEE 33 C9 C XOR CX,CX ;If CX was negative, zero it + 0DF0 C MAXREC: + 0DF0 F9 C STC + 0DF1 C3 C RET11: RET + C + 0DF2 C TRYOUT: + 0DF2 E8 0157 R C CALL UNPACK + 0DF5 74 0C C JZ HAVFRE + 0DF7 C TRYIN: + 0DF7 48 C DEC AX + 0DF8 7E C9 C JLE FINDFRE + 0DFA 93 C XCHG AX,BX + 0DFB E8 0157 R C CALL UNPACK + 0DFE 74 03 C JZ HAVFRE + 0E00 93 C XCHG AX,BX + 0E01 EB C0 C JMP SHORT FINDFRE + 0E03 C HAVFRE: + 0E03 87 DA C XCHG BX,DX + 0E05 8B C2 C MOV AX,DX + 0E07 E8 017F R C CALL PACK + 0E0A 8B D8 C MOV BX,AX + 0E0C E2 B3 C LOOP ALLOC + 0E0E BA 0FFF C MOV DX,0FFFH + 0E11 E8 017F R C CALL PACK + 0E14 C6 44 FF 01 C MOV BYTE PTR [SI-1],1 + 0E18 5B C POP BX + 0E19 59 C POP CX ;Don't need this stuff since we're successful + 0E1A 5A C POP DX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-46 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0E1B E8 0157 R C CALL UNPACK + 0E1E 8F 04 C POP [SI] + 0E20 87 DF C XCHG BX,DI + 0E22 0B FF C OR DI,DI + 0E24 75 CB C JNZ RET11 + 0E26 8B 3E 013E R C MOV DI,[FCB] + 0E2A 26: 89 5D 19 C MOV ES:[DI.FIRCLUS],BX + 0E2E C3 C RET12: RET + C + C + 0E2F C RELEASE: + C + C ; Inputs: + C ; DS = CS + C ; BX = Cluster in file + C ; SI = FAT pointer + C ; BP = Base of drive parameters + C ; Function: + C ; Frees cluster chain starting with [BX] + C ; AX,BX,DX,DI all destroyed. Other registers unchanged. + C + 0E2F 33 D2 C XOR DX,DX + 0E31 C RELBLKS: + C ; Enter here with DX=0FFFH to put an end-of-file mark + C ; in the first cluster and free the rest in the chain. + 0E31 E8 0157 R C CALL UNPACK + 0E34 74 F8 C JZ RET12 + 0E36 8B C7 C MOV AX,DI + 0E38 E8 017F R C CALL PACK + 0E3B 3D 0FF8 C CMP AX,0FF8H + 0E3E 8B D8 C MOV BX,AX + 0E40 72 ED C JB RELEASE + 0E42 C3 C RET13: RET + C + C + 0E43 C GETEOF: + C + C ; Inputs: + C ; BX = Cluster in a file + C ; SI = Base of drive FAT + C ; DS = CS + C ; Outputs: + C ; BX = Last cluster in the file + C ; DI destroyed. No other registers affected. + C + 0E43 E8 0157 R C CALL UNPACK + 0E46 81 FF 0FF8 C CMP DI,0FF8H + 0E4A 73 F6 C JAE RET13 + 0E4C 8B DF C MOV BX,DI + 0E4E EB F3 C JMP SHORT GETEOF + C + C + 0E50 C SRCHFRST: ;System call 17 + 0E50 E8 01C8 R C CALL GETFILE + 0E53 C SAVPLCE: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-47 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; Search-for-next enters here to save place and report + C ; findings. + 0E53 72 35 C JC KILLSRCH + 0E55 0A FF C OR BH,BH + 0E57 78 3A C JS SRCHDEV + 0E59 A1 0103 R C MOV AX,[LASTENT] + 0E5C 26: 89 45 10 C MOV ES:[DI.FILDIRENT],AX + 0E60 26: 89 6D 12 C MOV ES:[DI.DRVBP],BP + C ;Information in directory entry must be copied into the first + C ; 33 bytes starting at the disk transfer address. + 0E64 8B F3 C MOV SI,BX + 0E66 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 0E6A B8 00FF C MOV AX,00FFH + 0E6D 3A 06 012E R C CMP AL,[EXTFCB] + 0E71 75 09 C JNZ NORMFCB + 0E73 AB C STOSW + 0E74 FE C0 C INC AL + 0E76 AB C STOSW + 0E77 AB C STOSW + 0E78 A0 0116 R C MOV AL,[ATTRIB] + 0E7B AA C STOSB + 0E7C C NORMFCB: + 0E7C A0 013C R C MOV AL,[THISDRV] + 0E7F FE C0 C INC AL + 0E81 AA C STOSB ;Set drive number + 0E82 B9 0010 C MOV CX,16 + 0E85 F3/ A5 C REP MOVSW ;Copy remaining 10 characters of name + 0E87 32 C0 C XOR AL,AL + 0E89 C3 C RET + C + 0E8A C KILLSRCH: + = 0E8B C KILLSRCH1 EQU KILLSRCH+1 + C ;The purpose of the KILLSRCH1 label is to provide a jump label to the following + C ; instruction which leaves out the segment override. + 0E8A 26: C7 45 10 FFFF C MOV WORD PTR ES:[DI.FILDIRENT],-1 + 0E90 B0 FF C MOV AL,-1 + 0E92 C3 C RET + C + 0E93 C SRCHDEV: + 0E93 26: 89 5D 10 C MOV ES:[DI.FILDIRENT],BX + 0E97 C4 3E 0031 R C LES DI,DWORD PTR [DMAADD] + 0E9B 33 C0 C XOR AX,AX + 0E9D AA C STOSB ;Zero drive byte + 0E9E 83 EE 04 C SUB SI,4 ;Point to device name + 0EA1 A5 C MOVSW + 0EA2 A5 C MOVSW + 0EA3 B8 2020 C MOV AX,2020H + 0EA6 AA C STOSB + 0EA7 AB C STOSW + 0EA8 AB C STOSW + 0EA9 AB C STOSW ;Fill with 8 blanks + 0EAA 33 C0 C XOR AX,AX + 0EAC B9 000A C MOV CX,10 + 0EAF F3/ AB C REP STOSW + 0EB1 AA C STOSB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-48 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0EB2 C3 C RET14: RET + C + 0EB3 C SRCHNXT: ;System call 18 + 0EB3 E8 0372 R C CALL MOVNAME + 0EB6 8B FA C MOV DI,DX + 0EB8 72 D1 C JC NEAR PTR KILLSRCH1 + 0EBA 8B 6D 12 C MOV BP,[DI.DRVBP] + 0EBD 8B 45 10 C MOV AX,[DI.FILDIRENT] + 0EC0 0B C0 C OR AX,AX + 0EC2 78 C7 C JS NEAR PTR KILLSRCH1 + 0EC4 52 C PUSH DX + 0EC5 1E C PUSH DS + 0EC6 0E C PUSH CS + 0EC7 1F C POP DS + 0EC8 A3 0103 R C MOV [LASTENT],AX + 0ECB E8 01E6 R C CALL CONTSRCH + 0ECE 07 C POP ES + 0ECF 5F C POP DI + 0ED0 EB 81 C JMP SAVPLCE + C + C + 0ED2 C FILESIZE: ;System call 35 + 0ED2 E8 01C8 R C CALL GETFILE + 0ED5 B0 FF C MOV AL,-1 + 0ED7 72 D9 C JC RET14 + 0ED9 83 C7 21 C ADD DI,33 ;Write size in RR field + 0EDC 26: 8B 4D ED C MOV CX,ES:[DI.RECSIZ-33] + 0EE0 0B C9 C OR CX,CX + 0EE2 75 03 C JNZ RECOK + 0EE4 B9 0080 C MOV CX,128 + 0EE7 C RECOK: + 0EE7 33 C0 C XOR AX,AX + 0EE9 33 D2 C XOR DX,DX ;Intialize size to zero + 0EEB 0A FF C OR BH,BH ;Check for named I/O device + 0EED 78 14 C JS DEVSIZ + 0EEF 46 C INC SI + 0EF0 46 C INC SI ;Point to length field + 0EF1 8B 44 02 C MOV AX,[SI+2] ;Get high word of size + 0EF4 F7 F1 C DIV CX + 0EF6 50 C PUSH AX ;Save high part of result + 0EF7 AD C LODSW ;Get low word of size + 0EF8 F7 F1 C DIV CX + 0EFA 0B D2 C OR DX,DX ;Check for zero remainder + 0EFC 5A C POP DX + 0EFD 74 04 C JZ DEVSIZ + 0EFF 40 C INC AX ;Round up for partial record + 0F00 75 01 C JNZ DEVSIZ ;Propagate carry? + 0F02 42 C INC DX + 0F03 C DEVSIZ: + 0F03 AB C STOSW + 0F04 8B C2 C MOV AX,DX + 0F06 AA C STOSB + 0F07 B0 00 C MOV AL,0 + 0F09 83 F9 40 C CMP CX,64 + 0F0C 73 A4 C JAE RET14 ;Only 3-byte field if RECSIZ >= 64 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-49 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0F0E 26: 88 25 C MOV ES:[DI],AH + 0F11 C3 C RET + C + C + 0F12 C SETDMA: ;System call 26 + 0F12 2E: 89 16 0031 R C MOV CS:[DMAADD],DX + 0F17 2E: 8C 1E 0033 R C MOV CS:[DMAADD+2],DS + 0F1C C3 C RET + C + 0F1D C NOSUCHDRV: + 0F1D B0 FF C MOV AL,-1 + 0F1F C3 C RET + C + 0F20 C GETFATPT: ;System call 27 + 0F20 B2 00 C MOV DL,0 ;Use default drive + C + 0F22 C GETFATPTDL: ;System call 28 + 0F22 0E C PUSH CS + 0F23 1F C POP DS + 0F24 8A C2 C MOV AL,DL + 0F26 E8 03B9 R C CALL GETTHISDRV + 0F29 72 F2 C JC NOSUCHDRV + 0F2B E8 042C R C CALL FATREAD + 0F2E 8B 5E 12 C MOV BX,[BP.FAT] + 0F31 8A 46 04 C MOV AL,[BP.CLUSMSK] + 0F34 FE C0 C INC AL + 0F36 8B 56 0D C MOV DX,[BP.MAXCLUS] + 0F39 4A C DEC DX + 0F3A 8B 4E 02 C MOV CX,[BP.SECSIZ] + 0F3D C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0F41 89 5C 02 C MOV [SI.BXSAVE],BX + 0F44 89 54 06 C MOV [SI.DXSAVE],DX + 0F47 89 4C 04 C MOV [SI.CXSAVE],CX + 0F4A 8C 4C 0E C MOV [SI.DSSAVE],CS + 0F4D C3 C RET + C + C + 0F4E C GETDSKPT: ;System call 31 + 0F4E 0E C PUSH CS + 0F4F 1F C POP DS + 0F50 A0 004A R C MOV AL,[CURDRV] + 0F53 A2 013C R C MOV [THISDRV],AL + 0F56 E8 042C R C CALL FATREAD + 0F59 C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] + 0F5D 89 6C 02 C MOV [SI.BXSAVE],BP + 0F60 8C 4C 0E C MOV [SI.DSSAVE],CS + 0F63 C3 C RET + C + C + 0F64 C DSKRESET: ;System call 13 + 0F64 0E C PUSH CS + 0F65 1F C POP DS + 0F66 C WRTFATS: + C ; DS=CS. Writes back all dirty FATs. All registers destroyed. + 0F66 32 C0 C XOR AL,AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-50 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0F68 86 06 003E R C XCHG AL,[DIRTYBUF] + 0F6C 0A C0 C OR AL,AL + 0F6E 74 12 C JZ NOBUF + 0F70 8B 2E 003F R C MOV BP,[BUFDRVBP] + 0F74 8B 16 003B R C MOV DX,[BUFSECNO] + 0F78 8B 1E 0039 R C MOV BX,[BUFFER] + 0F7C B9 0001 C MOV CX,1 + 0F7F E8 068C R C CALL DWRITE + 0F82 C NOBUF: + 0F82 8A 0E 002D R C MOV CL,[NUMIO] + 0F86 B5 00 C MOV CH,0 + 0F88 8B 2E 004B R C MOV BP,[DRVTAB] + 0F8C C WRTFAT: + 0F8C 51 C PUSH CX + 0F8D E8 051F R C CALL CHKFATWRT + 0F90 59 C POP CX + 0F91 83 C5 14 C ADD BP,DPBSIZ + 0F94 E2 F6 C LOOP WRTFAT + 0F96 C3 C RET + C + C + 0F97 C GETDRV: ;System call 25 + 0F97 2E: A0 004A R C MOV AL,CS:[CURDRV] + 0F9B C3 C RET15: RET + C + C + 0F9C C SETRNDREC: ;System call 36 + 0F9C E8 0D9A R C CALL GETREC + 0F9F 89 45 21 C MOV [DI+33],AX + 0FA2 88 55 23 C MOV [DI+35],DL + 0FA5 83 7D 0E 40 C CMP [DI.RECSIZ],64 + 0FA9 73 F0 C JAE RET15 + 0FAB 88 75 24 C MOV [DI+36],DH ;Set 4th byte only if record size < 64 + 0FAE C3 C RET16: RET + C + C + 0FAF C SELDSK: ;System call 14 + 0FAF 2E: A0 002C R C MOV AL,CS:[NUMDRV] + 0FB3 3A D0 C CMP DL,AL + 0FB5 73 05 C JNB RET17 + 0FB7 2E: 88 16 004A R C MOV CS:[CURDRV],DL + 0FBC C3 C RET17: RET + C + 0FBD C BUFIN: ;System call 10 + 0FBD 8C C8 C MOV AX,CS + 0FBF 8E C0 C MOV ES,AX + 0FC1 8B F2 C MOV SI,DX + 0FC3 B5 00 C MOV CH,0 + 0FC5 AD C LODSW + 0FC6 0A C0 C OR AL,AL + 0FC8 74 F2 C JZ RET17 + 0FCA 8A DC C MOV BL,AH + 0FCC 8A FD C MOV BH,CH + 0FCE 3A C3 C CMP AL,BL + 0FD0 76 05 C JBE NOEDIT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-51 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0FD2 80 38 0D C CMP BYTE PTR [BX+SI],0DH + 0FD5 74 02 C JZ EDITON + 0FD7 C NOEDIT: + 0FD7 8A DD C MOV BL,CH + 0FD9 C EDITON: + 0FD9 8A D0 C MOV DL,AL + 0FDB 4A C DEC DX + 0FDC C NEWLIN: + 0FDC 2E: A0 0028 R C MOV AL,CS:[CARPOS] + 0FE0 2E: A2 0029 R C MOV CS:[STARTPOS],AL + 0FE4 56 C PUSH SI + 0FE5 BF 0000 R C MOV DI,OFFSET DOSGROUP:INBUF + 0FE8 8A E5 C MOV AH,CH + 0FEA 8A FD C MOV BH,CH + 0FEC 8A F5 C MOV DH,CH + 0FEE C GETCH: + 0FEE E8 125C R C CALL IN + 0FF1 3C 06 C CMP AL,"F"-"@" ;Ignore ^F + 0FF3 74 F9 C JZ GETCH + 0FF5 2E: 3A 06 0003 R C CMP AL,CS:ESCCHAR + 0FFA 74 32 C JZ ESC + 0FFC 3C 7F C CMP AL,7FH + 0FFE 74 7E C JZ BACKSP + 1000 3C 08 C CMP AL,8 + 1002 74 7A C JZ BACKSP + 1004 3C 0D C CMP AL,13 + 1006 74 3A C JZ ENDLIN + 1008 3C 0A C CMP AL,10 + 100A 74 5A C JZ PHYCRLF + 100C 3C 18 C CMP AL,CANCEL + 100E 74 5B C JZ KILNEW + 1010 C SAVCH: + 1010 3A F2 C CMP DH,DL + 1012 73 13 C JAE BUFFUL + 1014 AA C STOSB + 1015 FE C6 C INC DH + 1017 E8 117D R C CALL BUFOUT + 101A 0A E4 C OR AH,AH + 101C 75 D0 C JNZ GETCH + 101E 3A FB C CMP BH,BL + 1020 73 CC C JAE GETCH + 1022 46 C INC SI + 1023 FE C7 C INC BH + 1025 EB C7 C JMP SHORT GETCH + C + 1027 C BUFFUL: + 1027 B0 07 C MOV AL,7 + 1029 E8 119F R C CALL OUT + 102C EB C0 C JMP SHORT GETCH + C + 102E C ESC: + 102E E8 125C R C CALL IN + 1031 B1 0C C MOV CL,ESCTABLEN + 1033 57 C PUSH DI + 1034 BF 0004 R C MOV DI,OFFSET DOSGROUP:ESCTAB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-52 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1037 F2/ AE C REPNE SCASB + 1039 5F C POP DI + 103A D1 E1 C SHL CX,1 + 103C 8B E9 C MOV BP,CX + 103E FF A6 1165 R C JMP [BP+OFFSET DOSGROUP:ESCFUNC] + C + 1042 C ENDLIN: + 1042 AA C STOSB + 1043 E8 119F R C CALL OUT + 1046 5F C POP DI + 1047 88 75 FF C MOV [DI-1],DH + 104A FE C6 C INC DH + 104C C COPYNEW: + 104C 8C C5 C MOV BP,ES + 104E 8C DB C MOV BX,DS + 1050 8E C3 C MOV ES,BX + 1052 8E DD C MOV DS,BP + 1054 BE 0000 R C MOV SI,OFFSET DOSGROUP:INBUF + 1057 8A CE C MOV CL,DH + 1059 F3/ A4 C REP MOVSB + 105B C3 C RET + 105C C CRLF: + 105C B0 0D C MOV AL,13 + 105E E8 119F R C CALL OUT + 1061 B0 0A C MOV AL,10 + 1063 E9 119F R C JMP OUT + C + 1066 C PHYCRLF: + 1066 E8 105C R C CALL CRLF + 1069 EB 83 C JMP SHORT GETCH + C + 106B C KILNEW: + 106B B0 5C C MOV AL,"\" + 106D E8 119F R C CALL OUT + 1070 5E C POP SI + 1071 C PUTNEW: + 1071 E8 105C R C CALL CRLF + 1074 2E: A0 0029 R C MOV AL,CS:[STARTPOS] + 1078 E8 1228 R C CALL TAB + 107B E9 0FDC R C JMP NEWLIN + C + 107E C BACKSP: + 107E 0A F6 C OR DH,DH + 1080 74 11 C JZ OLDBAK + 1082 E8 10D3 R C CALL BACKUP + 1085 26: 8A 05 C MOV AL,ES:[DI] + 1088 3C 20 C CMP AL," " + 108A 73 07 C JAE OLDBAK + 108C 3C 09 C CMP AL,9 + 108E 74 11 C JZ BAKTAB + 1090 E8 10D6 R C CALL BACKMES + 1093 C OLDBAK: + 1093 0A E4 C OR AH,AH + 1095 75 07 C JNZ GETCH1 + 1097 0A FF C OR BH,BH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-53 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1099 74 03 C JZ GETCH1 + 109B FE CF C DEC BH + 109D 4E C DEC SI + 109E C GETCH1: + 109E E9 0FEE R C JMP GETCH + 10A1 C BAKTAB: + 10A1 57 C PUSH DI + 10A2 4F C DEC DI + 10A3 FD C STD + 10A4 8A CE C MOV CL,DH + 10A6 B0 20 C MOV AL," " + 10A8 53 C PUSH BX + 10A9 B3 07 C MOV BL,7 + 10AB E3 0E C JCXZ FIGTAB + 10AD C FNDPOS: + 10AD AE C SCASB + 10AE 76 09 C JNA CHKCNT + 10B0 26: 80 7D 01 09 C CMP ES:BYTE PTR [DI+1],9 + 10B5 74 09 C JZ HAVTAB + 10B7 FE CB C DEC BL + 10B9 C CHKCNT: + 10B9 E2 F2 C LOOP FNDPOS + 10BB C FIGTAB: + 10BB 2E: 2A 1E 0029 R C SUB BL,CS:[STARTPOS] + 10C0 C HAVTAB: + 10C0 2A DE C SUB BL,DH + 10C2 02 CB C ADD CL,BL + 10C4 80 E1 07 C AND CL,7 + 10C7 FC C CLD + 10C8 5B C POP BX + 10C9 5F C POP DI + 10CA 74 C7 C JZ OLDBAK + 10CC C TABBAK: + 10CC E8 10D6 R C CALL BACKMES + 10CF E2 FB C LOOP TABBAK + 10D1 EB C0 C JMP SHORT OLDBAK + 10D3 C BACKUP: + 10D3 FE CE C DEC DH + 10D5 4F C DEC DI + 10D6 C BACKMES: + 10D6 B0 08 C MOV AL,8 + 10D8 E8 119F R C CALL OUT + 10DB B0 20 C MOV AL," " + 10DD E8 119F R C CALL OUT + 10E0 B0 08 C MOV AL,8 + 10E2 E9 119F R C JMP OUT + C + 10E5 C TWOESC: + 10E5 B0 1B C MOV AL,ESCCH + 10E7 E9 1010 R C JMP SAVCH + C + 10EA C COPYLIN: + 10EA 8A CB C MOV CL,BL + 10EC 2A CF C SUB CL,BH + 10EE EB 07 C JMP SHORT COPYEACH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-54 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 10F0 C COPYSTR: + 10F0 E8 1123 R C CALL FINDOLD + 10F3 EB 02 C JMP SHORT COPYEACH + C + 10F5 C COPYONE: + 10F5 B1 01 C MOV CL,1 + 10F7 C COPYEACH: + 10F7 B4 00 C MOV AH,0 + 10F9 3A F2 C CMP DH,DL + 10FB 74 0F C JZ GETCH2 + 10FD 3A FB C CMP BH,BL + 10FF 74 0B C JZ GETCH2 + 1101 AC C LODSB + 1102 AA C STOSB + 1103 E8 117D R C CALL BUFOUT + 1106 FE C7 C INC BH + 1108 FE C6 C INC DH + 110A E2 EB C LOOP COPYEACH + 110C C GETCH2: + 110C E9 0FEE R C JMP GETCH + C + 110F C SKIPONE: + 110F 3A FB C CMP BH,BL + 1111 74 F9 C JZ GETCH2 + 1113 FE C7 C INC BH + 1115 46 C INC SI + 1116 E9 0FEE R C JMP GETCH + C + 1119 C SKIPSTR: + 1119 E8 1123 R C CALL FINDOLD + 111C 03 F1 C ADD SI,CX + 111E 02 F9 C ADD BH,CL + 1120 E9 0FEE R C JMP GETCH + C + 1123 C FINDOLD: + 1123 E8 125C R C CALL IN + 1126 8A CB C MOV CL,BL + 1128 2A CF C SUB CL,BH + 112A 74 17 C JZ NOTFND + 112C 49 C DEC CX + 112D 74 14 C JZ NOTFND + 112F 06 C PUSH ES + 1130 1E C PUSH DS + 1131 07 C POP ES + 1132 57 C PUSH DI + 1133 8B FE C MOV DI,SI + 1135 47 C INC DI + 1136 F2/ AE C REPNE SCASB + 1138 5F C POP DI + 1139 07 C POP ES + 113A 75 07 C JNZ NOTFND + 113C F6 D1 C NOT CL + 113E 02 CB C ADD CL,BL + 1140 2A CF C SUB CL,BH +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-55 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1142 C3 C RET30: RET + 1143 C NOTFND: + 1143 5D C POP BP + 1144 E9 0FEE R C JMP GETCH + C + 1147 C REEDIT: + 1147 B0 40 C MOV AL,"@" + 1149 E8 119F R C CALL OUT + 114C 5F C POP DI + 114D 57 C PUSH DI + 114E 06 C PUSH ES + 114F 1E C PUSH DS + 1150 E8 104C R C CALL COPYNEW + 1153 1F C POP DS + 1154 07 C POP ES + 1155 5E C POP SI + 1156 8A DE C MOV BL,DH + 1158 E9 1071 R C JMP PUTNEW + C + 115B C ENTERINS: + C ENDIF + C IF NOT TOGLINS + 115B B4 FF C MOV AH,-1 + 115D E9 0FEE R C JMP GETCH + C + 1160 C EXITINS: + 1160 B4 00 C MOV AH,0 + 1162 E9 0FEE R C JMP GETCH + C ENDIF + C + 1165 0FEE R C ESCFUNC DW GETCH + 1167 10E5 R C DW TWOESC + C IF NOT TOGLINS + 1169 1160 R C DW EXITINS + C ENDIF + 116B 115B R C DW ENTERINS + 116D 107E R C DW BACKSP + 116F 1147 R C DW REEDIT + 1171 106B R C DW KILNEW + 1173 10EA R C DW COPYLIN + 1175 1119 R C DW SKIPSTR + 1177 10F0 R C DW COPYSTR + 1179 110F R C DW SKIPONE + 117B 10F5 R C DW COPYONE + C + C ENDIF + 117D C BUFOUT: + 117D 3C 20 C CMP AL," " + 117F 73 1E C JAE OUT + 1181 3C 09 C CMP AL,9 + 1183 74 1A C JZ OUT + 1185 50 C PUSH AX + 1186 B0 5E C MOV AL,"^" + 1188 E8 119F R C CALL OUT + 118B 58 C POP AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-56 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 118C 0C 40 C OR AL,40H + 118E EB 0F C JMP SHORT OUT + C + 1190 C NOSTOP: + 1190 3C 10 C CMP AL,"P"-"@" + 1192 74 40 C JZ INCHK + C IF NOT TOGLPRN + 1194 3C 0E C CMP AL,"N"-"@" + 1196 74 3C C JZ INCHK + C ENDIF + 1198 3C 03 C CMP AL,"C"-"@" + 119A 74 38 C JZ INCHK + 119C C3 C RET + C + 119D C CONOUT: ;System call 2 + 119D 8A C2 C MOV AL,DL + 119F C OUT: + 119F 3C 20 C CMP AL,20H + 11A1 72 71 C JB CTRLOUT + 11A3 3C 7F C CMP AL,7FH + 11A5 74 05 C JZ OUTCH + 11A7 2E: FE 06 0028 R C INC CS:BYTE PTR [CARPOS] + 11AC C OUTCH: + 11AC 50 C PUSH AX + 11AD E8 11C4 R C CALL STATCHK + 11B0 58 C POP AX + 11B1 9A 0009 ---- R C CALL FAR PTR BIOSOUT + 11B6 2E: F6 06 002A R FF C TEST CS:BYTE PTR [PFLAG],-1 + 11BC 74 05 C JZ RET18 + 11BE 9A 000C ---- R C CALL FAR PTR BIOSPRINT + 11C3 C3 C RET18: RET + C + 11C4 C STATCHK: + 11C4 9A 0003 ---- R C CALL FAR PTR BIOSSTAT + 11C9 74 F8 C JZ RET18 + 11CB 3C 13 C CMP AL,'S'-'@' + 11CD 75 C1 C JNZ NOSTOP + 11CF 9A 0006 ---- R C CALL FAR PTR BIOSIN ;Eat Cntrl-S + 11D4 C INCHK: + 11D4 9A 0006 ---- R C CALL FAR PTR BIOSIN + 11D9 3C 10 C CMP AL,'P'-'@' + 11DB 74 29 C JZ PRINTON + C IF NOT TOGLPRN + 11DD 3C 0E C CMP AL,'N'-'@' + 11DF 74 2C C JZ PRINTOFF + C ENDIF + 11E1 3C 03 C CMP AL,'C'-'@' + 11E3 75 DE C JNZ RET18 + C ; Ctrl-C handler. + C ; "^C" and CR/LF is printed. Then the user registers are restored and the + C ; user CTRL-C handler is executed. At this point the top of the stack has + C ; 1) the interrupt return address should the user CTRL-C handler wish to + C ; allow processing to continue; 2) the original interrupt return address + C ; to the code that performed the function call in the first place. If the + C ; user CTRL-C handler wishes to continue, it must leave all registers +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-57 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ; unchanged and IRET. The function that was interrupted will simply be + C ; repeated. + 11E5 B0 03 C MOV AL,3 ;Display "^C" + 11E7 E8 117D R C CALL BUFOUT + 11EA E8 105C R C CALL CRLF + 11ED FA C CLI ;Prepare to play with stack + 11EE 2E: 8E 16 0133 R C MOV SS,CS:[SSSAVE] + 11F3 2E: 8B 26 0131 R C MOV SP,CS:[SPSAVE] ;User stack now restored + 11F8 58 C POP AX + 11F9 5B C POP BX + 11FA 59 C POP CX + 11FB 5A C POP DX + 11FC 5E C POP SI + 11FD 5F C POP DI + 11FE 5D C POP BP + 11FF 1F C POP DS + 1200 07 C POP ES ;User registers now restored + 1201 CD 23 C INT CONTC ;Execute user Ctrl-C handler + 1203 E9 004F R C JMP COMMAND ;Repeat command otherwise + C + 1206 C PRINTON: + C ENDIF + C IF NOT TOGLPRN + 1206 2E: C6 06 002A R 01 C MOV CS:BYTE PTR [PFLAG],1 + 120C C3 C RET + C + 120D C PRINTOFF: + 120D 2E: C6 06 002A R 00 C MOV CS:BYTE PTR [PFLAG],0 + 1213 C3 C RET + C ENDIF + C + 1214 C CTRLOUT: + 1214 3C 0D C CMP AL,13 + 1216 74 20 C JZ ZERPOS + 1218 3C 08 C CMP AL,8 + 121A 74 25 C JZ BACKPOS + 121C 3C 09 C CMP AL,9 + 121E 75 1E C JNZ OUTCHJ + 1220 2E: A0 0028 R C MOV AL,CS:[CARPOS] + 1224 0C F8 C OR AL,0F8H + 1226 F6 D8 C NEG AL + 1228 C TAB: + 1228 51 C PUSH CX + 1229 8A C8 C MOV CL,AL + 122B B5 00 C MOV CH,0 + 122D E3 07 C JCXZ POPTAB + 122F C TABLP: + 122F B0 20 C MOV AL," " + 1231 E8 119F R C CALL OUT + 1234 E2 F9 C LOOP TABLP + 1236 C POPTAB: + 1236 59 C POP CX + 1237 C3 C RET19: RET + C + 1238 C ZERPOS: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-58 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1238 2E: C6 06 0028 R 00 C MOV CS:BYTE PTR [CARPOS],0 + 123E E9 11AC R C OUTCHJ: JMP OUTCH + C + 1241 C BACKPOS: + 1241 2E: FE 0E 0028 R C DEC CS:BYTE PTR [CARPOS] + 1246 E9 11AC R C JMP OUTCH + C + C + 1249 C CONSTAT: ;System call 11 + 1249 E8 11C4 R C CALL STATCHK + 124C B0 00 C MOV AL,0 + 124E 74 E7 C JZ RET19 + 1250 0C FF C OR AL,-1 + 1252 C3 C RET + C + C + 1253 C CONIN: ;System call 1 + 1253 E8 125C R C CALL IN + 1256 50 C PUSH AX + 1257 E8 119F R C CALL OUT + 125A 58 C POP AX + 125B C3 C RET + C + C + 125C C IN: ;System call 8 + 125C E8 11D4 R C CALL INCHK + 125F 74 FB C JZ IN + 1261 C3 C RET29: RET + C + 1262 C RAWIO: ;System call 6 + 1262 8A C2 C MOV AL,DL + 1264 3C FF C CMP AL,-1 + 1266 75 1D C JNZ RAWOUT + 1268 2E: C5 36 0131 R C LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area + 126D 9A 0003 ---- R C CALL FAR PTR BIOSSTAT + 1272 75 07 C JNZ RESFLG + 1274 80 4C 16 40 C OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag + 1278 32 C0 C XOR AL,AL + 127A C3 C RET + C + 127B C RESFLG: + 127B 80 64 16 BF C AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag + 127F C RAWINP: ;System call 7 + 127F 9A 0006 ---- R C CALL FAR PTR BIOSIN + 1284 C3 C RET + 1285 C RAWOUT: + 1285 9A 0009 ---- R C CALL FAR PTR BIOSOUT + 128A C3 C RET + C + 128B C LIST: ;System call 5 + 128B 8A C2 C MOV AL,DL + 128D C LISTOUT: + 128D 50 C PUSH AX + 128E E8 11C4 R C CALL STATCHK + 1291 58 C POP AX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-59 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1292 9A 000C ---- R C CALL FAR PTR BIOSPRINT + 1297 C3 C RET20: RET + C + 1298 C PRTBUF: ;System call 9 + 1298 8B F2 C MOV SI,DX + 129A C OUTSTR: + 129A AC C LODSB + 129B 3C 24 C CMP AL,"$" + 129D 74 F8 C JZ RET20 + 129F E8 119F R C CALL OUT + 12A2 EB F6 C JMP SHORT OUTSTR + C + 12A4 C OUTMES: ;String output for internal messages + 12A4 2E: AC C LODS CS:BYTE PTR [SI] + 12A6 3C 24 C CMP AL,"$" + 12A8 74 ED C JZ RET20 + 12AA E8 119F R C CALL OUT + 12AD EB F5 C JMP SHORT OUTMES + C + C + 12AF C MAKEFCB: ;Interrupt call 41 + = 0002 C DRVBIT EQU 2 + = 0004 C NAMBIT EQU 4 + = 0008 C EXTBIT EQU 8 + 12AF B2 00 C MOV DL,0 ;Flag--not ambiguous file name + 12B1 A8 02 C TEST AL,DRVBIT ;Use current drive field if default? + 12B3 75 04 C JNZ DEFDRV + 12B5 26: C6 05 00 C MOV BYTE PTR ES:[DI],0 ;No - use default drive + 12B9 C DEFDRV: + 12B9 47 C INC DI + 12BA B9 0008 C MOV CX,8 + 12BD A8 04 C TEST AL,NAMBIT ;Use current name fiels as defualt? + 12BF 93 C XCHG AX,BX ;Save bits in BX + 12C0 B0 20 C MOV AL," " + 12C2 74 04 C JZ FILLB ;If not, go fill with blanks + 12C4 03 F9 C ADD DI,CX + 12C6 33 C9 C XOR CX,CX ;Don't fill any + 12C8 C FILLB: + 12C8 F3/ AA C REP STOSB + 12CA B1 03 C MOV CL,3 + 12CC F6 C3 08 C TEST BL,EXTBIT ;Use current extension as default + 12CF 74 04 C JZ FILLB2 + 12D1 03 F9 C ADD DI,CX + 12D3 33 C9 C XOR CX,CX + 12D5 C FILLB2: + 12D5 F3/ AA C REP STOSB + 12D7 91 C XCHG AX,CX ;Put zero in AX + 12D8 AB C STOSW + 12D9 AB C STOSW ;Initialize two words after to zero + 12DA 83 EF 10 C SUB DI,16 ;Point back at start + 12DD F6 C3 01 C TEST BL,1 ;Scan off separators if not zero + 12E0 74 09 C JZ SKPSPC + 12E2 E8 1352 R C CALL SCANB ;Peel off blanks and tabs + 12E5 E8 137F R C CALL DELIM ;Is it a one-time-only delimiter? + 12E8 75 04 C JNZ NOSCAN +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-60 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 12EA 46 C INC SI ;Skip over the delimiter + 12EB C SKPSPC: + 12EB E8 1352 R C CALL SCANB ;Always kill preceding blanks and tabs + 12EE C NOSCAN: + 12EE E8 135A R C CALL GETLET + 12F1 76 16 C JBE NODRV ;Quit if termination character + 12F3 80 3C 3A C CMP BYTE PTR[SI],":" ;Check for potential drive specifier + 12F6 75 11 C JNZ NODRV + 12F8 46 C INC SI ;Skip over colon + 12F9 2C 40 C SUB AL,"@" ;Convert drive letter to binary drive number + 12FB 76 07 C JBE BADDRV ;Valid drive numbers are 1-15 + 12FD 2E: 3A 06 002C R C CMP AL,CS:[NUMDRV] + 1302 76 02 C JBE HAVDRV + 1304 C BADDRV: + 1304 B2 FF C MOV DL,-1 + 1306 C HAVDRV: + 1306 AA C STOSB ;Put drive specifier in first byte + 1307 46 C INC SI + 1308 4F C DEC DI ;Counteract next two instructions + 1309 C NODRV: + 1309 4E C DEC SI ;Back up + 130A 47 C INC DI ;Skip drive byte + 130B B9 0008 C MOV CX,8 + 130E E8 132C R C CALL GETWORD ;Get 8-letter file name + 1311 80 3C 2E C CMP BYTE PTR [SI],"." + 1314 75 07 C JNZ NODOT + 1316 46 C INC SI ;Skip over dot if present + 1317 B9 0003 C MOV CX,3 ;Get 3-letter extension + 131A E8 1332 R C CALL MUSTGETWORD + 131D C NODOT: + 131D 2E: C5 1E 0131 R C LDS BX,CS:DWORD PTR [SPSAVE] + 1322 89 77 08 C MOV [BX.SISAVE],SI + 1325 8A C2 C MOV AL,DL + 1327 C3 C RET + C + 1328 C NONAM: + 1328 03 F9 C ADD DI,CX + 132A 4E C DEC SI + 132B C3 C RET + C + 132C C GETWORD: + 132C E8 135A R C CALL GETLET + 132F 76 F7 C JBE NONAM ;Exit if invalid character + 1331 4E C DEC SI + 1332 C MUSTGETWORD: + 1332 E8 135A R C CALL GETLET + 1335 76 15 C JBE FILLNAM + 1337 E3 F9 C JCXZ MUSTGETWORD + 1339 49 C DEC CX + 133A 3C 2A C CMP AL,"*" ;Check for ambiguous file specifier + 133C 75 04 C JNZ NOSTAR + 133E B0 3F C MOV AL,"?" + 1340 F3/ AA C REP STOSB + 1342 C NOSTAR: + 1342 AA C STOSB +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-61 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1343 3C 3F C CMP AL,"?" + 1345 75 EB C JNZ MUSTGETWORD + 1347 80 CA 01 C OR DL,1 ;Flag ambiguous file name + 134A EB E6 C JMP MUSTGETWORD + 134C C FILLNAM: + 134C B0 20 C MOV AL," " + 134E F3/ AA C REP STOSB + 1350 4E C DEC SI + 1351 C3 C RET21: RET + C + 1352 C SCANB: + 1352 AC C LODSB + 1353 E8 138F R C CALL SPCHK + 1356 74 FA C JZ SCANB + 1358 4E C DEC SI + 1359 C3 C RET + C + 135A C GETLET: + C ;Get a byte from [SI], convert it to upper case, and compare for delimiter. + C ;ZF set if a delimiter, CY set if a control character (other than TAB). + 135A AC C LODSB + 135B 24 7F C AND AL,7FH + 135D 3C 61 C CMP AL,"a" + 135F 72 06 C JB CHK + 1361 3C 7A C CMP AL,"z" + 1363 77 02 C JA CHK + 1365 2C 20 C SUB AL,20H ;Convert to upper case + 1367 C CHK: + 1367 3C 2E C CMP AL,"." + 1369 74 E6 C JZ RET21 + 136B 3C 22 C CMP AL,'"' + 136D 74 E2 C JZ RET21 + 136F 3C 2F C CMP AL,"/" + 1371 74 DE C JZ RET21 + 1373 3C 5B C CMP AL,"[" + 1375 74 DA C JZ RET21 + 1377 3C 5D C CMP AL,"]" + 1379 74 D6 C JZ RET21 + C + C ENDIF + 137B 3C 3A C CMP AL,":" ;Allow ":" as separator in IBM version + 137D 74 D2 C JZ RET21 + C IF NOT IBM + 137F C DELIM: + C ENDIF + C + 137F 3C 2B C CMP AL,"+" + 1381 74 12 C JZ RET101 + 1383 3C 3D C CMP AL,"=" + 1385 74 0E C JZ RET101 + 1387 3C 3B C CMP AL,";" + 1389 74 0A C JZ RET101 + 138B 3C 2C C CMP AL,"," + 138D 74 06 C JZ RET101 + 138F C SPCHK: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-62 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 138F 3C 09 C CMP AL,9 ;Filter out tabs too + 1391 74 02 C JZ RET101 + C ;WARNING! " " MUST be the last compare + 1393 3C 20 C CMP AL," " + 1395 C3 C RET101: RET + C + 1396 C SETVECT: ; Interrupt call 37 + 1396 33 DB C XOR BX,BX + 1398 8E C3 C MOV ES,BX + 139A 8A D8 C MOV BL,AL + 139C D1 E3 C SHL BX,1 + 139E D1 E3 C SHL BX,1 + 13A0 26: 89 17 C MOV ES:[BX],DX + 13A3 26: 8C 5F 02 C MOV ES:[BX+2],DS + 13A7 C3 C RET + C + C + 13A8 C NEWBASE: ; Interrupt call 38 + 13A8 8E C2 C MOV ES,DX + 13AA 2E: C5 36 0131 R C LDS SI,CS:DWORD PTR [SPSAVE] + 13AF 8E 5C 14 C MOV DS,[SI.CSSAVE] + 13B2 33 F6 C XOR SI,SI + 13B4 8B FE C MOV DI,SI + 13B6 A1 0002 C MOV AX,DS:[2] + 13B9 B9 0080 C MOV CX,80H + 13BC F3/ A5 C REP MOVSW + C + 13BE C SETMEM: + C + C ; Inputs: + C ; AX = Size of memory in paragraphs + C ; DX = Segment + C ; Function: + C ; Completely prepares a program base at the + C ; specified segment. + C ; Outputs: + C ; DS = DX + C ; ES = DX + C ; [0] has INT 20H + C ; [2] = First unavailable segment ([ENDMEM]) + C ; [5] to [9] form a long call to the entry point + C ; [10] to [13] have exit address (from INT 22H) + C ; [14] to [17] have ctrl-C exit address (from INT 23H) + C ; [18] to [21] have fatal error address (from INT 24H) + C ; DX,BP unchanged. All other registers destroyed. + C + 13BE 33 C9 C XOR CX,CX + 13C0 8E D9 C MOV DS,CX + 13C2 8E C2 C MOV ES,DX + 13C4 BE 0088 C MOV SI,EXIT + 13C7 BF 000A C MOV DI,SAVEXIT + 13CA A5 C MOVSW + 13CB A5 C MOVSW + 13CC A5 C MOVSW + 13CD A5 C MOVSW +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-63 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 13CE A5 C MOVSW + 13CF A5 C MOVSW + 13D0 26: A3 0002 C MOV ES:[2],AX + 13D4 2B C2 C SUB AX,DX + 13D6 3D 0FFF C CMP AX,MAXDIF + 13D9 76 03 C JBE HAVDIF + 13DB B8 0FFF C MOV AX,MAXDIF + 13DE C HAVDIF: + 13DE BB 000C C MOV BX,ENTRYPOINTSEG + 13E1 2B D8 C SUB BX,AX + 13E3 D1 E0 C SHL AX,1 + 13E5 D1 E0 C SHL AX,1 + 13E7 D1 E0 C SHL AX,1 + 13E9 D1 E0 C SHL AX,1 + 13EB 8E DA C MOV DS,DX + 13ED A3 0006 C MOV DS:[6],AX + 13F0 89 1E 0008 C MOV DS:[8],BX + 13F4 C7 06 0000 20CD C MOV DS:[0],20CDH ;"INT INTTAB" + 13FA C6 06 0005 9A C MOV DS:(BYTE PTR [5]),LONGCALL + 13FF C3 C RET + C + 1400 C DATE16: + 1400 51 C PUSH CX + 1401 E8 1427 R C CALL READTIME + 1404 D0 E1 C SHL CL,1 ;Minutes to left part of byte + 1406 D0 E1 C SHL CL,1 + 1408 D1 E1 C SHL CX,1 ;Push hours and minutes to left end + 140A D1 E1 C SHL CX,1 + 140C D1 E1 C SHL CX,1 + 140E D0 EE C SHR DH,1 ;Count every two seconds + 1410 0A CE C OR CL,DH ;Combine seconds with hours and minutes + 1412 8B D1 C MOV DX,CX + 1414 59 C POP CX + 1415 A1 0044 R C MOV AX,WORD PTR [MONTH] ;Fetch month and year + 1418 D0 E0 C SHL AL,1 ;Push month to left to make room for day + 141A D0 E0 C SHL AL,1 + 141C D0 E0 C SHL AL,1 + 141E D0 E0 C SHL AL,1 + 1420 D1 E0 C SHL AX,1 + 1422 0A 06 0043 R C OR AL,[DAY] + 1426 C3 C RET22: RET + C + = 05B5 C FOURYEARS EQU 3*365+366 + C + 1427 C READTIME: + C ;Gets time in CX:DX. Figures new date if it has changed. + C ;Uses AX, CX, DX. + 1427 9A 0024 ---- R C CALL FAR PTR BIOSGETTIME + 142C 3B 06 0047 R C CMP AX,[DAYCNT] ;See if day count is the same + 1430 74 F4 C JZ RET22 + 1432 3D AB36 C CMP AX,FOURYEARS*30 ;Number of days in 120 years + 1435 73 EF C JAE RET22 ;Ignore if too large + 1437 A3 0047 R C MOV [DAYCNT],AX + 143A 56 C PUSH SI + 143B 51 C PUSH CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-64 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 143C 52 C PUSH DX ;Save time + 143D 33 D2 C XOR DX,DX + 143F B9 05B5 C MOV CX,FOURYEARS ;Number of days in 4 years + 1442 F7 F1 C DIV CX ;Compute number of 4-year units + 1444 D1 E0 C SHL AX,1 + 1446 D1 E0 C SHL AX,1 + 1448 D1 E0 C SHL AX,1 ;Multiply by 8 (no. of half-years) + 144A 8B C8 C MOV CX,AX ;<240 implies AH=0 + 144C BE 1492 R C MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year + 144F E8 1475 R C CALL DSLIDE ;Find out which of four years we're in + 1452 D1 E9 C SHR CX,1 ;Convert half-years to whole years + 1454 73 04 C JNC SK ;Extra half-year? + 1456 81 C2 00C8 C ADD DX,200 + 145A C SK: + 145A E8 1481 R C CALL SETYEAR + 145D B1 01 C MOV CL,1 ;At least at first month in year + 145F BE 149A R C MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + 1462 E8 1475 R C CALL DSLIDE ;Find out which month we're in + 1465 88 0E 0044 R C MOV [MONTH],CL + 1469 42 C INC DX ;Remainder is day of month (start with one) + 146A 88 16 0043 R C MOV [DAY],DL + 146E E8 1529 R C CALL WKDAY ;Set day of week + 1471 5A C POP DX + 1472 59 C POP CX + 1473 5E C POP SI + 1474 C3 C RET23: RET + C + 1475 C DSLIDE: + 1475 B4 00 C MOV AH,0 + 1477 C DSLIDE1: + 1477 AC C LODSB ;Get count of days + 1478 3B D0 C CMP DX,AX ;See if it will fit + 147A 72 F8 C JB RET23 ;If not, done + 147C 2B D0 C SUB DX,AX + 147E 41 C INC CX ;Count one more month/year + 147F EB F6 C JMP SHORT DSLIDE1 + C + 1481 C SETYEAR: + C ;Set year with value in CX. Adjust length of February for this year. + 1481 88 0E 0045 R C MOV BYTE PTR [YEAR],CL + 1485 C CHKYR: + 1485 F6 C1 03 C TEST CL,3 ;Check for leap year + 1488 B0 1C C MOV AL,28 + 148A 75 02 C JNZ SAVFEB ;28 days if no leap year + 148C FE C0 C INC AL ;Add leap day + 148E C SAVFEB: + 148E A2 149B R C MOV [MONTAB+1],AL ;Store for February + 1491 C3 C RET + C + C ;Days in year + 1492 C8 A6 C YRTAB DB 200,166 ;Leap year + 1494 C8 A5 C DB 200,165 + 1496 C8 A5 C DB 200,165 + 1498 C8 A5 C DB 200,165 + C +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-65 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C ;Days of each month + 149A 1F C MONTAB DB 31 ;January + 149B 1C C DB 28 ;February--reset each time year changes + 149C 1F C DB 31 ;March + 149D 1E C DB 30 ;April + 149E 1F C DB 31 ;May + 149F 1E C DB 30 ;June + 14A0 1F C DB 31 ;July + 14A1 1F C DB 31 ;August + 14A2 1E C DB 30 ;September + 14A3 1F C DB 31 ;October + 14A4 1E C DB 30 ;November + 14A5 1F C DB 31 ;December + C + 14A6 C GETDATE: ;Function call 42 + 14A6 0E C PUSH CS + 14A7 1F C POP DS + 14A8 E8 1427 R C CALL READTIME ;Check for rollover to next day + 14AB A1 0045 R C MOV AX,[YEAR] + 14AE 8B 1E 0043 R C MOV BX,WORD PTR [DAY] + 14B2 C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + 14B6 89 5C 06 C MOV [SI.DXSAVE],BX ;DH=month, DL=day + 14B9 05 07BC C ADD AX,1980 ;Put bias back + 14BC 89 44 04 C MOV [SI.CXSAVE],AX ;CX=year + 14BF 2E: A0 0049 R C MOV AL,CS:[WEEKDAY] + 14C3 C3 C RET24: RET + C + 14C4 C SETDATE: ;Function call 43 + 14C4 B0 FF C MOV AL,-1 ;Be ready to flag error + 14C6 81 E9 07BC C SUB CX,1980 ;Fix bias in year + 14CA 72 F7 C JC RET24 ;Error if not big enough + 14CC 83 F9 77 C CMP CX,119 ;Year must be less than 2100 + 14CF 77 F2 C JA RET24 + 14D1 0A F6 C OR DH,DH + 14D3 74 EE C JZ RET24 + 14D5 0A D2 C OR DL,DL + 14D7 74 EA C JZ RET24 ;Error if either month or day is 0 + 14D9 80 FE 0C C CMP DH,12 ;Check against max. month + 14DC 77 E5 C JA RET24 + 14DE 0E C PUSH CS + 14DF 1F C POP DS + 14E0 E8 1485 R C CALL CHKYR ;Set Feb. up for new year + 14E3 8A C6 C MOV AL,DH + 14E5 BB 1499 R C MOV BX,OFFSET DOSGROUP:MONTAB-1 + 14E8 D7 C XLAT ;Look up days in month + 14E9 3A C2 C CMP AL,DL + 14EB B0 FF C MOV AL,-1 ;Restore error flag, just in case + 14ED 72 D4 C JB RET24 ;Error if too many days + 14EF E8 1481 R C CALL SETYEAR + 14F2 89 16 0043 R C MOV WORD PTR [DAY],DX ;Set both day and month + 14F6 D1 E9 C SHR CX,1 + 14F8 D1 E9 C SHR CX,1 + 14FA B8 05B5 C MOV AX,FOURYEARS + 14FD 8B DA C MOV BX,DX + 14FF F7 E1 C MUL CX +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-66 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1501 8A 0E 0045 R C MOV CL,BYTE PTR [YEAR] + 1505 80 E1 03 C AND CL,3 + 1508 BE 1492 R C MOV SI,OFFSET DOSGROUP:YRTAB + 150B 8B D0 C MOV DX,AX + 150D D1 E1 C SHL CX,1 ;Two entries per year, so double count + 150F E8 153C R C CALL DSUM ;Add up the days in each year + 1512 8A CF C MOV CL,BH ;Month of year + 1514 BE 149A R C MOV SI,OFFSET DOSGROUP:MONTAB + 1517 49 C DEC CX ;Account for months starting with one + 1518 E8 153C R C CALL DSUM ;Add up days in each month + 151B 8A CB C MOV CL,BL ;Day of month + 151D 49 C DEC CX ;Account for days starting with one + 151E 03 D1 C ADD DX,CX ;Add in to day total + 1520 92 C XCHG AX,DX ;Get day count in AX + 1521 A3 0047 R C MOV [DAYCNT],AX + 1524 9A 001E ---- R C CALL FAR PTR BIOSSETDATE + 1529 C WKDAY: + 1529 A1 0047 R C MOV AX,[DAYCNT] + 152C 33 D2 C XOR DX,DX + 152E B9 0007 C MOV CX,7 + 1531 40 C INC AX + 1532 40 C INC AX ;First day was Tuesday + 1533 F7 F1 C DIV CX ;Compute day of week + 1535 88 16 0049 R C MOV [WEEKDAY],DL + 1539 32 C0 C XOR AL,AL ;Flag OK + 153B C3 C RET25: RET + C + 153C C DSUM: + 153C B4 00 C MOV AH,0 + 153E E3 FB C JCXZ RET25 + 1540 C DSUM1: + 1540 AC C LODSB + 1541 03 D0 C ADD DX,AX + 1543 E2 FB C LOOP DSUM1 + 1545 C3 C RET + C + 1546 C GETTIME: ;Function call 44 + 1546 0E C PUSH CS + 1547 1F C POP DS + 1548 E8 1427 R C CALL READTIME + 154B C5 36 0131 R C LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + 154F 89 54 06 C MOV [SI.DXSAVE],DX + 1552 89 4C 04 C MOV [SI.CXSAVE],CX + 1555 32 C0 C XOR AL,AL + 1557 C3 C RET26: RET + C + 1558 C SETTIME: ;Function call 45 + C ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec. + 1558 B0 FF C MOV AL,-1 ;Flag in case of error + 155A 80 FD 18 C CMP CH,24 ;Check hours + 155D 73 F8 C JAE RET26 + 155F 80 F9 3C C CMP CL,60 ;Check minutes + 1562 73 F3 C JAE RET26 + 1564 80 FE 3C C CMP DH,60 ;Check seconds + 1567 73 EE C JAE RET26 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-67 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 1569 80 FA 64 C CMP DL,100 ;Check 1/100's + 156C 73 E9 C JAE RET26 + 156E 9A 0021 ---- R C CALL FAR PTR BIOSSETTIME + 1573 32 C0 C XOR AL,AL + 1575 C3 C RET + C + C + C ; Default handler for division overflow trap + 1576 C DIVOV: + 1576 56 C PUSH SI + 1577 50 C PUSH AX + 1578 BE 0014 R C MOV SI,OFFSET DOSGROUP:DIVMES + 157B E8 12A4 R C CALL OUTMES + 157E 58 C POP AX + 157F 5E C POP SI + 1580 CD 23 C INT 23H ;Use Ctrl-C abort on divide overflow + 1582 CF C IRET + C + = 1583 C CODSIZ EQU $-CODSTRT ;Size of code segment + 1583 C CODE ENDS + C + C + C ;***** DATA AREA ***** + 0000 C CONSTANTS SEGMENT BYTE + 0000 C ORG 0 + = 0000 C CONSTRT EQU $ ;Start of constants segment + C + 0000 C IONAME: + C IF NOT IBM + 0000 50 52 4E 20 4C 53 C DB "PRN ","LST ","NUL ","AUX ","CON " + 54 20 4E 55 4C 20 C + 41 55 58 20 43 4F C + 4E 20 C + C ENDIF + C ENDIF + 0014 0D 0A 44 69 76 69 C DIVMES DB 13,10,"Divide overflow",13,10,"$" + 64 65 20 6F 76 65 C + 72 66 6C 6F 77 0D C + 0A 24 C + 0028 00 C CARPOS DB 0 + 0029 00 C STARTPOS DB 0 + 002A 00 C PFLAG DB 0 + 002B 00 C DIRTYDIR DB 0 ;Dirty buffer flag + 002C 00 C NUMDRV DB 0 ;Number of drives + 002D ?? C NUMIO DB ? ;Number of disk tables + 002E 00 C VERFLG DB 0 ;Initialize with verify off + 002F 0000 C CONTPOS DW 0 + 0031 0080 C DMAADD DW 80H ;User's disk transfer address (disp/seg) + 0033 ???? C DW ? + 0035 ???? C ENDMEM DW ? + 0037 0000 C MAXSEC DW 0 + 0039 ???? C BUFFER DW ? + 003B 0000 C BUFSECNO DW 0 + 003D FF C BUFDRVNO DB -1 + 003E 00 C DIRTYBUF DB 0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-68 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 003F ???? C BUFDRVBP DW ? + 0041 FFFF C DIRBUFID DW -1 + 0043 00 C DAY DB 0 + 0044 00 C MONTH DB 0 + 0045 0000 C YEAR DW 0 + 0047 FFFF C DAYCNT DW -1 + 0049 00 C WEEKDAY DB 0 + 004A 00 C CURDRV DB 0 ;Default to drive A + 004B 0000 C DRVTAB DW 0 ;Address of start of DPBs + = 15D0 C DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments + 004D C CONSTANTS ENDS + C + 0000 C DATA SEGMENT WORD + C ; Init code overlaps with data area below + C + 0000 C ORG 0 + 0000 80 [ C INBUF DB 128 DUP (?) + ?? C + ] C + C + 0080 83 [ C CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer + ?? C + ] C + C + 0103 ???? C LASTENT DW ? + 0105 04 [ C EXITHOLD DB 4 DUP (?) + ?? C + ] C + C + 0109 ???? C FATBASE DW ? + 010B 0B [ C NAME1 DB 11 DUP (?) ;File name buffer + ?? C + ] C + C + 0116 ?? C ATTRIB DB ? + 0117 0B [ C NAME2 DB 11 DUP (?) + ?? C + ] C + C + 0122 0C [ C NAME3 DB 12 DUP (?) + ?? C + ] C + C + 012E ?? C EXTFCB DB ? + C ;WARNING - the following two items are accessed as a word + 012F ?? C CREATING DB ? + 0130 ?? C DELALL DB ? + 0131 C TEMP LABEL WORD + 0131 ???? C SPSAVE DW ? + 0133 ???? C SSSAVE DW ? + 0135 ???? C CONTSTK DW ? + 0137 ?? C SECCLUSPOS DB ? ;Position of first sector within cluster + 0138 ?? C DSKERR DB ? + 0139 ?? C TRANS DB ? + 013A ?? C PREREAD DB ? ;0 means preread; 1 means optional +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-69 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 013B ?? C READOP DB ? + 013C ?? C THISDRV DB ? + C + 013D 90 C EVEN + 013E ???? C FCB DW ? ;Address of user FCB + 0140 ???? C NEXTADD DW ? + 0142 04 [ C RECPOS DB 4 DUP (?) + ?? C + ] C + C + 0146 ???? C RECCNT DW ? + 0148 ???? C LASTPOS DW ? + 014A ???? C CLUSNUM DW ? + 014C ???? C SECPOS DW ? ;Position of first sector accessed + 014E ???? C VALSEC DW ? ;Number of valid (previously written) sectors + 0150 ???? C BYTSECPOS DW ? ;Position of first byte within sector + 0152 04 [ C BYTPOS DB 4 DUP (?) ;Byte position in file of access + ?? C + ] C + C + 0156 ???? C BYTCNT1 DW ? ;No. of bytes in first sector + 0158 ???? C BYTCNT2 DW ? ;No. of bytes in last sector + 015A ???? C SECCNT DW ? ;No. of whole sectors + 015C ???? C ENTFREE DW ? + C + 015E 80 [ C DB 80H DUP (?) ;Stack space + ?? C + ] C + C + 01DE C IOSTACK LABEL BYTE + 01DE 80 [ C DB 80H DUP (?) + ?? C + ] C + C + 025E C DSKSTACK LABEL BYTE + C + C ENDIF + C + 025E C DIRBUF LABEL WORD + C + C ;Init code below overlaps with data area above + C + 0000 C ORG 0 + C + 0000 C MOVFAT: + C ;This section of code is safe from being overwritten by block move + 0000 F3/ A4 C REP MOVS BYTE PTR [DI],[SI] + 0002 FC C CLD + 0003 26: 89 16 0033 R C MOV ES:[DMAADD+2],DX + 0008 8B 36 004B R C MOV SI,[DRVTAB] ;Address of first DPB + 000C B0 FF C MOV AL,-1 + 000E 8A 0E 002D R C MOV CL,[NUMIO] ;Number of DPBs + 0012 C FLGFAT: + 0012 26: 8B 7C 12 C MOV DI,ES:[SI.FAT] ;get pointer to FAT + 0016 4F C DEC DI ;Point to dirty byte +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-70 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0017 AA C STOSB ;Flag as unused + 0018 83 C6 14 C ADD SI,DPBSIZ ;Point to next DPB + 001B E2 F5 C LOOP FLGFAT + 001D A1 0035 R C MOV AX,[ENDMEM] + 0020 E8 13BE R C CALL SETMEM ;Set up segment + C + 0023 C XXX PROC FAR + 0023 CB C RET + 0024 C XXX ENDP + C + 0024 C DOSINIT: + 0024 FA C CLI + 0025 FC C CLD + 0026 0E C PUSH CS + 0027 07 C POP ES + 0028 26: 89 16 0035 R C MOV ES:[ENDMEM],DX + 002D AC C LODSB ;Get no. of drives & no. of I/O drivers + 002E 26: A2 002D R C MOV ES:[NUMIO],AL + 0032 BF 0247 R C MOV DI,OFFSET DOSGROUP:MEMSTRT + 0035 C PERDRV: + 0035 8B EF C MOV BP,DI + 0037 26: A0 0246 R C MOV AL,ES:[DRVCNT] + 003B AA C STOSB ;DEVNUM + 003C AC C LODSB ;Physical unit no. + 003D AA C STOSB ;DRVNUM + 003E 3C 0F C CMP AL,15 + 0040 77 5C C JA BADINIT + 0042 98 C CBW ;Index into FAT size table + 0043 D1 E0 C SHL AX,1 + 0045 05 0226 R C ADD AX,OFFSET DOSGROUP:FATSIZTAB + 0048 93 C XCHG BX,AX + 0049 AD C LODSW ;Pointer to DPT + 004A 56 C PUSH SI + 004B 8B F0 C MOV SI,AX + 004D AD C LODSW + 004E AB C STOSW ;SECSIZ + 004F 8B D0 C MOV DX,AX + 0051 26: 3B 06 0037 R C CMP AX,ES:[MAXSEC] + 0056 76 04 C JBE NOTMAX + 0058 26: A3 0037 R C MOV ES:[MAXSEC],AX + 005C C NOTMAX: + 005C AC C LODSB + 005D FE C8 C DEC AL + 005F AA C STOSB ;CLUSMSK + 0060 74 09 C JZ HAVSHFT + 0062 98 C CBW + 0063 C FIGSHFT: + 0063 FE C4 C INC AH + 0065 D0 F8 C SAR AL,1 + 0067 75 FA C JNZ FIGSHFT + 0069 8A C4 C MOV AL,AH + 006B C HAVSHFT: + 006B AA C STOSB ;CLUSSHFT + 006C A5 C MOVSW ;FIRFAT (= number of reserved sectors) + 006D A4 C MOVSB ;FATCNT +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-71 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 006E A5 C MOVSW ;MAXENT + 006F 8B C2 C MOV AX,DX ;SECSIZ again + 0071 B1 05 C MOV CL,5 + 0073 D3 E8 C SHR AX,CL + 0075 8B C8 C MOV CX,AX ;Directory entries per sector + 0077 48 C DEC AX + 0078 26: 03 46 09 C ADD AX,ES:[BP.MAXENT] + 007C 33 D2 C XOR DX,DX + 007E F7 F1 C DIV CX + 0080 AB C STOSW ;DIRSEC (temporarily) + 0081 A5 C MOVSW ;DSKSIZ (temporarily) + 0082 C FNDFATSIZ: + 0082 B0 01 C MOV AL,1 + 0084 BA 0001 C MOV DX,1 + 0087 C GETFATSIZ: + 0087 52 C PUSH DX + 0088 E8 01E5 R C CALL FIGFATSIZ + 008B 5A C POP DX + 008C 3A C2 C CMP AL,DL ;Compare newly computed FAT size with trial + 008E 74 16 C JZ HAVFATSIZ ;Has sequence converged? + 0090 3A C6 C CMP AL,DH ;Compare with previous trial + 0092 8A F2 C MOV DH,DL + 0094 8A D0 C MOV DL,AL ;Shuffle trials + 0096 75 EF C JNZ GETFATSIZ ;Continue iterations if not oscillating + 0098 26: FF 4E 0D C DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations + 009C EB E4 C JMP SHORT FNDFATSIZ ;Try again + C + 009E C BADINIT: + 009E BE 0213 R C MOV SI,OFFSET DOSGROUP:BADMES + 00A1 E8 12A4 R C CALL OUTMES + 00A4 FB C STI + 00A5 F4 C HLT + C + 00A6 C HAVFATSIZ: + 00A6 AA C STOSB ;FATSIZ + 00A7 26: F6 66 08 C MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs + 00AB 26: 03 46 06 C ADD AX,ES:[BP.FIRFAT] + 00AF AB C STOSW ;FIRDIR + 00B0 26: 03 46 0B C ADD AX,ES:[BP.DIRSEC] + 00B4 26: 89 46 0B C MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC + 00B8 E8 01F1 R C CALL FIGMAX + 00BB 26: 89 4E 0D C MOV ES:[BP.MAXCLUS],CX + 00BF 8B C3 C MOV AX,BX ;Pointer into FAT size table + 00C1 AB C STOSW ;Allocate space for FAT pointer + 00C2 26: 8A 46 0F C MOV AL,ES:[BP.FATSIZ] + 00C6 32 E4 C XOR AH,AH + 00C8 26: F7 66 02 C MUL ES:[BP.SECSIZ] + 00CC 26: 3B 07 C CMP AX,ES:[BX] ;Bigger than already allocated + 00CF 76 03 C JBE SMFAT + 00D1 26: 89 07 C MOV ES:[BX],AX + 00D4 C SMFAT: + 00D4 5E C POP SI ;Restore pointer to init. table + 00D5 26: A0 0246 R C MOV AL,ES:[DRVCNT] + 00D9 FE C0 C INC AL + 00DB 26: A2 0246 R C MOV ES:[DRVCNT],AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-72 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 00DF 26: 3A 06 002D R C CMP AL,ES:[NUMIO] + 00E4 73 05 C JAE CONTINIT + 00E6 E9 0035 R C JMP PERDRV + C + 00E9 C BADINITJ: + 00E9 EB B3 C JMP BADINIT + C + 00EB C CONTINIT: + 00EB 0E C PUSH CS + 00EC 1F C POP DS + C ;Calculate true address of buffers, FATs, free space + 00ED 8B 2E 0037 R C MOV BP,[MAXSEC] + 00F1 B8 025E R C MOV AX,OFFSET DOSGROUP:DIRBUF + 00F4 03 C5 C ADD AX,BP + 00F6 A3 0039 R C MOV [BUFFER],AX ;Start of buffer + 00F9 03 C5 C ADD AX,BP + 00FB A3 004B R C MOV [DRVTAB],AX ;Start of DPBs + 00FE D1 E5 C SHL BP,1 ;Two sectors - directory and buffer + 0100 03 EF C ADD BP,DI ;Allocate buffer space + 0102 81 C5 0017 C ADD BP,ADJFAC ;True address of FATs + 0106 55 C PUSH BP + 0107 BE 0226 R C MOV SI,OFFSET DOSGROUP:FATSIZTAB + 010A 8B FE C MOV DI,SI + 010C B9 0010 C MOV CX,16 + 010F C TOTFATSIZ: + 010F 45 C INC BP ;Add one for Dirty byte + 0110 45 C INC BP ;Add one for I/O device number + 0111 AD C LODSW ;Get size of this FAT + 0112 95 C XCHG AX,BP + 0113 AB C STOSW ;Save address of this FAT + 0114 03 E8 C ADD BP,AX ;Compute size of next FAT + 0116 3B C5 C CMP AX,BP ;If size was zero done + 0118 E0 F5 C LOOPNZ TOTFATSIZ + 011A B0 0F C MOV AL,15 + 011C 2A C1 C SUB AL,CL ;Compute number of FATs used + 011E A2 002C R C MOV [NUMDRV],AL + 0121 33 C0 C XOR AX,AX ;Set zero flag + 0123 F3/ AF C REPZ SCASW ;Make sure all other entries are zero + 0125 75 C2 C JNZ BADINITJ + 0127 83 C5 0F C ADD BP,15 ;True start of free space + 012A B1 04 C MOV CL,4 + 012C D3 ED C SHR BP,CL ;First free segment + 012E 8C CA C MOV DX,CS + 0130 03 D5 C ADD DX,BP + 0132 BB 000F C MOV BX,0FH + 0135 8B 0E 0035 R C MOV CX,[ENDMEM] + 0139 83 F9 01 C CMP CX,1 ;Use memory scan? + 013C 75 15 C JNZ SETEND + 013E 8B CA C MOV CX,DX ;Start scanning just after DOS + 0140 C MEMSCAN: + 0140 41 C INC CX + 0141 74 10 C JZ SETEND + 0143 8E D9 C MOV DS,CX + 0145 8A 07 C MOV AL,[BX] + 0147 F6 D0 C NOT AL +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-73 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 0149 88 07 C MOV [BX],AL + 014B 3A 07 C CMP AL,[BX] + 014D F6 D0 C NOT AL + 014F 88 07 C MOV [BX],AL + 0151 74 ED C JZ MEMSCAN + 0153 C SETEND: + C ENDIF + C IF NOT HIGHMEM + 0153 8C CD C MOV BP,CS + C ENDIF + C ; BP has segment of DOS (whether to load high or run in place) + C ; DX has program segment (whether after DOS or overlaying DOS) + C ; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) + 0155 2E: 89 0E 0035 R C MOV CS:[ENDMEM],CX + C ENDIF + 015A 33 C0 C XOR AX,AX + 015C 8E D8 C MOV DS,AX + 015E 8E C0 C MOV ES,AX + 0160 BF 0080 C MOV DI,INTBASE + 0163 B8 004B R C MOV AX,OFFSET DOSGROUP:QUIT + 0166 AB C STOSW ;Set abort address--displacement + 0167 8B C5 C MOV AX,BP + 0169 C6 06 00C0 EA C MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP + 016E C7 06 00C1 0057 R C MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY + 0174 A3 00C3 C MOV WORD PTR DS:[ENTRYPOINT+3],AX + 0177 C7 06 0000 1576 R C MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address + 017D A3 0002 C MOV DS:[2],AX + 0180 B9 0009 C MOV CX,9 + 0183 F3/ AB C REP STOSW ;Set 5 segments (skip 2 between each) + 0185 C7 06 0084 004F R C MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND + 018B C7 06 008C 0056 R C MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit + 0191 C7 06 0090 0056 R C MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit + 0197 B8 0015 R C MOV AX,OFFSET BIOSREAD + 019A AB C STOSW + 019B B8 0040 C MOV AX,BIOSSEG + 019E AB C STOSW + 019F AB C STOSW ;Add 2 to DI + 01A0 AB C STOSW + 01A1 C7 06 0098 0018 R C MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE + 01A7 C7 06 0088 0100 C MOV WORD PTR DS:[EXIT],100H + 01AD 89 16 008A C MOV WORD PTR DS:[EXIT+2],DX + C IF NOT IBM + 01B1 BE 0010 R C MOV SI,OFFSET DOSGROUP:HEADER + 01B4 E8 12A4 R C CALL OUTMES + C ENDIF + 01B7 0E C PUSH CS + 01B8 1F C POP DS + 01B9 0E C PUSH CS + 01BA 07 C POP ES + C ;Move the FATs into position + 01BB A0 002D R C MOV AL,[NUMIO] + 01BE 98 C CBW + 01BF 91 C XCHG AX,CX + 01C0 BF 0259 R C MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT + 01C3 C FATPOINT: +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-74 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + 01C3 8B 35 C MOV SI,WORD PTR [DI] ;Get address within FAT address table + 01C5 A5 C MOVSW ;Set address of this FAT + 01C6 83 C7 12 C ADD DI,DPBSIZ-2 ;Point to next DPB + 01C9 E2 F8 C LOOP FATPOINT + 01CB 59 C POP CX ;True address of first FAT + 01CC BE 0247 R C MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from + 01CF 8B 3E 004B R C MOV DI,[DRVTAB] ;Place to move DPBs to + 01D3 2B CF C SUB CX,DI ;Total length of DPBs + 01D5 3B FE C CMP DI,SI + 01D7 76 07 C JBE MOVJMP ;Are we moving to higher or lower memory? + 01D9 49 C DEC CX ;Move backwards to higher memory + 01DA 03 F9 C ADD DI,CX + 01DC 03 F1 C ADD SI,CX + 01DE 41 C INC CX + 01DF FD C STD + 01E0 C MOVJMP: + 01E0 8E C5 C MOV ES,BP + 01E2 E9 0000 R C JMP MOVFAT + C + 01E5 C FIGFATSIZ: + 01E5 26: F6 66 08 C MUL ES:BYTE PTR[BP.FATCNT] + 01E9 26: 03 46 06 C ADD AX,ES:[BP.FIRFAT] + 01ED 26: 03 46 0B C ADD AX,ES:[BP.DIRSEC] + 01F1 C FIGMAX: + C ;AX has equivalent of FIRREC + 01F1 26: 2B 46 0D C SUB AX,ES:[BP.DSKSIZ] + 01F5 F7 D8 C NEG AX + 01F7 26: 8A 4E 05 C MOV CL,ES:[BP.CLUSSHFT] + 01FB D3 E8 C SHR AX,CL + 01FD 40 C INC AX + 01FE 8B C8 C MOV CX,AX ;MAXCLUS + 0200 40 C INC AX + 0201 8B D0 C MOV DX,AX + 0203 D1 EA C SHR DX,1 + 0205 13 C2 C ADC AX,DX ;Size of FAT in bytes + 0207 26: 8B 76 02 C MOV SI,ES:[BP.SECSIZ] + 020B 03 C6 C ADD AX,SI + 020D 48 C DEC AX + 020E 33 D2 C XOR DX,DX + 0210 F7 F6 C DIV SI + 0212 C3 C RET + C + 0213 C BADMES: + 0213 0D 0A 49 4E 49 54 C DB 13,10,"INIT TABLE BAD",13,10,"$" + 20 54 41 42 4C 45 C + 20 42 41 44 0D 0A C + 24 C + C + 0226 C FATSIZTAB: + 0226 0000 0000 0000 0000 C DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0000 0000 0000 0000 C + 0000 0000 0000 0000 C + 0000 0000 0000 0000 C + C + 0246 00 C DRVCNT DB 0 +  The Microsoft MACRO Assembler 01-26-83 PAGE 1-75 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + + C + 0247 C MEMSTRT LABEL WORD + = 0017 C ADJFAC EQU DIRBUF-MEMSTRT + 0247 C DATA ENDS + C END + +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-1 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +Structures and records: + + N a m e Width # fields + Shift Width Mask Initial + +DPBLOCK. . . . . . . . . . . . . 0014 000D + DEVNUM . . . . . . . . . . . . . 0000 + DRVNUM . . . . . . . . . . . . . 0001 + SECSIZ . . . . . . . . . . . . . 0002 + CLUSMSK. . . . . . . . . . . . . 0004 + CLUSSHFT . . . . . . . . . . . . 0005 + FIRFAT . . . . . . . . . . . . . 0006 + FATCNT . . . . . . . . . . . . . 0008 + MAXENT . . . . . . . . . . . . . 0009 + FIRREC . . . . . . . . . . . . . 000B + MAXCLUS. . . . . . . . . . . . . 000D + FATSIZ . . . . . . . . . . . . . 000F + FIRDIR . . . . . . . . . . . . . 0010 + FAT. . . . . . . . . . . . . . . 0012 +FCBLOCK. . . . . . . . . . . . . 0024 000E + EXTENT . . . . . . . . . . . . . 000C + RECSIZ . . . . . . . . . . . . . 000E + FILSIZ . . . . . . . . . . . . . 0010 + DRVBP. . . . . . . . . . . . . . 0012 + FDATE. . . . . . . . . . . . . . 0014 + FTIME. . . . . . . . . . . . . . 0016 + DEVID. . . . . . . . . . . . . . 0018 + FIRCLUS. . . . . . . . . . . . . 0019 + LSTCLUS. . . . . . . . . . . . . 001B + CLUSPOS. . . . . . . . . . . . . 001D + NR . . . . . . . . . . . . . . . 0020 + RR . . . . . . . . . . . . . . . 0021 +STKPTRS. . . . . . . . . . . . . 0018 000C + AXSAVE . . . . . . . . . . . . . 0000 + BXSAVE . . . . . . . . . . . . . 0002 + CXSAVE . . . . . . . . . . . . . 0004 + DXSAVE . . . . . . . . . . . . . 0006 + SISAVE . . . . . . . . . . . . . 0008 + DISAVE . . . . . . . . . . . . . 000A + BPSAVE . . . . . . . . . . . . . 000C + DSSAVE . . . . . . . . . . . . . 000E + ESSAVE . . . . . . . . . . . . . 0010 + IPSAVE . . . . . . . . . . . . . 0012 + CSSAVE . . . . . . . . . . . . . 0014 + FSAVE. . . . . . . . . . . . . . 0016 + +Segments and groups: + + N a m e Size align combine class + +DOSGROUP . . . . . . . . . . . . GROUP + CODE . . . . . . . . . . . . . . 1583 PARA NONE + CONSTANTS. . . . . . . . . . . . 004D BYTE NONE + DATA . . . . . . . . . . . . . . 025E WORD NONE +SEGBIOS. . . . . . . . . . . . . 002D AT 0040 + +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-2 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +Symbols: + + N a m e Type Value Attr + +ABORT. . . . . . . . . . . . . . L NEAR 06B1 CODE +ADDREC . . . . . . . . . . . . . L NEAR 0B1C CODE +ADJFAC . . . . . . . . . . . . . Number 0017 +ALIGNED. . . . . . . . . . . . . L NEAR 019B CODE +ALLOC. . . . . . . . . . . . . . L NEAR 0DC1 CODE +ALLOCATE . . . . . . . . . . . . L NEAR 0DBA CODE +ATTRIB . . . . . . . . . . . . . L BYTE 0116 DATA +AUXIN. . . . . . . . . . . . . . L NEAR 0141 CODE +AUXOUT . . . . . . . . . . . . . L NEAR 014C CODE +BACKMES. . . . . . . . . . . . . L NEAR 10D6 CODE +BACKPOS. . . . . . . . . . . . . L NEAR 1241 CODE +BACKSP . . . . . . . . . . . . . L NEAR 107E CODE +BACKUP . . . . . . . . . . . . . L NEAR 10D3 CODE +BADCALL. . . . . . . . . . . . . L NEAR 0054 CODE +BADCLOSE . . . . . . . . . . . . L NEAR 0547 CODE +BADCLOSEJ. . . . . . . . . . . . L NEAR 04F8 CODE +BADDRV . . . . . . . . . . . . . L NEAR 1304 CODE +BADFAT . . . . . . . . . . . . . L NEAR 04A8 CODE +BADINIT. . . . . . . . . . . . . L NEAR 009E DATA +BADINITJ . . . . . . . . . . . . L NEAR 00E9 DATA +BADMES . . . . . . . . . . . . . L NEAR 0213 DATA +BAKTAB . . . . . . . . . . . . . L NEAR 10A1 CODE +BIOSAUXIN. . . . . . . . . . . . L BYTE 000F SEGBIOS Length =0003 +BIOSAUXOUT . . . . . . . . . . . L BYTE 0012 SEGBIOS Length =0003 +BIOSDSKCHG . . . . . . . . . . . L BYTE 001B SEGBIOS Length =0003 +BIOSFLUSH. . . . . . . . . . . . L BYTE 0027 SEGBIOS Length =0003 +BIOSGETTIME. . . . . . . . . . . L BYTE 0024 SEGBIOS Length =0003 +BIOSIN . . . . . . . . . . . . . L BYTE 0006 SEGBIOS Length =0003 +BIOSMAPDEV . . . . . . . . . . . L BYTE 002A SEGBIOS Length =0003 +BIOSOUT. . . . . . . . . . . . . L BYTE 0009 SEGBIOS Length =0003 +BIOSPRINT. . . . . . . . . . . . L BYTE 000C SEGBIOS Length =0003 +BIOSREAD . . . . . . . . . . . . L BYTE 0015 SEGBIOS Length =0003 +BIOSSEG. . . . . . . . . . . . . Number 0040 +BIOSSETDATE. . . . . . . . . . . L BYTE 001E SEGBIOS Length =0003 +BIOSSETTIME. . . . . . . . . . . L BYTE 0021 SEGBIOS Length =0003 +BIOSSTAT . . . . . . . . . . . . L BYTE 0003 SEGBIOS Length =0003 +BIOSWRITE. . . . . . . . . . . . L BYTE 0018 SEGBIOS Length =0003 +BLKDON . . . . . . . . . . . . . L NEAR 0D7D CODE +BLKRD. . . . . . . . . . . . . . L NEAR 071E CODE +BLKWRT . . . . . . . . . . . . . L NEAR 0726 CODE +BREAKDOWN. . . . . . . . . . . . L NEAR 084C CODE +BUFDRVBP . . . . . . . . . . . . L WORD 003F CONSTANTS +BUFDRVNO . . . . . . . . . . . . L BYTE 003D CONSTANTS +BUFFER . . . . . . . . . . . . . L WORD 0039 CONSTANTS +BUFFUL . . . . . . . . . . . . . L NEAR 1027 CODE +BUFIN. . . . . . . . . . . . . . L NEAR 0FBD CODE +BUFOK. . . . . . . . . . . . . . L NEAR 0462 CODE +BUFOUT . . . . . . . . . . . . . L NEAR 117D CODE +BUFRD. . . . . . . . . . . . . . L NEAR 0925 CODE +BUFSEC . . . . . . . . . . . . . L NEAR 08A0 CODE +BUFSECNO . . . . . . . . . . . . L WORD 003B CONSTANTS +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-3 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +BUFWRT . . . . . . . . . . . . . L NEAR 0938 CODE +BYTCNT1. . . . . . . . . . . . . L WORD 0156 DATA +BYTCNT2. . . . . . . . . . . . . L WORD 0158 DATA +BYTPOS . . . . . . . . . . . . . L BYTE 0152 DATA Length =0004 +BYTSECPOS. . . . . . . . . . . . L WORD 0150 DATA +CANCEL . . . . . . . . . . . . . Number 0018 +CARPOS . . . . . . . . . . . . . L BYTE 0028 CONSTANTS +CHK. . . . . . . . . . . . . . . L NEAR 1367 CODE +CHKCNT . . . . . . . . . . . . . L NEAR 10B9 CODE +CHKDIRWRITE. . . . . . . . . . . L NEAR 067A CODE +CHKFATWRT. . . . . . . . . . . . L NEAR 051F CODE +CHKYR. . . . . . . . . . . . . . L NEAR 1485 CODE +CLOSE. . . . . . . . . . . . . . L NEAR 04BB CODE +CLRET. . . . . . . . . . . . . . L NEAR 0993 CODE +CLUSNUM. . . . . . . . . . . . . L WORD 014A DATA +CODSIZ . . . . . . . . . . . . . Number 1583 +CODSTRT. . . . . . . . . . . . . Number 0000 CODE +COMMAND. . . . . . . . . . . . . L NEAR 004F CODE +CONBUF . . . . . . . . . . . . . L BYTE 0080 DATA Length =0083 +CONIN. . . . . . . . . . . . . . L NEAR 1253 CODE +CONOUT . . . . . . . . . . . . . L NEAR 119D CODE +CONSTAT. . . . . . . . . . . . . L NEAR 1249 CODE +CONSTRT. . . . . . . . . . . . . Number 0000 CONSTANTS +CONTC. . . . . . . . . . . . . . Number 0023 +CONTINIT . . . . . . . . . . . . L NEAR 00EB DATA +CONTPOS. . . . . . . . . . . . . L WORD 002F CONSTANTS +CONTSRCH . . . . . . . . . . . . L NEAR 01E6 CODE +CONTSTK. . . . . . . . . . . . . L WORD 0135 DATA +COPYEACH . . . . . . . . . . . . L NEAR 10F7 CODE +COPYLIN. . . . . . . . . . . . . L NEAR 10EA CODE +COPYNEW. . . . . . . . . . . . . L NEAR 104C CODE +COPYONE. . . . . . . . . . . . . L NEAR 10F5 CODE +COPYSTR. . . . . . . . . . . . . L NEAR 10F0 CODE +CREATE . . . . . . . . . . . . . L NEAR 056D CODE +CREATING . . . . . . . . . . . . L BYTE 012F DATA +CRET . . . . . . . . . . . . . . L NEAR 01B9 CODE +CRLF . . . . . . . . . . . . . . L NEAR 105C CODE +CTRLOUT. . . . . . . . . . . . . L NEAR 1214 CODE +CURDRV . . . . . . . . . . . . . L BYTE 004A CONSTANTS +DATE16 . . . . . . . . . . . . . L NEAR 1400 CODE +DAY. . . . . . . . . . . . . . . L BYTE 0043 CONSTANTS +DAYCNT . . . . . . . . . . . . . L WORD 0047 CONSTANTS +DEFDRV . . . . . . . . . . . . . L NEAR 12B9 CODE +DELALL . . . . . . . . . . . . . L BYTE 0130 DATA +DELETE . . . . . . . . . . . . . L NEAR 029B CODE +DELFILE. . . . . . . . . . . . . L NEAR 02C9 CODE +DELIM. . . . . . . . . . . . . . L NEAR 137F CODE +DELNXT . . . . . . . . . . . . . L NEAR 02E5 CODE +DEVNAME. . . . . . . . . . . . . L NEAR 01A4 CODE +DEVSIZ . . . . . . . . . . . . . L NEAR 0F03 CODE +DIRBUF . . . . . . . . . . . . . L WORD 025E DATA +DIRBUFID . . . . . . . . . . . . L WORD 0041 CONSTANTS +DIRCOMP. . . . . . . . . . . . . L NEAR 0560 CODE +DIRREAD. . . . . . . . . . . . . L NEAR 05E8 CODE +DIRSEC . . . . . . . . . . . . . Number 000B +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-4 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +DIRTYBUF . . . . . . . . . . . . L BYTE 003E CONSTANTS +DIRTYDIR . . . . . . . . . . . . L BYTE 002B CONSTANTS +DIRWRITE . . . . . . . . . . . . L NEAR 0681 CODE +DISPATCH . . . . . . . . . . . . L WORD 00B6 CODE +DIVMES . . . . . . . . . . . . . L BYTE 0014 CONSTANTS +DIVOV. . . . . . . . . . . . . . L NEAR 1576 CODE +DMAADD . . . . . . . . . . . . . L WORD 0031 CONSTANTS +DOOPEN . . . . . . . . . . . . . L NEAR 03D0 CODE +DOSINIT. . . . . . . . . . . . . L NEAR 0024 DATA +DOSLEN . . . . . . . . . . . . . Number 15D0 +DOWRT. . . . . . . . . . . . . . L NEAR 0C24 CODE +DOWRTJ . . . . . . . . . . . . . L NEAR 0BA3 CODE +DPBSIZ . . . . . . . . . . . . . Number 0014 +DREAD. . . . . . . . . . . . . . L NEAR 05FC CODE +DRVBIT . . . . . . . . . . . . . Number 0002 +DRVCNT . . . . . . . . . . . . . L BYTE 0246 DATA +DRVTAB . . . . . . . . . . . . . L WORD 004B CONSTANTS +DSKERR . . . . . . . . . . . . . L BYTE 0138 DATA +DSKREAD. . . . . . . . . . . . . L NEAR 0669 CODE +DSKRESET . . . . . . . . . . . . L NEAR 0F64 CODE +DSKSIZ . . . . . . . . . . . . . Number 000D +DSKSTACK . . . . . . . . . . . . L BYTE 025E DATA +DSKTEST. . . . . . . . . . . . . Alias FALSE +DSLIDE . . . . . . . . . . . . . L NEAR 1475 CODE +DSLIDE1. . . . . . . . . . . . . L NEAR 1477 CODE +DSUM . . . . . . . . . . . . . . L NEAR 153C CODE +DSUM1. . . . . . . . . . . . . . L NEAR 1540 CODE +DWRITE . . . . . . . . . . . . . L NEAR 068C CODE +EACHFAT. . . . . . . . . . . . . L NEAR 0533 CODE +EDITON . . . . . . . . . . . . . L NEAR 0FD9 CODE +ENDLIN . . . . . . . . . . . . . L NEAR 1042 CODE +ENDMEM . . . . . . . . . . . . . L WORD 0035 CONSTANTS +ENDRDCON . . . . . . . . . . . . L NEAR 09B1 CODE +ENDRDDEV . . . . . . . . . . . . L NEAR 09B5 CODE +ENDWRDEV . . . . . . . . . . . . L NEAR 0B7B CODE +ENTERINS . . . . . . . . . . . . L NEAR 115B CODE +ENTFREE. . . . . . . . . . . . . L WORD 015C DATA +ENTRY. . . . . . . . . . . . . . L NEAR 0057 CODE +ENTRYPOINT . . . . . . . . . . . Number 00C0 +ENTRYPOINTSEG. . . . . . . . . . Number 000C +ENUF . . . . . . . . . . . . . . L NEAR 0A43 CODE +EOFERR . . . . . . . . . . . . . L NEAR 0843 CODE +ERRET. . . . . . . . . . . . . . L NEAR 036F CODE +ERRET3 . . . . . . . . . . . . . L NEAR 059A CODE +ERRINT . . . . . . . . . . . . . L NEAR 0632 CODE +ERROR. . . . . . . . . . . . . . L NEAR 06C9 CODE +ERRPOP . . . . . . . . . . . . . L NEAR 0598 CODE +ESC. . . . . . . . . . . . . . . L NEAR 102E CODE +ESCCH. . . . . . . . . . . . . . Number 001B +ESCCHAR. . . . . . . . . . . . . L BYTE 0003 CODE +ESCFUNC. . . . . . . . . . . . . L WORD 1165 CODE +ESCTAB . . . . . . . . . . . . . L NEAR 0004 CODE +ESCTABLEN. . . . . . . . . . . . Number 000C +EVENFIL. . . . . . . . . . . . . L NEAR 0B05 CODE +EVENMOV. . . . . . . . . . . . . L NEAR 0ABA CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-5 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +EVENRD . . . . . . . . . . . . . L NEAR 0934 CODE +EVENWRT. . . . . . . . . . . . . L NEAR 095B CODE +EXISTENT . . . . . . . . . . . . L NEAR 059D CODE +EXIT . . . . . . . . . . . . . . Number 0088 +EXITHOLD . . . . . . . . . . . . L BYTE 0105 DATA Length =0004 +EXITINS. . . . . . . . . . . . . L NEAR 1160 CODE +EXTBIT . . . . . . . . . . . . . Number 0008 +EXTFCB . . . . . . . . . . . . . L BYTE 012E DATA +FALSE. . . . . . . . . . . . . . Number 0000 +FATAL. . . . . . . . . . . . . . L NEAR 0639 CODE +FATAL1 . . . . . . . . . . . . . L NEAR 063C CODE +FATBASE. . . . . . . . . . . . . L WORD 0109 DATA +FATERR . . . . . . . . . . . . . L NEAR 0418 CODE +FATPOINT . . . . . . . . . . . . L NEAR 01C3 DATA +FATREAD. . . . . . . . . . . . . L NEAR 042C CODE +FATSIZTAB. . . . . . . . . . . . L NEAR 0226 DATA +FATWRT . . . . . . . . . . . . . L NEAR 052C CODE +FCB. . . . . . . . . . . . . . . L WORD 013E DATA +FIGFAT . . . . . . . . . . . . . L NEAR 0551 CODE +FIGFATSIZ. . . . . . . . . . . . L NEAR 01E5 DATA +FIGMAX . . . . . . . . . . . . . L NEAR 01F1 DATA +FIGREC . . . . . . . . . . . . . L NEAR 0D8B CODE +FIGSHFT. . . . . . . . . . . . . L NEAR 0063 DATA +FIGTAB . . . . . . . . . . . . . L NEAR 10BB CODE +FILDIRENT. . . . . . . . . . . . Number 0010 +FILESIZE . . . . . . . . . . . . L NEAR 0ED2 CODE +FILLB. . . . . . . . . . . . . . L NEAR 12C8 CODE +FILLB2 . . . . . . . . . . . . . L NEAR 12D5 CODE +FILLNAM. . . . . . . . . . . . . L NEAR 134C CODE +FINBLK . . . . . . . . . . . . . L NEAR 072C CODE +FINBUF . . . . . . . . . . . . . L NEAR 0907 CODE +FINCLUS. . . . . . . . . . . . . L NEAR 0D3C CODE +FINDFRE. . . . . . . . . . . . . L NEAR 0DC3 CODE +FINDIT . . . . . . . . . . . . . L NEAR 088C CODE +FINDNAME . . . . . . . . . . . . L NEAR 01DA CODE +FINDOLD. . . . . . . . . . . . . L NEAR 1123 CODE +FINRND . . . . . . . . . . . . . L NEAR 073B CODE +FINSEQ . . . . . . . . . . . . . L NEAR 0704 CODE +FINWRT . . . . . . . . . . . . . L NEAR 0C8F CODE +FLGFAT . . . . . . . . . . . . . L NEAR 0012 DATA +FLUSHKB. . . . . . . . . . . . . L NEAR 011E CODE +FNDCLUS. . . . . . . . . . . . . L NEAR 0874 CODE +FNDDIR . . . . . . . . . . . . . L NEAR 04F5 CODE +FNDFATSIZ. . . . . . . . . . . . L NEAR 0082 DATA +FNDPOS . . . . . . . . . . . . . L NEAR 10AD CODE +FOUND. . . . . . . . . . . . . . L NEAR 0226 CODE +FOURYEARS. . . . . . . . . . . . Number 05B5 +FREE . . . . . . . . . . . . . . L NEAR 020F CODE +FREESPOT . . . . . . . . . . . . L NEAR 05B9 CODE +FULLREC. . . . . . . . . . . . . L NEAR 0B0A CODE +GETBP. . . . . . . . . . . . . . L NEAR 0492 CODE +GETBUF . . . . . . . . . . . . . L NEAR 09F6 CODE +GETCH. . . . . . . . . . . . . . L NEAR 0FEE CODE +GETCH1 . . . . . . . . . . . . . L NEAR 109E CODE +GETCH2 . . . . . . . . . . . . . L NEAR 110C CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-6 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +GETDATE. . . . . . . . . . . . . L NEAR 14A6 CODE +GETDRV . . . . . . . . . . . . . L NEAR 0F97 CODE +GETDSKPT . . . . . . . . . . . . L NEAR 0F4E CODE +GETENT . . . . . . . . . . . . . L NEAR 0247 CODE +GETENTRY . . . . . . . . . . . . L NEAR 023E CODE +GETEOF . . . . . . . . . . . . . L NEAR 0E43 CODE +GETFATPT . . . . . . . . . . . . L NEAR 0F20 CODE +GETFATPTDL . . . . . . . . . . . L NEAR 0F22 CODE +GETFATSIZ. . . . . . . . . . . . L NEAR 0087 DATA +GETFILE. . . . . . . . . . . . . L NEAR 01C8 CODE +GETIO. . . . . . . . . . . . . . L NEAR 0114 CODE +GETLET . . . . . . . . . . . . . L NEAR 135A CODE +GETNAME. . . . . . . . . . . . . L NEAR 01D5 CODE +GETRDONLY. . . . . . . . . . . . L NEAR 0114 CODE +GETREC . . . . . . . . . . . . . L NEAR 0D9A CODE +GETRRPOS . . . . . . . . . . . . L NEAR 076A CODE +GETRRPOS1. . . . . . . . . . . . L NEAR 0767 CODE +GETSEC . . . . . . . . . . . . . L NEAR 08BD CODE +GETTHISDRV . . . . . . . . . . . L NEAR 03B9 CODE +GETTIME. . . . . . . . . . . . . L NEAR 1546 CODE +GETWORD. . . . . . . . . . . . . L NEAR 132C CODE +HARDERR. . . . . . . . . . . . . L NEAR 060F CODE +HAVATTRB . . . . . . . . . . . . L NEAR 0397 CODE +HAVCLUS. . . . . . . . . . . . . L NEAR 016D CODE +HAVDIF . . . . . . . . . . . . . L NEAR 13DE CODE +HAVDIRBUF. . . . . . . . . . . . L NEAR 026C CODE +HAVDRV . . . . . . . . . . . . . L NEAR 1306 CODE +HAVFATSIZ. . . . . . . . . . . . L NEAR 00A6 DATA +HAVFRE . . . . . . . . . . . . . L NEAR 0E03 CODE +HAVIT. . . . . . . . . . . . . . L NEAR 0294 CODE +HAVRECSIZ. . . . . . . . . . . . L NEAR 079D CODE +HAVSHFT. . . . . . . . . . . . . L NEAR 006B DATA +HAVSTART . . . . . . . . . . . . L NEAR 0B86 CODE +HAVTAB . . . . . . . . . . . . . L NEAR 10C0 CODE +HEADER . . . . . . . . . . . . . L BYTE 0010 CODE +HIGHMEM. . . . . . . . . . . . . Alias FALSE +HURTFAT. . . . . . . . . . . . . L NEAR 0174 CODE +IBM. . . . . . . . . . . . . . . Alias FALSE +IN . . . . . . . . . . . . . . . L NEAR 125C CODE +INBUF. . . . . . . . . . . . . . L BYTE 0000 DATA Length =0080 +INCHK. . . . . . . . . . . . . . L NEAR 11D4 CODE +INTBASE. . . . . . . . . . . . . Number 0080 +INTTAB . . . . . . . . . . . . . Number 0020 +INUSE. . . . . . . . . . . . . . L NEAR 0114 CODE +IOCHK. . . . . . . . . . . . . . L NEAR 01BB CODE +IONAME . . . . . . . . . . . . . L NEAR 0000 CONSTANTS +IOSTACK. . . . . . . . . . . . . L BYTE 01DE DATA +IRET . . . . . . . . . . . . . . L NEAR 0056 CODE +KILLFIL. . . . . . . . . . . . . L NEAR 0D06 CODE +KILLSRCH . . . . . . . . . . . . L NEAR 0E8A CODE +KILLSRCH1. . . . . . . . . . . . E NEAR 0E8B CODE +KILNEW . . . . . . . . . . . . . L NEAR 106B CODE +LASTENT. . . . . . . . . . . . . L WORD 0103 DATA +LASTPOS. . . . . . . . . . . . . L WORD 0148 DATA +LEAVE. . . . . . . . . . . . . . L NEAR 009C CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-7 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +LIST . . . . . . . . . . . . . . L NEAR 128B CODE +LISTOUT. . . . . . . . . . . . . L NEAR 128D CODE +LOAD . . . . . . . . . . . . . . L NEAR 0A1E CODE +LODNAME. . . . . . . . . . . . . L NEAR 039F CODE +LONGCALL . . . . . . . . . . . . Number 009A +LONGJUMP . . . . . . . . . . . . Number 00EA +LOOKIO . . . . . . . . . . . . . L NEAR 01A9 CODE +LVDSK. . . . . . . . . . . . . . L NEAR 0B97 CODE +MAKEFCB. . . . . . . . . . . . . L NEAR 12AF CODE +MAPDRV . . . . . . . . . . . . . L NEAR 048F CODE +MAXCALL. . . . . . . . . . . . . Number 0024 +MAXCOM . . . . . . . . . . . . . Number 002E +MAXDIF . . . . . . . . . . . . . Number 0FFF +MAXREC . . . . . . . . . . . . . L NEAR 0DF0 CODE +MAXSEC . . . . . . . . . . . . . L WORD 0037 CONSTANTS +MEMSCAN. . . . . . . . . . . . . L NEAR 0140 DATA +MEMSTRT. . . . . . . . . . . . . L WORD 0247 DATA +MONTAB . . . . . . . . . . . . . L BYTE 149A CODE +MONTH. . . . . . . . . . . . . . L BYTE 0044 CONSTANTS +MOVCHK . . . . . . . . . . . . . L NEAR 03A8 CODE +MOVFAT . . . . . . . . . . . . . L NEAR 0000 DATA +MOVJMP . . . . . . . . . . . . . L NEAR 01E0 DATA +MOVNAME. . . . . . . . . . . . . L NEAR 0372 CODE +MSVER. . . . . . . . . . . . . . Alias TRUE +MUSTGETWORD. . . . . . . . . . . L NEAR 1332 CODE +NAMBIT . . . . . . . . . . . . . Number 0004 +NAME1. . . . . . . . . . . . . . L BYTE 010B DATA Length =000B +NAME2. . . . . . . . . . . . . . L BYTE 0117 DATA Length =000B +NAME3. . . . . . . . . . . . . . L BYTE 0122 DATA Length =000C +NEWBASE. . . . . . . . . . . . . L NEAR 13A8 CODE +NEWDSK . . . . . . . . . . . . . L NEAR 0450 CODE +NEWFAT . . . . . . . . . . . . . L NEAR 047A CODE +NEWLIN . . . . . . . . . . . . . L NEAR 0FDC CODE +NEWNAM . . . . . . . . . . . . . L NEAR 0320 CODE +NEXTADD. . . . . . . . . . . . . L WORD 0140 DATA +NEXTENT. . . . . . . . . . . . . L NEAR 0209 CODE +NEXTENTRY. . . . . . . . . . . . L NEAR 0275 CODE +NEXTFAT. . . . . . . . . . . . . L NEAR 046B CODE +NEXTSEC. . . . . . . . . . . . . L NEAR 0965 CODE +NOBUF. . . . . . . . . . . . . . L NEAR 0F82 CODE +NOCHG. . . . . . . . . . . . . . L NEAR 0327 CODE +NOCLUS . . . . . . . . . . . . . L NEAR 089D CODE +NODOT. . . . . . . . . . . . . . L NEAR 131D CODE +NODRV. . . . . . . . . . . . . . L NEAR 1309 CODE +NOEDIT . . . . . . . . . . . . . L NEAR 0FD7 CODE +NOFILERR . . . . . . . . . . . . L NEAR 077B CODE +NONAM. . . . . . . . . . . . . . L NEAR 1328 CODE +NONE . . . . . . . . . . . . . . L NEAR 0296 CODE +NONEXT . . . . . . . . . . . . . L NEAR 0995 CODE +NOREAD . . . . . . . . . . . . . L NEAR 0949 CODE +NORMCH . . . . . . . . . . . . . L NEAR 09A0 CODE +NORMFCB. . . . . . . . . . . . . L NEAR 0E7C CODE +NORMFCB1 . . . . . . . . . . . . L NEAR 0774 CODE +NORMFCB2 . . . . . . . . . . . . L NEAR 0DA4 CODE +NORMFCB3 . . . . . . . . . . . . L NEAR 04C5 CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-8 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +NORNDUP. . . . . . . . . . . . . L NEAR 0BED CODE +NOROOM . . . . . . . . . . . . . L NEAR 084A CODE +NOSCAN . . . . . . . . . . . . . L NEAR 12EE CODE +NOSKIP . . . . . . . . . . . . . L NEAR 0C1C CODE +NOSTAR . . . . . . . . . . . . . L NEAR 1342 CODE +NOSTOP . . . . . . . . . . . . . L NEAR 1190 CODE +NOSUCHDRV. . . . . . . . . . . . L NEAR 0F1D CODE +NOTALL . . . . . . . . . . . . . L NEAR 02BE CODE +NOTBUFFED. . . . . . . . . . . . L NEAR 0ABB CODE +NOTDEVICE. . . . . . . . . . . . L NEAR 07A7 CODE +NOTFND . . . . . . . . . . . . . L NEAR 1143 CODE +NOTINBUF . . . . . . . . . . . . L NEAR 0C62 CODE +NOTMAX . . . . . . . . . . . . . L NEAR 005C DATA +NUMDEV . . . . . . . . . . . . . Number 0005 +NUMDRV . . . . . . . . . . . . . L BYTE 002C CONSTANTS +NUMIO. . . . . . . . . . . . . . L BYTE 002D CONSTANTS +OK . . . . . . . . . . . . . . . L NEAR 083B CODE +OKRET. . . . . . . . . . . . . . L NEAR 0544 CODE +OKRET1 . . . . . . . . . . . . . L NEAR 04B8 CODE +OLDBAK . . . . . . . . . . . . . L NEAR 1093 CODE +ONSEC. . . . . . . . . . . . . . L NEAR 0A74 CODE +OPEN . . . . . . . . . . . . . . L NEAR 03CD CODE +OPENDEV. . . . . . . . . . . . . L NEAR 03FF CODE +OPENJMP. . . . . . . . . . . . . L NEAR 05E2 CODE +OPTCLUS. . . . . . . . . . . . . L NEAR 0D28 CODE +OPTIMIZE . . . . . . . . . . . . L NEAR 0D15 CODE +OUT. . . . . . . . . . . . . . . L NEAR 119F CODE +OUTCH. . . . . . . . . . . . . . L NEAR 11AC CODE +OUTCHJ . . . . . . . . . . . . . L NEAR 123E CODE +OUTMES . . . . . . . . . . . . . L NEAR 12A4 CODE +OUTSTR . . . . . . . . . . . . . L NEAR 129A CODE +PACK . . . . . . . . . . . . . . L NEAR 017F CODE +PACKIN . . . . . . . . . . . . . L NEAR 019F CODE +PARTSEG. . . . . . . . . . . . . L NEAR 0829 CODE +PERDRV . . . . . . . . . . . . . L NEAR 0035 DATA +PFLAG. . . . . . . . . . . . . . L BYTE 002A CONSTANTS +PHYCRLF. . . . . . . . . . . . . L NEAR 1066 CODE +PHYDRV . . . . . . . . . . . . . L NEAR 03C8 CODE +POPTAB . . . . . . . . . . . . . L NEAR 1236 CODE +PREREAD. . . . . . . . . . . . . L BYTE 013A DATA +PRINTOFF . . . . . . . . . . . . L NEAR 120D CODE +PRINTON. . . . . . . . . . . . . L NEAR 1206 CODE +PRTBUF . . . . . . . . . . . . . L NEAR 1298 CODE +PUNCH. . . . . . . . . . . . . . L NEAR 014A CODE +PUTNEW . . . . . . . . . . . . . L NEAR 1071 CODE +QUIT . . . . . . . . . . . . . . L NEAR 004B CODE +RAWINP . . . . . . . . . . . . . L NEAR 127F CODE +RAWIO. . . . . . . . . . . . . . L NEAR 1262 CODE +RAWOUT . . . . . . . . . . . . . L NEAR 1285 CODE +RDERR. . . . . . . . . . . . . . L NEAR 0A16 CODE +RDLAST . . . . . . . . . . . . . L NEAR 0B2D CODE +RDLASTJ. . . . . . . . . . . . . L NEAR 0A1B CODE +RDLP . . . . . . . . . . . . . . L NEAR 0A80 CODE +RDMID. . . . . . . . . . . . . . L NEAR 0A63 CODE +RDSEC. . . . . . . . . . . . . . L NEAR 08DD CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-9 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +READAUX. . . . . . . . . . . . . L NEAR 09D5 CODE +READCON. . . . . . . . . . . . . L NEAR 09DF CODE +READDEV. . . . . . . . . . . . . L NEAR 09C8 CODE +READER . . . . . . . . . . . . . L NEAR 0141 CODE +READOP . . . . . . . . . . . . . L BYTE 013B DATA +READTIME . . . . . . . . . . . . L NEAR 1427 CODE +RECCNT . . . . . . . . . . . . . L WORD 0146 DATA +RECOK. . . . . . . . . . . . . . L NEAR 0EE7 CODE +RECPOS . . . . . . . . . . . . . L BYTE 0142 DATA Length =0004 +REDISP . . . . . . . . . . . . . L NEAR 0084 CODE +REDISPJ. . . . . . . . . . . . . L NEAR 013E CODE +REEDIT . . . . . . . . . . . . . L NEAR 1147 CODE +RELBLKS. . . . . . . . . . . . . L NEAR 0E31 CODE +RELEASE. . . . . . . . . . . . . L NEAR 0E2F CODE +RELFILE. . . . . . . . . . . . . L NEAR 0CFA CODE +RENAME . . . . . . . . . . . . . L NEAR 02F3 CODE +RENERR . . . . . . . . . . . . . L NEAR 036C CODE +RENFIL . . . . . . . . . . . . . L NEAR 0317 CODE +RESFLG . . . . . . . . . . . . . L NEAR 127B CODE +RET1 . . . . . . . . . . . . . . L NEAR 01C7 CODE +RET10. . . . . . . . . . . . . . L NEAR 0873 CODE +RET100 . . . . . . . . . . . . . L NEAR 0D7C CODE +RET101 . . . . . . . . . . . . . L NEAR 1395 CODE +RET11. . . . . . . . . . . . . . L NEAR 0DF1 CODE +RET12. . . . . . . . . . . . . . L NEAR 0E2E CODE +RET13. . . . . . . . . . . . . . L NEAR 0E42 CODE +RET14. . . . . . . . . . . . . . L NEAR 0EB2 CODE +RET15. . . . . . . . . . . . . . L NEAR 0F9B CODE +RET16. . . . . . . . . . . . . . L NEAR 0FAE CODE +RET17. . . . . . . . . . . . . . L NEAR 0FBC CODE +RET18. . . . . . . . . . . . . . L NEAR 11C3 CODE +RET19. . . . . . . . . . . . . . L NEAR 1237 CODE +RET2 . . . . . . . . . . . . . . L NEAR 01D4 CODE +RET20. . . . . . . . . . . . . . L NEAR 1297 CODE +RET21. . . . . . . . . . . . . . L NEAR 1351 CODE +RET22. . . . . . . . . . . . . . L NEAR 1426 CODE +RET23. . . . . . . . . . . . . . L NEAR 1474 CODE +RET24. . . . . . . . . . . . . . L NEAR 14C3 CODE +RET25. . . . . . . . . . . . . . L NEAR 153B CODE +RET26. . . . . . . . . . . . . . L NEAR 1557 CODE +RET28. . . . . . . . . . . . . . L NEAR 0B2C CODE +RET29. . . . . . . . . . . . . . L NEAR 1261 CODE +RET3 . . . . . . . . . . . . . . L NEAR 020E CODE +RET30. . . . . . . . . . . . . . L NEAR 1142 CODE +RET4 . . . . . . . . . . . . . . L NEAR 029A CODE +RET5 . . . . . . . . . . . . . . L NEAR 0371 CODE +RET6 . . . . . . . . . . . . . . L NEAR 03B8 CODE +RET7 . . . . . . . . . . . . . . L NEAR 04A7 CODE +RET8 . . . . . . . . . . . . . . L NEAR 05FB CODE +RET9 . . . . . . . . . . . . . . L NEAR 0679 CODE +RNDRD. . . . . . . . . . . . . . L NEAR 070E CODE +RNDWRT . . . . . . . . . . . . . L NEAR 0716 CODE +SAMSIZ . . . . . . . . . . . . . L NEAR 0CB9 CODE +SAMSTK . . . . . . . . . . . . . L NEAR 0097 CODE +SAVCH. . . . . . . . . . . . . . L NEAR 1010 CODE +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-10 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +SAVEXIT. . . . . . . . . . . . . Number 000A +SAVFEB . . . . . . . . . . . . . L NEAR 148E CODE +SAVFIR . . . . . . . . . . . . . L NEAR 0862 CODE +SAVPLCE. . . . . . . . . . . . . L NEAR 0E53 CODE +SAVPOS . . . . . . . . . . . . . L NEAR 0990 CODE +SAVREGS. . . . . . . . . . . . . L NEAR 006D CODE +SCANB. . . . . . . . . . . . . . L NEAR 1352 CODE +SECCLUSPOS . . . . . . . . . . . L BYTE 0137 DATA +SECCNT . . . . . . . . . . . . . L WORD 015A DATA +SECPOS . . . . . . . . . . . . . L WORD 014C DATA +SELDSK . . . . . . . . . . . . . L NEAR 0FAF CODE +SEQRD. . . . . . . . . . . . . . L NEAR 06F6 CODE +SEQWRT . . . . . . . . . . . . . L NEAR 06FE CODE +SETATTRIB. . . . . . . . . . . . L NEAR 0114 CODE +SETBUF . . . . . . . . . . . . . L NEAR 08F9 CODE +SETCLUS. . . . . . . . . . . . . L NEAR 0B0E CODE +SETDATE. . . . . . . . . . . . . L NEAR 14C4 CODE +SETDIRT. . . . . . . . . . . . . L NEAR 0D00 CODE +SETDMA . . . . . . . . . . . . . L NEAR 0F12 CODE +SETEND . . . . . . . . . . . . . L NEAR 0153 DATA +SETFCB . . . . . . . . . . . . . L NEAR 0ACD CODE +SETFCBJ. . . . . . . . . . . . . L NEAR 09C5 CODE +SETIO. . . . . . . . . . . . . . L NEAR 0114 CODE +SETMEM . . . . . . . . . . . . . L NEAR 13BE CODE +SETNREX. . . . . . . . . . . . . L NEAR 074B CODE +SETRNDREC. . . . . . . . . . . . L NEAR 0F9C CODE +SETTIME. . . . . . . . . . . . . L NEAR 1558 CODE +SETUP. . . . . . . . . . . . . . L NEAR 0784 CODE +SETVECT. . . . . . . . . . . . . L NEAR 1396 CODE +SETYEAR. . . . . . . . . . . . . L NEAR 1481 CODE +SK . . . . . . . . . . . . . . . L NEAR 145A CODE +SKIPONE. . . . . . . . . . . . . L NEAR 110F CODE +SKIPSTR. . . . . . . . . . . . . L NEAR 1119 CODE +SKPCLP . . . . . . . . . . . . . L NEAR 088E CODE +SKPSPC . . . . . . . . . . . . . L NEAR 12EB CODE +SMALLENT . . . . . . . . . . . . L NEAR 05DA CODE +SMALREC. . . . . . . . . . . . . L NEAR 07B4 CODE +SMFAT. . . . . . . . . . . . . . L NEAR 00D4 DATA +SPCHK. . . . . . . . . . . . . . L NEAR 138F CODE +SPSAVE . . . . . . . . . . . . . L WORD 0131 DATA +SRCH . . . . . . . . . . . . . . L NEAR 01EB CODE +SRCHDEV. . . . . . . . . . . . . L NEAR 0E93 CODE +SRCHFRST . . . . . . . . . . . . L NEAR 0E50 CODE +SRCHNXT. . . . . . . . . . . . . L NEAR 0EB3 CODE +SSSAVE . . . . . . . . . . . . . L WORD 0133 DATA +STARTPOS . . . . . . . . . . . . L BYTE 0029 CONSTANTS +STARTSRCH. . . . . . . . . . . . L NEAR 0423 CODE +STATCHK. . . . . . . . . . . . . L NEAR 11C4 CODE +STOLET . . . . . . . . . . . . . L NEAR 03B4 CODE +STORE. . . . . . . . . . . . . . L NEAR 0BA9 CODE +TAB. . . . . . . . . . . . . . . L NEAR 1228 CODE +TABBAK . . . . . . . . . . . . . L NEAR 10CC CODE +TABLP. . . . . . . . . . . . . . L NEAR 122F CODE +TEMP . . . . . . . . . . . . . . L WORD 0131 DATA +THISDRV. . . . . . . . . . . . . L BYTE 013C DATA +  The Microsoft MACRO Assembler 01-26-83 PAGE Symbols-11 +MS-DOS version 1.25 by Tim Paterson March 3, 1982 + + +TOGLINS. . . . . . . . . . . . . Alias FALSE +TOGLPRN. . . . . . . . . . . . . Alias FALSE +TOTFATSIZ. . . . . . . . . . . . L NEAR 010F DATA +TRANBUF. . . . . . . . . . . . . L NEAR 0997 CODE +TRANS. . . . . . . . . . . . . . L BYTE 0139 DATA +TRUE . . . . . . . . . . . . . . Number FFFF +TRYIN. . . . . . . . . . . . . . L NEAR 0DF7 CODE +TRYOUT . . . . . . . . . . . . . L NEAR 0DF2 CODE +TSTALL . . . . . . . . . . . . . L NEAR 021E CODE +TWOESC . . . . . . . . . . . . . L NEAR 10E5 CODE +UNPACK . . . . . . . . . . . . . L NEAR 0157 CODE +UPDATE . . . . . . . . . . . . . L NEAR 0CE3 CODE +USERCODE . . . . . . . . . . . . L NEAR 0114 CODE +VALSEC . . . . . . . . . . . . . L WORD 014E DATA +VERFLG . . . . . . . . . . . . . L BYTE 002E CONSTANTS +VERIFY . . . . . . . . . . . . . L NEAR 0117 CODE +WEEKDAY. . . . . . . . . . . . . L BYTE 0049 CONSTANTS +WILDCRD. . . . . . . . . . . . . L NEAR 01FF CODE +WKDAY. . . . . . . . . . . . . . L NEAR 1529 CODE +WRTAUX . . . . . . . . . . . . . L NEAR 0B67 CODE +WRTCON . . . . . . . . . . . . . L NEAR 0B71 CODE +WRTDEV . . . . . . . . . . . . . L NEAR 0B47 CODE +WRTEOF . . . . . . . . . . . . . L NEAR 0CC3 CODE +WRTEOFJ. . . . . . . . . . . . . L NEAR 0BA6 CODE +WRTERR . . . . . . . . . . . . . L NEAR 0B92 CODE +WRTERRJ. . . . . . . . . . . . . L NEAR 0CC0 CODE +WRTFAT . . . . . . . . . . . . . L NEAR 0F8C CODE +WRTFATS. . . . . . . . . . . . . L NEAR 0F66 CODE +WRTLAST. . . . . . . . . . . . . L NEAR 0C79 CODE +WRTLP. . . . . . . . . . . . . . L NEAR 0C51 CODE +WRTLST . . . . . . . . . . . . . L NEAR 0B5B CODE +WRTMID . . . . . . . . . . . . . L NEAR 0C32 CODE +XXX. . . . . . . . . . . . . . . F PROC 0023 DATA Length =0001 +YEAR . . . . . . . . . . . . . . L WORD 0045 CONSTANTS +YRTAB. . . . . . . . . . . . . . L BYTE 1492 CODE +ZEROEXT. . . . . . . . . . . . . Alias FALSE +ZERPOS . . . . . . . . . . . . . L NEAR 1238 CODE + +Warning Severe +Errors Errors +0 0 + \ No newline at end of file diff --git a/2_printed_files/bundle_02/86DOS.A86 b/2_printed_files/bundle_02/86DOS.A86 new file mode 100644 index 0000000..98cd956 --- /dev/null +++ b/2_printed_files/bundle_02/86DOS.A86 @@ -0,0 +1,3901 @@ +00010 +00020 ; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +00030 ; by Tim Paterson +00040 +00050 ; ****************** Revision History ************************* +00060 ; >> EVERY change must noted below!! << +00070 ; +00080 ; 0.34 12/29/80 General release, updating all past customers +00090 ; 0.42 02/25/81 32-byte directory entries added +00100 ; 0.56 03/23/81 Variable record and sector sizes +00110 ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +00120 ; 0.74 04/15/81 Recognize I/O devices with file names +00130 ; 0.75 04/17/81 Improve and correct buffer handling +00140 ; 0.76 04/23/81 Correct directory size when not 2^N entries +00150 ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +00160 ; 1.00 04/28/81 Renumber for general release +00170 ; +00180 ; ************************************************************* +00190 +00192 EXCESS: EQU 511 ;Make 86-DOS artificially larger +00194 +00200 ; Use the switch below to generate code to accept the old 16-byte +00210 ; directory entry as well as the new 32-byte entry. +00220 +00230 SMALLDIR: EQU 0 ;1 to enable, 0 to disable +00240 +00250 +00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +00270 ; up a different stack for disk I/O (functions > 11) than that used for +00280 ; character I/O which effectively makes the DOS re-entrant. +00290 +00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +00310 +00320 +00330 ; Interrupt Entry Points: +00340 +00350 ; INTBASE: ABORT +00360 ; INTBASE+4: COMMAND +00370 ; INTBASE+8: BASE EXIT ADDRESS +00380 ; INTBASE+C: CONTROL-C ABORT +00390 ; INTBASE+10H: FATAL ERROR ABORT +00400 ; INTBASE+14H: BIOS DISK READ +00410 ; INTBASE+18H: BIOS DISK WRITE +00420 ; INTBASE+40H: Long jump to CALL entry point +00430 +00440 +00450 MAXCALL:EQU 36 +00460 MAXCOM: EQU 45 +00470 ESCCH: EQU 0 +00480 INTBASE:EQU 80H +00490 INTTAB: EQU 20H +00500 ENTRYPOINTSEG: EQU 0CH +00510 ENTRYPOINT: EQU INTBASE+40H +00520 CONTC: EQU INTTAB+3 +00530 EXIT: EQU INTBASE+8 +00540 LONGJUMP:EQU 0EAH +00550 LONGCALL:EQU 9AH +00560 MAXDIF: EQU 0FFFH +00570 SAVEXIT:EQU 10 +00580 ;Date format +00590 ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 +00600 ; y y y y y y y m m m m d d d d d +00610 ; +00620 ;where y=year,m=month,d=day +00630 +00640 ; Field definition for FCBs +00650 +00660 ORG 0 +00670 DS 12 ;Drive code and name +00680 EXTENT: DS 2 +00690 RECSIZ: DS 2 ;Size of record (user settable) +00700 FILSIZ: DS 4 ;Size of file in bytes +00710 FDATE: DS 2 ;Date of last writing +00720 FILDIRBLK:DS 2 ;Location in directory +00730 FIRCLUS:DS 2 ;First cluster of file +00740 LSTCLUS:DS 2 ;Last cluster accessed +00750 CLUSPOS:DS 2 ;Position of last cluster accessed +00760 DIRTYFIL:DS 1 ;File has been written to if <>0 +00770 ORG 32 +00780 NR: DS 1 ;Next record +00790 RR: DS 3 ;Random record +00800 +00810 +00820 ; Description of 32-byte directory entry (same as returned by SEARCH FIRST +00830 ; and SEARCH NEXT, functions 17 and 18). +00840 +00850 ; Location bytes Description +00860 +00870 ; 0 11 File name and extension ( 0E5H if empty) +00880 ; 11 1 Attributes. Bits 1 or 2 make file hidden +00890 ; 12 12 Zero field (for expansion) +00900 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +00910 ; 26 2 First allocation unit ( < 4080 ) +00920 ; 28 4 File size, in bytes (LSB first, 30 bits max.) +00930 +00940 +00950 ; Field definition for Drive Parameter Block +00960 +00970 ORG 0 +00980 DRVNUM: DS 1 ;Drive number +00990 SECSIZ: DS 2 ;Size of physical sector in bytes +01000 CLUSMSK:DS 1 ;Sectors/cluster - 1 +01010 CLUSSHFT:DS 1 ;Log2 of sectors/cluster +01020 FIRFAT: DS 2 ;Starting record of FATs +01030 FATCNT: DS 1 ;Number of FATs for this drive +01040 MAXENT: DS 2 ;Number of directory entries +01050 DIRSEC: ;Number of dir. sectors (init temporary) +01060 FIRREC: DS 2 ;First sector of first cluster +01070 DSKSIZ: ;Size of disk (temp used during init only) +01080 MAXCLUS:DS 2 ;Number of clusters on drive + 1 +01090 FATSIZ: DS 1 ;Number of records occupied by FAT +01100 FIRDIR: DS 2 ;Starting record of directory +01110 +01120 IF SMALLDIR +01130 FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +01140 MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +01150 FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +01160 MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries +01170 ENDIF +01180 +01190 DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +01200 FAT: ;Start of FAT +01210 DIRSIZ: ;-1=small dir. entry, else large +01220 +01230 +01240 ; BIOS entry point defintions +01250 +01260 BIOSSEG: EQU 60H +01270 ORG 0 +01280 DS 3 +01290 BIOSSTAT: DS 3 +01300 BIOSIN: DS 3 +01310 BIOSOUT: DS 3 +01320 BIOSPRINT: DS 3 +01330 BIOSAUXIN: DS 3 +01340 BIOSAUXOUT: DS 3 +01350 BIOSREAD: DS 3 +01360 BIOSWRITE: DS 3 +01370 BIOSDSKCHG: DS 3 +01380 +01390 +01400 ; Location of user registers relative user stack pointer +01410 +01420 ORG 0 +01430 AXSAVE: DS 2 +01440 BXSAVE: DS 2 +01450 CXSAVE: DS 2 +01460 DXSAVE: DS 2 +01470 SISAVE: DS 2 +01480 DISAVE: DS 2 +01490 BPSAVE: DS 2 +01500 DSSAVE: DS 2 +01510 ESSAVE: DS 2 +01520 IPSAVE: DS 2 +01530 CSSAVE: DS 2 +01540 FSAVE: DS 2 +01550 +01560 +01570 ; Start of code +01580 +01590 ORG 0 +01600 PUT 100H +01610 +01620 JMP DOSINIT +01630 ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +01640 ESCTAB: +01650 DB 77 ;Copy one char--RIGHT ARROW +01660 DB 59 ;Copy one char--F1 +01670 DB 83 ;Skip one char--DELETE +01680 DB 60 ;Copy to char--F2 +01690 DB 62 ;Skip to char--F4 +01700 DB 61 ;Copy line--F3 +01710 DB 64 ;Ctrl-Z--F6 +01720 DB 63 ;Reedit line (new template)--F5 +01730 DB 75 ;Backspace--LEFT ARROW +01740 DB 82 ;Toggle insert mode--INSERT +01750 DB 65 ;Escape character--F7 +01760 DB 65 ;End of table +01770 +01780 ESCTABLEN:EQU $-ESCTAB +01790 +01800 +01810 QUIT: +01820 MOV AH,0 +01830 JP SAVREGS +01840 +01850 COMMAND: ;Interrupt call entry point +01860 CMP AH,MAXCOM +01870 JBE SAVREGS +01880 BADCALL: +01890 MOV AL,0 +01900 IRET: IRET +01910 +01920 ENTRY: ;System call entry point and dispatcher +01930 POP AX ;IP from the long call at 5 +01940 POP AX ;Segment from the long call at 5 +01950 SEG CS +01960 POP [TEMP] ;IP from the CALL 5 +01970 PUSHF ;Start re-ordering the stack +01980 DI +01990 PUSH AX ;Save segment +02000 SEG CS +02010 PUSH [TEMP] ;Stack now ordered as if INT had been used +02020 CMP CL,MAXCALL ;This entry point doesn't get as many calls +02030 JA BADCALL +02040 MOV AH,CL +02050 SAVREGS: +02060 PUSH ES +02070 PUSH DS +02080 PUSH BP +02090 PUSH DI +02100 PUSH SI +02110 PUSH DX +02120 PUSH CX +02130 PUSH BX +02140 PUSH AX +02150 +02160 IF DSKTEST +02170 SEG CS +02180 MOV AX,[SPSAVE] +02190 SEG CS +02200 MOV [NSP],AX +02210 SEG CS +02220 MOV AX,[SSSAVE] +02230 SEG CS +02240 MOV [NSS],AX +02250 POP AX +02260 PUSH AX +02270 ENDIF +02280 +02290 SEG CS +02300 MOV [SPSAVE],SP +02310 SEG CS +02320 MOV [SSSAVE],SS +02330 MOV SP,CS +02340 MOV SS,SP +02350 REDISP: +02360 MOV SP,IOSTACK +02370 EI ;Stack OK now +02380 SEG CS +02390 MOV [FUNC],AH +02400 MOV BL,AH +02410 MOV BH,0 +02420 SHL BX +02430 UP +02440 CMP AH,12 +02450 JLE SAMSTK +02460 MOV SP,DSKSTACK +02470 SAMSTK: +02480 SEG CS +02490 CALL [BX+DISPATCH] +02500 LEAVE: +02510 DI +02520 SEG CS +02530 MOV SP,[SPSAVE] +02540 SEG CS +02550 MOV SS,[SSSAVE] +02560 MOV BP,SP +02570 MOV [BP+AXSAVE],AL +02580 +02590 IF DSKTEST +02600 SEG CS +02610 MOV AX,[NSP] +02620 SEG CS +02630 MOV [SPSAVE],AX +02640 SEG CS +02650 MOV AX,[NSS] +02660 SEG CS +02670 MOV [SSSAVE],AX +02680 ENDIF +02690 +02700 POP AX +02710 POP BX +02720 POP CX +02730 POP DX +02740 POP SI +02750 POP DI +02760 POP BP +02770 POP DS +02780 POP ES +02790 IRET +02800 +02810 DISPATCH: +02820 ; Standard Functions +02830 DW ABORT +02840 DW CONIN +02850 DW CONOUT +02860 DW READER +02870 DW PUNCH +02880 DW LIST +02890 DW RAWIO +02900 DW RAWINP +02910 DW IN +02920 DW PRTBUF +02930 DW BUFIN +02940 DW CONSTAT +02950 DW FLUSHKB +02960 DW DSKRESET +02970 DW SELDSK +02980 DW OPEN +02990 DW CLOSE +03000 DW SRCHFRST +03010 DW SRCHNXT +03020 DW DELETE +03030 DW SEQRD +03040 DW SEQWRT +03050 DW CREATE +03060 DW RENAME +03070 DW INUSE +03080 DW CURDRV +03090 DW SETDMA +03100 DW GETFATPT +03110 DW WRTPROT +03120 DW GETRDONLY +03130 DW SETATTRIB +03140 DW GETDSKPT +03150 DW USERCODE +03160 DW RNDRD +03170 DW RNDWRT +03180 DW FILESIZE +03190 DW SETRNDREC +03200 ; Extended Functions +03210 DW SETVECT +03220 DW NEWBASE +03230 DW BLKRD +03240 DW BLKWRT ;40 +03250 DW MAKEFCB +03260 DW GETDATE +03270 DW SETDATE +03280 DW GETTIME +03290 DW SETTIME ;45 +03300 +03310 GETIO: +03320 SETIO: +03330 WRTPROT: +03340 GETRDONLY: +03350 SETATTRIB: +03360 USERCODE: +03370 INUSE: +03380 GETDSKPT: +03390 MOV AL,0 +03400 RET +03410 +03420 FLUSHKB: +03430 XOR BX,BX +03440 MOV ES,BX ;Select segment 0 +03450 SEG ES +03460 MOV B,[41AH],1EH ;Reset KB queue head pointer +03470 SEG ES +03480 MOV B,[41CH],1EH ;Reset tail pointer +03490 MOV AH,AL +03500 CMP AL,1 +03510 JZ REDISPJ +03512 CMP AL,6 +03514 JZ REDISPJ +03520 CMP AL,7 +03530 JZ REDISPJ +03540 CMP AL,8 +03550 JZ REDISPJ +03560 CMP AL,10 +03570 JZ REDISPJ +03575 MOV AL,0 +03580 RET +03590 +03600 REDISPJ:JMP REDISP +03610 +03620 READER: +03630 AUXIN: +03640 CALL STATCHK +03650 CALL BIOSAUXIN,BIOSSEG +03660 RET +03670 +03680 PUNCH: +03690 MOV AL,DL +03700 AUXOUT: +03710 PUSH AX +03720 CALL STATCHK +03730 POP AX +03740 CALL BIOSAUXOUT,BIOSSEG +03750 RET +03760 +03770 +03780 UNPACK: +03790 +03800 ; Inputs: +03810 ; DS = CS +03820 ; BX = Cluster number +03830 ; BP = Base of drive parameters +03840 ; SI = Pointer to drive FAT +03850 ; Outputs: +03860 ; DI = Contents of FAT for given cluster +03870 ; Zero set means DI=0 (free cluster) +03880 ; No other registers affected. Fatal error if cluster too big. +03890 +03900 CMP BX,[BP+MAXCLUS] +03910 JA HURTFAT +03920 LEA DI,[SI+BX] +03930 SHR BX +03940 MOV DI,[DI+BX] +03950 JNC HAVCLUS +03960 SHR DI +03970 SHR DI +03980 SHR DI +03990 SHR DI +04000 STC +04010 HAVCLUS: +04020 RCL BX +04030 AND DI,0FFFH +04040 RET +04050 +04060 HURTFAT: +04070 PUSH AX +04080 MOV AH,80H +04090 MOV DI,0FFFH +04100 CALL FATAL +04110 POP AX +04120 RET +04130 +04140 +04150 PACK: +04160 +04170 ; Inputs: +04180 ; DS = CS +04190 ; BX = Cluster number +04200 ; DX = Data +04210 ; SI = Pointer to drive FAT +04220 ; Outputs: +04230 ; The data is stored in the FAT at the given cluster. +04240 ; BX,DX,DI all destroyed +04250 ; No other registers affected +04260 +04270 MOV DI,BX +04280 SHR BX +04290 ADD BX,SI +04300 ADD BX,DI +04310 SHR DI +04320 MOV DI,[BX] +04330 JNC ALIGNED +04340 SHL DX +04350 SHL DX +04360 SHL DX +04370 SHL DX +04380 AND DI,0FH +04390 JP PACKIN +04400 ALIGNED: +04410 AND DI,0F000H +04420 PACKIN: +04430 OR DI,DX +04440 MOV [BX],DI +04450 RET +04452 +04454 DEVNAME: +04455 MOV SI,IONAME ;List of I/O devices with file names +04456 MOV BL,6 ;BL = number of device names +04457 LOOKIO: +04458 MOV DI,NAME1 +04459 MOV CX,4 ;All device names are 4 letters +04460 REPE +04461 CMPB ;Check for name in list +04462 JZ IOCHK ;If first 4 letters OK, check the rest +04463 ADD SI,CX ;Point to next device name +04464 DEC BL +04465 JNZ LOOKIO +04466 CRET: +04467 STC +04468 RET +04470 IOCHK: +04480 MOV CX,4 ;Check rest of name but not extension +04490 MOV AL," " +04500 REPE +04510 SCAB ;Make sure rest of name is blanks +04520 JNZ CRET +04530 MOV AL,BL +04540 MOV BX,IONUM-1 +04550 XLAT ;Translate to internal device number +04560 MOV BL,AL +04570 MOV BH,-1 +04580 RET +04590 +04600 GETFILE: +04610 ; Same as GETNAME except ES:DI points to FCB on successful return +04620 CALL MOVNAME +04630 JC RET +04640 PUSH DX +04650 PUSH DS +04660 CALL FINDNAME +04670 POP ES +04680 POP DI +04690 RET +04700 +04710 GETNAME: +04720 +04730 ; Inputs: +04740 ; DS,DX point to FCB +04750 ; Function: +04760 ; Find file name in disk directory. First byte is +04770 ; drive number (0=current disk). "?" matches any +04780 ; character. +04790 ; Outputs: +04800 ; Carry set if file not found +04810 ; ELSE +04820 ; Zero set if attributes match (always except when creating) +04830 ; BP = Base of drive parameters +04840 ; DS = CS +04850 ; ES = CS +04860 ; BX = Pointer into directory buffer +04870 ; SI = Pointer to First Cluster field in directory entry +04880 ; [DIRBUF] has directory record with match +04890 ; [NAME1] has file name +04900 ; All other registers destroyed. +04910 +04920 CALL MOVNAME +04930 JC RET ;Bad file name? +04940 FINDNAME: +04950 MOV AX,CS +04960 MOV DS,AX +04961 CALL DEVNAME +04962 JNC RET +05090 CALL STARTSRCH +05100 CONTSRCH: +05110 CALL GETENTRY +05120 JC RET +05130 SRCH: +05140 CMP B,[BX],0E5H +05150 JZ NEXTENT +05160 MOV SI,BX +05170 MOV DI,NAME1 +05180 MOV CX,11 +05190 WILDCRD: +05200 REPE +05210 CMPB +05220 JZ FOUND +05230 CMP B,[DI-1],"?" +05240 JZ WILDCRD +05250 NEXTENT: +05260 CALL NEXTENTRY +05270 JNC SRCH +05280 RET +05290 +05300 FOUND: +05310 +05320 IF SMALLDIR +05330 CMP B,[BP+DIRSIZ],-1 +05340 JZ RET +05350 ENDIF +05360 +05370 ;Check if attributes allow finding it +05380 MOV AH,[ATTRIB] ;Attributes of search +05390 NOT AH +05400 AND AH,[SI] ;Compare with attributes of file +05410 ADD SI,15 +05420 AND AH,6 ;Only look at bits 1 and 2 +05430 JZ RET +05440 TEST B,[CREATING],-1 +05450 JZ NEXTENT +05460 RET +05470 +05480 +05490 GETENTRY: +05500 +05510 ; Inputs: +05520 ; [LASTENT] has previously searched directory entry +05530 ; Function: +05540 ; Locates next sequential directory entry in preparation for search +05550 ; Outputs: +05560 ; Carry set if none +05570 ; ELSE +05580 ; AL = Current directory block +05590 ; BX = Pointer to next directory entry in [DIRBUF] +05600 ; DX = Pointer to first byte after end of DIRBUF +05610 ; [LASTENT] = New directory entry number +05620 +05630 MOV AX,[LASTENT] +05640 INC AX ;Start with next entry +05650 CMP AX,[BP+MAXENT] +05660 JAE NONE +05670 GETENT: +05680 MOV [LASTENT],AX +05690 MOV CL,4 +05700 SHL AX,CL +05710 XOR DX,DX +05720 +05730 IF SMALLDIR +05740 CMP B,[BP+DIRSIZ],-1 +05750 JZ SMALENT1 +05760 ENDIF +05770 +05780 SHL AX +05790 RCL DX ;Account for overflow in last shift +05800 SMALENT1: +05810 MOV BX,[BP+SECSIZ] +05820 AND BL,255-31 ;Must be multiple of 32 +05830 DIV AX,BX +05840 MOV BX,DX ;Position within sector +05850 MOV AH,[BP+DRVNUM] ;AL=Directory sector no. +05860 CMP AX,[DIRBUFID] +05870 JZ HAVDIRBUF +05880 PUSH BX +05890 CALL DIRREAD +05900 POP BX +05910 HAVDIRBUF: +05920 MOV DX,DIRBUF +05930 ADD BX,DX +05940 ADD DX,[BP+SECSIZ] +05950 RET +05960 +05970 NEXTENTRY: +05980 +05990 ; Inputs: +06000 ; Same as outputs of GETENTRY, above +06010 ; Function: +06020 ; Update AL, BX, and [LASTENT] for next directory entry. +06030 ; Carry set if no more. +06040 +06050 MOV DI,[LASTENT] +06060 INC DI +06070 CMP DI,[BP+MAXENT] +06080 JAE NONE +06090 MOV [LASTENT],DI +06100 ADD BX,32 +06110 +06120 IF SMALLDIR +06130 CMP B,[BP+DIRSIZ],-1 +06140 JNZ BIGENT3 +06150 SUB BX,16 +06160 BIGENT3: +06170 ENDIF +06180 +06190 CMP BX,DX +06200 JB HAVIT +06210 INC AL ;Next directory sector +06220 PUSH DX ;Save limit +06230 CALL DIRREAD +06240 POP DX +06250 MOV BX,DIRBUF +06260 HAVIT: +06270 CLC +06280 RET +06290 +06300 NONE: +06310 CALL CHKDIRWRITE +06320 STC +06330 RET +06340 +06350 +06360 DELETE: ; System call 19 +06370 CALL GETNAME +06375 MOV AL,-1 +06380 JC RET +06390 CMP BH,AL ;Check if device name +06400 JZ RET ;Can't delete I/O devices +06410 DELFILE: +06420 MOV B,[DIRTYDIR],-1 +06430 MOV B,[BX],0E5H +06440 MOV BX,[SI] +06450 LEA SI,[BP+FAT] +06460 OR BX,BX +06470 JZ DELNXT +06480 CMP BX,[BP+MAXCLUS] +06490 JA DELNXT +06500 CALL RELEASE +06510 DELNXT: +06520 CALL CONTSRCH +06530 JNC DELFILE +06540 CALL FATWRT +06550 CALL CHKDIRWRITE +06560 XOR AL,AL +06570 RET +06580 +06590 +06600 RENAME: ;System call 23 +06610 CALL MOVNAME +06620 JC ERRET +06650 ADD SI,5 +06660 MOV DI,NAME2 +06670 CALL LODNAME +06675 JC ERRET +06680 CALL FINDNAME +06690 JC ERRET +06692 CMP BH,-1 ;Check if I/O device name +06694 JZ ERRET ;If so, can't rename it +06700 MOV SI,NAME1 +06710 MOV DI,NAME3 +06720 MOV CX,6 ;Include attribute byte +06730 REP +06740 MOVW ;Copy name to search for +06750 RENFIL: +06760 MOV DI,NAME1 +06770 MOV SI,NAME2 +06780 MOV CX,11 +06790 NEWNAM: +06800 LODB +06810 CMP AL,"?" +06820 JNZ NOCHG +06830 MOV AL,[BX] +06840 NOCHG: +06850 STOB +06860 INC BX +06870 LOOP NEWNAM +06871 MOV B,[DI],6 ;Stop duplicates with any attributes +06872 CALL DEVNAME ;Check if giving it a device name +06874 JNC RENERR +06890 PUSH [LASTENT] ;Save position of match +06895 MOV [LASTENT],-1 ;Search entire dirctory for duplicate +06900 CALL CONTSRCH ;See if new name already exists +06910 POP AX +06920 JNC RENERR ;Error if found +06930 CALL GETENT ;Re-read matching entry +06940 MOV DI,BX +06950 MOV SI,NAME1 +06960 MOV CX,11 +06970 REP +06980 MOVB ;Replace old name with new +06990 MOV B,[DIRTYDIR],-1 ;Flag change in directory +07000 MOV SI,NAME3 +07010 MOV DI,NAME1 +07020 MOV CX,6 ;Include attribute byte +07030 REP +07040 MOVW ;Copy name back into search buffer +07050 CALL CONTSRCH +07060 JNC RENFIL +07070 CALL CHKDIRWRITE +07080 XOR AL,AL +07090 RET +07100 +07102 RENERR: +07104 CALL CHKDIRWRITE +07110 ERRET: +07120 MOV AL,-1 +07130 RET +07140 +07150 +07160 MOVNAME: +07170 +07180 ; Inputs: +07190 ; DS, DX point to FCB or extended FCB +07200 ; Outputs: +07210 ; DS:DX point to normal FCB +07220 ; ES = CS +07230 ; If file name OK: +07240 ; BP has base of driver parameters +07250 ; [NAME1] has name in upper case +07260 ; All registers except DX destroyed +07270 ; Carry set if bad file name or drive +07280 +07290 SEG CS +07300 MOV B,[CREATING],0 +07310 MOV AX,CS +07320 MOV ES,AX +07330 MOV DI,NAME1 +07340 MOV SI,DX +07350 LODB +07360 SEG CS +07370 MOV [EXTFCB],AL +07380 MOV AH,0 +07390 CMP AL,-1 +07400 JNZ HAVATTRB +07410 ADD DX,7 +07420 ADD SI,6 +07430 MOV AH,[SI-1] +07440 LODB +07450 HAVATTRB: +07460 SEG CS +07470 MOV [ATTRIB],AH +07480 CALL GETBP +07490 JB RET +07500 LODNAME: +07510 ; This entry point copies a file name from DS,SI +07520 ; to ES,DI converting to upper case. +07522 CMP B,[SI]," " ;First letter may not be blank +07524 STC ;Ready to indicate error +07526 JZ RET +07530 MOV CX,11 +07540 MOVCHK: +07550 CALL GETLET +07560 JNZ CTRLCHK ;Is it a delimiter? +07570 CMP AL," " ;This is the only delimiter allowed +07580 STC ;In case of error +07590 JNZ RET +07600 CTRLCHK: +07610 CMP AL,20H +07620 JC RET +07630 STOB +07640 LOOP MOVCHK +07650 RET +07660 +07670 GETBP: +07680 SEG CS +07690 CMP [NUMDRV],AL +07700 JC RET +07710 CBW +07720 XCHG BP,AX +07730 SHL BP +07740 MOV BP,[BP+CURDRVPT] +07750 RET +07760 +07770 +07780 OPEN: ;System call 15 +07790 CALL GETFILE +07800 DOOPEN: +07810 ; Enter here to perform OPEN on file already found +07820 ; in directory. DS=CS, BX points to directory +07830 ; entry in DIRBUF, SI points to First Cluster field, and +07840 ; ES:DI point to the FCB to be opened. This entry point +07850 ; is used by CREATE. +07860 JC ERRET +07870 CMP BH,-1 ;Check if file is I/O device +07880 JZ OPENDEV ;Special handler if so +07890 MOV AL,[BP+DRVNUM] +07900 INC AL +07910 STOB +07920 ADD DI,11 ;Point to extent field +07930 XOR AX,AX +07940 STOW ;Set extent field to 0 +07950 MOV AX,128 ;Default record size +07960 STOW ;Set record size +07970 LODW ;Get starting cluster +07980 MOV DX,AX ;Save it for the moment +07990 MOVW ;Transfer size to FCB +08000 MOVW +08010 MOV AX,[SI-8] ;Get date +08020 +08030 IF SMALLDIR +08040 CMP B,[BP+DIRSIZ],-1 +08050 JNZ BIGENT10 +08060 SEG ES +08070 MOV [DI-1],0 +08080 XOR AX,AX ;Date not available in small entry +08090 BIGENT10: +08100 ENDIF +08110 +08120 STOW ;Save date in FCB +08130 MOV AX,[LASTENT] +08140 STOW ;directory location +08150 MOV AX,DX ;Restore starting cluster +08160 STOW ; first cluster +08170 STOW ; last cluster accessed +08180 XOR AX,AX +08190 STOW ; position of last cluster +08200 STOB ; dirty flag +08210 RET +08220 +08230 OPENDEV: +08240 SEG ES +08250 MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag +08260 XOR AL,AL +08270 RET +08280 +08290 +08300 STARTSRCH: +08310 MOV [LASTENT],-1 +08320 FATREAD: +08330 +08340 ; Inputs: +08350 ; DS = CS +08360 ; BP = Base of drive parameters +08370 ; Function: +08380 ; If disk may have been changed, FAT is read in and buffers are +08390 ; flagged invalid. If not, no action is taken. +08400 ; Outputs: +08410 ; AL = 0 +08420 ; BP unchanged +08430 ; All other registers destroyed +08440 +08450 MOV AL,[BP+DRVNUM] +08460 CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say +08470 MOV AL,[BP+DRVNUM] +08480 OR AH,[BP+DIRTYFAT] +08490 JS NEWDSK ;If either say new disk, then it's so +08500 DEC AH ;Check for AH=1 (disk not changed) +08510 JZ RET +08520 MOV AH,1 +08530 CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? +08540 JZ RET ;If so, disk has not been changed +08550 NEWDSK: +08560 CMP AL,[BUFDRVNO] ;See if buffer is for this drive +08570 JNZ BUFOK ;If not, don't touch it +08580 MOV [BUFSECNO],0 ;Flag buffers invalid +08590 MOV [BUFDRVNO],00FFH +08600 BUFOK: +08610 MOV [DIRBUFID],-1 +08620 CALL FIGFAT +08630 NEXTFAT: +08640 PUSH AX +08650 CALL DSKREAD +08660 POP AX +08670 JC BADFAT +08680 +08690 IF SMALLDIR +08700 MOV DL,AL +08710 LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries +08720 CMP B,[BP+DIRSIZ],-1 +08730 JZ SETSIZ +08740 ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +08750 SETSIZ: +08760 LODW +08770 MOV [BP+FIRREC],AX +08780 LODW +08790 MOV [BP+MAXCLUS],AX +08800 MOV AL,DL +08810 ENDIF +08820 +08830 SUB AL,[BP+FATCNT] +08840 JZ RET +08850 NEG AL +08860 ;{Insert error code here. AL=number of bad fats. +08870 ;Since one good FAT was read, should include option +08880 ;to rewrite all FATs.} +08890 JMP FATWRT +08900 +08910 BADFAT: +08920 MOV CX,DI +08930 ADD DX,CX +08940 DEC AL +08950 JNZ NEXTFAT +08960 CALL FIGFAT ;Reset registers +08970 JMP DREAD ;Try first FAT once more +08980 +08990 OKRET1: +09000 MOV AL,0 +09010 RET +09020 +09030 CLOSE: ;System call 16 +09040 MOV DI,DX +09050 CMP B,[DI],-1 +09060 JNZ NORMFCB3 +09070 ADD DI,7 +09080 NORMFCB3: +09090 CMP B,[DI+FILDIRBLK+1],-1 ;Check for I/O device +09100 JZ OKRET1 ;Can't close I/O device +09110 TEST B,[DI+DIRTYFIL],-1 +09120 JZ OKRET1 ;If not written to, do nothing +09130 MOV AL,[DI] ;Get drive number +09140 CALL GETBP ;Get base of drive parameters +09150 JC BADCLOSEJ +09160 MOV AL,[BP+DRVNUM] +09170 MOV AH,1 ;Look for dirty buffer +09180 SEG CS +09190 CMP AX,[BUFDRVNO] +09200 JNZ FNDDIR +09210 ;Write back dirty buffer if on same drive +09220 PUSH DX +09230 PUSH DS +09240 PUSH CS +09250 POP DS +09260 MOV B,[DIRTYBUF],0 +09270 MOV BX,[BUFFER] +09280 MOV CX,1 +09290 MOV DX,[BUFSECNO] +09300 CALL DWRITE +09310 POP DS +09320 POP DX +09330 FNDDIR: +09340 CALL GETFILE +09350 BADCLOSEJ: +09360 JC BADCLOSE +09370 MOV AX,[LASTENT] +09380 SEG ES +09390 CMP AX,[DI+FILDIRBLK] +09400 JNZ BADCLOSE +09410 SEG ES +09420 MOV CX,[DI+FIRCLUS] +09430 MOV [SI],CX +09440 SEG ES +09450 MOV DX,[DI+FILSIZ] +09460 MOV [SI+2],DX +09470 SEG ES +09480 MOV DX,[DI+FILSIZ+2] +09490 +09500 IF SMALLDIR +09510 CMP B,[BP+DIRSIZ],-1 +09520 JNZ BIGENT11 +09530 MOV [SI+4],DL +09540 JP SMALLENT2 +09550 BIGENT11: +09560 ENDIF +09570 +09580 MOV [SI+4],DX +09590 SEG ES +09600 MOV DX,[DI+FDATE] +09610 MOV [SI-2],DX +09620 SMALLENT2: +09630 CALL DIRWRITE +09640 +09650 CHKFATWRT: +09660 ; Do FATWRT only if FAT is dirty +09670 +09680 CMP B,[BP+DIRTYFAT],1 +09690 JNZ OKRET +09700 +09710 FATWRT: +09720 +09730 ; Inputs: +09740 ; DS = CS +09750 ; BP = Base of drive parameter table +09760 ; Function: +09770 ; Write the FAT back to disk and reset FAT +09780 ; dirty bit. +09790 ; Outputs: +09800 ; AL = 0 +09810 ; BP unchanged +09820 ; All other registers destroyed +09830 +09840 MOV B,[BP+DIRTYFAT],0 +09850 CALL FIGFAT +09860 EACHFAT: +09870 PUSH DX +09880 PUSH CX +09890 PUSH BX +09900 PUSH AX +09910 CALL DWRITE +09920 POP AX +09930 POP BX +09940 POP CX +09950 POP DX +09960 ADD DX,CX +09970 DEC AL +09980 JNZ EACHFAT +09990 OKRET: +10000 MOV AL,0 +10010 RET +10020 +10030 BADCLOSE: +10040 MOV B,[BP+DIRTYFAT],0 +10050 MOV AL,-1 +10060 RET +10070 +10080 +10090 FIGFAT: +10100 ; Loads registers with values needed to read or +10110 ; write a FAT. +10120 MOV AL,[BP+FATCNT] +10130 LEA BX,[BP+FAT] +10140 MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT +10150 MOV CH,0 +10160 MOV DX,[BP+FIRFAT] ;Record number of start of FATs +10170 RET +10180 +10190 +10200 DIRCOMP: +10210 ; Prepare registers for directory read or write +10220 CBW +10230 ADD AX,[BP+FIRDIR] +10240 MOV DX,AX +10250 MOV BX,DIRBUF +10260 MOV CX,1 +10270 RET +10280 +10290 +10300 CREATE: ;System call 22 +10310 CALL MOVNAME +10320 JC ERRET3 +10330 MOV DI,NAME1 +10340 MOV CX,11 +10350 MOV AL,"?" +10360 REPNE +10370 SCAB +10380 JZ ERRET3 +10390 SEG CS +10400 MOV B,[CREATING],1 +10410 PUSH DX +10420 PUSH DS +10430 CALL FINDNAME +10440 JNC EXISTENT +10450 CALL STARTSRCH +10460 CALL GETENTRY +10470 LOOKFRE: +10480 CMP B,[BX],0E5H +10490 JZ FREESPOT +10500 CALL NEXTENTRY +10510 JNC LOOKFRE +10520 ERRPOP: +10530 POP DS +10540 POP DX +10550 ERRET3: +10560 MOV AL,-1 +10570 RET +10580 +10590 EXISTENT: +10600 JNZ ERRPOP ;Error if attributes don't match +10610 CMP BH,-1 ;Check if file is I/O device +10620 JZ OPENJMP ;If so, no action +10630 MOV CX,[SI] ;Get pointer to clusters +10640 JCXZ FREESPOT +10650 CMP CX,[BP+MAXCLUS] +10660 JA FREESPOT +10670 PUSH BX +10680 MOV BX,CX +10690 LEA SI,[BP+FAT] +10700 CALL RELEASE ;Free any data already allocated +10710 CALL FATWRT +10720 POP BX +10730 FREESPOT: +10740 MOV DI,BX +10750 MOV SI,NAME1 +10760 MOV CX,5 +10770 MOVB +10780 REP +10790 MOVW +10800 +10810 IF SMALLDIR +10820 CMP B,[BP+DIRSIZ],-1 +10830 JNZ BIGENT4 +10840 PUSH DI +10850 MOV CL,5 +10860 XOR AX,AX +10870 JP SMALLENT +10880 BIGENT4: +10890 ENDIF +10900 +10910 MOV AL,[ATTRIB] +10920 STOB +10930 XOR AX,AX +10940 MOV CL,6 +10950 REP +10960 STOW +10970 CALL DATE16 +10980 STOW +10990 XOR AX,AX +11000 PUSH DI +11010 MOV CL,6 +11020 SMALLENT: +11030 REP +11040 STOB +11050 PUSH BX +11060 CALL DIRWRITE +11070 POP BX +11080 POP SI +11090 OPENJMP: +11100 CLC ;Clear carry so OPEN won't fail +11110 POP ES +11120 POP DI +11130 JMP DOOPEN +11140 +11150 +11160 DIRREAD: +11170 +11180 ; Inputs: +11190 ; DS = CS +11200 ; AL = Directory block number +11210 ; BP = Base of drive parameters +11220 ; Function: +11230 ; Read the directory block into DIRBUF. +11240 ; Outputs: +11250 ; AX,BP unchanged +11260 ; All other registers destroyed. +11270 +11280 PUSH AX +11290 CALL CHKDIRWRITE +11300 POP AX +11310 PUSH AX +11320 MOV AH,[BP+DRVNUM] +11330 MOV [DIRBUFID],AX +11340 CALL DIRCOMP +11350 CALL DREAD +11360 POP AX +11370 RET +11380 +11390 +11400 DREAD: +11410 +11420 ; Inputs: +11430 ; BX,DS = Transfer address +11440 ; CX = Number of sectors +11450 ; DX = Absolute record number +11460 ; BP = Base of drive parameters +11470 ; Function: +11480 ; Calls BIOS to perform disk read. If BIOS reports +11490 ; errors, will call HARDERR for further action. +11500 ; BP preserved. All other registers destroyed. +11510 +11520 CALL DSKREAD +11530 JNC RET +11540 SEG CS +11550 MOV B,[READOP],0 +11560 CALL HARDERR +11570 CMP AL,1 ;Check for retry +11580 JZ DREAD +11590 RET ;Ignore otherwise +11600 +11610 HARDERR: +11620 ;Hard disk error handler. Entry conditions: +11630 ; DS:BX = Original disk transfer address +11640 ; DX = Original logical sector number +11650 ; CX = Number of sectors to go (first one gave the error) +11660 ; AX = Hardware error code +11670 ; DI = Original sector transfer count +11680 ; BP = Base of drive parameters +11690 ; [READOP] = 0 for read, 1 for write +11700 +11710 XCHG AX,DI ;Error code in DI, count in AX +11720 SUB AX,CX ;Number of sectors successfully transferred +11730 ADD DX,AX ;First sector number to retry +11740 PUSH DX +11750 MUL AX,[BP+SECSIZ] ;Number of bytes transferred +11760 POP DX +11770 ADD BX,AX ;First address for retry +11780 MOV AH,0 ;Flag disk section in error +11790 CMP DX,[BP+FIRFAT] ;In reserved area? +11800 JB ERRINT +11810 INC AH ;Flag for FAT +11820 CMP DX,[FIRDIR] ;In FAT? +11830 JB ERRINT +11840 INC AH +11850 CMP DX,[FIRREC] ;In directory? +11860 JB ERRINT +11870 INC AH ;Must be in data area +11880 ERRINT: +11890 SHL AH ;Make room for read/write bit +11900 SEG CS +11910 OR AH,[READOP] +11920 FATAL: +11930 MOV AL,[BP+DRVNUM] ;Get drive number +11940 PUSH BP ;The only thing we preserve +11950 SEG CS +11960 MOV [CONTSTK],SP +11970 DI ;Prepare to play with stack +11980 SEG CS +11990 MOV SS,[SSSAVE] +12000 SEG CS +12010 MOV SP,[SPSAVE] ;User stack pointer restored +12020 INT 24H ;Fatal error interrupt vector +12030 SEG CS +12040 MOV [SPSAVE],SP +12050 SEG CS +12060 MOV [SSSAVE],SS +12070 MOV SP,CS +12080 MOV SS,SP +12090 SEG CS +12100 MOV SP,[CONTSTK] +12110 EI +12120 POP BP +12130 CMP AL,2 +12140 JZ ERROR +12150 RET +12160 +12170 DSKREAD: +12180 MOV AL,[BP+DRVNUM] +12190 PUSH BP +12200 PUSH BX +12210 PUSH CX +12220 PUSH DX +12230 CALL BIOSREAD,BIOSSEG +12240 POP DX +12250 POP DI +12260 POP BX +12270 POP BP +12280 RET +12290 +12300 +12310 CHKDIRWRITE: +12320 TEST B,[DIRTYDIR],-1 +12330 JZ RET +12340 +12350 DIRWRITE: +12360 +12370 ; Inputs: +12380 ; DS = CS +12390 ; AL = Directory block number +12400 ; BP = Base of drive parameters +12410 ; Function: +12420 ; Write the directory block into DIRBUF. +12430 ; Outputs: +12440 ; BP unchanged +12450 ; All other registers destroyed. +12460 +12470 MOV B,[DIRTYDIR],0 +12480 MOV AL,[DIRBUFID] +12490 CALL DIRCOMP +12500 +12510 +12520 DWRITE: +12530 +12540 ; Inputs: +12550 ; BX,DS = Transfer address +12560 ; CX = Number of sectors +12570 ; DX = Absolute record number +12580 ; BP = Base of drive parameters +12590 ; Function: +12600 ; Calls BIOS to perform disk write. If BIOS reports +12610 ; errors, will call HARDERR for further action. +12620 ; BP preserved. All other registers destroyed. +12630 +12640 MOV AL,[BP+DRVNUM] +12650 PUSH BP +12660 PUSH BX +12670 PUSH CX +12680 PUSH DX +12690 CALL BIOSWRITE,BIOSSEG +12700 POP DX +12710 POP DI +12720 POP BX +12730 POP BP +12740 JNC RET +12750 SEG CS +12760 MOV B,[READOP],1 +12770 CALL HARDERR +12780 CMP AL,1 ;Check for retry +12790 JZ DWRITE +12800 RET +12810 +12820 ABORT: +12830 SEG CS +12840 LDS SI,[SPSAVE] +12850 MOV DS,[SI+CSSAVE] +12860 XOR AX,AX +12870 MOV ES,AX +12880 MOV SI,SAVEXIT +12890 MOV DI,EXIT +12900 MOVW +12910 MOVW +12920 MOVW +12930 MOVW +12940 ERROR: +12950 MOV AX,CS +12960 MOV DS,AX +12970 MOV ES,AX +12980 CALL WRTFATS +12990 XOR AX,AX +13000 DI +13010 MOV SS,[SSSAVE] +13020 MOV SP,[SPSAVE] +13030 MOV DS,AX +13040 MOV SI,EXIT +13050 MOV DI,EXITHOLD +13060 MOVW +13070 MOVW +13080 POP AX +13090 POP BX +13100 POP CX +13110 POP DX +13120 POP SI +13130 POP DI +13140 POP BP +13150 POP DS +13160 POP ES +13170 EI ;Stack OK now +13180 SEG CS +13190 JMP L,[EXITHOLD] +13200 +13210 +13220 SEQRD: ;System call 20 +13230 CALL GETREC +13240 CALL LOAD +13250 JP FINSEQ +13260 +13270 SEQWRT: ;System call 21 +13280 CALL GETREC +13290 CALL STORE +13300 FINSEQ: +13310 JCXZ SETNREX +13320 ADD AX,1 +13330 ADC DX,0 +13340 JP SETNREX +13350 +13360 RNDRD: ;System call 33 +13370 CALL GETRRPOS1 +13380 CALL LOAD +13390 JP FINRND +13400 +13410 RNDWRT: ;System call 34 +13420 CALL GETRRPOS1 +13430 CALL STORE +13440 JP FINRND +13450 +13460 BLKRD: ;System call 39 +13470 CALL GETRRPOS +13480 CALL LOAD +13490 JP FINBLK +13500 +13510 BLKWRT: ;System call 40 +13520 CALL GETRRPOS +13530 CALL STORE +13540 FINBLK: +13550 LDS SI,[SPSAVE] +13560 MOV [SI+CXSAVE],CX +13570 JCXZ FINRND +13580 ADD AX,1 +13590 ADC DX,0 +13600 FINRND: +13610 SEG ES +13620 MOV [DI+RR],AX +13630 SEG ES +13640 MOV [DI+RR+2],DL +13650 OR DH,DH +13660 JZ SETNREX +13670 SEG ES +13680 MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +13690 SETNREX: +13700 MOV CX,AX +13710 AND AL,7FH +13720 SEG ES +13730 MOV [DI+NR],AL +13740 AND CL,80H +13750 SHL CX +13760 RCL DX +13770 MOV AL,CH +13780 MOV AH,DL +13790 SEG ES +13800 MOV [DI+EXTENT],AX +13810 SEG CS +13820 MOV AL,[DSKERR] +13830 RET +13840 +13850 GETRRPOS1: +13860 MOV CX,1 +13870 GETRRPOS: +13880 MOV DI,DX +13890 CMP B,[DI],-1 +13900 JNZ NORMFCB1 +13910 ADD DI,7 +13920 NORMFCB1: +13930 MOV AX,[DI+RR] +13940 MOV DX,[DI+RR+2] +13950 RET +13960 +13970 NOFILERR: +13980 XOR CX,CX +13990 MOV B,[DSKERR],4 +14000 POP BX +14010 RET +14020 +14030 SETUP: +14040 +14050 ; Inputs: +14060 ; DS:DI point to FCB +14070 ; DX:AX = Record position in file of disk transfer +14080 ; CX = Record count +14090 ; Outputs: +14100 ; DS = CS +14110 ; ES:DI point to FCB +14120 ; CX = No. of bytes to transfer +14130 ; BP = Base of drive parameters +14140 ; SI = FAT pointer +14150 ; [RECCNT] = Record count +14160 ; [RECPOS] = Record position in file +14170 ; [FCB] = DI +14180 ; [NEXTADD] = Displacement of disk transfer within segment +14190 ; [SECPOS] = Position of first sector +14200 ; [BYTPOS] = Byte position in file +14210 ; [BYTSECPOS] = Byte position in first sector +14220 ; [CLUSNUM] = First cluster +14230 ; [SECCLUSPOS] = Sector within first cluster +14240 ; [DSKERR] = 0 (no errors yet) +14250 ; [TRANS] = 0 (No transfers yet) +14260 ; If SETUP detects no records will be transfered, it returns 1 level up +14270 ; with CX = 0. +14280 +14290 PUSH AX +14300 MOV AL,[DI] +14310 MOV SI,[DI+RECSIZ] +14320 OR SI,SI +14330 JNZ HAVRECSIZ +14340 MOV SI,128 +14350 MOV [DI+RECSIZ],SI +14360 HAVRECSIZ: +14370 MOV BX,DS +14380 MOV ES,BX +14390 MOV BX,CS +14400 MOV DS,BX +14410 CALL GETBP +14420 POP AX +14430 JC NOFILERR +14440 CMP SI,64 ;Check if highest byte of RECPOS is significant +14450 JB SMALREC +14460 MOV DH,0 ;Ignore MSB if record >= 64 bytes +14470 SMALREC: +14480 MOV [RECCNT],CX +14490 MOV [RECPOS],AX +14500 MOV [RECPOS+2],DX +14510 MOV [FCB],DI +14520 MOV BX,[DMAADD] +14530 MOV [NEXTADD],BX +14540 MOV B,[DSKERR],0 +14550 MOV B,[TRANS],0 +14560 MOV BX,DX +14570 MUL AX,SI +14580 MOV [BYTPOS],AX +14590 PUSH DX +14600 MOV AX,BX +14610 MUL AX,SI +14620 POP BX +14630 ADD AX,BX +14640 ADC DX,0 ;Ripple carry +14650 JNZ EOFERR +14660 MOV [BYTPOS+2],AX +14670 MOV DX,AX +14680 MOV AX,[BYTPOS] +14690 MOV BX,[BP+SECSIZ] +14700 CMP DX,BX ;See if divide will overflow +14710 JNC EOFERR +14720 DIV AX,BX +14730 MOV [SECPOS],AX +14740 MOV [BYTSECPOS],DX +14750 MOV DX,AX +14760 AND AL,[BP+CLUSMSK] +14770 MOV [SECCLUSPOS],AL +14780 MOV AX,CX ;Record count +14790 MOV CL,[BP+CLUSSHFT] +14800 SHR DX,CL +14810 MOV [CLUSNUM],DX +14820 MUL AX,SI ;Multiply by bytes per record +14830 MOV CX,AX +14840 ADD AX,[DMAADD] ;See if it will fit in one segment +14850 ADC DX,0 +14860 JZ OK ;Must be less than 64K +14870 MOV AX,[DMAADD] +14880 NEG AX ;Amount of room left in segment +14890 JNZ PARTSEG ;All 64K available? +14900 DEC AX ;If so, reduce it by one +14910 PARTSEG: +14920 XOR DX,DX +14930 DIV AX,SI ;How many records will fit? +14940 MOV [RECCNT],AX +14950 MUL AX,SI ;Translate that back into bytes +14960 MOV B,[DSKERR],2 ;Flag that trimming took place +14970 MOV CX,AX +14980 JCXZ NOROOM +14990 OK: +15000 LEA SI,[BP+FAT] +15010 RET +15020 +15030 EOFERR: +15040 MOV B,[DSKERR],1 +15050 XOR CX,CX +15060 NOROOM: +15070 POP BX ;Kill return address +15080 RET +15090 +15100 BREAKDOWN: +15110 +15120 ;Inputs: +15130 ; DS = CS +15140 ; CX = Length of disk transfer in bytes +15150 ; BP = Base of drive parameters +15160 ; [BYTSECPOS] = Byte position witin first sector +15170 ;Outputs: +15180 ; [BYTCNT1] = Bytes to transfer in first sector +15190 ; [SECCNT] = No. of whole sectors to transfer +15200 ; [BYTCNT2] = Bytes to transfer in last sector +15210 ;AX, BX, DX destroyed. No other registers affected. +15220 +15230 MOV AX,[BYTSECPOS] +15240 MOV BX,CX +15250 OR AX,AX +15260 JZ SAVFIR ;Partial first sector? +15270 SUB AX,[BP+SECSIZ] +15280 NEG AX ;Max number of bytes left in first sector +15290 SUB BX,AX ;Subtract from total length +15300 JAE SAVFIR +15310 ADD AX,BX ;Don't use all of the rest of the sector +15320 XOR BX,BX ;And no bytes are left +15330 SAVFIR: +15340 MOV [BYTCNT1],AX +15350 MOV AX,BX +15360 XOR DX,DX +15370 DIV AX,[BP+SECSIZ] ;How many whole sectors? +15380 MOV [SECCNT],AX +15390 MOV [BYTCNT2],DX ;Bytes remaining for last sector +15400 RET +15410 +15420 +15430 FNDCLUS: +15440 +15450 ; Inputs: +15460 ; DS = CS +15470 ; CX = No. of clusters to skip +15480 ; BP = Base of drive parameters +15490 ; SI = FAT pointer +15500 ; ES:DI point to FCB +15510 ; Outputs: +15520 ; BX = Last cluster skipped to +15530 ; CX = No. of clusters remaining (0 unless EOF) +15540 ; DX = Position of last cluster +15550 ; DI destroyed. No other registers affected. +15560 +15570 SEG ES +15580 MOV BX,[DI+LSTCLUS] +15590 SEG ES +15600 MOV DX,[DI+CLUSPOS] +15610 OR BX,BX +15620 JZ NOCLUS +15630 SUB CX,DX +15640 JNB FINDIT +15650 ADD CX,DX +15660 XOR DX,DX +15670 SEG ES +15680 MOV BX,[DI+FIRCLUS] +15690 FINDIT: +15700 JCXZ RET +15710 SKPCLP: +15720 CALL UNPACK +15730 CMP DI,0FF8H +15740 JAE RET +15750 XCHG BX,DI +15760 INC DX +15770 LOOP SKPCLP +15780 RET +15790 NOCLUS: +15800 INC CX +15810 DEC DX +15820 RET +15830 +15840 +15850 BUFSEC: +15860 ; Inputs: +15870 ; AL = 0 if buffer must be read, 1 if no pre-read needed +15880 ; BP = Base of drive parameters +15890 ; [CLUSNUM] = Physical cluster number +15900 ; [SECCLUSPOS] = Sector position of transfer within cluster +15910 ; [BYTCNT1] = Size of transfer +15920 ; Function: +15930 ; Insure specified sector is in buffer, flushing buffer before +15940 ; read if necessary. +15950 ; Outputs: +15960 ; SI = Pointer to buffer +15970 ; DI = Pointer to transfer address +15980 ; CX = Number of bytes +15990 ; [NEXTADD] updated +16000 ; [TRANS] set to indicate a transfer will occur +16010 +16020 MOV DX,[CLUSNUM] +16030 MOV BL,[SECCLUSPOS] +16040 CALL FIGREC +16050 MOV [PREREAD],AL +16060 CMP DX,[BUFSECNO] +16070 JNZ GETSEC +16080 MOV AL,[BUFDRVNO] +16090 CMP AL,[BP+DRVNUM] +16100 JZ FINBUF ;Already have it? +16110 GETSEC: +16120 TEST B,[DIRTYBUF],-1 +16130 JZ RDSEC +16140 PUSH DX +16150 PUSH BP +16160 MOV BP,[BUFDRVBP] +16170 MOV BX,[BUFFER] +16180 MOV CX,1 +16190 MOV DX,[BUFSECNO] +16200 CALL DWRITE +16210 POP BP +16220 POP DX +16230 RDSEC: +16240 TEST B,[PREREAD],-1 +16250 JNZ SETBUF +16260 MOV BX,[BUFFER] +16270 MOV CX,1 +16280 PUSH DX +16290 CALL DREAD +16300 POP DX +16310 SETBUF: +16320 MOV [BUFSECNO],DX +16330 MOV AL,[BP+DRVNUM] +16340 MOV AH,0 +16350 MOV [BUFDRVNO],AX +16360 MOV [BUFDRVBP],BP +16370 FINBUF: +16380 MOV B,[TRANS],1 ;A transfer is taking place +16390 MOV DI,[NEXTADD] +16400 MOV SI,DI +16410 MOV CX,[BYTCNT1] +16420 ADD SI,CX +16430 MOV [NEXTADD],SI +16440 MOV SI,[BUFFER] +16450 ADD SI,[BYTSECPOS] +16460 RET +16470 +16480 BUFRD: +16490 XOR AL,AL ;Pre-read necessary +16500 CALL BUFSEC +16510 PUSH ES +16520 MOV ES,[DMAADD+2] +16530 SHR CX +16540 JNC EVENRD +16550 MOVB +16560 EVENRD: +16570 REP +16580 MOVW +16590 POP ES +16600 RET +16610 +16620 BUFWRT: +16630 MOV AX,[SECPOS] +16640 INC AX ;Set for next sector +16650 MOV [SECPOS],AX +16660 CMP AX,[VALSEC] ;Has sector been written before? +16670 MOV AL,1 +16680 JA NOREAD ;Skip preread if SECPOS>VALSEC +16690 MOV AL,0 +16700 NOREAD: +16710 CALL BUFSEC +16720 XCHG DI,SI +16730 PUSH DS +16740 PUSH ES +16750 PUSH CS +16760 POP ES +16770 MOV DS,[DMAADD+2] +16780 SHR CX +16790 JNC EVENWRT +16800 MOVB +16810 EVENWRT: +16820 REP +16830 MOVW +16840 POP ES +16850 POP DS +16860 MOV B,[DIRTYBUF],1 +16870 RET +16880 +16890 NEXTSEC: +16900 TEST B,[TRANS],-1 +16910 JZ CLRET +16920 MOV AL,[SECCLUSPOS] +16930 INC AL +16940 CMP AL,[BP+CLUSMSK] +16950 JBE SAVPOS +16960 MOV BX,[CLUSNUM] +16970 CMP BX,0FF8H +16980 JAE NONEXT +16990 LEA SI,[BP+FAT] +17000 CALL UNPACK +17010 MOV [CLUSNUM],DI +17020 INC [LASTPOS] +17030 MOV AL,0 +17040 SAVPOS: +17050 MOV [SECCLUSPOS],AL +17060 CLRET: +17070 CLC +17080 RET +17090 NONEXT: +17100 STC +17110 RET +17120 +17130 TRANBUF: +17140 LODB +17150 STOB +17160 CMP AL,13 ;Check for carriage return +17170 JNZ NORMCH +17180 MOV B,[SI],10 +17190 NORMCH: +17200 CMP AL,10 +17210 LOOPNZ TRANBUF +17220 JNZ ENDRDCON +17230 CALL OUT ;Transmit linefeed +17240 XOR SI,SI +17250 OR CX,CX +17260 JNZ GETBUF +17270 OR AL,1 ;Clear zero flag--not end of file +17280 ENDRDCON: +17290 MOV [CONTPOS],SI +17300 ENDRDDEV: +17310 MOV [NEXTADD],DI +17320 POP ES +17330 JNZ SETFCBJ ;Zero set if Ctrl-Z found in input +17340 MOV DI,[FCB] +17350 SEG ES +17360 OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +17370 SETFCBJ: +17380 JMP SETFCB +17390 +17400 READDEV: +17410 PUSH ES +17420 LES DI,[DMAADD] +17430 OR BL,BL +17440 JZ READCON +17450 DEC BL +17460 JNZ ENDRDDEV +17470 READAUX: +17480 CALL AUXIN +17490 STOB +17500 CMP AL,1AH +17510 LOOPNZ READAUX +17520 JP ENDRDDEV +17530 +17540 READCON: +17550 PUSH CS +17560 POP DS +17570 MOV SI,[CONTPOS] +17580 OR SI,SI +17590 JNZ TRANBUF +17600 CMP B,[CONBUF],128 +17610 JZ GETBUF +17620 MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +17630 GETBUF: +17640 PUSH CX +17650 PUSH ES +17660 PUSH DI +17670 MOV DX,CONBUF +17680 CALL BUFIN ;Get input buffer +17690 POP DI +17700 POP ES +17710 POP CX +17720 MOV SI,CONBUF+2 +17730 CMP B,[SI],1AH ;Check for Ctrl-Z in first character +17740 JNZ TRANBUF +17750 MOV AL,1AH +17760 STOB +17770 MOV AL,10 +17780 CALL OUT ;Send linefeed +17790 XOR SI,SI +17800 JP ENDRDCON +17810 +17820 RDERR: +17830 XOR CX,CX +17840 JMP WRTERR +17850 +17860 RDLASTJ:JMP RDLAST +17870 +17880 LOAD: +17890 +17900 ; Inputs: +17910 ; DS:DI point to FCB +17920 ; DX:AX = Position in file to read +17930 ; CX = No. of records to read +17940 ; Outputs: +17950 ; DX:AX = Position of last record read +17960 ; CX = No. of bytes read +17970 ; ES:DI point to FCB +17980 ; LSTCLUS, CLUSPOS fields in FCB set +17990 +18000 CALL SETUP +18010 SEG ES +18020 MOV BX,[DI+FILDIRBLK] +18030 CMP BH,-1 ;Check for named device I/O +18040 JZ READDEV +18050 SEG ES +18060 MOV AX,[DI+FILSIZ] +18070 SEG ES +18080 MOV BX,[DI+FILSIZ+2] +18090 SUB AX,[BYTPOS] +18100 SBC BX,[BYTPOS+2] +18110 JB RDERR +18120 JNZ ENUF +18130 OR AX,AX +18140 JZ RDERR +18150 CMP AX,CX +18160 JAE ENUF +18170 MOV CX,AX +18180 ENUF: +18190 CALL BREAKDOWN +18200 MOV CX,[CLUSNUM] +18210 CALL FNDCLUS +18220 OR CX,CX +18230 JNZ RDERR +18240 MOV [LASTPOS],DX +18250 MOV [CLUSNUM],BX +18260 CMP [BYTCNT1],0 +18270 JZ RDMID +18280 CALL BUFRD +18290 RDMID: +18300 CMP [SECCNT],0 +18310 JZ RDLASTJ +18320 CALL NEXTSEC +18330 JC SETFCB +18340 MOV B,[TRANS],1 ;A transfer is taking place +18350 ONSEC: +18360 MOV DL,[SECCLUSPOS] +18370 MOV CX,[SECCNT] +18380 MOV BX,[CLUSNUM] +18390 RDLP: +18400 CALL OPTIMIZE +18410 PUSH DI +18420 PUSH AX +18430 PUSH DS +18440 MOV DS,[DMAADD+2] +18450 CALL DREAD +18460 POP DS +18470 POP CX +18480 POP BX +18490 JCXZ RDLAST +18500 CMP BX,0FF8H +18510 JAE SETFCB +18520 MOV DL,0 +18530 INC [LASTPOS] ;We'll be using next cluster +18540 JP RDLP +18550 +18560 SETFCB: +18570 MOV SI,[FCB] +18580 MOV AX,[NEXTADD] +18590 MOV DI,AX +18600 SUB AX,[DMAADD] ;Number of bytes transfered +18610 XOR DX,DX +18620 SEG ES +18630 MOV CX,[SI+RECSIZ] +18640 DIV AX,CX ;Number of records +18650 CMP AX,[RECCNT] ;Check if all records transferred +18660 JZ FULLREC +18670 MOV B,[DSKERR],1 +18680 OR DX,DX +18690 JZ FULLREC ;If remainder 0, then full record transfered +18700 MOV B,[DSKERR],3 ;Flag partial last record +18710 SUB CX,DX ;Bytes left in last record +18720 PUSH ES +18730 MOV ES,[DMAADD+2] +18740 XCHG AX,BX ;Save the record count temporarily +18750 XOR AX,AX ;Fill with zeros +18760 SHR CX +18770 JNC EVENFIL +18780 STOB +18790 EVENFIL: +18800 REP +18810 STOW +18820 XCHG AX,BX ;Restore record count to AX +18830 POP ES +18840 INC AX ;Add last (partial) record to total +18850 FULLREC: +18860 MOV CX,AX +18870 MOV DI,SI ;ES:DI point to FCB +18880 SETCLUS: +18890 MOV AX,[CLUSNUM] +18900 SEG ES +18910 MOV [DI+LSTCLUS],AX +18920 MOV AX,[LASTPOS] +18930 SEG ES +18940 MOV [DI+CLUSPOS],AX +18950 ADDREC: +18960 MOV AX,[RECPOS] +18970 MOV DX,[RECPOS+2] +18975 JCXZ RET ;If no records read, don't change pos. +18980 DEC CX +18990 ADD AX,CX ;Update current record position +19000 ADC DX,0 +19010 INC CX +19020 RET +19030 +19040 RDLAST: +19050 MOV AX,[BYTCNT2] +19060 OR AX,AX +19070 JZ SETFCB +19080 MOV [BYTCNT1],AX +19090 CALL NEXTSEC +19100 JC SETFCB +19110 MOV [BYTSECPOS],0 +19120 CALL BUFRD +19130 JP SETFCB +19140 +19150 WRTDEV: +19160 PUSH DS +19170 LDS SI,[DMAADD] +19180 AND BL,7FH +19190 OR BL,BL +19200 JZ WRTCON +19210 DEC BL +19220 JZ WRTAUX +19230 DEC BL +19240 JNZ ENDWRDEV ;Done if device is NUL +19250 WRTLST: +19260 LODB +19270 CMP AL,1AH +19280 JZ ENDWRDEV +19290 CALL LISTOUT +19300 LOOP WRTLST +19310 JP ENDWRDEV +19320 +19330 WRTAUX: +19340 LODB +19350 CALL AUXOUT +19360 CMP AL,1AH +19370 LOOPNZ WRTAUX +19380 JP ENDWRDEV +19390 +19400 WRTCON: +19410 LODB +19420 CMP AL,1AH +19430 JZ ENDWRDEV +19440 CALL OUT +19450 LOOP WRTCON +19460 ENDWRDEV: +19470 POP DS +19480 MOV CX,[RECCNT] +19490 MOV DI,[FCB] +19500 JP ADDREC +19510 +19520 HAVSTART: +19530 MOV CX,AX +19540 CALL SKPCLP +19550 JCXZ DOWRTJ +19560 CALL ALLOCATE +19570 JNC DOWRTJ +19580 WRTERR: +19590 MOV B,[DSKERR],1 +19600 LVDSK: +19610 MOV AX,[RECPOS] +19620 MOV DX,[RECPOS+2] +19630 MOV DI,[FCB] +19640 RET +19650 +19660 DOWRTJ: JMP DOWRT +19670 +19680 WRTEOFJ: +19690 JMP WRTEOF +19700 +19710 STORE: +19720 +19730 ; Inputs: +19740 ; DS:DI point to FCB +19750 ; DX:AX = Position in file of disk transfer +19760 ; CX = Record count +19770 ; Outputs: +19780 ; DX:AX = Position of last record written +19790 ; CX = No. of records written +19800 ; ES:DI point to FCB +19810 ; LSTCLUS, CLUSPOS fields in FCB set +19820 +19830 MOV B,[DI+DIRTYFIL],1 +19840 CALL SETUP +19850 CALL DATE16 +19860 SEG ES +19870 MOV [DI+FDATE],AX +19880 SEG ES +19890 MOV BX,[DI+FILDIRBLK] +19900 CMP BH,-1 +19910 JZ WRTDEV +19920 CALL BREAKDOWN +19930 MOV AX,[BYTPOS] +19940 MOV DX,[BYTPOS+2] +19950 JCXZ WRTEOFJ +19960 DEC CX +19970 ADD AX,CX +19980 ADC DX,0 ;AX:DX=last byte accessed +19990 DIV AX,[BP+SECSIZ] ;AX=last sector accessed +20000 MOV CL,[BP+CLUSSHFT] +20010 SHR AX,CL ;Last cluster to be accessed +20020 PUSH AX +20030 SEG ES +20040 MOV AX,[DI+FILSIZ] +20050 SEG ES +20060 MOV DX,[DI+FILSIZ+2] +20070 DIV AX,[BP+SECSIZ] +20080 OR DX,DX +20090 JZ NORNDUP +20100 INC AX ;Round up if any remainder +20110 NORNDUP: +20120 MOV [VALSEC],AX ;Number of sectors that have been written +20130 POP AX +20140 MOV CX,[CLUSNUM] ;First cluster accessed +20150 CALL FNDCLUS +20160 MOV [CLUSNUM],BX +20170 MOV [LASTPOS],DX +20180 SUB AX,DX ;Last cluster minus current cluster +20190 JZ DOWRT ;If we have last clus, we must have first +20200 JCXZ HAVSTART ;See if no more data +20210 PUSH CX ;No. of clusters short of first +20220 MOV CX,AX +20230 CALL ALLOCATE +20240 POP AX +20250 JC WRTERR +20260 MOV CX,AX +20270 MOV DX,[LASTPOS] +20280 INC DX +20290 DEC CX +20300 JZ NOSKIP +20310 CALL SKPCLP +20320 NOSKIP: +20330 MOV [CLUSNUM],BX +20340 MOV [LASTPOS],DX +20350 DOWRT: +20360 CMP [BYTCNT1],0 +20370 JZ WRTMID +20380 MOV BX,[CLUSNUM] +20390 CALL BUFWRT +20400 WRTMID: +20410 MOV AX,[SECCNT] +20420 OR AX,AX +20430 JZ WRTLAST +20440 ADD [SECPOS],AX +20450 CALL NEXTSEC +20460 MOV B,[TRANS],1 ;A transfer is taking place +20470 MOV DL,[SECCLUSPOS] +20480 MOV BX,[CLUSNUM] +20490 MOV CX,[SECCNT] +20500 WRTLP: +20510 CALL OPTIMIZE +20520 PUSH DI +20530 PUSH AX +20540 PUSH DS +20550 MOV DS,[DMAADD+2] +20560 CALL DWRITE +20570 POP DS +20580 POP CX +20590 POP BX +20600 JCXZ WRTLAST +20610 MOV DL,0 +20620 INC [LASTPOS] ;We'll be using next cluster +20630 JP WRTLP +20640 WRTLAST: +20650 MOV AX,[BYTCNT2] +20660 OR AX,AX +20670 JZ FINWRT +20680 MOV [BYTCNT1],AX +20690 CALL NEXTSEC +20700 MOV [BYTSECPOS],0 +20710 CALL BUFWRT +20720 FINWRT: +20730 MOV AX,[NEXTADD] +20740 SUB AX,[DMAADD] +20750 ADD AX,[BYTPOS] +20760 MOV DX,[BYTPOS+2] +20770 ADC DX,0 +20780 MOV CX,DX +20790 MOV DI,[FCB] +20800 SEG ES +20810 CMP AX,[DI+FILSIZ] +20820 SEG ES +20830 SBB CX,[DI+FILSIZ+2] +20840 JB SAMSIZ +20850 SEG ES +20860 MOV [DI+FILSIZ],AX +20870 SEG ES +20880 MOV [DI+FILSIZ+2],DX +20890 SAMSIZ: +20900 MOV CX,[RECCNT] +20910 JMP SETCLUS +20920 +20930 +20940 WRTERRJ:JMP WRTERR +20950 +20960 WRTEOF: +20970 MOV CX,AX +20980 OR CX,DX +20990 JZ KILLFIL +21000 SUB AX,1 +21010 SBC DX,0 +21020 DIV AX,[BP+SECSIZ] +21030 MOV CL,[BP+CLUSSHFT] +21040 SHR AX,CL +21050 MOV CX,AX +21060 CALL FNDCLUS +21070 JCXZ RELFILE +21080 CALL ALLOCATE +21090 JC WRTERRJ +21100 UPDATE: +21110 MOV DI,[FCB] +21120 MOV AX,[BYTPOS] +21130 SEG ES +21140 MOV [DI+FILSIZ],AX +21150 MOV AX,[BYTPOS+2] +21160 SEG ES +21170 MOV [DI+FILSIZ+2],AX +21180 XOR CX,CX +21190 RET +21200 +21210 RELFILE: +21220 MOV DX,0FFFH +21230 CALL RELBLKS +21240 SETDIRT: +21250 MOV B,[BP+DIRTYFAT],1 +21260 JP UPDATE +21270 +21280 KILLFIL: +21290 XOR BX,BX +21300 SEG ES +21310 XCHG BX,[DI+FIRCLUS] +21320 OR BX,BX +21330 JZ UPDATE +21340 CALL RELEASE +21350 JP SETDIRT +21360 +21370 +21380 OPTIMIZE: +21390 +21400 ; Inputs: +21410 ; DS = CS +21420 ; BX = Physical cluster +21430 ; CX = No. of records +21440 ; DL = sector within cluster +21450 ; BP = Base of drives parameters +21460 ; [NEXTADD] = transfer address +21470 ; Outputs: +21480 ; AX = No. of records remaining +21490 ; BX = Transfer address +21500 ; CX = No. or records to be transferred +21510 ; DX = Physical sector address +21520 ; DI = Next cluster +21530 ; [CLUSNUM] = Last cluster accessed +21540 ; [NEXTADD] updated +21550 ; BP unchanged. Note that segment of transfer not set. +21560 +21570 PUSH DX +21580 PUSH BX +21590 MOV AL,[BP+CLUSMSK] +21600 INC AL ;Number of sectors per cluster +21610 MOV AH,AL +21620 SUB AL,DL ;AL = Number of sectors left in first cluster +21630 MOV DX,CX +21640 LEA SI,[BP+FAT] +21650 MOV CX,0 +21660 OPTCLUS: +21670 ;AL has number of sectors available in current cluster +21680 ;AH has number of sectors available in next cluster +21690 ;BX has current physical cluster +21700 ;CX has number of sequential sectors found so far +21710 ;DX has number of sectors left to transfer +21720 ;SI has FAT pointer +21730 CALL UNPACK +21740 ADD CL,AL +21750 ADC CH,0 +21760 CMP CX,DX +21770 JAE BLKDON +21780 MOV AL,AH +21790 INC BX +21800 CMP DI,BX +21810 JZ OPTCLUS +21820 DEC BX +21830 FINCLUS: +21840 MOV [CLUSNUM],BX ;Last cluster accessed +21850 SUB DX,CX ;Number of sectors still needed +21860 PUSH DX +21870 MOV AX,CX +21880 MUL AX,[BP+SECSIZ] ;Number of sectors times sector size +21890 MOV SI,[NEXTADD] +21900 ADD AX,SI ;Adjust by size of transfer +21910 MOV [NEXTADD],AX +21920 POP AX ;Number of sectors still needed +21930 POP DX ;Starting cluster +21940 SUB BX,DX ;Number of new clusters accessed +21950 ADD [LASTPOS],BX +21960 POP BX ;BL = sector postion within cluster +21970 CALL FIGREC +21980 MOV BX,SI +21990 RET +22000 BLKDON: +22010 SUB CX,DX ;Number of sectors in cluster we don't want +22020 SUB AH,CL ;Number of sectors in cluster we accepted +22030 DEC AH ;Adjust to mean position within cluster +22040 MOV [SECCLUSPOS],AH +22050 MOV CX,DX ;Anyway, make the total equal to the request +22060 JP FINCLUS +22070 +22080 +22090 FIGREC: +22100 +22110 ;Inputs: +22120 ; DX = Physical cluster number +22130 ; BL = Sector postion within cluster +22140 ; BP = Base of drive parameters +22150 ;Outputs: +22160 ; DX = physical sector number +22170 ;No other registers affected. +22180 +22190 PUSH CX +22200 MOV CL,[BP+CLUSSHFT] +22210 DEC DX +22220 DEC DX +22230 SHL DX,CL +22240 OR DL,BL +22250 ADD DX,[BP+FIRREC] +22260 POP CX +22270 RET +22280 +22290 GETREC: +22300 +22310 ; Inputs: +22320 ; DS:DX point to FCB +22330 ; Outputs: +22340 ; CX = 1 +22350 ; DX:AX = Record number determined by EXTENT and NR fields +22360 ; DS:DI point to FCB +22370 ; No other registers affected. +22380 +22390 MOV DI,DX +22400 CMP B,[DI],-1 +22410 JNZ NORMFCB2 +22420 ADD DI,7 +22430 NORMFCB2: +22440 MOV CX,1 +22450 MOV AL,[DI+NR] +22460 MOV DX,[DI+EXTENT] +22470 SHL AL +22480 SHR DX +22490 RCR AL +22500 MOV AH,DL +22510 MOV DL,DH +22520 MOV DH,0 +22530 RET +22540 +22550 +22560 ALLOCATE: +22570 +22580 ; Inputs: +22590 ; DS = CS +22600 ; ES = Segment of FCB +22610 ; BX = Last cluster of file (0 if null file) +22620 ; CX = No. of clusters to allocate +22630 ; DX = Position of cluster BX +22640 ; BP = Base of drive parameters +22650 ; SI = FAT pointer +22660 ; [FCB] = Displacement of FCB within segment +22670 ; Outputs: +22680 ; IF insufficient space +22690 ; THEN +22700 ; Carry set +22710 ; CX = max. no. of records that could be added to file +22720 ; ELSE +22730 ; Carry clear +22740 ; BX = First cluster allocated +22750 ; FAT is fully updated including dirty bit +22760 ; FIRCLUS field of FCB set if file was null +22770 ; SI,BP unchanged. All other registers destroyed. +22780 +22790 PUSH [SI] +22800 PUSH DX +22810 PUSH CX +22820 PUSH BX +22830 MOV AX,BX +22840 ALLOC: +22850 MOV DX,BX +22860 FINDFRE: +22870 INC BX +22880 CMP BX,[BP+MAXCLUS] +22890 JLE TRYOUT +22900 CMP AX,1 +22910 JG TRYIN +22920 POP BX +22930 MOV DX,0FFFH +22940 CALL RELBLKS +22950 POP AX ;No. of clusters requested +22960 SUB AX,CX ;AX=No. of clusters allocated +22970 POP DX +22980 POP [SI] +22990 INC DX ;Position of first cluster allocated +23000 ADD AX,DX ;AX=max no. of cluster in file +23010 MOV DL,[BP+CLUSMSK] +23020 MOV DH,0 +23030 INC DX ;DX=records/cluster +23040 MUL AX,DX ;AX=max no. of records in file +23050 MOV CX,AX +23060 SUB CX,[RECPOS] ;CX=max no. of records that could be written +23070 JA MAXREC +23080 XOR CX,CX ;If CX was negative, zero it +23090 MAXREC: +23100 STC +23110 RET +23120 +23130 TRYOUT: +23140 CALL UNPACK +23150 JZ HAVFRE +23160 TRYIN: +23170 DEC AX +23180 JLE FINDFRE +23190 XCHG AX,BX +23200 CALL UNPACK +23210 JZ HAVFRE +23220 XCHG AX,BX +23230 JP FINDFRE +23240 HAVFRE: +23250 XCHG BX,DX +23260 MOV AX,DX +23270 CALL PACK +23280 MOV BX,AX +23290 LOOP ALLOC +23300 MOV DX,0FFFH +23310 CALL PACK +23320 MOV B,[BP+DIRTYFAT],1 +23330 POP BX +23340 POP CX ;Don't need this stuff since we're successful +23350 POP DX +23360 CALL UNPACK +23370 POP [SI] +23380 XCHG BX,DI +23390 OR DI,DI +23400 JNZ RET +23410 MOV DI,[FCB] +23420 SEG ES +23430 MOV [DI+FIRCLUS],BX +23440 RET +23450 +23460 +23470 RELEASE: +23480 +23490 ; Inputs: +23500 ; DS = CS +23510 ; BX = Cluster in file +23520 ; SI = FAT pointer +23530 ; BP = Base of drive parameters +23540 ; Function: +23550 ; Frees cluster chain starting with [BX] +23560 ; AX,BX,DX,DI all destroyed. Other registers unchanged. +23570 +23580 XOR DX,DX +23590 RELBLKS: +23600 ; Enter here with DX=0FFFH to put an end-of-file mark +23610 ; in the first cluster and free the rest in the chain. +23620 CALL UNPACK +23630 JZ RET +23640 MOV AX,DI +23650 CALL PACK +23660 CMP AX,0FF8H +23670 MOV BX,AX +23680 JB RELEASE +23690 RET +23700 +23710 +23720 GETEOF: +23730 +23740 ; Inputs: +23750 ; BX = Cluster in a file +23760 ; SI = Base of drive FAT +23770 ; DS = CS +23780 ; Outputs: +23790 ; BX = Last cluster in the file +23800 ; DI destroyed. No other registers affected. +23810 +23820 CALL UNPACK +23830 CMP DI,0FF8H +23840 JAE RET +23850 MOV BX,DI +23860 JP GETEOF +23870 +23880 +23890 SRCHFRST: ;System call 17 +23900 CALL GETFILE +23910 SAVPLCE: +23920 ; Search-for-next enters here to save place and report +23930 ; findings. +23940 JC KILLSRCH +23950 CMP BH,-1 +23960 JZ SRCHDEV +23970 MOV AX,[LASTENT] +23980 SEG ES +23990 MOV [DI+FILDIRBLK],AX +24000 ;Information in directory entry must be copied into the first +24010 ; 33 bytes starting at the disk transfer address. +24020 MOV SI,BX +24030 LES DI,[DMAADD] +24040 MOV AX,00FFH +24050 CMP AL,[EXTFCB] +24060 JNZ NORMFCB +24070 STOW +24080 INC AL +24090 STOW +24100 STOW +24110 MOV AL,[ATTRIB] +24120 STOB +24130 NORMFCB: +24140 MOV AL,[BP+DRVNUM] +24150 INC AL +24160 STOB ;Set drive number +24170 MOVB ;Copy first character of name +24180 MOV CX,5 +24190 REP +24200 MOVW ;Copy remaining 10 characters of name +24210 XOR AX,AX +24220 +24230 IF SMALLDIR +24240 CMP B,[BP+DIRSIZ],-1 +24250 JNZ BIGENT5 +24260 STOB ;Zero out unused portion +24270 MOV CX,7 +24280 REP +24290 STOW ;Zero a total of 15 bytes +24300 MOVW ;Copy first cluster pointer +24310 MOVW ;Copy low word of length +24320 MOVB ;Copy 3rd byte of length +24330 STOB ;4th byte of length must be zero +24340 RET +24350 BIGENT5: +24360 ENDIF +24370 +24380 MOV CX,10 +24390 REP +24400 MOVW +24410 MOVB +24420 RET +24430 +24440 KILLSRCH: +24450 SEG ES +24460 KILLSRCH1: +24470 MOV [DI+FILDIRBLK],-2 +24480 MOV AL,-1 +24490 RET +24500 +24510 SRCHDEV: +24520 SEG ES +24530 MOV [DI+FILDIRBLK],BX +24540 LES DI,[DMAADD] +24550 XOR AX,AX +24560 STOB ;Zero drive byte +24570 SUB SI,4 ;Point to device name +24580 MOVW +24590 MOVW +24600 MOV AX,2020H +24610 MOV CX,3 +24620 REP +24630 STOW ;Fill with 6 blanks +24640 STOB ;And a 7th +24650 XOR AX,AX +24660 MOV CX,10 +24670 REP +24680 STOW +24690 STOB +24700 RET +24710 +24720 SRCHNXT: ;System call 18 +24730 CALL MOVNAME +24740 MOV DI,DX +24750 JC KILLSRCH1 +24760 PUSH DX +24770 PUSH DS +24780 MOV AX,[DI+FILDIRBLK] +24790 PUSH CS +24800 POP DS +24810 MOV [LASTENT],AX +24820 CALL CONTSRCH +24830 POP ES +24840 POP DI +24850 JMP SAVPLCE +24860 +24870 +24880 FILESIZE: ;System call 35 +24890 CALL GETFILE +24900 MOV AL,-1 +24910 JC RET +24920 ADD DI,33 ;Write size in RR field +24930 SEG ES +24940 MOV CX,[DI-33+RECSIZ] +24950 OR CX,CX +24960 JNZ RECOK +24970 MOV CX,128 +24980 RECOK: +24990 XOR AX,AX +25000 XOR DX,DX ;Intialize size to zero +25010 CMP BH,-1 ;Check for named I/O device +25020 JZ DEVSIZ +25030 INC SI +25040 INC SI ;Point to length field +25050 MOV AX,[SI+2] ;Get high word of size +25060 +25070 IF SMALLDIR +25080 CMP B,[BP+DIRSIZ],-1 +25090 JNZ BIGSIZ +25100 MOV AH,0 +25110 BIGSIZ: +25120 ENDIF +25130 +25140 DIV AX,CX +25150 PUSH AX ;Save high part of result +25160 LODW ;Get low word of size +25170 DIV AX,CX +25180 OR DX,DX ;Check for zero remainder +25190 POP DX +25200 JZ DEVSIZ +25210 INC AX ;Round up for partial record +25220 JNZ DEVSIZ ;Propagate carry? +25230 INC DX +25240 DEVSIZ: +25250 STOW +25260 MOV AX,DX +25270 STOB +25280 MOV AL,0 +25290 CMP CX,64 +25300 JAE RET ;Only 3-byte field if RECSIZ >= 64 +25310 SEG ES +25320 MOV [DI],AH +25330 RET +25340 +25350 +25360 SETDMA: ;System call 26 +25370 SEG CS +25380 MOV [DMAADD],DX +25390 SEG CS +25400 MOV [DMAADD+2],DS +25410 RET +25420 +25430 +25440 GETFATPT: ;System call 27 +25450 MOV AX,CS +25460 MOV DS,AX +25470 MOV BP,[CURDRVPT] +25480 CALL FATREAD +25490 LEA BX,[BP+FAT] +25500 MOV AL,[BP+CLUSMSK] +25510 INC AL +25520 MOV DX,[BP+MAXCLUS] +25530 DEC DX +25540 MOV B,[BP+DIRTYFAT],1 +25550 MOV CX,[BP+SECSIZ] +25560 LDS SI,[SPSAVE] +25570 MOV [SI+BXSAVE],BX +25580 MOV [SI+DXSAVE],DX +25590 MOV [SI+CXSAVE],CX +25600 MOV [SI+DSSAVE],CS +25610 RET +25620 +25630 +25640 DSKRESET: ;System call 13 +25650 SEG CS +25660 MOV [DMAADD+2],DS +25670 MOV AX,CS +25680 MOV DS,AX +25690 MOV [DMAADD],80H +25700 MOV AX,[CURDRVPT+2] +25710 MOV [CURDRVPT],AX +25720 WRTFATS: +25730 ; DS=CS. Writes back all dirty FATs. All registers destroyed. +25740 MOV AX,[BUFDRVNO] +25750 OR AH,AH +25760 JZ NOBUF +25770 CBW +25780 MOV BX,AX +25790 SHL BX +25800 MOV BP,[BX+DRVTAB] +25810 MOV B,[DIRTYBUF],0 +25820 MOV DX,[BUFSECNO] +25830 MOV BX,BUFFER +25840 MOV CX,1 +25850 CALL DWRITE +25860 NOBUF: +25870 MOV CL,[NUMDRV] +25880 MOV CH,0 +25890 MOV SI,CURDRVPT+2 +25900 WRTFAT: +25910 LODW +25920 PUSH CX +25930 PUSH SI +25940 MOV BP,AX +25950 CALL CHKFATWRT +25960 POP SI +25970 POP CX +25980 LOOP WRTFAT +25990 RET +26000 +26010 +26020 CURDRV: ;System call 25 +26030 SEG CS +26040 MOV BP,[CURDRVPT] +26050 MOV AL,[BP+DRVNUM] +26060 RET +26070 +26080 +26090 SETRNDREC: ;System call 36 +26100 CALL GETREC +26110 MOV [DI+33],AX +26120 MOV [DI+35],DL +26130 CMP [DI+RECSIZ],64 +26140 JAE RET +26150 MOV [DI+36],DH ;Set 4th byte only if record size < 64 +26160 RET +26170 +26180 +26190 SELDSK: ;System call 14 +26200 MOV DH,0 +26210 MOV BX,DX +26220 PUSH CS +26230 POP DS +26240 MOV AL,[NUMDRV] +26250 CMP BL,AL +26260 JNB RET +26270 SHL BX +26280 MOV DX,[BX+CURDRVPT+2] +26290 MOV [CURDRVPT],DX +26300 RET +26310 +26320 +26330 BUFIN: ;System call 10 +26340 MOV AX,CS +26350 MOV ES,AX +26360 MOV SI,DX +26370 MOV CH,0 +26380 LODW +26390 OR AL,AL +26400 JZ RET +26410 MOV BL,AH +26420 MOV BH,CH +26430 CMP AL,BL +26440 JBE NOEDIT +26450 CMP B,[BX+SI],0DH +26460 JZ EDITON +26470 NOEDIT: +26480 MOV BL,CH +26490 EDITON: +26500 MOV DL,AL +26510 DEC DX +26520 NEWLIN: +26530 SEG CS +26540 MOV AL,[CARPOS] +26550 SEG CS +26560 MOV [STARTPOS],AL +26570 PUSH SI +26580 MOV DI,INBUF +26590 MOV AH,CH +26600 MOV BH,CH +26610 MOV DH,CH +26620 GETCH: +26630 CALL IN +26640 CMP AL,7FH +26650 JZ BACKSPJ +26660 CMP AL,8 +26670 JZ BACKSPJ +26680 CMP AL,13 +26690 JZ ENDLIN +26700 CMP AL,10 +26710 JZ PHYCRLF +26720 CMP AL,"X"-"@" +26730 JZ KILNEW +26740 CMP AL,1BH +26750 JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X +26760 CMP AL,ESCCH +26770 JZ ESC +26780 SAVCH: +26790 CMP DH,DL +26800 JAE BELL +26810 STOB +26820 INC DH +26830 CALL BUFOUT +26840 OR AH,AH +26850 JNZ GETCH +26860 CMP BH,BL +26870 JAE GETCH +26880 INC SI +26890 INC BH +26900 JP GETCH +26910 +26920 BELL: +26930 MOV AL,7 +26940 CALL OUTCH +26950 JP GETCH +26960 +26970 BACKSPJ:JP BACKSP +26980 +26990 ESC: +27000 CALL IN +27010 PUSH DI +27020 MOV CL,ESCTABLEN +27030 MOV DI,ESCTAB +27040 REPNE +27050 SCAB +27060 POP DI +27070 MOV BP,CX +27080 SHL BP +27090 SEG CS ;To work in init +27100 JMP [BP+ESCFUNC] +27110 +27120 ENDLIN: +27130 STOB +27140 CALL OUT +27150 POP DI +27160 MOV [DI-1],DH +27170 INC DH +27180 COPYNEW: +27190 MOV BP,ES +27200 MOV BX,DS +27210 MOV ES,BX +27220 MOV DS,BP +27230 MOV SI,INBUF +27240 MOV CL,DH +27250 REP +27260 MOVB +27270 RET +27280 CRLF: +27290 MOV AL,13 +27300 CALL OUT +27310 MOV AL,10 +27320 JMP OUT +27330 +27340 PHYCRLF: +27350 CALL CRLF +27360 JP GETCH +27370 +27380 KILNEW: +27390 MOV AL,"\" +27400 CALL OUT +27410 POP SI +27420 PUTNEW: +27430 CALL CRLF +27440 SEG CS +27450 MOV AL,[STARTPOS] +27460 CALL TAB +27470 JMP NEWLIN +27480 +27490 BACKSP: +27500 OR DH,DH +27510 JZ OLDBAK +27520 CALL BACKUP +27530 SEG ES +27540 MOV AL,[DI] +27550 CMP AL," " +27560 JAE OLDBAK +27570 CMP AL,9 +27580 JZ BAKTAB +27590 CALL BACKMES +27600 OLDBAK: +27610 OR AH,AH +27620 JNZ GETCH1 +27630 OR BH,BH +27640 JZ GETCH1 +27650 DEC BH +27660 DEC SI +27670 GETCH1: +27680 JMP GETCH +27690 BAKTAB: +27700 PUSH DI +27710 DEC DI +27720 DOWN +27730 MOV CL,DH +27740 MOV AL," " +27750 PUSH BX +27760 MOV BL,7 +27770 JCXZ FIGTAB +27780 FNDPOS: +27790 SCAB +27800 JNA CHKCNT +27810 SEG ES +27820 CMP B,[DI+1],9 +27830 JZ HAVTAB +27840 DEC BL +27850 CHKCNT: +27860 LOOP FNDPOS +27870 FIGTAB: +27880 SEG CS +27890 SUB BL,[STARTPOS] +27900 HAVTAB: +27910 SUB BL,DH +27920 ADD CL,BL +27930 AND CL,7 +27940 UP +27950 POP BX +27960 POP DI +27970 JZ OLDBAK +27980 TABBAK: +27990 CALL BACKMES +28000 LOOP TABBAK +28010 JP OLDBAK +28020 BACKUP: +28030 DEC DH +28040 DEC DI +28050 BACKMES: +28060 MOV AL,8 +28070 CALL OUT +28080 MOV AL," " +28090 CALL OUT +28100 MOV AL,8 +28110 JMP OUT +28120 +28130 TWOESC: +28140 MOV AL,ESCCH +28150 JMP SAVCH +28160 +28170 COPYLIN: +28180 MOV CL,BL +28190 SUB CL,BH +28200 JP COPYEACH +28210 +28220 COPYSTR: +28230 CALL FINDOLD +28240 JP COPYEACH +28250 +28260 COPYONE: +28270 MOV CL,1 +28280 COPYEACH: +28290 MOV AH,0 ;Turn off insert mode when copying +28300 CMP DH,DL +28310 JZ GETCH2 +28320 CMP BH,BL +28330 JZ GETCH2 +28340 LODB +28350 STOB +28360 CALL BUFOUT +28370 INC BH +28380 INC DH +28390 LOOP COPYEACH +28400 GETCH2: +28410 JMP GETCH +28420 +28430 SKIPONE: +28440 CMP BH,BL +28450 JZ GETCH2 +28460 INC BH +28470 INC SI +28480 JMP GETCH +28490 +28500 SKIPSTR: +28510 CALL FINDOLD +28520 ADD SI,CX +28530 ADD BH,CL +28540 JMP GETCH +28550 +28560 FINDOLD: +28570 CALL IN +28580 MOV CL,BL +28590 SUB CL,BH +28600 JZ NOTFND +28610 DEC CX +28620 JZ NOTFND +28630 PUSH ES +28640 PUSH DS +28650 POP ES +28660 PUSH DI +28670 MOV DI,SI +28680 INC DI +28690 REPNE +28700 SCAB +28710 POP DI +28720 POP ES +28730 JNZ NOTFND +28740 NOT CL +28750 ADD CL,BL +28760 SUB CL,BH +28770 RET +28780 NOTFND: +28790 POP BP +28800 JMP GETCH +28810 +28820 REEDIT: +28830 MOV AL,"@" +28840 CALL OUT +28850 POP DI +28860 PUSH DI +28870 PUSH ES +28880 PUSH DS +28890 CALL COPYNEW +28900 POP DS +28910 POP ES +28920 POP SI +28930 MOV BL,DH +28940 JMP PUTNEW +28950 +28960 TOGGLINS: +28970 NOT AH +28980 JMP GETCH +28990 +29000 CTRLZ: +29010 MOV AL,1AH +29020 JMP SAVCH +29030 +29040 ESCFUNC: +29050 DW GETCH +29060 DW TWOESC +29070 DW TOGGLINS +29080 DW BACKSP +29090 DW REEDIT +29100 DW CTRLZ +29110 DW COPYLIN +29120 DW SKIPSTR +29130 DW COPYSTR +29140 DW SKIPONE +29150 DW COPYONE +29160 DW COPYONE +29170 +29180 BUFOUT: +29190 CMP AL," " +29200 JAE OUT +29210 CMP AL,9 +29220 JZ OUT +29230 PUSH AX +29240 MOV AL,"^" +29250 CALL OUT +29260 POP AX +29270 OR AL,40H +29280 JP OUT +29290 +29300 CONOUT: ;System call 2 +29310 MOV AL,DL +29320 OUT: +29330 CMP AL,20H +29340 JB CTRLOUT +29350 CMP AL,7FH +29360 JZ OUTCH +29370 SEG CS +29380 INC B,[CARPOS] +29390 OUTCH: +29400 PUSH AX +29410 CALL STATCHK +29420 POP AX +29430 CALL BIOSOUT,BIOSSEG +29440 SEG CS +29450 TEST B,[PFLAG],-1 +29460 JZ RET +29470 CALL BIOSPRINT,BIOSSEG +29480 RET +29490 +29500 NOSTOP: +29510 CMP AL,"P"-"@" +29520 JZ INCHK +29530 CMP AL,"C"-"@" +29540 JZ INCHK +29550 RET +29560 +29570 STATCHK: +29580 CALL BIOSSTAT,BIOSSEG +29590 JZ RET +29600 CMP AL,'S'-'@' +29610 JNZ NOSTOP +29620 CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +29630 INCHK: +29640 CALL BIOSIN,BIOSSEG +29650 CMP AL,'P'-'@' +29660 JZ PRINTOGL +29670 CMP AL,'C'-'@' +29680 JNZ RET +29690 ; Ctrl-C handler. +29700 ; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +29710 ; to show line is canceled. Then the user registers are restored and the +29720 ; user CTRL-C handler is executed. At this point the top of the stack has +29730 ; 1) the interrupt return address should the user CTRL-C handler wish to +29740 ; allow processing to continue; 2) the original interrupt return address +29750 ; to the code that performed the function call in the first place. If the +29760 ; user CTRL-C handler wishes to continue, it must leave all registers +29770 ; unchanged and IRET. The function that was interrupted will simply be +29780 ; repeated. +29790 SEG CS +29800 MOV AL,[FUNC] ;Get currently executing function +29810 CMP AL,10 ;Check if buffered line input +29820 JZ CANLIN +29830 CMP AL,9 ;Check if buffered line output +29840 JNZ RESTREG +29850 CANLIN: +29860 MOV AL,"\" ;Display cancel line symbol +29870 CALL OUT +29880 CALL CRLF +29890 RESTREG: +29900 DI ;Prepare to play with stack +29910 SEG CS +29920 MOV SS,[SSSAVE] +29930 SEG CS +29940 MOV SP,[SPSAVE] ;User stack now restored +29950 POP AX +29960 POP BX +29970 POP CX +29980 POP DX +29990 POP SI +30000 POP DI +30010 POP BP +30020 POP DS +30030 POP ES ;User registers now restored +30040 INT CONTC ;Execute user Ctrl-C handler +30050 JMP COMMAND ;Repeat command otherwise +30060 +30070 PRINTOGL: +30080 SEG CS +30090 XOR B,[PFLAG],1 +30100 XOR AL,AL ;Set zero flag--character not received +30110 RET +30120 CTRLOUT: +30130 CMP AL,13 +30140 JZ ZERPOS +30150 CMP AL,8 +30160 JZ BACKPOS +30170 CMP AL,9 +30180 JNZ OUTCHJ +30190 SEG CS +30200 MOV AL,[CARPOS] +30210 OR AL,0F8H +30220 NEG AL +30230 TAB: +30240 PUSH CX +30250 MOV CL,AL +30260 MOV CH,0 +30265 JCXZ POPTAB +30270 TABLP: +30280 MOV AL," " +30290 CALL OUT +30300 LOOP TABLP +30305 POPTAB: +30310 POP CX +30320 RET +30330 +30340 ZERPOS: +30350 SEG CS +30360 MOV B,[CARPOS],0 +30370 OUTCHJ: JMP OUTCH +30380 +30390 BACKPOS: +30400 SEG CS +30410 DEC B,[CARPOS] +30420 JMP OUTCH +30430 +30440 +30450 CONSTAT: ;System call 11 +30460 CALL BIOSSTAT,BIOSSEG +30470 MOV AL,0 +30480 JZ RET +30490 OR AL,-1 +30500 RET +30510 +30520 +30530 CONIN: ;System call 1 +30540 CALL IN +30550 PUSH AX +30560 CALL OUT +30570 POP AX +30580 RET +30590 +30600 +30610 IN: ;Internal input routine +30620 CALL INCHK +30630 JZ IN +30640 RET +30650 +30660 RAWIO: ;System call 6 +30670 MOV AL,DL +30680 CMP AL,-1 +30690 JNZ RAWOUT +30700 CALL BIOSSTAT,BIOSSEG +30710 MOV AL,0 +30720 JZ RET +30730 RAWINP: ;System call 7 +30740 CALL BIOSIN,BIOSSEG +30750 RET +30760 RAWOUT: +30770 CALL BIOSOUT,BIOSSEG +30780 RET +30790 +30800 LIST: ;System call 5 +30810 MOV AL,DL +30820 LISTOUT: +30830 PUSH AX +30840 CALL STATCHK +30850 POP AX +30860 CALL BIOSPRINT,BIOSSEG +30870 RET +30880 +30890 PRTBUF: ;System call 9 +30900 MOV SI,DX +30910 OUTSTR: +30920 LODB +30930 CMP AL,"$" +30940 JZ RET +30950 CALL OUT +30960 JP OUTSTR +30970 +30980 OUTMES: ;String output for internal messages +30990 SEG CS +31000 LODB +31010 CMP AL,"$" +31020 JZ RET +31030 CALL OUT +31040 JP OUTMES +31050 +31060 +31070 MAKEFCB: ;Interrupt call 41 +31080 MOV DL,0 ;Flag--not ambiguous file name +31090 OR AL,AL ;Scan off separators if not zero +31100 JZ NOSCAN +31110 SCAN: +31120 CALL GETLET +31130 JZ SCAN ;Get rid of leading separators (e.g., blanks) +31140 DEC SI ;Point back to first non-separator +31150 NOSCAN: +31160 MOV AL,0 +31170 CMP B,[SI],20H ;Check for termination character +31180 JB HAVDRV +31190 CMP B,[SI+1],":" ;Check for potential drive specifier +31200 JNZ HAVDRV +31210 CALL GETLET +31220 SUB AL,"@" ;Convert drive letter to binary drive number +31230 JBE BADDRV ;Valid drive numbers are 1-15 +31240 SEG CS +31250 CMP AL,[NUMDRV] +31252 JBE OKDRV +31254 BADDRV: +31256 MOV DL,-1 +31258 OKDRV: +31270 INC SI ;Skip over colon +31280 HAVDRV: +31290 STOB ;Put drive specifier in first byte +31300 MOV CX,8 +31310 CALL GETWORD ;Get 8-letter file name +31320 CMP B,[SI],"." +31330 JNZ NODOT +31340 INC SI ;Skip over dot if present +31350 NODOT: +31360 MOV CX,3 ;Get 3-letter extension +31370 CALL GETWORD +31380 SEG CS +31390 LDS BX,[SPSAVE] +31400 MOV [BX+SISAVE],SI +31410 XOR AX,AX +31420 STOW +31430 STOW +31440 MOV AL,DL +31450 RET +31460 +31510 GETWORD: +31520 CALL GETLET +31530 JZ FILLNAM ;Exit if invalid character +31540 CMP AL," " +31550 JBE FILLNAM +31560 CMP AL,"*" ;Check for ambiguous file specifier +31570 JNZ NOSTAR +31580 MOV AL,"?" +31590 DEC CX +31600 REP +31610 STOB ;Fill rest of word with "?" +31620 INC CX +31630 NOSTAR: +31640 STOB +31650 CMP AL,"?" +31660 JNZ NOTQ +31670 OR DL,1 ;Flag ambiguous file name +31680 NOTQ: +31690 LOOP GETWORD +31700 INC SI ;Point to "termination" character +31710 FILLNAM: +31720 MOV AL," " +31730 REP +31740 STOB +31750 DEC SI +31760 RET +31770 +31780 GETLET: +31790 LODB +31800 AND AL,7FH +31810 CMP AL,"a" +31820 JB CHK +31830 CMP AL,"z" +31840 JA CHK +31850 SUB AL,20H ;Convert to upper case +31860 CHK: +31870 CMP AL," " +31880 JZ RET +31890 CMP AL,"=" +31900 JZ RET +31910 CMP AL,"," +31920 JZ RET +31930 CMP AL,";" +31940 JZ RET +31950 CMP AL,"." +31960 JZ RET +31970 CMP AL,":" +31980 JZ RET +31990 CMP AL,'"' +32000 JZ RET +32010 CMP AL,"+" +32020 JZ RET +32030 CMP AL,"/" +32040 JZ RET +32050 CMP AL,"[" +32060 JZ RET +32070 CMP AL,"]" +32080 JZ RET +32090 CMP AL,9 ;Filter out TABs too +32100 RET +32110 +32120 +32130 SETVECT: ; Interrupt call 37 +32140 XOR BX,BX +32150 MOV ES,BX +32160 MOV BL,AL +32170 SHL BX +32180 SHL BX +32190 SEG ES +32200 MOV [BX],DX +32210 SEG ES +32220 MOV [BX+2],DS +32230 RET +32240 +32250 +32260 NEWBASE: ; Interrupt call 38 +32270 MOV ES,DX +32280 SEG CS +32290 LDS SI,[SPSAVE] +32300 MOV DS,[SI+CSSAVE] +32310 XOR SI,SI +32320 MOV DI,SI +32330 MOV CX,80H +32340 REP +32350 MOVW +32360 +32370 SETMEM: +32380 +32390 ; Inputs: +32400 ; DX = Segment +32410 ; Function: +32420 ; Completely prepares a program base at the +32430 ; specified segment. +32440 ; Outputs: +32450 ; DS = DX +32460 ; ES = DX +32470 ; [0] has INT 20H +32480 ; [2] = First unavailable segment ([ENDMEM]) +32490 ; [5] to [9] form a long call to the entry point +32500 ; [10] to [13] have exit address (from INT 22H) +32510 ; [14] to [17] have ctrl-C exit address (from INT 23H) +32520 ; AX,DX,BP unchanged. All other registers destroyed. +32530 +32540 XOR CX,CX +32550 MOV DS,CX +32560 MOV ES,DX +32570 MOV SI,EXIT +32580 MOV DI,SAVEXIT +32590 MOVW +32600 MOVW +32610 MOVW +32620 MOVW +32630 SEG CS +32640 MOV CX,[ENDMEM] +32650 SEG ES +32660 MOV [2],CX +32670 SUB CX,DX +32680 CMP CX,MAXDIF +32690 JBE HAVDIF +32700 MOV CX,MAXDIF +32710 HAVDIF: +32720 MOV BX,ENTRYPOINTSEG +32730 SUB BX,CX +32740 SHL CX +32750 SHL CX +32760 SHL CX +32770 SHL CX +32780 MOV DS,DX +32790 MOV [6],CX +32800 MOV [8],BX +32810 MOV [0],20CDH ;"INT INTTAB" +32820 MOV B,[5],LONGCALL +32830 RET +32840 +32850 +32860 SHFTDI7: +32870 SHL DI +32880 SHL DI +32890 SHL DI +32900 SHL DI +32910 SHL DI +32920 SHL DI +32930 SHL DI +32940 RET +32950 +32960 DATE16: +32970 PUSH CX +32980 PUSH DX +32990 PUSH BX +33000 CALL READTIME +33010 POP BX +33020 POP DX +33030 POP CX +33040 MOV AX,[MONTH] ;Fetch month and year +33050 SHL AL ;Push month to left to make room for day +33060 SHL AL +33070 SHL AL +33080 SHL AL +33090 SHL AX +33100 OR AL,[DAY] +33110 RET +33120 +33130 READTIME: +33140 ;Gets tick count in CX:DX. Causes date rollover if new day has started +33150 ;since last call. Destroys AX, BX. +33160 MOV AH,0 ;Request get time +33170 INT 1AH ;Time-of-day interrupt +33180 OR AL,AL ;See if day has changed +33190 JZ RET +33200 ADD AL,[DAY] +33210 MOV [DAY],AL +33220 MOV AH,AL +33230 MOV AL,[MONTH] +33240 MOV BX,DAYTAB-1 ;Table of days in each month +33250 XLAT ;Get number of days in current month +33260 SUB AH,AL ;Have we rolled into next month? +33270 JBE RET +33280 MOV [DAY],AH ;Yes-store day of new month +33290 MOV AL,[MONTH] +33300 INC AL +33310 MOV [MONTH],AL +33320 CMP AL,12 ;Have we rolled into next year? +33330 JBE RET +33340 MOV B,[MONTH],1 ;Set first month to January +33350 MOV AL,[YEAR] +33360 INC AL +33370 SETYEAR: +33380 ;Set year with value in AL. Adjust length of February for this year. +33390 MOV [YEAR],AL +33400 AND AL,3 ;Check for leap year +33410 MOV AL,28 +33420 JNZ SAVFEB ;28 days if no leap year +33430 INC AL ;Add leap day +33440 SAVFEB: +33450 MOV [DAYTAB+1],AL ;Store for February +33460 RET +33470 +33480 DAYTAB: ;Days of each month +33490 DB 31 ;January +33500 DB 28 ;February--reset each time year changes +33510 DB 31 ;March +33520 DB 30 ;April +33530 DB 31 ;May +33540 DB 30 ;June +33550 DB 31 ;July +33560 DB 31 ;August +33570 DB 30 ;September +33580 DB 31 ;October +33590 DB 30 ;November +33600 DB 31 ;December +33610 +33620 GETDATE: ;Function call 42 +33630 PUSH CS +33640 POP DS +33650 CALL READTIME ;Check for rollover to next day +33660 MOV AX,[YEAR] +33670 MOV BX,[DAY] +33680 LDS SI,[SPSAVE] ;Get pointer to user registers +33690 MOV [SI+DXSAVE],BX ;DH=month, DL=day +33700 ADD AX,1980 ;Put bias back +33710 MOV [SI+CXSAVE],AX ;CX=year +33720 XOR AL,AL +33730 RET +33740 +33750 SETDATE: ;Function call 43 +33760 MOV AL,-1 ;Be ready to flag an error +33770 SUB CX,1980 ;Fix bias in year +33780 JC RET ;Error if not big enough +33790 CMP CX,119 ;Year must be less than 2100 +33800 JA RET +33810 OR DH,DH +33820 JZ RET +33830 OR DL,DL +33840 JZ RET ;Error if either month or day is 0 +33850 CMP DH,12 ;Check against max. month +33860 JA RET +33870 PUSH CS +33880 POP DS +33890 CMP DH,2 ;Check for Feb.--needs special handling +33900 JNE DAYCHK +33910 CMP DL,29 +33920 JA RET ;Max 29 days in Feb. +33930 JB DAYOK ;If 28 or less, definitely OK +33940 TEST CL,3 ;Check for leap year +33950 JZ DAYOK ;If it is, 29 days OK +33960 RET ;Error if it's not +33970 DAYCHK: +33980 MOV AL,DH +33990 MOV BX,DAYTAB-1 +34000 XLAT ;Look up days in month +34010 CMP AL,DL +34020 MOV AL,-1 ;Restore error flag, just in case +34030 JB RET ;Error if too many days +34040 DAYOK: +34050 PUSH DX +34060 PUSH CX +34070 MOV AH,0 +34080 INT 1AH ;Read time to clear day overflow +34090 POP AX ;Year +34100 CALL SETYEAR +34110 POP [DAY] ;Set both day and month +34120 XOR AL,AL ;Flag OK +34130 RET +34140 +34150 ;*************************************** +34160 ; Time Functions +34170 ; +34180 ; Uses clock with 1,193,180/65536 ticks per second. User sees only +34190 ; time in hours, minutes, seconds, and 1/100 second, in registers +34200 ; CH, CL, DH, DL respectively. (Each is a binary number.) To +34210 ; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +34220 ; reciprocal of the tick rate. To convert the other way, 1/100 secs +34230 ; is multiplied by 59659/(5 * 2**16). +34240 +34250 GETTIME: ;Function call 44 +34260 PUSH CS +34270 POP DS +34280 CALL READTIME ;Get tick count in CX:DX +34290 ;First multiply by 5 +34300 MOV AX,CX +34310 MOV BX,DX +34320 SHL DX +34330 RCL CX ;Times 2 +34340 SHL DX +34350 RCL CX ;Times 4 +34360 ADD DX,BX +34370 ADC AX,CX ;Times 5 +34380 XCHG AX,DX +34390 MOV CX,59659 +34400 DIV AX,CX +34410 MOV BX,AX ;Save quotient +34420 XOR AX,AX ;Extend precision +34430 DIV AX,CX +34440 ;Rounding based on the remainder may be added here +34450 ;The result in BX:AX is time in 1/100 second. +34460 MOV DX,BX +34470 MOV CX,200 ;Extract 1/100's +34480 ;Division by 200 is necessary to ensure no overflow--max result +34490 ;is number of seconds in a day/2 = 43200. +34500 DIV AX,CX +34510 CMP DL,100 ;Remainder over 100? +34520 JB NOADJ +34530 SUB DL,100 ;Keep 1/100's less than 100 +34540 NOADJ: +34550 CMC ;If we subtracted 100, carry is now set +34560 MOV BL,DL ;Save 1/100's +34570 ;To compensate for dividing by 200 instead of 100, we now multiply +34580 ;by two, shifting a one in if the remainder had exceeded 100. +34590 RCL AX +34600 MOV DL,0 +34610 RCL DX +34620 MOV CX,60 ;Divide out seconds +34630 DIV AX,CX +34640 MOV BH,DL ;Save the seconds +34650 DIV AL,CL ;Break into hours and minutes +34660 XCHG AL,AH +34670 ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) +34680 LDS SI,[SPSAVE] ;Get pointer to user registers +34690 MOV [SI+DXSAVE],BX +34700 MOV [SI+CXSAVE],AX +34710 XOR AL,AL +34720 RET +34730 +34740 SETTIME: ;Function call 45 +34750 ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec +34760 MOV AL,-1 ;Flag in case of error +34770 CMP CH,24 ;Check hours +34780 JAE RET +34790 CMP CL,60 ;Check minutes +34800 JAE RET +34810 CMP DH,60 ;Check seconds +34820 JAE RET +34830 CMP DL,100 ;Check 1/100's +34840 JAE RET +34850 MOV AL,60 +34860 MUL AL,CH ;Hours to minutes +34870 MOV CH,0 +34880 ADD AX,CX ;Total minutes +34890 MOV CX,6000 ;60*100 +34900 MOV BX,DX ;Get out of the way of the multiply +34910 MUL AX,CX ;Convert to 1/100 sec +34920 MOV CX,AX +34930 MOV AL,100 +34940 MUL AL,BH ;Convert seconds to 1/100 sec +34950 ADD CX,AX ;Combine seconds with hours and min. +34960 ADC DX,0 ;Ripple carry +34970 MOV BH,0 +34980 ADD CX,BX ;Combine 1/100 sec +34990 ADC DX,0 +35000 ;DX:CX is time in 1/100 sec +35010 XCHG AX,DX +35020 XCHG AX,CX ;Now time is in CX:AX +35030 MOV BX,59659 +35040 MUL AX,BX ;Multiply low half +35050 XCHG DX,CX +35060 XCHG AX,DX ;CX->AX, AX->DX, DX->CX +35070 MUL AX,BX ;Multiply high half +35080 ADD AX,CX ;Combine overlapping products +35090 ADC DX,0 +35100 XCHG AX,DX ;AX:DX=time*59659 +35110 MOV BX,5 +35120 DIV AL,BL ;Divide high half by 5 +35130 MOV CL,AL +35140 MOV CH,0 +35150 MOV AL,AH ;Remainder of divide-by-5 +35160 CBW +35170 XCHG AX,DX ;Use it to extend low half +35180 DIV AX,BX ;Divde low half by 5 +35190 MOV DX,AX +35200 ;CX:DX now has time in ticks +35210 MOV AH,1 +35220 INT 1AH ;Set clock +35230 XOR AL,AL ;Return no error +35240 RET +35250 +35260 ;***** DATA AREA ***** +35270 +35280 ;Device number mapping +35290 ;0,1 = CON, AUX (Bidirectional devices) +35300 ;2,3 = Printer, bit bucket (output only) +35310 +35320 IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +35330 IONUM: DB 3,0,1,1,2,2 +35340 +35350 CARPOS: DB 0 +35360 INSFLG: DB 0 +35370 STARTPOS:DB 0 +35380 PFLAG: DB 0 +35390 DAY: DB 0 +35400 MONTH: DB 0 +35410 YEAR: DW 0 +35420 DIRTYDIR:DB 0 ;Dirty buffer flag +35430 NUMDRV: DS 1 ;Number of drives +35440 CONTPOS:DW 0 +35450 DMAADD: DW 80H ;User's disk transfer address (disp/seg) +35460 DS 2 +35470 ENDMEM: DS 2 +35480 MAXSEC: DW 0 +35490 BUFFER: DS 2 +35500 BUFSECNO:DW 0 +35510 BUFDRVNO:DB -1 +35520 DIRTYBUF:DB 0 +35530 BUFDRVBP:DS 2 +35540 DIRBUFID:DW -1 +35550 CURDRVPT:DS 2 +35560 DRVTAB: DS 30 ;Enough for 15 drives +35570 INBUF: DS 15 ;Only the first part +35580 +35590 ; Init code overlaps with data area below +35600 +35610 INITCODE: +35620 +35630 DS 128-15 ;More of INBUF +35640 CONBUF: DS 130 ;The rest of INBUF and console buffer +35650 FUNC: DS 1 ;Currently executing function code +35660 LASTENT:DS 2 +35670 EXITHOLD:DS 4 +35680 FATBASE:DS 2 +35690 NAME1: DS 11 ;File name buffer +35700 ATTRIB: DS 1 ;Search attributes +35710 NAME2: DS 11 +35715 NAME3: DS 12 +35720 EXTFCB: DS 1 +35730 CREATING:DS 1 +35740 TEMP: +35750 SPSAVE: DS 2 +35760 SSSAVE: DS 2 +35770 CONTSTK:DS 2 +35780 SECCLUSPOS:DS 1 ;Position of first sector within cluster +35790 DSKERR: DS 1 +35800 TRANS: DS 1 +35810 PREREAD:DS 1 ;0 means must preread; 1 means optional +35820 READOP: DS 1 +35830 +35840 ALIGN +35850 FCB: DS 2 ;Address of user FCB +35860 NEXTADD:DS 2 +35870 RECPOS: DS 4 +35880 RECCNT: DS 2 +35890 LASTPOS:DS 2 +35900 CLUSNUM:DS 2 +35910 SECPOS: DS 2 ;Position of first sector accessed +35920 VALSEC: DS 2 ;Number of valid (previously written) sectors +35930 BYTSECPOS:DS 2 ;Position of first byte within sector +35940 BYTPOS: DS 4 ;Byte position in file of access +35950 BYTCNT1:DS 2 ;No. of bytes in first sector +35960 BYTCNT2:DS 2 ;No. of bytes in last sector +35970 SECCNT: DS 2 ;No. of whole sectors +35980 +35990 DS 100H ;Stack space +36000 IOSTACK: +36010 DS 100H +36020 DSKSTACK: +36030 +36040 IF DSKTEST +36050 NSS: DS 2 +36060 NSP: DS 2 +36070 ENDIF +36080 +36090 DIRBUF: +36100 +36110 ;Init code below overlaps with data area above +36120 +36130 ORG INITCODE +36140 PUT $+100H +36150 +36160 MOVFAT: +36170 ;This section of code is safe from being overwritten by block move +36180 SEG ES +36190 REP +36200 MOVB +36210 UP +36220 FININIT: +36230 CALL SETMEM ;Set up segment +36240 RET L +36250 +36260 DOSINIT: +36270 DI +36280 UP +36290 PUSH CS +36300 POP ES +36310 LODB +36320 SEG ES +36330 MOV [NUMDRV],AL +36340 MOV BX,DRVTAB +36350 MOV DI,MEMSTRT +36360 PERDRV: +36370 SEG ES +36380 MOV [BX],DI +36390 MOV BP,DI +36400 INC BX +36410 INC BX +36420 SEG ES +36430 MOV AL,[DRVCNT] +36440 STOB ;DRVNUM +36450 LODW ;Pointer to DPT +36460 PUSH SI +36470 MOV SI,AX +36480 LODW +36490 STOW ;SECSIZ +36500 MOV DX,AX +36510 SEG ES +36520 CMP AX,[MAXSEC] +36530 JBE NOTMAX +36540 SEG ES +36550 MOV [MAXSEC],AX +36560 NOTMAX: +36570 LODB +36580 DEC AL +36590 STOB ;CLUSMSK +36600 JZ HAVSHFT +36610 CBW +36620 FIGSHFT: +36630 INC AH +36640 SAR AL +36650 JNZ FIGSHFT +36660 MOV AL,AH +36670 HAVSHFT: +36680 STOB ;CLUSSHFT +36690 MOVW ;FIRFAT (= number of reserved sectors) +36700 MOVB ;FATCNT +36710 MOVW ;MAXENT +36720 MOV AX,DX ;SECSIZ again +36730 MOV CL,5 +36740 SHR AX,CL +36750 MOV CX,AX ;Directory entries per sector +36760 DEC AX +36770 SEG ES +36780 ADD AX,[BP+MAXENT] +36790 XOR DX,DX +36800 DIV AX,CX +36810 STOW ;DIRSEC (temporarily) +36820 SHR AX ;Divide by two +36830 ADC AX,0 ;Round up +36840 SEG ES +36850 MOV [SDIRSEC],AX ;Number of directory records for small entries +36860 MOVW ;DSKSIZ (temporarily) +36870 FNDFATSIZ: +36880 MOV AL,1 +36890 MOV DX,1 +36900 GETFATSIZ: +36910 PUSH DX +36920 CALL FIGFATSIZ +36930 POP DX +36940 CMP AL,DL ;Compare newly computed FAT size with trial +36950 JZ HAVFATSIZ ;Has sequence converged? +36960 CMP AL,DH ;Compare with previous trial +36970 MOV DH,DL +36980 MOV DL,AL ;Shuffle trials +36990 JNZ GETFATSIZ ;Continue iterations if not oscillating +37000 SEG ES +37010 DEC [BP+DSKSIZ] ;Damp those oscillations +37020 JP FNDFATSIZ ;Try again +37030 HAVFATSIZ: +37040 STOB ;FATSIZ +37050 SEG ES +37060 MUL AL,[BP+FATCNT] ;Space occupied by all FATs +37070 SEG ES +37080 ADD AX,[BP+FIRFAT] +37090 STOW ;FIRDIR +37100 +37110 IF SMALLDIR-1 +37120 SEG ES +37130 ADD AX,[BP+DIRSEC] +37140 SEG ES +37150 MOV [BP+FIRREC],AX ;Destroys DIRSEC +37160 CALL FIGMAX +37170 SEG ES +37180 MOV [BP+MAXCLUS],CX +37190 ENDIF +37200 +37210 IF SMALLDIR +37220 MOV DX,AX ;Save FIRDIR momentarily +37230 SEG ES +37240 ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry +37250 STOW ;FIRREC1 +37260 XCHG AX,CX ;Previously computed MAXCLUS +37270 STOW ;MAXCLUS1 +37280 XCHG DX,AX +37290 SEG ES +37300 ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry +37310 STOW ;FIRREC2 +37320 CALL FIGMAX +37330 XCHG AX,CX +37340 STOW ;MAXCLUS2 +37350 ENDIF +37360 +37370 MOV AX,0FFH +37380 STOB ;DIRTYFAT +37390 SEG ES +37400 MOV AL,[BP+FATSIZ] +37410 SEG ES +37420 MUL AX,[BP+SECSIZ] +37430 ADD DI,AX ;Allocate FAT +37440 POP SI ;Restore pointer to init. table +37450 SEG ES +37460 MOV AL,[DRVCNT] +37470 INC AL +37480 SEG ES +37490 MOV [DRVCNT],AL +37500 SEG ES +37510 CMP AL,[NUMDRV] +37520 JAE CONTINIT +37530 JMP PERDRV +37540 CONTINIT: +37550 LODW ;Max. buffer size +37560 SEG ES +37570 MOV BX,[MAXSEC] +37580 MOV AX,DIRBUF +37590 ADD AX,BX +37600 SEG ES +37610 MOV [BUFFER],AX ;Start of buffer +37620 PUSH DI ;Save ending location +37630 ADD DI,BX ;Allocate directory buffer +37640 ADD DI,BX ;Allocate buffer space +37650 ADD DI,ADJFAC+15 ;True start of free space +37660 MOV CL,4 +37670 SHR DI,CL ;First free segment +37680 MOV BP,DI +37690 XOR AX,AX +37700 MOV DS,AX +37710 MOV ES,AX +37720 MOV DI,INTBASE +37730 MOV AX,QUIT +37740 STOW ;Set abort address--displacement +37750 MOV AX,CS +37760 MOV B,[ENTRYPOINT],LONGJUMP +37770 MOV [ENTRYPOINT+1],ENTRY +37780 MOV [ENTRYPOINT+3],AX +37790 MOV CX,9 +37800 REP +37810 STOW ;Set 5 segments (skip 2 between each) +37820 MOV [INTBASE+4],COMMAND +37830 MOV [INTBASE+12],IRET ;CTRL-C exit +37840 MOV [INTBASE+16],IRET ;Fatal error exit +37850 MOV AX,BIOSREAD +37860 STOW +37870 MOV AX,BIOSSEG +37880 STOW +37890 STOW ;Add 2 to DI +37900 STOW +37910 MOV [INTBASE+18H],BIOSWRITE +37920 MOV DX,CS +37930 MOV DS,DX +37940 ADD DX,BP +37950 MOV [DMAADD],80H +37960 MOV [DMAADD+2],DX +37970 MOV AX,[DRVTAB] +37980 MOV [CURDRVPT],AX +37990 INT 12H ;Get memory size--1K blocks in AX +38000 MOV CL,6 +38010 SHL AX,CL ;Convert to 16-byte blocks (segment no.) +38020 SEG CS +38030 MOV [ENDMEM],AX +38040 XOR CX,CX +38050 MOV DS,CX +38060 MOV [EXIT],100H +38070 MOV [EXIT+2],DX +38080 PUSH CS +38090 POP DS +38100 PUSH CS +38110 POP ES +38120 MOV [ENDDOS],DX +38130 ;Move FATs into position. Segment of COMMAND still in DX. +38140 POP SI +38150 MOV AX,[MAXSEC] +38160 SHL AX ;Allocate two buffers +38170 ADD AX,ADJFAC +38180 JZ FINJMP +38190 MOV DI,DRVTAB +38200 MOV CX,15 +38210 ADJLP: +38220 ADD [DI],AX +38230 INC DI +38240 INC DI +38250 LOOP ADJLP +38260 MOV CX,SI +38270 MOV SI,MEMSTRT ;Place to move FATs from +38280 SUB CX,SI ;Total length of FATs +38290 MOV DI,AX +38300 ADD DI,SI ;Place to move FATs to +38310 OR AX,AX +38320 JS MOVJMP +38330 DEC CX +38340 ADD DI,CX +38350 ADD SI,CX +38360 INC CX +38370 DOWN +38380 MOVJMP: +38390 JMP MOVFAT +38400 FINJMP: JMP FININIT +38410 +38420 FIGFATSIZ: +38430 SEG ES +38440 MUL AL,[BP+FATCNT] +38450 SEG ES +38460 ADD AX,[BP+FIRFAT] +38470 SEG ES +38480 ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +38490 FIGMAX: +38500 ;AX has equivalent of FIRREC +38510 SEG ES +38520 SUB AX,[BP+DSKSIZ] +38530 NEG AX +38540 SEG ES +38550 MOV CL,[BP+CLUSSHFT] +38560 SHR AX,CL +38570 INC AX +38580 MOV CX,AX ;MAXCLUS +38590 INC AX +38600 MOV DX,AX +38610 SHR DX +38620 ADC AX,DX ;Size of FAT in bytes +38630 SEG ES +38640 MOV SI,[BP+SECSIZ] +38650 ADD AX,SI +38660 DEC AX +38670 XOR DX,DX +38680 DIV AX,SI +38690 RET +38700 +38710 DRVCNT: DB 0 +38720 SDIRSEC:DS 1 +38730 +38740 MEMSTRT: +38750 ADJFAC: EQU DIRBUF-MEMSTRT +38760 +38770 DS EXCESS +38780 DB 0 diff --git a/2_printed_files/bundle_03/CHKDSK.A86 b/2_printed_files/bundle_03/CHKDSK.A86 new file mode 100644 index 0000000..04fc292 --- /dev/null +++ b/2_printed_files/bundle_03/CHKDSK.A86 @@ -0,0 +1,611 @@ +00100 +00200 ; CHKDSK Version 1.0 03/10/81 +00300 +00400 ; Verifies and repairs 86-DOS disk directory. +00500 +00600 SETDRV: EQU 14 +00700 GETDRV: EQU 25 +00800 GETMAP: EQU 27 +00900 OPEN: EQU 15 +01000 CLOSE: EQU 16 +01100 DELETE: EQU 19 +01200 SETDMA: EQU 26 +01300 SRCHFST:EQU 17 +01400 SRCHNXT:EQU 18 +01500 OUTCH: EQU 2 +01600 BLKWRT: EQU 40 +01700 PRINTBUF:EQU 9 +01800 +01900 ORG 100H +02000 PUT 100H +02100 +02200 CHKDSK: +02205 MOV SP,STACK +02210 OR AL,AL ;SEE IF INVALID DRIVE SPECIFIED +02215 JNZ DRVERR ;IF SO JUST EXIT +02220 CMP B,[5DH],20H ;MAKE SURE TYPED CORRECTLY +02225 JNZ PRMERR ;IF NOT PARAMETER ERROR +02300 MOV AH,GETDRV +02400 INT 21H +02500 MOV [CURDRV],AL +02600 MOV DL,[5CH] +02700 OR DL,DL +02800 JZ DRVMOV +02900 MOV AH,SETDRV +03000 DEC DL +03100 INT 21H +03110 CMP AL,DL +03120 JA DRVSET +03130 DRVERR: MOV DX,BADDRV +03135 ERROR: +03140 MOV AH,PRINTBUF +03150 INT 33 +03160 INT 32 +03170 +03171 PRMERR: MOV DX,INVPRM ;Invalid parameter +03172 JP ERROR +03175 BADDSK: +03177 MOV AX,CS +03178 MOV DS,AX +03180 MOV AH,SETDRV +03185 MOV DL,[CURDRV] +03190 INT 33 +03195 MOV DX,DIRBAD +03197 JP ERROR +03199 DRVMOV: MOV DL,AL ;Correct drive designator +03200 DRVSET: +03202 MOV B,[WRKDRV],DL ;Save drive indicator +03203 INC DL ;FOR FCB SET +03204 MOV B,[ALLDRV],DL ;FCB ok now +03205 DEC DL +03300 CALL DRVXCG ;Change drives and do map read +03410 CMP B,[BX],0FEH ;Check for initialized disk +03420 JNE BADDSK +03500 PUSH DS +03600 PUSH ES +03700 POP DS +03800 MOV [DSKSIZ],DX ;Number of allocation units +03900 MOV [SECSIZ],CX ;Size of physical sector +04000 MOV AH,0 +04100 MOV [CLUSSIZ],AX ;Sectors per cluster +04200 MOV CX,DX +04300 MOV DI,MAP +04400 XOR AX,AX +04500 REP +04600 STOW ;Zero out allocation map +04700 MOV CX,AX +04800 MOV [ALLOC],AX ;Count of allocation units used +04900 MOV [FILECNT],AX ;Number of files found +05000 MOV [DELCNT],AX ;Number of files deleted due to error +05100 MOV BP,DI +05200 MOV [NAMTAB],BP ;First address of file list +05300 MOV DX,DI +05400 MOV AH,SETDMA +05500 INT 21H +05600 MOV AH,SRCHFST +05700 MOV DX,ALLFILE +05800 INT 21H +05900 INC AL +06000 POP ES ;ES:BX point to FAT +06100 JNZ GETFILES +06200 JMP COMPMAP +06300 GETFILES: +06400 INC CX ;Count number of files +06500 ADD DI,44 ;Separate in file in list by 44 bytes +06600 MOV DX,DI +06700 MOV AH,SETDMA +06800 INT 21H +06900 MOV AH,SRCHNXT +07000 MOV DX,ALLFILE +07100 INT 21H +07200 INC AL +07300 JNZ GETFILES ;Loop until all files are in list +07400 MOV [FILECNT],CX +07500 MOV CX,1 ;File number (position in list) +07600 MOV DX,[DSKSIZ] +07700 INC DX ;Maximum cluster number +07800 MOV [MAXCLUS],DX +07900 ADD BP,34 ;Point to "first cluster" entry +08000 EACHFIL: +08100 XOR AX,AX ;No. of clusters in file +08200 MOV SI,[BP] ;First cluster of file +08300 CMP SI,[MAXCLUS] ;Make sure it's legal +08400 MOV DI,BADDIR +08500 JA BADFIRST +08600 OR SI,SI ;Check for zero-length file +08700 JZ HAVENDJ +08800 SCANFAT: +08900 MOV DI,CX +09000 SHL SI +09100 XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. +09200 SHR SI +09300 OR DI,DI ;Should be zero for unallocated cluster +09400 JNZ CROSSLINK +09500 INC AX ;Count cluster as part of this file +09600 CALL UNPACK +09700 JZ FORCEND ;Make sure cluster knows it's allocated +09800 CMP DI,0FF8H ;Bigger than this means End of File +09900 HAVENDJ:JAE HAVEND +10000 CMP DI,[MAXCLUS] ;Make sure it's a legal value +10100 JA FORCEND +10200 MOV SI,DI +10300 JP SCANFAT ;Visit each cluster allocated to file +10400 +10500 BADFIRST: +10600 PUSH AX ;Because FILERR will pop it later +10610 MOV [BP+2],AX ;AX is zero +10620 MOV [BP+4],AX ;Set size to zero so we won't change it +10700 MOV AX,CX +10800 MOV DX,44 +10900 DEC AX +11000 MUL AX,DX ;Get position in file name table +11100 MOV DX,AX +11200 ADD DX,[NAMTAB] +11300 MOV AH,DELETE +11303 INT 21H +11305 PUSH DS +11309 PUSH CX +11310 PUSH AX +11312 CALL DRVXCG ;Reset dirty bit to rewrite FAT +11313 POP AX +11315 POP CX +11318 POP DS +11321 OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY +11324 JZ DISKOK +11327 JMP BADDSK +11330 DISKOK: +11333 INC [DELCNT] ;Count one deleted file +11600 MOV DX,BADDIR +11700 JP FILERR +11800 +11900 CROSSLINK: +12000 MOV DX,LINKED +12100 PUSH AX +12200 MOV AH,PRINTBUF +12300 INT 21H +12400 MOV AX,DI +12500 CALL PRINTNAM +12600 MOV DX,FILE2 +12700 MOV AH,PRINTBUF +12800 INT 33 +12900 MOV AX,CX +13000 CALL PRINTNAM +13100 MOV DX,CRLF +13200 MOV AH,PRINTBUF +13300 INT 33 +13400 POP AX +13500 ADD [ALLOC],AX +13600 JMP SIZSET1 +13700 +13800 FORCEND: +13900 ; Come here if a cluster allocated to a file contained an illegal +14000 ; link--either a zero (meaning unallocated), or a value larger than +14100 ; the maximum cluster number, but not End of File. Put an End of File +14200 ; mark there so the FAT will at least be well-formed. +14300 MOV DX,0FFFH +14400 CALL PACK +14500 MOV DX,BADCLUS +14600 PUSH AX +14700 +14800 FILERR: +14900 MOV AH,PRINTBUF +15000 INT 21H +15100 MOV AX,CX +15200 CALL PRINTNAM +15300 MOV DX,CRLF +15400 MOV AH,PRINTBUF +15500 INT 21H +15600 POP AX +15700 +15800 HAVEND: +15900 ADD [ALLOC],AX ;Total up allocated clusters +16000 MOV SI,AX +16100 MOV AX,[BP+2] +16200 MOV DX,[BP+4] ;AX:DX now have file length +16300 PUSH CX +16400 MOV CX,[CLUSSIZ] +16500 DEC CX +16600 ADD AX,CX +16700 ADC DX,0 +16800 INC CX +16900 SCALE: +17000 SHR CX +17100 JC SCALED +17200 SHR DX +17300 RCR AX +17400 JP SCALE +17500 SCALED: +17600 DIV AX,[SECSIZ] +17700 OR DX,DX +17800 JZ HAVSIZ +17900 INC AX +18000 HAVSIZ: +18100 CMP AX,SI ;See if file size corresponds with allocation +18200 JZ SIZSET +18300 XOR DI,DI +18400 MOV CX,[CLUSSIZ] +18500 CALL UNSCALE +18600 MOV [BP+6],SI +18700 MOV [BP+8],DI +18800 MOV DX,BP +18900 SUB DX,34 +19000 MOV AH,OPEN +19100 INT 21H +19110 OR AL,AL +19120 JZ DISKOK2 +19130 JMP BADDSK +19140 DISKOK2: +19200 MOV AX,[SECSIZ] +19300 MOV [BP-27+14],AX ;Make record size=sector size +19400 MOV CX,0 +19500 MOV AH,BLKWRT +19600 INT 21H +19700 MOV AH,CLOSE ;Write back corrected directory entry +19800 INT 21H +20000 PUSH DS +20100 CALL DRVXCG ;Change the drives and get the map +20200 POP DS +20300 MOV DX,BADSIZ +20400 MOV AH,PRINTBUF +20500 INT 21H +20600 POP AX +20700 PUSH AX +20800 CALL PRINTNAM +20900 MOV DX,CRLF +21000 MOV AH,PRINTBUF +21100 INT 21H +21200 SIZSET: +21300 POP CX +21400 SIZSET1: +21500 ADD BP,44 ;Scan next file +21600 INC CX +21700 CMP CX,[FILECNT] +21800 JA COMPMAP +21900 JMP EACHFIL +22000 ; Now compare the allocation map we have made with the FAT. Any +22100 ; clusters not allocated in the map will be released. +22200 COMPMAP: +22300 XOR AX,AX ;Keep count of clusters released +22400 MOV BP,MAP +22500 MOV SI,2 ;First usable cluster number +22600 MOV CX,[DSKSIZ] +22700 RELCLUS: +22800 TEST [BP],-1 ;Allocated in our map? +22900 JNZ NXTCLUS ;If so, skip to next +23000 CALL UNPACK +23100 JZ NXTCLUS ;If not allocated, skip to next +23200 XOR DX,DX +23300 CALL PACK ;Change to "Free" status +23400 INC AX ;Count clusters released +23500 NXTCLUS: +23600 INC BP +23700 INC BP +23800 INC SI +23900 LOOP RELCLUS +24000 OR AX,AX ;Any clusters released? +24100 JZ REPORT ;If not, do final report +24200 MOV BX,FREED +24300 CALL DISPCLUS +24400 REPORT: +24500 ; Make status report. Include no. of files, total disk space, +24600 ; free space on disk, total memory, and free memory. +24610 SEG CS +24620 MOV DL,[CURDRV] +24630 MOV AH,SETDRV +24640 INT 21H +24700 MOV SI,[FILECNT] +24800 SUB SI,[DELCNT] +24900 XOR DI,DI +25000 MOV BX,NUMFIL +25100 CALL DISP32BITS +25200 MOV AX,[DSKSIZ] +25300 MOV BX,DSKSPC +25400 CALL DISPCLUS +25500 MOV AX,[DSKSIZ] +25600 SUB AX,[ALLOC] +25700 MOV BX,FRESPC +25800 CALL DISPCLUS +25900 MOV AX,[2] +26000 MOV DX,16 +26100 MUL AX,DX +26200 MOV SI,AX +26300 MOV DI,DX +26400 MOV BX,TOTMEM +26500 CALL DISP32BITS +26600 MOV AX,[2] +26700 MOV DX,CS +26800 SUB AX,DX +26900 MOV DX,16 +27000 MUL AX,DX +27100 MOV SI,AX +27200 MOV DI,DX +27300 MOV BX,FREMEM +27400 CALL DISP32BITS +27405 CALL WRTFRC ;Force all writes and handle write +27410 ;protect violation +27412 SEG CS +27414 MOV B,DL,[CURDRV] ;Get default +27416 MOV AH,SETDRV ;And make it current again +27418 INT 21H +27900 INT 20H ;All done +27902 +27904 WRTFRC: ;******************************************************** +27906 ; This code forces all writes by performing a disk +27908 ; reset (function 13). When the attempt to write +27910 ; the allocation table fails in the case of a write- +27912 ; protected diskette, this logic determines if the +27914 ; allocation table had changed and if no changes were +27916 ; made a normal termination will be forced +27918 ;********************************************************* +27919 MOV AX,DS +27920 PUSH DS ;Must first intercept INT 24H +27921 MOV ES,AX +27922 XOR AX,AX +27924 MOV DS,AX +27926 MOV SI,90H +27928 MOV DI,INT24 ;will move vector to local address +27930 MOV CX,2 +27931 CLD ;So move will increment +27932 REP +27934 MOVW ;Vector now locally stored +27936 MOV AL,24H ; +27938 MOV AH,37 +27940 MOV DX,WRTPRT ; +27942 POP DS ;Get local segment +27944 INT 21H ;Interrupt vector now set +27946 MOV AH,13 +27948 INT 21H +27953 PUSH ES ;Will now reset INT 24H vector +27955 XOR AX,AX +27957 MOV ES,AX +27959 CLD +27961 MOV DI,90H +27963 MOV SI,INT24 +27965 MOV CX,2 +27967 REP +27969 MOVW +27971 POP ES +27973 RET +27974 +27976 WRTPRT: ;********************************************************* +27978 ; This logic is designed to handle the case where +27980 ; CHKDSK found no problems and upon rewriting the +27982 ; allocation table (by the DOS) the disk was write- +27984 ; protected and an error thus occured. With no problems +27986 ; this code will cause normal termination, otherwise +27987 ; normal error handling will occur. +27988 ;********************************************************* +27990 EI ;Run with interrupts live +27992 AND DI,0FFH ;See if write-protect +27994 JNZ WRT100 ;Do normal error handling +27996 CMP AH,3 ;File allocation write? +27998 JNZ WRT100 ;If not do normal handling +27999 SEG CS +28000 CMP [WRKDRV],AL ;Correct drive? +28002 JNZ WRT100 ; +28003 SEG CS +28004 CMP B,[CHGCLS],1 ;Legitimate change? +28006 JZ WRT100 ;If so do normal handling +28007 XOR AL,AL ;Ignore the error +28008 IRET +28009 WRT100: SEG CS +28010 MOV SI,AX ;Save AX +28011 PUSH DX +28012 MOV DL,[CURDRV] ;Fetch current drive +28015 MOV AH,SETDRV +28018 INT 33 ;Drive now ok +28019 POP DX ;Restore DX +28020 MOV AX,SI ;Restore AX +28021 SEG CS +28024 JMP L,[INT24] ;Do normal recovery +28027 +28030 +28060 DRVXCG: +28061 ;********************************************** +28062 ; WILL CHANGE DEFAULT TO WRKDRV READ THE FAT +28063 ; AND CHANGE THE DEFAULT BACK TO CURDRV +28064 ;********************************************** +28065 SEG CS +28068 MOV DL,[WRKDRV] ;Will change the default to this +28070 MOV AH,SETDRV +28072 INT 33 ;Default now "WRKDRV" +28073 MOV AH,GETMAP +28074 INT 33 +28076 PUSH DX +28077 PUSH AX +28078 SEG CS +28080 MOV DL,[CURDRV] ;Get current drive +28082 MOV AH,SETDRV +28084 INT 33 +28085 POP AX +28086 POP DX +28088 RET +28090 +28092 +28094 UNPACK: +28200 MOV DI,SI +28300 SHR DI +28400 ADD DI,SI +28500 SEG ES +28600 MOV DI,[DI+BX] +28700 TEST SI,1 +28800 JZ HAVCLUS +28900 SHR DI +29000 SHR DI +29100 SHR DI +29200 SHR DI +29300 HAVCLUS: +29400 AND DI,0FFFH +29500 RET +29600 +29700 PACK: +29705 ;************************************************************* +29710 ; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +29715 ; SI CLUSTER NUMBER TO BE PACKED +29720 ; DX POINTER TO BE PLACED IN CLUSTER (SI) +29725 ;************************************************************* +29730 MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED +29800 PUSH SI +29900 MOV DI,SI +30000 SHR SI +30100 ADD SI,BX +30200 ADD SI,DI +30300 SHR DI +30400 SEG ES +30500 MOV DI,[SI] +30600 JNC ALIGNED +30700 SHL DX +30800 SHL DX +30900 SHL DX +31000 SHL DX +31100 AND DI,0FH +31200 JP PACKIN +31300 ALIGNED: +31400 AND DI,0F000H +31500 PACKIN: +31600 OR DI,DX +31700 SEG ES +31800 MOV [SI],DI +31900 POP SI +32000 RET +32100 +32200 UNSCALE: +32300 SHR CX +32400 JC RET +32500 SHL SI +32600 RCL DI +32700 JP UNSCALE +32800 +32900 DISPCLUS: +33000 MUL AX,[SECSIZ] +33100 MOV CX,[CLUSSIZ] +33200 MOV SI,AX +33300 MOV DI,DX +33400 CALL UNSCALE +33500 DISP32BITS: +33600 PUSH BX +33700 XOR AX,AX +33800 MOV BX,AX +33900 MOV BP,AX +34000 MOV CX,32 +34100 CONVLP: +34200 SHL SI +34300 RCL DI +34400 XCHG AX,BP +34500 CALL CONVWRD +34600 XCHG AX,BP +34700 XCHG AX,BX +34800 CALL CONVWRD +34900 XCHG AX,BX +35000 ADC AL,0 +35100 LOOP CONVLP +35200 ; Conversion complete. Print 10-digit number with 2 leading blanks. +35300 MOV CX,1B10H +35400 CALL OUTWORD +35500 MOV AX,BX +35600 CALL OUTWORD +35700 MOV AX,BP +35800 CALL OUTWORD +35900 POP DX +36000 MOV AH,PRINTBUF +36100 INT 21H +36200 RET +36300 +36400 OUTWORD: +36500 PUSH AX +36600 MOV DL,AH +36700 CALL OUTBYTE +36800 POP DX +36900 OUTBYTE: +37000 MOV DH,DL +37100 SHR DL +37200 SHR DL +37300 SHR DL +37400 SHR DL +37500 CALL DIGIT +37600 MOV DL,DH +37700 DIGIT: +37800 AND DL,0FH +37900 JZ BLANKZER +38000 MOV CL,0 +38100 BLANKZER: +38200 DEC CH +38300 AND CL,CH +38400 OR DL,30H +38500 SUB DL,CL +38600 MOV AH,OUTCH +38700 INT 21H +38800 RET +38900 +39000 CONVWRD: +39100 ADC AL,AL +39200 DAA +39300 XCHG AL,AH +39400 ADC AL,AL +39500 DAA +39600 XCHG AL,AH +39700 RET +39800 +39900 PRINTNAM: +39910 PUSH CX +40000 DEC AX +40100 MOV CX,44 +40200 MUL AX,CX +40300 MOV SI,AX +40400 ADD SI,[NAMTAB] +40500 ADD SI,8 +40600 MOV CX,8 +40700 MOV AH,OUTCH +40800 CALL PRINTCNT +40900 MOV DL," " +41000 INT 21H +41100 MOV CL,3 +41110 CALL PRINTCNT +41120 POP CX +41130 RET +41140 +41200 PRINTCNT: +41300 LODB +41400 MOV DL,AL +41500 INT 21H +41700 LOOP PRINTCNT +41800 RET +41900 +41950 ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB +42000 ALLDRV: DB 0,"???????????" +42100 DS 25 +42200 +42300 FILE2: DB " and $" +42305 BADDRV: DB "Invalid drive specification$" +42306 INVPRM: DB "Invalid parameter$" +42400 BADCLUS:DB "Allocation error for file $" +42500 BADDIR: DB "Directory error-file : $" +42600 LINKED: DB "Files cross-linked: " +42605 DB 13,10 +42610 DB " $" +42700 BADSIZ: DB "File size error for file $" +42705 DIRBAD: DB "Diskette not initialized $" +42800 FREED: DB " bytes disk space freed",13,10,13,10,"$" +42900 NUMFIL: DB " disk files",13,10,"$" +43000 DSKSPC: DB " bytes total disk space",13,10,"$" +43100 FRESPC: DB " bytes remain available",13,10,13,10,"$" +43200 TOTMEM: DB " bytes total memory",13,10,"$" +43300 FREMEM: DB " bytes free" +43400 CRLF: DB 13,10,"$" +43500 +43600 DSKSIZ: DS 2 +43700 SECSIZ: DS 2 +43800 CLUSSIZ:DS 2 +43805 CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +43810 WRKDRV: DB 0 +43815 INT24: DS 4 +43900 FILECNT:DS 2 +44000 NAMTAB: DS 2 +44100 ALLOC: DS 2 +44200 MAXCLUS:DS 2 +44300 DELCNT: DS 2 +44400 CURDRV: DS 1 +44405 DS 100H +44410 STACK: +44500 +44600 MAP: diff --git a/2_printed_files/bundle_03/EDLIN.DIF b/2_printed_files/bundle_03/EDLIN.DIF new file mode 100644 index 0000000..f034caa --- /dev/null +++ b/2_printed_files/bundle_03/EDLIN.DIF @@ -0,0 +1,242 @@ +File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +1)1 ;EDLIN - Simple line-oriented editor for 86-DOS version 1.00 04/24/81 +1 FCB: EQU 5CH +**** +2) 00040 ;EDLIN - Simple line-oriented editor for 86-DOS version 0.32 04/15/81 +2) 00080 FCB: EQU 5CH +************** +1)1 HEADER: DB 13,10,"EDLIN version 1.00",13,10,"$" +1) NONAME: +1) MOV DX,NDNAME +1) JMP ERROR +1) SIMPED: +**** +2)1 00460 HEADER: DB 13,10,"The IBM Personal Computer EDITOR",13,10 +2) 00480 DB "Version 1.00 (C)Copyright IBM Corp 1981",13,10,"$" +2) 00500 DB "Licensed Material - Program Property of IBM" +2) 00540 NONAME: +2) 00560 MOV DX,NDNAME +2) 00580 ERRJ: JMP ERROR +2) 00620 SIMPED: +************** +1)1 MOV DX,HEADER +1) MOV AH,PRINT +1) INT 33 +1) CMP B,[FCB+1]," " +1) JZ NONAME +1) MOV SI,BAK +**** +2)1 00680 ; MOV DX,HEADER +2) 00700 ; MOV AH,PRINT +2) 00720 ; INT 33 +2) 00740 CMP B,[FCB+1]," " +2) 00760 JZ NONAME +2) 00780 OR AL,AL +2) 00800 MOV DX,BADDRV +2) 00820 JNZ ERRJ +2) 00840 MOV SI,BAK +************** +1)1 ADD CX,AX ;3/4 of available memory +1) ;Read in input file +**** +2)1 02200 MOV [ONE4TH],CX ;Save amount of 1/4 full +2) 02220 ADD CX,AX ;3/4 of available memory +2) 02240 MOV DX,CX +2) 02260 ADD DX,START +2) 02280 MOV [THREE4TH],DX ;Save pointer to 3/4 full +2) 02300 ;Read in input file +************** +1)1 DEC SI +1) CALL GETNUM +**** +2)1 03140 DEC SI +2) 03160 CALL GETNUM +************** +1)1 AND AL,5FH +1) MOV DI,COMTAB +**** + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2)1 03305 CMP AL,5FH +2) 03310 JBE UPCASE +2) 03320 AND AL,5FH +2) 03325 UPCASE: +2) 03340 MOV DI,COMTAB +************** +1)1 SHL BX +**** +2)1 03460 MOV AX,[PARAM2] +2) 03480 OR AX,AX +2) 03500 JZ PARMOK +2) 03520 CMP AX,[PARAM1] +2) 03540 JB COMERR ;Param. 2 must be >= param 1 +2) 03560 PARMOK: +2) 03580 SHL BX +************** +1)1 JP COMMAND +1) GETNUM: +**** +2)1 03880 JMP COMMAND +2) 03940 GETNUM: +************** +1)1 NUMLP: +1) CMP AL,"0" +1) JB RET +1) CMP AL,"9" +1) JA RET +1) SUB AL,"0" +**** +2)1 04080 MOV CL,0 ;Flag no parameter seen yet +2) 04100 NUMLP: +2) 04120 CMP AL," " +2) 04140 JB NUMCHK +2) 04160 CMP AL,"9" +2) 04180 JA NUMCHK +2) 04200 CMP DX,6553 ;Max line/10 +2) 04220 JAE COMERR ;Ten times this is too big +2) 04240 MOV CL,1 ;Parameter digit has been found +2) 04260 SUB AL,"0" +************** +1)1 CURLIN: +**** +2)1 04460 NUMCHK: +2) 04480 CMP CL,0 +2) 04500 JZ RET +2) 04520 OR DX,DX +2) 04540 JZ COMERR ;Don't allow zero as a parameter +2) 04560 RET +2) 04600 CURLIN: +************** +1)1 APPEND: +1) TEST B,[HAVEOF],-1 +1) JNZ NOMORE +1) MOV DX,[ENDTXT] +1) MOV DI,DX +**** + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2)1 05380 NOMOREJ:JMP NOMORE +2) 05420 APPEND: +2) 05440 TEST B,[HAVEOF],-1 +2) 05460 JNZ NOMOREJ +2) 05480 MOV DX,[ENDTXT] +2) 05500 CMP [PARAM1],0 ;See if parameter is missing +2) 05520 JNZ PARMAPP +2) 05540 CMP DX,[THREE4TH] ;See if already 3/4ths full +2) 05560 JAE RET ;If so, then done already +2) 05580 PARMAPP: +2) 05600 MOV DI,DX +************** +1)1 MOV BX,[PARAM1] +1) CMP BX,1 +1) SBC BX,0 ;Make a zero a -1 +1) XOR DX,DX +1) CALL SCANLN ;Look for BX lines +**** +2)1 05900 XOR DX,DX +2) 05920 MOV BX,[PARAM1] +2) 05940 OR BX,BX +2) 05960 JNZ COUNTLN +2) 05980 MOV AX,DI +2) 06000 ADD AX,CX ;First byte after loaded text +2) 06020 CMP AX,[THREE4TH] ;See if we made 3/4 full +2) 06040 JBE COUNTLN +2) 06060 MOV DI,[THREE4TH] +2) 06080 MOV CX,AX +2) 06100 SUB CX,DI ;Length remaining over 3/4 +2) 06120 MOV BX,1 ;Look for one more line +2) 06140 COUNTLN: +2) 06160 CALL SCANLN ;Look for BX lines +************** +1)1 EOFCHK: +**** +2)1 06640 NOMORE: +2) 06660 MOV DX,EOF +2) 06680 MOV AH,PRINT +2) 06700 INT 33 +2) 06720 RET +2) 06740 EOFCHK: +************** +1)1 NOMORE: +1) MOV DX,EOF +1) MOV AH,PRINT +1) INT 33 +1) RET +1) WRITE: +**** +2)1 06880 WRITE: +************** +1)1 MOV BX,[CURRENT] +1) DEC BX +1) WRT: +**** +2)1 06960 MOV CX,[ONE4TH] + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2) 06980 MOV DI,[ENDTXT] +2) 07000 SUB DI,CX ;Write everything in front of here +2) 07010 JBE RET +2) 07020 CMP DI,START ;See if there's anything to write +2) 07040 JBE RET +2) 07060 XOR DX,DX +2) 07080 MOV BX,1 ;Look for one more line +2) 07100 CALL SCANLN +2) 07120 JP WRTADD +2) 07140 WRT: +************** +1)1 MOV CX,DI +**** +2)1 07180 WRTADD: +2) 07200 MOV CX,DI +************** +1)1 INC DX +**** +2)1 12680 JAE SOMELEFT +2) 12700 MOV [SRCHCNT],0 +2) 12720 SOMELEFT: +2) 12740 INC DX +************** +1)1 MOV [CURRENT],BX +1) MOV [POINTER],DI +1) PUSH DI +**** +2)1 16620 PUSH BX +2) 16660 PUSH DI +************** +1)1 XOR CX,CX +1) JP REPLACE +1) NOCOM: +**** +2)1 16862 JBE COMERRJ +2) 16864 POP [CURRENT] +2) 16866 MOV [POINTER],DI +2) 16880 XOR CX,CX +2) 16900 JP REPLACE +2) 16910 COMERRJ:JMP COMERR +2) 16960 NOCOM: +************** +1)1 MOV BX,-2 ;Write max. no of lines +1) CALL WRT +**** +2)1 20480 MOV BX,-1 ;Write max. no of lines +2) 20500 CALL WRT +************** +1)1 NDNAME: DB "File name must be specified$" +**** +2)1 21760 BADDRV: DB "Invalid drive or file name$" +2) 21780 NDNAME: DB "File name must be specified$" +************** +1)1 END: DS 2 +**** +2)1 22340 ONE4TH: DS 2 + File 1) DSKC:EDLIN.ASM[500,500] created: 1231 06-MAY-1981 +File 2) DSKC:EDLIN.A86[500,500] created: 1007 01-JULY-1981 + +2) 22360 THREE4TH:DS 2 +2) 22380 END: DS 2 +************** diff --git a/2_printed_files/bundle_04/86DOS.ASM b/2_printed_files/bundle_04/86DOS.ASM new file mode 100644 index 0000000..286a78b --- /dev/null +++ b/2_printed_files/bundle_04/86DOS.ASM @@ -0,0 +1,3605 @@ +00010 +00020 ; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +00030 ; by Tim Paterson +00040 +00050 ; ****************** Revision History ************************* +00060 ; >> EVERY change must noted below!! << +00070 ; +00080 ; 0.34 12/29/80 General release, updating all past customers +00090 ; 0.42 02/25/81 32-byte directory entries added +00100 ; 0.56 03/23/81 Variable record and sector sizes +00110 ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +00120 ; 0.74 04/15/81 Recognize I/O devices with file names +00130 ; 0.75 04/17/81 Improve and correct buffer handling +00140 ; 0.76 04/23/81 Correct directory size when not 2^N entries +00150 ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +00160 ; 1.00 04/28/81 Renumber for general release +00170 ; +00180 ; ************************************************************* +00190 +00200 ; Use the switch below to generate code to accept the old 16-byte +00210 ; directory entry as well as the new 32-byte entry. +00220 +00230 SMALLDIR: EQU 1 ;1 to enable, 0 to disable +00240 +00250 +00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +00270 ; up a different stack for disk I/O (functions > 11) than that used for +00280 ; character I/O which effectively makes the DOS re-entrant. +00290 +00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +00310 +00320 +00330 ; Interrupt Entry Points: +00340 +00350 ; INTBASE: ABORT +00360 ; INTBASE+4: COMMAND +00370 ; INTBASE+8: BASE EXIT ADDRESS +00380 ; INTBASE+C: CONTROL-C ABORT +00390 ; INTBASE+10H: FATAL ERROR ABORT +00400 ; INTBASE+14H: BIOS DISK READ +00410 ; INTBASE+18H: BIOS DISK WRITE +00420 ; INTBASE+40H: Long jump to CALL entry point +00430 +00440 +00450 MAXCALL:EQU 36 +00460 MAXCOM: EQU 41 +00470 ESCCH: EQU 1BH +00480 INTBASE:EQU 80H +00490 INTTAB: EQU 20H +00500 ENTRYPOINTSEG: EQU 0CH +00510 ENTRYPOINT: EQU INTBASE+40H +00520 CONTC: EQU INTTAB+3 +00530 EXIT: EQU INTBASE+8 +00540 LONGJUMP:EQU 0EAH +00550 LONGCALL:EQU 9AH +00560 MAXDIF: EQU 0FFFH +00570 SAVEXIT:EQU 10 +00580 +00590 ; Field definition for FCBs +00600 +00610 ORG 0 +00620 DS 12 ;Drive code and name +00630 EXTENT: DS 2 +00640 RECSIZ: DS 2 ;Size of record (user settable) +00650 FILSIZ: DS 4 ;Size of file in bytes +00660 FDATE: DS 2 ;Date of last writing +00670 FILDIRBLK:DS 2 ;Location in directory +00680 FIRCLUS:DS 2 ;First cluster of file +00690 LSTCLUS:DS 2 ;Last cluster accessed +00700 CLUSPOS:DS 2 ;Position of last cluster accessed +00710 DIRTYFIL:DS 1 ;File has been written to if <>0 +00720 ORG 32 +00730 NR: DS 1 ;Next record +00740 RR: DS 3 ;Random record +00750 +00760 +00770 ; Description of 32-byte directory entry (same as returned by SEARCH FIRST +00780 ; and SEARCH NEXT, functions 17 and 18). +00790 ; +00800 ; Location bytes Description +00810 ; +00820 ; 0 11 File name and extension ( 0E5H if empty) +00830 ; 11 13 Zero field (for expansion) +00840 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +00850 ; 26 2 First allocation unit ( < 4080 ) +00860 ; 28 4 File size, in bytes (LSB first, 30 bits max.) +00870 ; +00880 ; The File Allocation Table uses a 12-bit entry for each allocation unit on +00890 ; the disk. These entries are packed, two for every three bytes. The contents +00900 ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +00910 ; to the base address of the Allocation Table; 3) fetching the 16-bit word at +00920 ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +00930 ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +00940 ; zero is used as an end-of-file trap in the OS and as a flag for directory +00950 ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The +00960 ; first available allocation unit is assigned entry number two, and for Drive Parameter Block +00970 +00980 ORG 0 +00990 DRVNUM: DS 1 ;Drive number +01000 SECSIZ: DS 2 ;Size of physical sector in bytes +01010 CLUSMSK:DS 1 ;Sectors/cluster - 1 +01020 CLUSSHFT:DS 1 ;Log2 of sectors/cluster +01030 FIRFAT: DS 2 ;Starting record of FATs +01040 FATCNT: DS 1 ;Number of FATs for this drive +01050 MAXENT: DS 2 ;Number of directory entries +01060 DIRSEC: ;Number of dir. sectors (init temporary) +01070 FIRREC: DS 2 ;First sector of first cluster +01080 DSKSIZ: ;Size of disk (temp used during init only) +01090 MAXCLUS:DS 2 ;Number of clusters on drive + 1 +01100 FATSIZ: DS 1 ;Number of records occupied by FAT +01110 FIRDIR: DS 2 ;Starting record of directory +01120 +01130 IF SMALLDIR +01140 FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +01150 MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +01160 FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +01170 MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries +01180 ENDIF +01190 +01200 DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +01210 FAT: ;Start of FAT +01220 DIRSIZ: ;-1=small dir. entry, else large +01230 +01240 +01250 ; BIOS entry point defintions +01260 +01270 BIOSSEG: EQU 40H +01280 ORG 0 +01290 DS 3 +01300 BIOSSTAT: DS 3 +01310 BIOSIN: DS 3 +01320 BIOSOUT: DS 3 +01330 BIOSPRINT: DS 3 +01340 BIOSAUXIN: DS 3 +01350 BIOSAUXOUT: DS 3 +01360 BIOSREAD: DS 3 +01370 BIOSWRITE: DS 3 +01380 BIOSDSKCHG: DS 3 +01390 +01400 +01410 ; Location of user registers relative user stack pointer +01420 +01430 ORG 0 +01440 AXSAVE: DS 2 +01450 BXSAVE: DS 2 +01460 CXSAVE: DS 2 +01470 DXSAVE: DS 2 +01480 SISAVE: DS 2 +01490 DISAVE: DS 2 +01500 BPSAVE: DS 2 +01510 DSSAVE: DS 2 +01520 ESSAVE: DS 2 +01530 IPSAVE: DS 2 +01540 CSSAVE: DS 2 +01550 FSAVE: DS 2 +01560 +01570 +01580 ; Start of code +01590 +01600 ORG 0 +01610 PUT 100H +01620 +01630 JMP DOSINIT +01640 +01650 ESCTAB: +01660 DB "SC" ;Copy one char +01670 DB "VN" ;Skip one char +01680 DB "TA" ;Copy to char +01690 DB "WB" ;Skip to char +01700 DB "UH" ;Copy line +01710 DB "HH" ;Kill line (no change in template) +01720 DB "RM" ;Reedit line (new template) +01730 DB "DD" ;Backspace +01740 DB "P@" ;Enter insert mode +01750 DB "QL" ;Exit insert mode +01760 DB ESCCH,ESCCH ;Escape character +01770 DB ESCCH,ESCCH ;End of table +01780 +01790 ESCTABLEN:EQU $-ESCTAB +01800 +01810 HEADER: DB 13,10,"86-DOS version 1.00" +01820 +01830 IF DSKTEST +01840 DB "D" +01850 ENDIF +01860 +01870 DB 13,10 +01880 DB "Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$" +01890 +01900 QUIT: +01910 MOV AH,0 +01920 JP SAVREGS +01930 +01940 COMMAND: ;Interrupt call entry point +01950 CMP AH,MAXCOM +01960 JBE SAVREGS +01970 BADCALL: +01980 MOV AL,0 +01990 IRET: IRET +02000 +02010 ENTRY: ;System call entry point and dispatcher +02020 POP AX ;IP from the long call at 5 +02030 POP AX ;Segment from the long call at 5 +02040 SEG CS +02050 POP [TEMP] ;IP from the CALL 5 +02060 PUSHF ;Start re-ordering the stack +02070 DI +02080 PUSH AX ;Save segment +02090 SEG CS +02100 PUSH [TEMP] ;Stack now ordered as if INT had been used +02110 CMP CL,MAXCALL ;This entry point doesn't get as many calls +02120 JA BADCALL +02130 MOV AH,CL +02140 SAVREGS: +02150 PUSH ES +02160 PUSH DS +02170 PUSH BP +02180 PUSH DI +02190 PUSH SI +02200 PUSH DX +02210 PUSH CX +02220 PUSH BX +02230 PUSH AX +02240 +02250 IF DSKTEST +02260 SEG CS +02270 MOV AX,[SPSAVE] +02280 SEG CS +02290 MOV [NSP],AX +02300 SEG CS +02310 MOV AX,[SSSAVE] +02320 SEG CS +02330 MOV [NSS],AX +02340 POP AX +02350 PUSH AX +02360 ENDIF +02370 +02380 SEG CS +02390 MOV [SPSAVE],SP +02400 SEG CS +02410 MOV [SSSAVE],SS +02420 MOV BP,SP +02430 MOV BX,[BP+CSSAVE] +02440 SEG CS +02450 MOV [CSLOC],BX +02460 MOV SP,CS +02470 MOV SS,SP +02480 MOV SP,STACK +02490 EI ;Stack OK now +02500 SEG CS +02510 MOV [FUNC],AH +02520 MOV BL,AH +02530 MOV BH,0 +02540 SHL BX +02550 UP +02560 +02570 IF DSKTEST +02580 CMP AH,12 +02590 JL SAMSTK +02600 MOV SP,TESTSTK +02610 SAMSTK: +02620 ENDIF +02630 +02640 SEG CS +02650 CALL [BX+DISPATCH] +02660 LEAVE: +02670 DI +02680 SEG CS +02690 MOV SP,[SPSAVE] +02700 SEG CS +02710 MOV SS,[SSSAVE] +02720 MOV BP,SP +02730 MOV [BP+AXSAVE],AL +02740 +02750 IF DSKTEST +02760 SEG CS +02770 MOV AX,[NSP] +02780 SEG CS +02790 MOV [SPSA ENDIF +02800 +02810 PBX +02820 POP CX +02830 POP DX +02840 POP SI +02850 POP DI +02860 POP BP +02870 POP DS +02880 POP ES +02890 IRET +02900 +02910 DISPATCH: +02920 ; Standard Functions +02930 DW ABORT ;0 +02940 DW CONIN +02950 DW CONOUT +02960 DW READER +02970 DW PUNCH +02980 DW LIST ;5 +02990 DW RAWIO +03000 DW RAWINP +03010 DW IN +03020 DW PRTBUF +03030 DW BUFIN ;10 +03040 DW CONSTAT +03050 DW VERSION +03060 DW DSKRESET +03070 DW SELDSK +03080 DW OPEN ;15 +03090 DW CLOSE +03100 DW SRCHFRST +03110 DW SRCHNXT +03120 DW DELETE +03130 DW SEQRD ;20 +03140 DW SEQWRT +03150 DW CREATE +03160 DW RENAME +03170 DW INUSE +03180 DW CURDRV ;25 +03190 DW SETDMA +03200 DW GETFATPT +03210 DW WRTPROT +03220 DW GETRDONLY +03230 DW SETATTRIB ;30 +03240 DW GETDSKPT +03250 DW USERCODE +03260 DW RNDRD +03270 DW RNDWRT +03280 DW FILESIZE ;35 +03290 DW SETRNDREC +03300 ; Extended Functions +03310 DW SETVECT +03320 DW NEWBASE +03330 DW BLKRD +03340 DW BLKWRT ;40 +03350 DW MAKEFCB +03360 +03370 VERSION: +03380 GETIO: +03390 SETIO: +03400 WRTPROT: +03410 GETRDONLY: +03420 SETATTRIB: +03430 USERCODE: +03440 MOV AL,0 +03450 RET +03460 +03470 +03480 READER: +03490 CALL BIOSAUXIN,BIOSSEG +03500 RET +03510 +03520 PUNCH: +03530 MOV AL,DL +03540 CALL BIOSAUXOUT,BIOSSEG +03550 RET +03560 +03570 +03580 UNPACK: +03590 +03600 ; Inputs: +03610 ; DS = CS +03620 ; BX = Cluster number +03630 ; BP = Base of drive parameters +03640 ; SI = Pointer to drive FAT +03650 ; Outputs: +03660 ; DI = Contents of FAT for given cluster +03670 ; Zero set means DI=0 (free cluster) +03680 ; No other registers affected. Fatal error if cluster too big. +03690 +03700 CMP BX,[BP+MAXCLUS] +03710 JA HURTFAT +03720 LEA DI,[SI+BX] +03730 SHR BX +03740 MOV DI,[DI+BX] +03750 JNC HAVCLUS +03760 SHR DI +03770 SHR DI +03780 SHR DI +03790 SHR DI +03800 STC +03810 HAVCLUS: +03820 RCL BX +03830 AND DI,0FFFH +03840 RET +03850 HURTFAT: +03860 MOV SI,BADMES +03870 CALL OUTMES +03880 JMP ERROR +03890 +03900 +03910 PACK: +03920 +03930 ; Inputs: +03940 ; DS = CS +03950 ; BX = Cluster number +03960 ; DX = Data +03970 ; SI = Pointer to drive FAT +03980 ; Outputs: +03990 ; The data is stored in the FAT at the given cluster. +04000 ; BX,DX,DI all destroyed +04010 ; No other registers affected +04020 +04030 MOV DI,BX +04040 SHR BX +04050 ADD BX,SI +04060 ADD BX,DI +04070 SHR DI +04080 MOV DI,[BX] +04090 JNC ALIGNED +04100 SHL DX +04110 SHL DX +04120 SHL DX +04130 SHL DX +04140 AND DI,0FH +04150 JP PACKIN +04160 ALIGNED: +04170 AND DI,0F000H +04180 PACKIN: +04190 OR DI,DX +04200 MOV [BX],DI +04210 RET +04220 +04230 IOCHK: +04240 MOV CX,5 ;Check rest of name but not extension +04250 CMP B,[DI],":" +04260 JNZ NOCOL +04270 INC DI ;Skip over colon +04280 DEC CX +04290 NOCOL: +04300 MOV AL," " +04310 REPE +04320 SCAB ;Make sure rest of name is blanks +04330 JNZ FILSRCH +04340 DEC BL +04350 RET +04360 +04370 GETFILE: +04380 +04390 ; Inputs: +04400 ; DS,DX point to FCB +04410 ; Function: +04420 ; Find file name in disk directory. First byte is +04430 ; drive number (0=current disk). "?" matches any +04440 ; character. +04450 ; Outputs: +04460 ; Carry set if file not found +04470 ; ELSE +04480 ; BP = Base of drive parameters +04490 ; DS = CS +04500 ; ES = CS +04510 ; BX = Pointer into directory buffer +04520 ; SI = Pointer to First Cluster field in directory entry +04530 ; [DIRBUF] has directory record with match +04540 ; [NAME1] has file name +04550 ; All other registers destroyed. +04560 +04570 CALL MOVNAME +04580 JC RET ;Bad file name? +04590 FINDNAME: +04600 MOV AX,CS +04610 MOV DS,AX +04620 MOV SI,IONAME ;List of I/O devices with file names +04630 MOV BX,0FF04H ;BL = number of devices +04640 LOOKIO: +04650 MOV DI,NAME1 +04660 MOV CX,3 ;All device names are 3 letters +04670 REPE +04680 CMPB ;Check for name in list +04690 JZ IOCHK ;If first 3 letters OK, check the rest +04700 ADD SI,CX ;Point to next device name +04710 DEC BL +04720 JNZ LOOKIO +04730 FILSRCH: ;Not a device name +04740 CALL STARTSRCH +04750 CONTSRCH: +04760 CALL GETENTRY +04770 JC RET +04780 SRCH: +04790 CMP B,[BX],0E5H +04800 JZ NEXTENT +04810 MOV SI,BX +04820 MOV DI,NAME1 +04830 MOV CX,11 +04840 WILDCRD: +04850 REPE +04860 CMPB +04870 JZ FOUND +04880 CMP B,[DI-1],"?" +04890 JZ WILDCRD +04900 NEXTENT: +04910 CALL NEXTENTRY +04920 JNC SRCH +04930 RET +04940 +04950 FOUND: +04960 IF SMALLDIR +04970 CMP B,[BP+DIRSIZ],-1 +04980 JZ RET +04990 ENDIF +05000 +05010 ADD SI,15 +05020 RET +05030 +05040 +05050 GETENTRY: +05060 +05070 ; Inputs: +05080 ; [LASTENT] has previously searched directory entry +05090 ; Function: +05100 ; Locates next sequential directory entry in preparation for search +05110 ; Outputs: +05120 ; Carry set if none +05130 ; ELSE +05140 ; AL = Current directory block +05150 ; BX = Pointer to next directory entry in [DIRBUF] +05160 ; DX = Pointer to first byte after end of DIRBUF +05170 ; [LASTENT] = New directory entry number +05180 +05190 MOV AX,[LASTENT] +05200 INC AX ;Start with next entry +05210 CMP AX,[BP+MAXENT] +05220 JAE NONE +05230 MOV [LASTENT],AX +05240 MOV CL,4 +05250 SHL AX,CL +05260 XOR DX,DX +05270 +05280 IF SMALLDIR +05290 CMP B,[BP+DIRSIZ],-1 +05300 JZ SMALENT1 +05310 ENDIF +05320 +05330 SHL AX +05340 RCL DX ;Account for overflow in last shift +05350 SMALENT1: +05360 MOV BX,[BP+SECSIZ] +05370 AND BL,255-31 ;Must be multiple of 32 +05380 DIV AX,BX +05390 MOV BX,DX ;Position within sector +05400 MOV AH,[BP+DRVNUM] ;AL=Directory sector no. +05410 CMP AX,[DIRBUFID] +05420 JZ HAVDIRBUF +05430 PUSH BX +05440 CALL DIRREAD +05450 POP BX +05460 HAVDIRBUF: +05470 MOV DX,DIRBUF +05480 ADD BX,DX +05490 ADD DX,[BP+SECSIZ] +05500 RET +05510 +05520 NEXTENTRY: +05530 +05540 ; Inputs: +05550 ; Same as outputs of GETENTRY, above +05560 ; Function: +05570 ; Update AL, BX, and [LASTENT] for next directory entry. +05580 ; Carry set if no more. +05590 +05600 MOV DI,[LASTENT] +05610 INC DI +05620 CMP DI,[BP+MAXENT] +05630 JAE NONE +05640 MOV [LASTENT],DI +05650 ADD BX,32 +05660 +05670 IF SMALLDIR +05680 CMP B,[BP+DIRSIZ],-1 +05690 JNZ BIGENT3 +05700 SUB BX,16 +05710 BIGENT3: +05720 ENDIF +05730 +05740 CMP BX,DX +05750 JB HAVIT +05760 INC AL ;Next directory sector +05770 PUSH DX ;Save limit +05780 CALL DIRREAD +05790 POP DX +05800 MOV BX,DIRBUF +05810 HAVIT: +05820 CLC +05830 RET +05840 +05850 NONE: +05860 CALL CHKDIRWRITE +05870 STC +05880 RET +05890 +05900 +05910 DELETE: ; System call 19 +05920 CALL GETFILE +05930 JC ERRET +05940 CMP BH,-1 ;Check if device name +05950 JZ ERRET ;Can't delete I/O devices +05960 DELFILE: +05970 MOV B,[DIRTYDIR],-1 +05980 MOV B,[BX],0E5H +05990 MOV BX,[SI] +06000 LEA SI,[BP+FAT] +06010 OR BX,BX +06020 JZ DELNXT +06030 CMP BX,[BP+MAXCLUS] +06040 JA DELNXT +06050 CALL RELEASE +06060 DELNXT: +06070 CALL CONTSRCH +06080 JNC DELFILE +06090 CALL FATWRT +06100 CALL CHKDIRWRITE +06110 XOR AL,AL +06120 RET +06130 +06140 +06150 RENAME: ;System call 23 +06160 CALL MOVNAME +06170 JC ERRET +06180 CMP BH,-1 ;Check if I/O device name +06190 JZ ERRET ;If so, can't rename it +06200 ADD SI,5 +06210 MOV DI,NAME2 +06220 CALL LODNAME +06230 CALL FINDNAME +06240 JC ERRET +06250 RENFIL: +06260 MOV B,[DIRTYDIR],-1 +06270 MOV DI,BX +06280 MOV SI,NAME2 +06290 MOV CX,11 +06300 NEWNAM: +06310 LODB +06320 CMP AL,"?" +06330 JZ NOCHG +06340 MOV [DI],AL +06350 NOCHG: +06360 INC DI +06370 LOOP NEWNAM +06380 CALL CONTSRCH +06390 JNC RENFIL +06400 CALL CHKDIRWRITE +06410 XOR AL,AL +06420 RET +06430 +06440 ERRET: +06450 MOV AL,-1 +06460 RET +06470 +06480 +06490 MOVNAME: +06500 +06510 ; Inputs: +06520 ; DS, DX point to FCB +06530 ; Outputs: +06540 ; ES = CS +06550 ; If file name OK: +06560 ; BP has base of driver parameters +06570 ; [NAME1] has name in upper case +06580 ; All registers except DX destroyed +06590 ; Carry set if bad file name or drive +06600 +06610 MOV AX,CS +06620 MOV ES,AX +06630 MOV DI,NAME1 +06640 MOV SI,DX +06650 LODB +06660 CALL GETBP +06670 JB RET +06680 LODNAME: +06690 ; This entry point copies a file name from DS,SI +06700 ; to ES,DI converting to upper case. +06710 MOV CX,11 +06720 MOVCHK: +06730 LODB +06740 AND AL,7FH +06750 CMP AL,60H +06760 JLE CASEOK +06770 AND AL,5FH +06780 CASEOK: +06790 CMP AL,20H +06800 JC RET +06810 STOB +06820 LOOP MOVCHK +06830 RET +06840 +06850 GETBP: +06860 SEG CS +06870 CMP [NUMDRV],AL +06880 JC RET +06890 CBW +06900 XCHG BP,AX +06910 SHL BP +06920 MOV BP,[BP+CURDRVPT] +06930 RET +06940 +06950 +06960 OPEN: ;System call 15 +06970 PUSH DX +06980 PUSH DS +06990 CALL GETFILE +07000 DOOPEN: +07010 ; Enter here to perform OPEN on file already found +07020 ; in directory. DS=ES=CS, BX points to directory +07030 ; entry in DIRBUF, SI points to First Cluster field, and +07040 ; the top of the stack has the address and segment +07050 ; of the FCB to be opened. This entry point is used +07060 ; by CREATE. +07070 POP ES +07080 POP DI +07090 JC ERRET +07100 CMP BH,-1 ;Check if file is I/O device +07110 JZ OPENDEV ;Special handler if so +07120 MOV AL,[BP+DRVNUM] +07130 INC AL +07140 STOB +07150 ADD DI,11 ;Point to extent field +07160 XOR AX,AX +07170 STOW ;Set extent field to 0 +07180 MOV AX,128 ;Default record size +07190 STOW ;Set record size +07200 LODW ;Get starting cluster +07210 MOV DX,AX ;Save it for the moment +07220 MOVW ;Transfer size to FCB +07230 MOVW +07240 MOV AX,[SI-8] ;Get date +07250 +07260 IF SMALLDIR +07270 CMP B,[BP+DIRSIZ],-1 +07280 JNZ BIGENT10 +07290 SEG ES +07300 MOV [DI-1],0 +07310 XOR AX,AX ;Date not available in small entry +07320 BIGENT10: +07330 ENDIF +07340 +07350 STOW ;Save date in FCB +07360 MOV AX,[LASTENT] +07370 STOW ;directory location +07380 MOV AX,DX ;Restore starting cluster +07390 STOW ; first cluster +07400 STOW ; last cluster accessed +07410 XOR AX,AX +07420 STOW ; position of last cluster +07430 STOB ; dirty flag +07440 RET +07450 +07460 OPENDEV: +07470 SEG ES +07480 MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag +07490 XOR AL,AL +07500 RET +07510 +07520 +07530 STARTSRCH: +07540 MOV [LASTENT],-1 +07550 FATREAD: +07560 +07570 ; Inputs: +07580 ; DS = CS +07590 ; BP = Base of drive parameters +07600 ; Function: +07610 ; If disk may have been changed, FAT is read in and buffers are +07620 ; flagged invalid. If not, no action is taken. +07630 ; Outputs: +07640 ; AL = 0 +07650 ; BP unchanged +07660 ; All other registers destroyed +07670 +07680 MOV AL,[BP+DRVNUM] +07690 CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say +07700 MOV AL,[BP+DRVNUM] +07710 OR AH,[BP+DIRTYFAT] +07720 JS NEWDSK ;If either say new disk, then it's so +07730 DEC AH ;Check for AH=1 (disk not changed) +07740 JZ RET +07750 MOV AH,1 +07760 CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? +07770 JZ RET ;If so, disk has not been changed +07780 NEWDSK: +07790 CMP AL,[BUFDRVNO] ;See if buffer is for this drive +07800 JNZ BUFOK ;If not, don't touch it +07810 MOV [BUFSECNO],0 ;Flag buffers invalid +07820 MOV [BUFDRVNO],00FFH +07830 BUFOK: +07840 MOV [DIRBUFID],-1 +07850 CALL FIGFAT +07860 NEXTFAT: +07870 PUSH DX +07880 PUSH CX +07890 PUSH BX +07900 PUSH AX +07910 CALL DREAD +07920 OR AL,AL +07930 POP AX +07940 POP BX +07950 POP CX +07960 POP DX +07970 JNZ BADFAT +07980 +07990 IF SMALLDIR +08000 MOV DL,AL +08010 LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries +08020 CMP B,[BP+DIRSIZ],-1 +08030 JZ SETSIZ +08040 ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +08050 SETSIZ: +08060 LODW +08070 MOV [BP+FIRREC],AX +08080 LODW +08090 MOV [BP+MAXCLUS],AX +08100 MOV AL,DL +08110 ENDIF +08120 +08130 SUB AL,[BP+FATCNT] +08140 JZ RET +08150 NEG AL +08160 ;{Insert error code here. AL=number of bad fats. +08170 ;Since one good FAT was read, should include option +08180 ;to rewrite all FATs.} +08190 JMP FATWRT +08200 +08210 BADFAT: +08220 ADD DX,CX +08230 DEC AL +08240 JNZ NEXTFAT +08250 POP BP +08260 ;{Insert error code here. All FATs on drive are bad.} +08270 MOV SI,BADFATMES +08280 CALL HARDERR +08290 JP FATREAD +08300 +08310 OKRET1: +08320 MOV AL,0 +08330 RET +08340 +08350 CLOSE: ;System call 16 +08360 MOV DI,DX +08370 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +08380 JZ OKRET1 ;Can't close I/O device +08390 TEST B,[DI+DIRTYFIL],-1 +08400 JZ OKRET1 ;If not written to, do nothing +08410 MOV AL,[DI] ;Get drive number +08420 CALL GETBP ;Get base of drive parameters +08430 JC BADCLOSEJ +08440 MOV AL,[BP+DRVNUM] +08450 MOV AH,1 ;Look for dirty buffer +08460 SEG CS +08470 CMP AX,[BUFDRVNO] +08480 JNZ FNDDIR +08490 ;Write back dirty buffer if on same drive +08500 PUSH DX +08510 PUSH DS +08520 PUSH CS +08530 POP DS +08540 MOV B,[DIRTYBUF],0 +08550 MOV BX,[BUFFER] +08560 MOV CX,1 +08570 MOV DX,[BUFSECNO] +08580 CALL DWRITE +08590 POP DS +08600 POP DX +08610 FNDDIR: +08620 PUSH DX +08630 PUSH DS +08640 CALL GETFILE +08650 POP ES +08660 POP DI +08670 BADCLOSEJ: +08680 JC BADCLOSE +08690 MOV AX,[LASTENT] +08700 SEG ES +08710 CMP AX,[DI+FILDIRBLK] +08720 JNZ BADCLOSE +08730 SEG ES +08740 MOV CX,[DI+FIRCLUS] +08750 MOV [SI],CX +08760 SEG ES +08770 MOV DX,[DI+FILSIZ] +08780 MOV [SI+2],DX +08790 SEG ES +08800 MOV DX,[DI+FILSIZ+2] +08810 +08820 IF SMALLDIR +08830 CMP B,[BP+DIRSIZ],-1 +08840 JNZ BIGENT11 +08850 MOV [SI+4],DL +08860 JP SMALLENT2 +08870 BIGENT11: +08880 ENDIF +08890 +08900 MOV [SI+4],DX +08910 SEG ES +08920 MOV DX,[DI+FDATE] +08930 MOV [SI-2],DX +08940 SMALLENT2: +08950 CALL DIRWRITE +08960 +08970 CHKFATWRT: +08980 ; Do FATWRT only if FAT is dirty +08990 +09000 CMP B,[BP+DIRTYFAT],1 +09010 JNZ OKRET +09020 +09030 FATWRT: +09040 +09050 ; Inputs: +09060 ; DS = CS +09070 ; BP = Base of drive parameter table +09080 ; Function: +09090 ; Write the FAT back to disk and reset FAT +09100 ; dirty bit. +09110 ; Outputs: +09120 ; AL = 0 +09130 ; BP unchanged +09140 ; All other registers destroyed +09150 +09160 MOV B,[BP+DIRTYFAT],0 +09170 CALL FIGFAT +09180 EACHFAT: +09190 PUSH DX +09200 PUSH CX +09210 PUSH BX +09220 PUSH AX +09230 CALL DWRITE +09240 POP AX +09250 POP BX +09260 POP CX +09270 POP DX +09280 ADD DX,CX +09290 DEC AL +09300 JNZ EACHFAT +09310 OKRET: +09320 MOV AL,0 +09330 RET +09340 +09350 BADCLOSE: +09360 MOV B,[BP+DIRTYFAT],0 +09370 MOV AL,-1 +09380 RET +09390 +09400 +09410 FIGFAT: +09420 ; Loads registers with values needed to read or +09430 ; write a FAT. +09440 MOV AL,[BP+FATCNT] +09450 LEA BX,[BP+FAT] +09460 MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT +09470 MOV CH,0 +09480 MOV DX,[BP+FIRFAT] ;Record number of start of FATs +09490 RET +09500 +09510 +09520 DIRCOMP: +09530 ; Prepare registers for directory read or write +09540 CBW +09550 ADD AX,[BP+FIRDIR] +09560 MOV DX,AX +09570 MOV BX,DIRBUF +09580 MOV CX,1 +09590 RET +09600 +09610 +09620 CREATE: ;System call 22 +09630 CALL MOVNAME +09640 JC ERRET3 +09650 MOV DI,NAME1 +09660 MOV CX,11 +09670 MOV AL,"?" +09680 REPNE +09690 SCAB +09700 JZ ERRET3 +09710 PUSH DX +09720 PUSH DS +09730 CALL FINDNAME +09740 JNC EXISTENT +09750 CALL STARTSRCH +09760 CALL GETENTRY +09770 LOOKFRE: +09780 CMP B,[BX],0E5H +09790 JZ FREESPOT +09800 CALL NEXTENTRY +09810 JNC LOOKFRE +09820 POP DS +09830 POP DX +09840 ERRET3: +09850 MOV AL,-1 +09860 RET +09870 +09880 EXISTENT: +09890 CMP BH,-1 ;Check if file is I/O device +09900 JZ OPENJMP ;If so, no action +09910 XOR CX,CX +09920 MOV [SI+2],CX +09930 MOV AX,[DATE] +09940 +09950 IF SMALLDIR +09960 MOV [SI+4],CL +09970 CMP B,[BP+DIRSIZ],-1 +09980 JZ SMLENT +09990 MOV [SI+5],CL +10000 MOV [SI-2],AX +10010 SMLENT: +10020 ENDIF +10030 +10040 IF 1-SMALLDIR +10050 MOV [SI+4],CX +10060 MOV [SI-2],AX +10070 ENDIF +10080 +10090 XCHG CX,[SI] +10100 PUSH SI +10110 PUSH BX +10120 JCXZ WRTBACK +10130 CMP CX,[BP+MAXCLUS] +10140 JA WRTBACK +10150 MOV BX,CX +10160 LEA SI,[BP+FAT] +10170 CALL RELEASE +10180 CALL FATWRT +10190 JP WRTBACK +10200 +10210 FREESPOT: +10220 MOV DI,BX +10230 MOV SI,NAME1 +10240 MOV CX,5 +10250 MOVB +10260 REP +10270 MOVW +10280 XOR AX,AX +10290 +10300 IF SMALLDIR +10310 CMP B,[BP+DIRSIZ],-1 +10320 JNZ BIGENT4 +10330 PUSH DI +10340 MOV CL,5 +10350 JP SMALLENT +10360 BIGENT4: +10370 ENDIF +10380 +10390 MOV CL,13 +10400 REP +10410 STOB +10420 MOV AX,[DATE] +10430 STOW +10440 XOR AX,AX +10450 PUSH DI +10460 MOV CL,6 +10470 SMALLENT: +10480 REP +10490 STOB +10500 PUSH BX +10510 WRTBACK: +10520 CALL DIRWRITE +10530 POP BX +10540 POP SI +10550 OPENJMP: +10560 CLC ;Clear carry so OPEN won't fail +10570 JMP DOOPEN +10580 +10590 +10600 DIRREAD: +10610 +10620 ; Inputs: +10630 ; DS = CS +10640 ; AL = Directory block number +10650 ; BP = Base of drive parameters +10660 ; Function: +10670 ; Read the directory block into DIRBUF. +10680 ; Outputs: +10690 ; AX,BP unchanged +10700 ; All other registers destroyed. +10710 +10720 PUSH AX +10730 CALL CHKDIRWRITE +10740 POP AX +10750 PUSH AX +10760 MOV AH,[BP+DRVNUM] +10770 MOV [DIRBUFID],AX +10780 CALL DIRCOMP +10790 CALL DREAD +10800 POP AX +10810 RET +10820 +10830 +10840 DREAD: +10850 +10860 ; Inputs: +10870 ; BX,DS = Transfer address +10880 ; CX = Number of sectors +10890 ; DX = Absolute record number +10900 ; BP = Base of drive parameters +10910 ; Function: +10920 ; Calls BIOS to perform disk read. If BIOS reports +10930 ; errors, will call HARDERR for further action. +10940 ; Outputs: +10950 ; AL = 0 if no error, otherwise non-zero +10960 ; BP preserved. All other registers destroyed. +10970 +10980 MOV AL,[BP+DRVNUM] +10990 PUSH BP +11000 PUSH BX +11010 PUSH CX +11020 PUSH DX +11030 CALL BIOSREAD,BIOSSEG +11040 POP DX +11050 POP DI +11060 POP BX +11070 POP BP +11080 JC HARDREAD +11090 XOR AL,AL +11100 RET +11110 +11120 HARDREAD: +11130 MOV SI,RDERRMES +11140 CALL HARDERR +11150 JP DREAD +11160 +11170 +11180 CHKDIRWRITE: +11190 TEST B,[DIRTYDIR],-1 +11200 JZ RET +11210 +11220 DIRWRITE: +11230 +11240 ; Inputs: +11250 ; DS = CS +11260 ; AL = Directory block number +11270 ; BP = Base of drive parameters +11280 ; Function: +11290 ; Write the directory block into DIRBUF. +11300 ; Outputs: +11310 ; BP unchanged +11320 ; All other registers destroyed. +11330 +11340 MOV B,[DIRTYDIR],0 +11350 MOV AL,[DIRBUFID] +11360 CALL DIRCOMP +11370 +11380 +11390 DWRITE: +11400 +11410 ; Inputs: +11420 ; BX,DS = Transfer address +11430 ; CX = Number of sectors +11440 ; DX = Absolute record number +11450 ; BP = Base of drive parameters +11460 ; Function: +11470 ; Calls BIOS to perform disk write. If BIOS reports +11480 ; errors, will call HARDERR for further action. +11490 ; Outputs: +11500 ; AL = 0 if no error, otherwise non-zero +11510 ; BP preserved. All other registers destroyed. +11520 +11530 MOV AL,[BP+DRVNUM] +11540 WRTDRV: +11550 PUSH AX +11560 PUSH BP +11570 PUSH BX +11580 PUSH CX +11590 PUSH DX +11600 CALL BIOSWRITE,BIOSSEG +11610 POP DX +11620 POP DI +11630 POP BX +11640 POP BP +11650 POP AX +11660 JC HARDWRITE +11670 XOR AL,AL +11680 RET +11690 HARDWRITE: +11700 MOV SI,WRTERRMES +11710 CALL HARDERR +11720 JP WRTDRV +11730 +11740 +11750 HARDERR: +11760 SUB DI,CX +11770 ADD DX,DI +11780 CALL SHFTDI7 +11790 ADD BX,DI +11800 MOV AH,AL ;Save drive number +11810 CALL OUTMES +11820 GETINSTR: +11830 CALL IN +11840 OR AL,20H +11850 CMP AL,"a" +11860 JZ ERROR +11870 CMP AL,"r" +11880 JZ RETRY +11890 CMP AL,"i" +11900 JZ IGNORE +11910 CMP AL,"c" +11920 JNZ GETINSTR +11930 CONTINUE: +11940 POP AX +11950 MOV AL,1 +11960 RET +11970 IGNORE: +11980 POP AX +11990 MOV AL,0 +12000 RET +12010 RETRY: +12020 MOV AL,AH ;Restore drive number +12030 RET +12040 +12050 +12060 ABORT: +12070 SEG CS +12080 MOV DS,[CSLOC] +12090 XOR AX,AX +12100 MOV ES,AX +12110 MOV SI,SAVEXIT +12120 MOV DI,EXIT +12130 MOVW +12140 MOVW +12150 MOVW +12160 MOVW +12170 ERROR: +12180 MOV AX,CS +12190 MOV DS,AX +12200 MOV ES,AX +12210 CALL WRTFATS +12220 XOR AX,AX +12230 DI +12240 MOV SS,[SSSAVE] +12250 MOV SP,[SPSAVE] +12260 MOV DS,AX +12270 MOV SI,EXIT +12280 MOV DI,EXITHOLD +12290 MOVW +12300 MOVW +12310 POP AX +12320 POP BX +12330 POP CX +12340 POP DX +12350 POP SI +12360 POP DI +12370 POP BP +12380 POP DS +12390 POP ES +12400 EI ;Stack OK now +12410 SEG CS +12420 JMP L,[EXITHOLD] +12430 +12440 +12450 SEQRD: ;System call 20 +12460 CALL GETREC +12470 CALL LOAD +12480 JP FINSEQ +12490 +12500 SEQWRT: ;System call 21 +12510 CALL GETREC +12520 CALL STORE +12530 FINSEQ: +12540 JCXZ SETNREX +12550 ADD AX,1 +12560 ADC DX,0 +12570 JP SETNREX +12580 +12590 RNDRD: ;System call 33 +12600 CALL GETRRPOS1 +12610 CALL LOAD +12620 JP FINRND +12630 +12640 RNDWRT: ;System call 34 +12650 CALL GETRRPOS1 +12660 CALL STORE +12670 JP FINRND +12680 +12690 BLKRD: ;System call 39 +12700 CALL GETRRPOS +12710 CALL LOAD +12720 JP FINBLK +12730 +12740 BLKWRT: ;System call 40 +12750 CALL GETRRPOS +12760 CALL STORE +12770 FINBLK: +12780 LDS SI,[SPSAVE] +12790 MOV [SI+CXSAVE],CX +12800 JCXZ FINRND +12810 ADD AX,1 +12820 ADC DX,0 +12830 FINRND: +12840 SEG ES +12850 MOV [DI+RR],AX +12860 SEG ES +12870 MOV [DI+RR+2],DL +12880 OR DH,DH +12890 JZ SETNREX +12900 SEG ES +12910 MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +12920 SETNREX: +12930 MOV CX,AX +12940 AND AL,7FH +12950 SEG ES +12960 MOV [DI+NR],AL +12970 AND CL,80H +12980 SHL CX +12990 RCL DX +13000 MOV AL,CH +13010 MOV AH,DL +13020 SEG ES +13030 MOV [DI+EXTENT],AX +13040 SEG CS +13050 MOV AL,[DSKERR] +13060 RET +13070 +13080 GETRRPOS1: +13090 MOV CX,1 +13100 GETRRPOS: +13110 MOV DI,DX +13120 MOV AX,[DI+RR] +13130 MOV DX,[DI+RR+2] +13140 RET +13150 +13160 NOFILERR: +13170 XOR CX,CX +13180 MOV B,[DSKERR],-2 +13190 POP BX +13200 RET +13210 +13220 SETUP: +13230 +13240 ; Inputs: +13250 ; DS:DI point to FCB +13260 ; DX:AX = Record position in file of disk transfer +13270 ; CX = Record count +13280 ; Outputs: +13290 ; DS = CS +13300 ; ES:DI point to FCB +13310 ; CX = No. of bytes to transfer +13320 ; BP = Base of drive parameters +13330 ; SI = FAT pointer +13340 ; [RECCNT] = Record count +13350 ; [RECPOS] = Record position in file +13360 ; [FCB] = DI +13370 ; [NEXTADD] = Displacement of disk transfer within segment +13380 ; [SECPOS] = Position of first sector +13390 ; [BYTPOS] = Byte position in file +13400 ; [BYTSECPOS] = Byte position in first sector +13410 ; [CLUSNUM] = First cluster +13420 ; [SECCLUSPOS] = Sector within first cluster +13430 ; [DSKERR] = 0 (no errors yet) +13440 ; [TRANS] = 0 (No transfers yet) +13450 ; If SETUP detects no records will be transfered, it returns 1 level up +13460 ; with CX = 0. +13470 +13480 PUSH AX +13490 MOV AL,[DI] +13500 MOV SI,[DI+RECSIZ] +13510 OR SI,SI +13520 JNZ HAVRECSIZ +13530 MOV SI,128 +13540 MOV [DI+RECSIZ],SI +13550 HAVRECSIZ: +13560 MOV BX,DS +13570 MOV ES,BX +13580 MOV BX,CS +13590 MOV DS,BX +13600 CALL GETBP +13610 POP AX +13620 JC NOFILERR +13630 CMP SI,64 ;Check if highest byte of RECPOS is significant +13640 JB SMALREC +13650 MOV DH,0 ;Ignore MSB if record >= 64 bytes +13660 SMALREC: +13670 MOV [RECCNT],CX +13680 MOV [RECPOS],AX +13690 MOV [RECPOS+2],DX +13700 MOV [FCB],DI +13710 MOV BX,[DMAADD] +13720 MOV [NEXTADD],BX +13730 MOV B,[DSKERR],0 +13740 MOV B,[TRANS],0 +13750 MOV BX,DX +13760 MUL AX,SI +13770 MOV [BYTPOS],AX +13780 PUSH DX +13790 MOV AX,BX +13800 MUL AX,SI +13810 POP BX +13820 ADD AX,BX +13830 ADC DX,0 ;Ripple carry +13840 JNZ EOFERR +13850 MOV [BYTPOS+2],AX +13860 MOV DX,AX +13870 MOV AX,[BYTPOS] +13880 DIV AX,[BP+SECSIZ] +13890 MOV [SECPOS],AX +13900 MOV [BYTSECPOS],DX +13910 MOV DX,AX +13920 AND AL,[BP+CLUSMSK] +13930 MOV [SECCLUSPOS],AL +13940 MOV AX,CX ;Record count +13950 MOV CL,[BP+CLUSSHFT] +13960 SHR DX,CL +13970 MOV [CLUSNUM],DX +13980 MUL AX,SI ;Multiply by bytes per record +13990 MOV CX,AX +14000 ADD AX,[DMAADD] ;See if it will fit in one segment +14010 ADC DX,0 +14020 JZ OK ;Must stay within 64K +14030 MOV AX,[DMAADD] +14040 NEG AX ;Amount of room left in segment +14050 XOR DX,DX +14060 DIV AX,SI ;How many records will fit? +14070 MUL AX,SI ;Translate that back into bytes +14080 MOV B,[DSKERR],2 ;Flag that trimming took place +14090 MOV CX,AX +14100 JCXZ NOROOM +14110 OK: +14120 LEA SI,[BP+FAT] +14130 RET +14140 +14150 EOFERR: +14160 MOV B,[DSKERR],1 +14170 XOR CX,CX +14180 NOROOM: +14190 POP BX ;Kill return address +14200 RET +14210 +14220 BREAKDOWN: +14230 +14240 ;Inputs: +14250 ; DS = CS +14260 ; CX = Length of disk transfer in bytes +14270 ; BP = Base of drive parameters +14280 ; [BYTSECPOS] = Byte position witin first sector +14290 ;Outputs: +14300 ; [BYTCNT1] = Bytes to transfer in first sector +14310 ; [SECCNT] = No. of whole sectors to transfer +14320 ; [BYTCNT2] = Bytes to transfer in last sector +14330 ;AX, BX, DX destroyed. No other registers affected. +14340 +14350 MOV AX,[BYTSECPOS] +14360 MOV BX,CX +14370 OR AX,AX +14380 JZ SAVFIR ;Partial first sector? +14390 SUB AX,[BP+SECSIZ] +14400 NEG AX ;Max number of bytes left in first sector +14410 SUB BX,AX ;Subtract from total length +14420 JAE SAVFIR +14430 ADD AX,BX ;Don't use all of the rest of the sector +14440 XOR BX,BX ;And no bytes are left +14450 SAVFIR: +14460 MOV [BYTCNT1],AX +14470 MOV AX,BX +14480 XOR DX,DX +14490 DIV AX,[BP+SECSIZ] ;How many whole sectors? +14500 MOV [SECCNT],AX +14510 MOV [BYTCNT2],DX ;Bytes remaining for last sector +14520 RET +14530 +14540 +14550 FNDCLUS: +14560 +14570 ; Inputs: +14580 ; DS = CS +14590 ; CX = No. of clusters to skip +14600 ; BP = Base of drive parameters +14610 ; SI = FAT pointer +14620 ; ES:DI point to FCB +14630 ; Outputs: +14640 ; BX = Last cluster skipped to +14650 ; CX = No. of clusters remaining (0 unless EOF) +14660 ; DX = Position of last cluster +14670 ; DI destroyed. No other registers affected. +14680 +14690 SEG ES +14700 MOV BX,[DI+LSTCLUS] +14710 SEG ES +14720 MOV DX,[DI+CLUSPOS] +14730 OR BX,BX +14740 JZ NOCLUS +14750 SUB CX,DX +14760 JNB FINDIT +14770 ADD CX,DX +14780 XOR DX,DX +14790 SEG ES +14800 MOV BX,[DI+FIRCLUS] +14810 FINDIT: +14820 JCXZ RET +14830 SKPCLP: +14840 CALL UNPACK +14850 CMP DI,0FF8H +14860 JAE RET +14870 XCHG BX,DI +14880 INC DX +14890 LOOP SKPCLP +14900 RET +14910 NOCLUS: +14920 INC CX +14930 DEC DX +14940 RET +14950 +14960 +14970 BUFSEC: +14980 ; Inputs: +14990 ; AL = 0 if buffer must be read, 1 if no pre-read needed +15000 ; BP = Base of drive parameters +15010 ; [CLUSNUM] = Physical cluster number +15020 ; [SECCLUSPOS] = Sector position of transfer within cluster +15030 ; [BYTCNT1] = Size of transfer +15040 ; Function: +15050 ; Insure specified sector is in buffer, flushing buffer before +15060 ; read if necessary. +15070 ; Outputs: +15080 ; SI = Pointer to buffer +15090 ; DI = Pointer to transfer address +15100 ; CX = Number of bytes +15110 ; [NEXTADD] updated +15120 ; [TRANS] set to indicate a transfer will occur +15130 +15140 MOV DX,[CLUSNUM] +15150 MOV BL,[SECCLUSPOS] +15160 CALL FIGREC +15170 OR AL,AL +15180 JNZ SETBUF +15190 CMP DX,[BUFSECNO] +15200 JNZ GETSEC +15210 MOV AL,[BUFDRVNO] +15220 CMP AL,[BP+DRVNUM] +15230 JZ FINBUF ;Already have it? +15240 GETSEC: +15250 TEST B,[DIRTYBUF],-1 +15260 JZ RDSEC +15270 PUSH DX +15280 MOV AL,[BUFDRVNO] +15290 MOV BX,[BUFFER] +15300 MOV CX,1 +15310 MOV DX,[BUFSECNO] +15320 CALL WRTDRV +15330 POP DX +15340 RDSEC: +15350 MOV BX,[BUFFER] +15360 MOV CX,1 +15370 PUSH DX +15380 CALL DREAD +15390 POP DX +15400 SETBUF: +15410 MOV [BUFSECNO],DX +15420 MOV AL,[BP+DRVNUM] +15430 MOV AH,0 +15440 MOV [BUFDRVNO],AX +15450 FINBUF: +15460 MOV B,[TRANS],1 ;A transfer is taking place +15470 MOV DI,[NEXTADD] +15480 MOV SI,DI +15490 MOV CX,[BYTCNT1] +15500 ADD SI,CX +15510 MOV [NEXTADD],SI +15520 MOV SI,[BUFFER] +15530 ADD SI,[BYTSECPOS] +15540 RET +15550 +15560 BUFRD: +15570 XOR AL,AL ;Pre-read necessary +15580 CALL BUFSEC +15590 PUSH ES +15600 MOV ES,[DMAADD+2] +15610 SHR CX +15620 JNC EVENRD +15630 MOVB +15640 EVENRD: +15650 REP +15660 MOVW +15670 POP ES +15680 RET +15690 +15700 BUFWRT: +15710 MOV AX,[SECPOS] +15720 INC AX ;Set for next sector +15730 MOV [SECPOS],AX +15740 CMP AX,[VALSEC] ;Has sector been written before? +15750 MOV AL,1 +15760 JA NOREAD ;Skip preread if SECPOS>VALSEC +15770 MOV AL,0 +15780 NOREAD: +15790 CALL BUFSEC +15800 XCHG DI,SI +15810 PUSH DS +15820 PUSH ES +15830 PUSH CS +15840 POP ES +15850 MOV DS,[DMAADD+2] +15860 SHR CX +15870 JNC EVENWRT +15880 MOVB +15890 EVENWRT: +15900 REP +15910 MOVW +15920 POP ES +15930 POP DS +15940 MOV B,[DIRTYBUF],1 +15950 RET +15960 +15970 NEXTSEC: +15980 TEST B,[TRANS],-1 +15990 JZ CLRET +16000 MOV AL,[SECCLUSPOS] +16010 INC AL +16020 CMP AL,[BP+CLUSMSK] +16030 JBE SAVPOS +16040 MOV BX,[CLUSNUM] +16050 CMP BX,0FF8H +16060 JAE NONEXT +16070 LEA SI,[BP+FAT] +16080 CALL UNPACK +16090 MOV [CLUSNUM],DI +16100 INC [LASTPOS] +16110 MOV AL,0 +16120 SAVPOS: +16130 MOV [SECCLUSPOS],AL +16140 CLRET: +16150 CLC +16160 RET +16170 NONEXT: +16180 STC +16190 RET +16200 +16210 TRANBUF: +16220 LODB +16230 STOB +16240 CMP AL,13 ;Check for carriage return +16250 JNZ NORMCH +16260 MOV [SI],10 +16270 NORMCH: +16280 CMP AL,10 +16290 LOOPNZ TRANBUF +16300 JNZ ENDRDCON +16310 CALL OUT ;Transmit linefeed +16320 XOR SI,SI +16330 OR CX,CX +16340 JNZ GETBUF +16350 OR AL,1 ;Clear zero flag--not end of file +16360 ENDRDCON: +16370 MOV [CONTPOS],SI +16380 ENDRDDEV: +16390 MOV [NEXTADD],DI +16400 POP ES +16410 JNZ SETFCBJ ;Zero set if Ctrl-Z found in input +16420 MOV DI,[FCB] +16430 SEG ES +16440 OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +16450 SETFCBJ: +16460 JMP SETFCB +16470 +16480 READDEV: +16490 PUSH ES +16500 LES DI,[DMAADD] +16510 OR BL,BL +16520 JZ READCON +16530 DEC BL +16540 JNZ ENDRDDEV +16550 READAUX: +16560 CALL BIOSAUXIN,BIOSSEG +16570 STOB +16580 CMP AL,1AH +16590 LOOPNZ READAUX +16600 JP ENDRDDEV +16610 +16620 READCON: +16630 PUSH CS +16640 POP DS +16650 MOV SI,[CONTPOS] +16660 OR SI,SI +16670 JNZ TRANBUF +16680 CMP B,[CONBUF],128 +16690 JZ GETBUF +16700 MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +16710 GETBUF: +16720 PUSH CX +16730 PUSH ES +16740 PUSH DI +16750 MOV DX,CONBUF +16760 CALL BUFIN ;Get input buffer +16770 POP DI +16780 POP ES +16790 POP CX +16800 MOV SI,CONBUF+2 +16810 CMP B,[SI],1AH ;Check for Ctrl-Z in first character +16820 JNZ TRANBUF +16830 MOV AL,1AH +16840 STOB +16850 MOV AL,10 +16860 CALL OUT ;Send linefeed +16870 XOR SI,SI +16880 JP ENDRDCON +16890 +16900 RDERR: +16910 XOR CX,CX +16920 JMP WRTERR +16930 +16940 RDLASTJ:JMP RDLAST +16950 +16960 LOAD: +16970 +16980 ; Inputs: +16990 ; DS:DI point to FCB +17000 ; DX:AX = Position in file to read +17010 ; CX = No. of records to read +17020 ; Outputs: +17030 ; DX:AX = Position of last record read +17040 ; CX = No. of bytes read +17050 ; ES:DI point to FCB +17060 ; LSTCLUS, CLUSPOS fields in FCB set +17070 +17080 CALL SETUP +17090 SEG ES +17100 MOV BX,[DI+FILDIRBLK] +17110 CMP BH,-1 ;Check for named device I/O +17120 JZ READDEV +17130 SEG ES +17140 MOV AX,[DI+FILSIZ] +17150 SEG ES +17160 MOV BX,[DI+FILSIZ+2] +17170 SUB AX,[BYTPOS] +17180 SBC BX,[BYTPOS+2] +17190 JB RDERR +17200 JNZ ENUF +17210 OR AX,AX +17220 JZ RDERR +17230 CMP AX,CX +17240 JAE ENUF +17250 MOV CX,AX +17260 ENUF: +17270 CALL BREAKDOWN +17280 MOV CX,[CLUSNUM] +17290 CALL FNDCLUS +17300 OR CX,CX +17310 JNZ RDERR +17320 MOV [LASTPOS],DX +17330 MOV [CLUSNUM],BX +17340 CMP [BYTCNT1],0 +17350 JZ RDMID +17360 CALL BUFRD +17370 RDMID: +17380 CMP [SECCNT],0 +17390 JZ RDLASTJ +17400 CALL NEXTSEC +17410 JC SETFCB +17420 MOV B,[TRANS],1 ;A transfer is taking place +17430 ONSEC: +17440 MOV DL,[SECCLUSPOS] +17450 MOV CX,[SECCNT] +17460 MOV BX,[CLUSNUM] +17470 RDLP: +17480 CALL OPTIMIZE +17490 PUSH DI +17500 PUSH AX +17510 PUSH DS +17520 MOV DS,[DMAADD+2] +17530 CALL DREAD +17540 POP DS +17550 POP CX +17560 POP BX +17570 JCXZ RDLAST +17580 CMP BX,0FF8H +17590 JAE SETFCB +17600 MOV DL,0 +17610 INC [LASTPOS] ;We'll be using next cluster +17620 JP RDLP +17630 +17640 SETFCB: +17650 MOV SI,[FCB] +17660 MOV AX,[NEXTADD] +17670 MOV DI,AX +17680 SUB AX,[DMAADD] ;Number of bytes transfered +17690 XOR DX,DX +17700 SEG ES +17710 MOV CX,[SI+RECSIZ] +17720 DIV AX,CX ;Number of records +17730 CMP AX,[RECCNT] ;Check if all records transferred +17740 JZ FULLREC +17750 MOV B,[DSKERR],1 +17760 OR DX,DX +17770 JZ FULLREC ;If remainder 0, then full record transfered +17780 MOV B,[DSKERR],3 ;Flag partial last record +17790 SUB CX,DX ;Bytes left in last record +17800 PUSH ES +17810 MOV ES,[DMAADD+2] +17820 XCHG AX,BX ;Save the record count temporarily +17830 XOR AX,AX ;Fill with zeros +17840 SHR CX +17850 JNC EVENFIL +17860 STOB +17870 EVENFIL: +17880 REP +17890 STOW +17900 XCHG AX,BX ;Restore record count to AX +17910 POP ES +17920 INC AX ;Add last (partial) record to total +17930 FULLREC: +17940 MOV CX,AX +17950 MOV DI,SI ;ES:DI point to FCB +17960 SETCLUS: +17970 MOV AX,[CLUSNUM] +17980 SEG ES +17990 MOV [DI+LSTCLUS],AX +18000 MOV AX,[LASTPOS] +18010 SEG ES +18020 MOV [DI+CLUSPOS],AX +18030 ADDREC: +18040 MOV AX,[RECPOS] +18050 MOV DX,[RECPOS+2] +18060 DEC CX +18070 ADD AX,CX ;Update current record position +18080 ADC DX,0 +18090 INC CX +18100 RET +18110 +18120 RDLAST: +18130 MOV AX,[BYTCNT2] +18140 OR AX,AX +18150 JZ SETFCB +18160 MOV [BYTCNT1],AX +18170 CALL NEXTSEC +18180 JC SETFCB +18190 MOV [BYTSECPOS],0 +18200 CALL BUFRD +18210 JP SETFCB +18220 +18230 WRTDEV: +18240 PUSH DS +18250 LDS SI,[DMAADD] +18260 AND BL,7FH +18270 OR BL,BL +18280 JZ WRTCON +18290 DEC BL +18300 JZ WRTAUX +18310 WRTLST: +18320 LODB +18330 CMP AL,1AH +18340 JZ ENDWRDEV +18350 CALL BIOSPRINT,BIOSSEG +18360 LOOP WRTLST +18370 JP ENDWRDEV +18380 +18390 WRTAUX: +18400 LODB +18410 CALL BIOSAUXOUT,BIOSSEG +18420 CMP AL,1AH +18430 LOOPNZ WRTAUX +18440 JP ENDWRDEV +18450 +18460 WRTCON: +18470 LODB +18480 CMP AL,1AH +18490 JZ ENDWRDEV +18500 CALL OUT +18510 LOOP WRTCON +18520 ENDWRDEV: +18530 POP DS +18540 MOV CX,[RECCNT] +18550 MOV DI,[FCB] +18560 JP ADDREC +18570 +18580 HAVSTART: +18590 MOV CX,AX +18600 CALL SKPCLP +18610 JCXZ DOWRTJ +18620 CALL ALLOCATE +18630 JNC DOWRTJ +18640 WRTERR: +18650 MOV B,[DSKERR],1 +18660 LVDSK: +18670 MOV AX,[RECPOS] +18680 MOV DX,[RECPOS+2] +18690 MOV DI,[FCB] +18700 RET +18710 +18720 DOWRTJ: JMP DOWRT +18730 +18740 WRTEOFJ: +18750 JMP WRTEOF +18760 +18770 STORE: +18780 +18790 ; Inputs: +18800 ; DS:DI point to FCB +18810 ; DX:AX = Position in file of disk transfer +18820 ; CX = Record count +18830 ; Outputs: +18840 ; DX:AX = Position of last record written +18850 ; CX = No. of records written +18860 ; ES:DI point to FCB +18870 ; LSTCLUS, CLUSPOS fields in FCB set +18880 +18890 MOV B,[DI+DIRTYFIL],1 +18900 SEG CS +18910 MOV BX,[DATE] +18920 MOV [DI+FDATE],BX +18930 CALL SETUP +18940 SEG ES +18950 MOV BX,[DI+FILDIRBLK] +18960 CMP BH,-1 +18970 JZ WRTDEV +18980 CALL BREAKDOWN +18990 MOV AX,[BYTPOS] +19000 MOV DX,[BYTPOS+2] +19010 JCXZ WRTEOFJ +19020 DEC CX +19030 ADD AX,CX +19040 ADC DX,0 ;AX:DX=last byte accessed +19050 DIV AX,[BP+SECSIZ] ;AX=last sector accessed +19060 MOV CL,[BP+CLUSSHFT] +19070 SHR AX,CL ;Last cluster to be accessed +19080 PUSH AX +19090 SEG ES +19100 MOV AX,[DI+FILSIZ] +19110 SEG ES +19120 MOV DX,[DI+FILSIZ] +19130 DIV AX,[BP+SECSIZ] +19140 OR DX,DX +19150 JZ NORNDUP +19160 INC AX ;Round up if any remainder +19170 NORNDUP: +19180 MOV [VALSEC],AX ;Number of sectors that have been written +19190 POP AX +19200 MOV CX,[CLUSNUM] ;First cluster accessed +19210 CALL FNDCLUS +19220 MOV [CLUSNUM],BX +19230 MOV [LASTPOS],DX +19240 SUB AX,DX ;Last cluster minus current cluster +19250 JZ DOWRT ;If we have last clus, we must have first +19260 JCXZ HAVSTART +19270 PUSH CX ;No. of clusters short of first +19280 MOV CX,AX +19290 CALL ALLOCATE +19300 POP AX +19310 JC WRTERR +19320 MOV CX,AX +19330 MOV DX,[LASTPOS] +19340 INC DX +19350 DEC CX +19360 JZ NOSKIP +19370 CALL SKPCLP +19380 NOSKIP: +19390 MOV [CLUSNUM],BX +19400 MOV [LASTPOS],DX +19410 DOWRT: +19420 CMP [BYTCNT1],0 +19430 JZ WRTMID +19440 MOV BX,[CLUSNUM] +19450 CALL BUFWRT +19460 WRTMID: +19470 MOV AX,[SECCNT] +19480 OR AX,AX +19490 JZ WRTLAST +19500 ADD [SECPOS],AX +19510 CALL NEXTSEC +19520 MOV B,[TRANS],1 ;A transfer is taking place +19530 MOV DL,[SECCLUSPOS] +19540 MOV BX,[CLUSNUM] +19550 MOV CX,[SECCNT] +19560 WRTLP: +19570 CALL OPTIMIZE +19580 PUSH DI +19590 PUSH AX +19600 PUSH DS +19610 MOV DS,[DMAADD+2] +19620 CALL DWRITE +19630 POP DS +19640 POP CX +19650 POP BX +19660 JCXZ WRTLAST +19670 MOV DL,0 +19680 INC [LASTPOS] ;We'll be using next cluster +19690 JP WRTLP +19700 WRTLAST: +19710 MOV AX,[BYTCNT2] +19720 OR AX,AX +19730 JZ FINWRT +19740 MOV [BYTCNT1],AX +19750 CALL NEXTSEC +19760 MOV [BYTSECPOS],0 +19770 CALL BUFWRT +19780 FINWRT: +19790 MOV AX,[NEXTADD] +19800 SUB AX,[DMAADD] +19810 ADD AX,[BYTPOS] +19820 MOV DX,[BYTPOS+2] +19830 ADC DX,0 +19840 MOV CX,DX +19850 MOV DI,[FCB] +19860 SEG ES +19870 CMP AX,[DI+FILSIZ] +19880 SEG ES +19890 SBB CX,[DI+FILSIZ+2] +19900 JB SAMSIZ +19910 SEG ES +19920 MOV [DI+FILSIZ],AX +19930 SEG ES +19940 MOV [DI+FILSIZ+2],DX +19950 SAMSIZ: +19960 MOV CX,[RECCNT] +19970 JMP SETCLUS +19980 +19990 +20000 WRTERRJ:JMP WRTERR +20010 +20020 WRTEOF: +20030 MOV CX,AX +20040 OR CX,DX +20050 JZ KILLFIL +20060 SUB AX,1 +20070 SBC DX,0 +20080 DIV AX,[BP+SECSIZ] +20090 MOV CL,[BP+CLUSSHFT] +20100 SHR AX,CL +20110 MOV CX,AX +20120 CALL FNDCLUS +20130 JCXZ RELFILE +20140 CALL ALLOCATE +20150 JC WRTERRJ +20160 UPDATE: +20170 MOV DI,[FCB] +20180 MOV AX,[BYTPOS] +20190 SEG ES +20200 MOV [DI+FILSIZ],AX +20210 MOV AX,[BYTPOS+2] +20220 SEG ES +20230 MOV [DI+FILSIZ+2],AX +20240 XOR CX,CX +20250 RET +20260 +20270 RELFILE: +20280 MOV DX,0FFFH +20290 CALL RELBLKS +20300 SETDIRT: +20310 MOV B,[BP+DIRTYFAT],1 +20320 JP UPDATE +20330 +20340 KILLFIL: +20350 XOR BX,BX +20360 SEG ES +20370 XCHG BX,[DI+FIRCLUS] +20380 OR BX,BX +20390 JZ UPDATE +20400 CALL RELEASE +20410 JP SETDIRT +20420 +20430 +20440 OPTIMIZE: +20450 +20460 ; Inputs: +20470 ; DS = CS +20480 ; BX = Physical cluster +20490 ; CX = No. of records +20500 ; DL = sector within cluster +20510 ; BP = Base of drives parameters +20520 ; [NEXTADD] = transfer address +20530 ; Outputs: +20540 ; AX = No. of records remaining +20550 ; BX = Transfer address +20560 ; CX = No. or records to be transferred +20570 ; DX = Physical sector address +20580 ; DI = Next cluster +20590 ; [CLUSNUM] = Last cluster accessed +20600 ; [NEXTADD] updated +20610 ; BP unchanged. Note that segment of transfer not set. +20620 +20630 PUSH DX +20640 PUSH BX +20650 MOV AL,[BP+CLUSMSK] +20660 INC AL ;Number of sectors per cluster +20670 MOV AH,AL +20680 SUB AL,DL ;AL = Number of sectors left in first cluster +20690 MOV DX,CX +20700 LEA SI,[BP+FAT] +20710 MOV CX,0 +20720 OPTCLUS: +20730 ;AL has number of sectors available in current cluster +20740 ;AH has number of sectors available in next cluster +20750 ;BX has current physical cluster +20760 ;CX has number of sequential sectors found so far +20770 ;DX has number of sectors left to transfer +20780 ;SI has FAT pointer +20790 CALL UNPACK +20800 ADD CL,AL +20810 ADC CH,0 +20820 CMP CX,DX +20830 JAE BLKDON +20840 MOV AL,AH +20850 INC BX +20860 CMP DI,BX +20870 JZ OPTCLUS +20880 DEC BX +20890 FINCLUS: +20900 MOV [CLUSNUM],BX ;Last cluster accessed +20910 SUB DX,CX ;Number of sectors still needed +20920 PUSH DX +20930 MOV AX,CX +20940 MUL AX,[BP+SECSIZ] ;Number of sectors times sector size +20950 MOV SI,[NEXTADD] +20960 ADD AX,SI ;Adjust by size of transfer +20970 MOV [NEXTADD],AX +20980 POP AX ;Number of sectors still needed +20990 POP DX ;Starting cluster +21000 SUB BX,DX ;Number of new clusters accessed +21010 ADD [LASTPOS],BX +21020 POP BX ;BL = sector postion within cluster +21030 CALL FIGREC +21040 MOV BX,SI +21050 RET +21060 BLKDON: +21070 SUB CX,DX ;Number of sectors in cluster we don't want +21080 SUB AH,CL ;Number of sectors in cluster we accepted +21090 DEC AH ;Adjust to mean position within cluster +21100 MOV [SECCLUSPOS],AH +21110 MOV CX,DX ;Anyway, make the total equal to the request +21120 JP FINCLUS +21130 +21140 +21150 FIGREC: +21160 +21170 ;Inputs: +21180 ; DX = Physical cluster number +21190 ; BL = Sector postion within cluster +21200 ; BP = Base of drive parameters +21210 ;Outputs: +21220 ; DX = physical sector number +21230 ;No other registers affected. +21240 +21250 PUSH CX +21260 MOV CL,[BP+CLUSSHFT] +21270 DEC DX +21280 DEC DX +21290 SHL DX,CL +21300 OR DL,BL +21310 ADD DX,[BP+FIRREC] +21320 POP CX +21330 RET +21340 +21350 GETREC: +21360 +21370 ; Inputs: +21380 ; DS:DX point to FCB +21390 ; Outputs: +21400 ; CX = 1 +21410 ; DX:AX = Record number determined by EXTENT and NR fields +21420 ; DS:DI point to FCB +21430 ; No other registers affected. +21440 +21450 MOV DI,DX +21460 MOV CX,1 +21470 MOV AL,[DI+NR] +21480 MOV DX,[DI+EXTENT] +21490 SHL AL +21500 SHR DX +21510 RCR AL +21520 MOV AH,DL +21530 MOV DL,DH +21540 MOV DH,0 +21550 RET +21560 +21570 +21580 ALLOCATE: +21590 +21600 ; Inputs: +21610 ; DS = CS +21620 ; ES = Segment of FCB +21630 ; BX = Last cluster of file (0 if null file) +21640 ; CX = No. of clusters to allocate +21650 ; DX = Position of cluster BX +21660 ; BP = Base of drive parameters +21670 ; SI = FAT pointer +21680 ; [FCB] = Displacement of FCB within segment +21690 ; Outputs: +21700 ; IF insufficient space +21710 ; THEN +21720 ; Carry set +21730 ; CX = max. no. of records that could be added to file +21740 ; ELSE +21750 ; Carry clear +21760 ; BX = First cluster allocated +21770 ; FAT is fully updated including dirty bit +21780 ; FIRCLUS field of FCB set if file was null +21790 ; SI,BP unchanged. All other registers destroyed. +21800 +21810 PUSH [SI] +21820 PUSH DX +21830 PUSH CX +21840 PUSH BX +21850 MOV AX,BX +21860 ALLOC: +21870 MOV DX,BX +21880 FINDFRE: +21890 INC BX +21900 CMP BX,[BP+MAXCLUS] +21910 JLE TRYOUT +21920 CMP AX,1 +21930 JG TRYIN +21940 POP BX +21950 MOV DX,0FFFH +21960 CALL RELBLKS +21970 POP AX ;No. of clusters requested +21980 SUB AX,CX ;AX=No. of clusters allocated +21990 POP DX +22000 POP [SI] +22010 INC DX ;Position of first cluster allocated +22020 ADD AX,DX ;AX=max no. of cluster in file +22030 MOV DL,[BP+CLUSMSK] +22040 MOV DH,0 +22050 INC DX ;DX=records/cluster +22060 MUL AX,DX ;AX=max no. of records in file +22070 MOV CX,AX +22080 SUB CX,[RECPOS] ;CX=max no. of records that could be written +22090 JA MAXREC +22100 XOR CX,CX ;If CX was negative, zero it +22110 MAXREC: +22120 STC +22130 RET +22140 +22150 TRYOUT: +22160 CALL UNPACK +22170 JZ HAVFRE +22180 TRYIN: +22190 DEC AX +22200 JLE FINDFRE +22210 XCHG AX,BX +22220 CALL UNPACK +22230 JZ HAVFRE +22240 XCHG AX,BX +22250 JP FINDFRE +22260 HAVFRE: +22270 XCHG BX,DX +22280 MOV AX,DX +22290 CALL PACK +22300 MOV BX,AX +22310 LOOP ALLOC +22320 MOV DX,0FFFH +22330 CALL PACK +22340 MOV B,[BP+DIRTYFAT],1 +22350 POP BX +22360 POP CX ;Don't need this stuff since we're successful +22370 POP DX +22380 CALL UNPACK +22390 POP [SI] +22400 XCHG BX,DI +22410 OR DI,DI +22420 JNZ RET +22430 MOV DI,[FCB] +22440 SEG ES +22450 MOV [DI+FIRCLUS],BX +22460 RET +22470 +22480 +22490 RELEASE: +22500 +22510 ; Inputs: +22520 ; DS = CS +22530 ; BX = Cluster in file +22540 ; SI = FAT pointer +22550 ; BP = Base of drive parameters +22560 ; Function: +22570 ; Frees cluster chain starting with [BX] +22580 ; AX,BX,DX,DI all destroyed. Other registers unchanged. +22590 +22600 XOR DX,DX +22610 RELBLKS: +22620 ; Enter here with DX=0FFFH to put an end-of-file mark +22630 ; in the first cluster and free the rest in the chain. +22640 CALL UNPACK +22650 JZ RET +22660 MOV AX,DI +22670 CALL PACK +22680 CMP AX,0FF8H +22690 MOV BX,AX +22700 JB RELEASE +22710 RET +22720 +22730 +22740 GETEOF: +22750 +22760 ; Inputs: +22770 ; BX = Cluster in a file +22780 ; SI = Base of drive FAT +22790 ; DS = CS +22800 ; Outputs: +22810 ; BX = Last cluster in the file +22820 ; DI destroyed. No other registers affected. +22830 +22840 CALL UNPACK +22850 CMP DI,0FF8H +22860 JAE RET +22870 MOV BX,DI +22880 JP GETEOF +22890 +22900 +22910 SRCHFRST: ;System call 17 +22920 PUSH DX +22930 PUSH DS +22940 CALL GETFILE +22950 SAVPLCE: +22960 ; Search-for-next enters here to save place and report +22970 ; findings. +22980 POP ES +22990 POP DI +23000 JC KILLSRCH +23010 CMP BH,-1 +23020 JZ SRCHDEV +23030 MOV AX,[LASTENT] +23040 SEG ES +23050 MOV [DI+FILDIRBLK],AX +23060 ;Information in directory entry must be copied into the first +23070 ; 33 bytes starting at the disk transfer address. +23080 MOV SI,BX +23090 LES DI,[DMAADD] +23100 MOV AL,[BP+DRVNUM] +23110 INC AL +23120 STOB ;Set drive number +23130 MOVB ;Copy first character of name +23140 MOV CX,5 +23150 REP +23160 MOVW ;Copy remaining 10 characters of name +23170 XOR AX,AX +23180 +23190 IF SMALLDIR +23200 CMP B,[BP+DIRSIZ],-1 +23210 JNZ BIGENT5 +23220 STOB ;Zero out unused portion +23230 MOV CX,7 +23240 REP +23250 STOW ;Zero a total of 15 bytes +23260 MOVW ;Copy first cluster pointer +23270 MOVW ;Copy low word of length +23280 MOVB ;Copy 3rd byte of length +23290 STOB ;4th byte of length must be zero +23300 RET +23310 BIGENT5: +23320 ENDIF +23330 +23340 MOV CX,10 +23350 REP +23360 MOVW +23370 MOVB +23380 RET +23390 +23400 KILLSRCH: +23410 SEG ES +23420 KILLSRCH1: +23430 MOV [DI+FILDIRBLK],-2 +23440 MOV AL,-1 +23450 RET +23460 +23470 SRCHDEV: +23480 SEG ES +23490 MOV [DI+FILDIRBLK],BX +23500 LES DI,[DMAADD] +23510 XOR AX,AX +23520 STOB ;Zero drive byte +23530 SUB SI,3 ;Point to device name +23540 MOVW +23550 MOVB +23560 MOV AX,2020H +23570 MOV CX,4 +23580 REP +23590 STOW ;Fill with 8 blanks +23600 XOR AX,AX +23610 MOV CX,10 +23620 REP +23630 STOW +23640 STOB +23650 RET +23660 +23670 SRCHNXT: ;System call 18 +23680 CALL MOVNAME +23690 MOV DI,DX +23700 JC KILLSRCH1 +23710 PUSH DX +23720 PUSH DS +23730 MOV AX,[DI+FILDIRBLK] +23740 PUSH CS +23750 POP DS +23760 MOV [LASTENT],AX +23770 CALL CONTSRCH +23780 JMP SAVPLCE +23790 +23800 +23810 FILESIZE: ;System call 35 +23820 PUSH DS +23830 PUSH DX +23840 CALL GETFILE +23850 POP DI +23860 POP ES +23870 MOV AL,-1 +23880 JC RET +23890 ADD DI,33 ;Write size in RR field +23900 SEG ES +23910 MOV CX,[DI-33+RECSIZ] +23920 OR CX,CX +23930 JNZ RECOK +23940 MOV CX,128 +23950 RECOK: +23960 XOR AX,AX +23970 XOR DX,DX ;Intialize size to zero +23980 CMP BH,-1 ;Check for named I/O device +23990 JZ DEVSIZ +24000 INC SI +24010 INC SI ;Point to length field +24020 MOV AX,[SI+2] ;Get high word of size +24030 +24040 IF SMALLDIR +24050 CMP B,[BP+DIRSIZ],-1 +24060 JNZ BIGSIZ +24070 MOV AH,0 +24080 BIGSIZ: +24090 ENDIF +24100 +24110 DIV AX,CX +24120 PUSH AX ;Save high part of result +24130 LODW ;Get low word of size +24140 DIV AX,CX +24150 OR DX,DX ;Check for zero remainder +24160 POP DX +24170 JZ DEVSIZ +24180 INC AX ;Round up for partial record +24190 JNZ DEVSIZ ;Propagate carry? +24200 INC DX +24210 DEVSIZ: +24220 STOW +24230 MOV AX,DX +24240 STOB +24250 MOV AL,0 +24260 CMP CX,64 +24270 JAE RET ;Only 3-byte field if RECSIZ >= 64 +24280 SEG ES +24290 MOV [DI],AH +24300 RET +24310 +24320 +24330 SETDMA: ;System call 26 +24340 SEG CS +24350 MOV [DMAADD],DX +24360 SEG CS +24370 MOV [DMAADD+2],DS +24380 RET +24390 +24400 +24410 GETFATPT: ;System call 27 +24420 MOV AX,CS +24430 MOV DS,AX +24440 MOV BP,[CURDRVPT] +24450 CALL FATREAD +24460 LEA BX,[BP+FAT] +24470 MOV AL,[BP+CLUSMSK] +24480 INC AL +24490 MOV DX,[BP+MAXCLUS] +24500 DEC DX +24510 MOV B,[BP+DIRTYFAT],1 +24520 MOV CX,[BP+SECSIZ] +24530 LDS SI,[SPSAVE] +24540 MOV [SI+BXSAVE],BX +24550 MOV [SI+DXSAVE],DX +24560 MOV [SI+CXSAVE],CX +24570 MOV [SI+DSSAVE],CS +24580 RET +24590 +24600 +24610 GETDSKPT: ;System call 31 +24620 SEG CS +24630 MOV BX,[CURDRVPT] +24640 SEG CS +24650 LDS SI,[SPSAVE] +24660 MOV [SI+BXSAVE],BX +24670 MOV [SI+DSSAVE],CS +24680 RET +24690 +24700 +24710 DSKRESET: ;System call 13 +24720 SEG CS +24730 MOV [DMAADD+2],DS +24740 MOV AX,CS +24750 MOV DS,AX +24760 MOV [DMAADD],80H +24770 MOV AX,[CURDRVPT+2] +24780 MOV [CURDRVPT],AX +24790 WRTFATS: +24800 ; DS=CS. Writes back all dirty FATs. All registers destroyed. +24810 MOV CL,[NUMDRV] +24820 MOV CH,0 +24830 MOV SI,CURDRVPT+2 +24840 WRTFAT: +24850 LODW +24860 PUSH CX +24870 PUSH SI +24880 MOV BP,AX +24890 CALL CHKFATWRT +24900 POP SI +24910 POP CX +24920 LOOP WRTFAT +24930 MOV AX,[BUFDRVNO] +24940 OR AH,AH +24950 JZ RET +24960 CBW +24970 MOV BX,AX +24980 SHL BX +24990 MOV BP,[BX+DRVTAB] +25000 MOV B,[DIRTYBUF],0 +25010 MOV DX,[BUFSECNO] +25020 MOV BX,BUFFER +25030 MOV CX,1 +25040 JMP DWRITE +25050 +25060 +25070 CURDRV: ;System call 25 +25080 SEG CS +25090 MOV BP,[CURDRVPT] +25100 MOV AL,[BP+DRVNUM] +25110 RET +25120 +25130 +25140 INUSE: ;System call 24 +25150 MOV AX,CS +25160 MOV DS,AX +25170 MOV CL,[NUMDRV] +25180 MOV CH,0 +25190 MOV SI,CX +25200 SHL SI +25210 ADD SI,CURDRVPT +25220 MOV BX,0 +25230 DOWN +25240 CHKUSE: +25250 LODW +25260 MOV BP,AX +25270 CMP B,[BP+DIRTYFAT],-1 ;Carry set if not equal +25280 RCL BX +25290 LOOP CHKUSE +25300 MOV AL,BL +25310 RET +25320 +25330 +25340 SETRNDREC: ;System call 36 +25350 CALL GETREC +25360 MOV [DI+33],AX +25370 MOV [DI+35],DL +25380 RET +25390 +25400 +25410 SELDSK: ;System call 14 +25420 MOV DH,0 +25430 MOV BX,DX +25440 PUSH CS +25450 POP DS +25460 MOV AL,[NUMDRV] +25470 CMP BL,AL +25480 JNB RET +25490 SHL BX +25500 MOV DX,[BX+CURDRVPT+2] +25510 MOV [CURDRVPT],DX +25520 RET +25530 +25540 +25550 BUFIN: ;System call 10 +25560 MOV AX,CS +25570 MOV ES,AX +25580 MOV SI,DX +25590 MOV CH,0 +25600 LODW +25610 OR AL,AL +25620 JZ RET +25630 MOV BL,AH +25640 MOV BH,CH +25650 CMP AL,BL +25660 JBE NOEDIT +25670 CMP B,[BX+SI],0DH +25680 JZ EDITON +25690 NOEDIT: +25700 MOV BL,CH +25710 EDITON: +25720 MOV DL,AL +25730 DEC DX +25740 NEWLIN: +25750 SEG CS +25760 MOV AL,[CARPOS] +25770 SEG CS +25780 MOV [STARTPOS],AL +25790 PUSH SI +25800 MOV DI,INBUF +25810 MOV AH,CH +25820 MOV BH,CH +25830 MOV DH,CH +25840 GETCH: +25850 CALL IN +25860 CMP AL,7FH +25870 JZ BACKSP +25880 CMP AL,8 +25890 JZ BACKSP +25900 CMP AL,13 +25910 JZ ENDLIN +25920 CMP AL,10 +25930 JZ PHYCRLF +25940 CMP AL,"X"-"@" +25950 JZ KILNEW +25960 CMP AL,ESCCH +25970 JZ ESC +25980 SAVCH: +25990 CMP DH,DL +26000 JAE GETCH +26010 STOB +26020 INC DH +26030 CALL BUFOUT +26040 OR AH,AH +26050 JNZ GETCH +26060 CMP BH,BL +26070 JAE GETCH +26080 INC SI +26090 INC BH +26100 JP GETCH +26110 +26120 ESC: +26130 CALL IN +26140 MOV CL,ESCTABLEN +26150 PUSH DI +26160 MOV DI,ESCTAB +26170 REPNE +26180 SCAB +26190 POP DI +26200 AND CL,0FEH +26210 MOV BP,CX +26220 SEG CS ;To work in init +26230 JMP [BP+ESCFUNC] +26240 +26250 ENDLIN: +26260 STOB +26270 CALL OUT +26280 POP DI +26290 MOV [DI-1],DH +26300 INC DH +26310 COPYNEW: +26320 MOV BP,ES +26330 MOV BX,DS +26340 MOV ES,BX +26350 MOV DS,BP +26360 MOV SI,INBUF +26370 MOV CL,DH +26380 REP +26390 MOVB +26400 RET +26410 CRLF: +26420 MOV AL,13 +26430 CALL OUT +26440 MOV AL,10 +26450 JMP OUT +26460 +26470 PHYCRLF: +26480 CALL CRLF +26490 JP GETCH +26500 +26510 KILNEW: +26520 MOV AL,"\" +26530 CALL OUT +26540 POP SI +26550 PUTNEW: +26560 CALL CRLF +26570 SEG CS +26580 MOV AL,[STARTPOS] +26590 CALL TAB +26600 JMP NEWLIN +26610 +26620 BACKSP: +26630 OR DH,DH +26640 JZ OLDBAK +26650 CALL BACKUP +26660 SEG ES +26670 MOV AL,[DI] +26680 CMP AL," " +26690 JAE OLDBAK +26700 CMP AL,9 +26710 JZ BAKTAB +26720 CALL BACKMES +26730 OLDBAK: +26740 OR AH,AH +26750 JNZ GETCH1 +26760 OR BH,BH +26770 JZ GETCH1 +26780 DEC BH +26790 DEC SI +26800 GETCH1: +26810 JMP GETCH +26820 BAKTAB: +26830 PUSH DI +26840 DEC DI +26850 DOWN +26860 MOV CL,DH +26870 MOV AL," " +26880 PUSH BX +26890 MOV BL,7 +26900 JCXZ FIGTAB +26910 FNDPOS: +26920 SCAB +26930 JNA CHKCNT +26940 SEG ES +26950 CMP B,[DI+1],9 +26960 JZ HAVTAB +26970 DEC BL +26980 CHKCNT: +26990 LOOP FNDPOS +27000 FIGTAB: +27010 SEG CS +27020 SUB BL,[STARTPOS] +27030 HAVTAB: +27040 SUB BL,DH +27050 ADD CL,BL +27060 AND CL,7 +27070 UP +27080 POP BX +27090 POP DI +27100 JZ OLDBAK +27110 TABBAK: +27120 CALL BACKMES +27130 LOOP TABBAK +27140 JP OLDBAK +27150 BACKUP: +27160 DEC DH +27170 DEC DI +27180 BACKMES: +27190 MOV AL,8 +27200 CALL OUT +27210 MOV AL," " +27220 CALL OUT +27230 MOV AL,8 +27240 JMP OUT +27250 +27260 TWOESC: +27270 MOV AL,ESCCH +27280 JMP SAVCH +27290 +27300 COPYLIN: +27310 MOV CL,BL +27320 SUB CL,BH +27330 JP COPYEACH +27340 +27350 COPYSTR: +27360 CALL FINDOLD +27370 JP COPYEACH +27380 +27390 COPYONE: +27400 MOV CL,1 +27410 COPYEACH: +27420 CMP DH,DL +27430 JZ GETCH2 +27440 CMP BH,BL +27450 JZ GETCH2 +27460 LODB +27470 STOB +27480 CALL BUFOUT +27490 INC BH +27500 INC DH +27510 LOOP COPYEACH +27520 GETCH2: +27530 JMP GETCH +27540 +27550 SKIPONE: +27560 CMP BH,BL +27570 JZ GETCH2 +27580 INC BH +27590 INC SI +27600 JMP GETCH +27610 +27620 SKIPSTR: +27630 CALL FINDOLD +27640 ADD SI,CX +27650 ADD BH,CL +27660 JMP GETCH +27670 +27680 FINDOLD: +27690 CALL IN +27700 MOV CL,BL +27710 SUB CL,BH +27720 JZ NOTFND +27730 DEC CX +27740 JZ NOTFND +27750 PUSH ES +27760 PUSH DS +27770 POP ES +27780 PUSH DI +27790 MOV DI,SI +27800 INC DI +27810 REPNE +27820 SCAB +27830 POP DI +27840 POP ES +27850 JNZ NOTFND +27860 NOT CL +27870 ADD CL,BL +27880 SUB CL,BH +27890 RET +27900 NOTFND: +27910 POP BP +27920 JMP GETCH +27930 +27940 REEDIT: +27950 MOV AL,"@" +27960 CALL OUT +27970 POP DI +27980 PUSH DI +27990 PUSH ES +28000 PUSH DS +28010 CALL COPYNEW +28020 POP DS +28030 POP ES +28040 POP SI +28050 MOV BL,DH +28060 JMP PUTNEW +28070 +28080 ENTERINS: +28090 MOV AH,-1 +28100 JMP GETCH +28110 +28120 EXITINS: +28130 MOV AH,0 +28140 JMP GETCH +28150 +28160 ESCFUNC: +28170 DW GETCH +28180 DW TWOESC +28190 DW EXITINS +28200 DW ENTERINS +28210 DW BACKSP +28220 DW REEDIT +28230 DW KILNEW +28240 DW COPYLIN +28250 DW SKIPSTR +28260 DW COPYSTR +28270 DW SKIPONE +28280 DW COPYONE +28290 +28300 BUFOUT: +28310 CMP AL," " +28320 JAE OUT +28330 CMP AL,9 +28340 JZ OUT +28350 PUSH AX +28360 MOV AL,"^" +28370 CALL OUT +28380 POP AX +28390 OR AL,40H +28400 JP OUT +28410 +28420 CONOUT: ;System call 2 +28430 MOV AL,DL +28440 OUT: +28450 CMP AL,20H +28460 JB CTRLOUT +28470 CMP AL,7FH +28480 JZ OUTCH +28490 SEG CS +28500 INC B,[CARPOS] +28510 OUTCH: +28520 CALL BIOSOUT,BIOSSEG +28530 SEG CS +28540 TEST B,[PFLAG],-1 +28550 JZ STATCHK +28560 CALL BIOSPRINT,BIOSSEG +28570 STATCHK: +28580 CALL BIOSSTAT,BIOSSEG +28590 JZ RET +28600 INCHK: +28610 CALL BIOSIN,BIOSSEG +28620 CMP AL,'S'-'@' +28630 JNZ NOSTOP +28640 CALL BIOSIN,BIOSSEG +28650 NOSTOP: +28660 CMP AL,'P'-'@' +28670 JZ PRINTON +28680 CMP AL,'N'-'@' +28690 JZ PRINTOFF +28700 CMP AL,'C'-'@' +28710 JNZ RET +28720 ; Ctrl-C handler. +28730 ; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +28740 ; to show line is canceled. Then the user registers are restored and the +28750 ; user CTRL-C handler is executed. At this point the top of the stack has +28760 ; 1) the interrupt return address should the user CTRL-C handler wish to +28770 ; allow processing to continue; 2) the original interrupt return address +28780 ; to the code that performed the function call in the first place. If the +28790 ; user CTRL-C handler wishes to continue, it must leave all registers +28800 ; unchanged and IRET. The function that was interrupted will simply be +28810 ; repeated, except for console output (function 2), which has already output +28820 ; its character before the interrupt. +28830 SEG CS +28840 MOV AL,[FUNC] ;Get currently executing function +28850 CMP AL,10 ;Check if buffered line input +28860 JZ CANLIN +28870 CMP AL,9 ;Check if buffered line output +28880 JNZ RESTREG +28890 CANLIN: +28900 MOV AL,"\" ;Display cancel line symbol +28910 CALL OUT +28920 CALL CRLF +28930 RESTREG: +28940 DI ;Prepare to play with stack +28950 SEG CS +28960 MOV SS,[SSSAVE] +28970 SEG CS +28980 MOV SP,[SPSAVE] ;User stack now restored +28990 POP AX +29000 POP BX +29010 POP CX +29020 POP DX +29030 POP SI +29040 POP DI +29050 POP BP +29060 POP DS +29070 POP ES ;User registers now restored +29080 INT CONTC ;Execute user Ctrl-C handler +29090 CMP AH,2 ;Check if function was console output +29100 JZ SETAL +29110 JMP COMMAND ;Repeat command otherwise +29120 SETAL: +29130 MOV AL,DL +29140 IRET ;Return to user program +29150 +29160 PRINTON: +29170 SEG CS +29180 MOV B,[PFLAG],1 +29190 RET +29200 PRINTOFF: +29210 SEG CS +29220 MOV B,[PFLAG],0 +29230 RET +29240 CTRLOUT: +29250 CMP AL,13 +29260 JZ ZERPOS +29270 CMP AL,8 +29280 JZ BACKPOS +29290 CMP AL,9 +29300 JNZ OUTCHJ +29310 SEG CS +29320 MOV AL,[CARPOS] +29330 OR AL,0F8H +29340 NEG AL +29350 TAB: +29360 PUSH CX +29370 MOV CL,AL +29380 MOV CH,0 +29390 TABLP: +29400 MOV AL," " +29410 CALL OUT +29420 LOOP TABLP +29430 POP CX +29440 RET +29450 +29460 ZERPOS: +29470 SEG CS +29480 MOV B,[CARPOS],0 +29490 OUTCHJ: JMP OUTCH +29500 +29510 BACKPOS: +29520 SEG CS +29530 DEC B,[CARPOS] +29540 JMP OUTCH +29550 +29560 +29570 CONSTAT: ;System call 11 +29580 CALL BIOSSTAT,BIOSSEG +29590 JZ RET +29600 OR AL,-1 +29610 RET +29620 +29630 +29640 CONIN: ;System call 1 +29650 CALL IN +29660 PUSH AX +29670 CALL OUT +29680 POP AX +29690 RET +29700 +29710 +29720 IN: ;Internal input routine +29730 CALL INCHK +29740 JZ IN +29750 RET +29760 +29770 RAWIO: ;System call 6 +29780 MOV AL,DL +29790 CMP AL,-1 +29800 JNZ RAWOUT +29810 CALL BIOSSTAT,BIOSSEG +29820 JZ RET +29830 RAWINP: ;System call 7 +29840 CALL BIOSIN,BIOSSEG +29850 RET +29860 RAWOUT: +29870 CALL BIOSOUT,BIOSSEG +29880 RET +29890 +29900 LIST: ;System call 5 +29910 MOV AL,DL +29920 CALL BIOSPRINT,BIOSSEG +29930 RET +29940 +29950 PRTBUF: ;System call 9 +29960 MOV SI,DX +29970 OUTSTR: +29980 LODB +29990 CMP AL,"$" +30000 JZ RET +30010 CALL OUT +30020 JP OUTSTR +30030 +30040 OUTMES: ;String output for internal messages +30050 SEG CS +30060 LODB +30070 CMP AL,"$" +30080 JZ RET +30090 CALL OUT +30100 JP OUTMES +30110 +30120 +30130 MAKEFCB: ;Interrupt call 41 +30140 MOV DL,0 ;Flag--not ambiguous file name +30150 OR AL,AL ;Scan off separators if not zero +30160 JZ NOSCAN +30170 SCAN: +30180 CALL GETLET +30190 JZ SCAN ;Get rid of leading separators (e.g., blanks) +30200 DEC SI ;Point back to first non-separator +30210 NOSCAN: +30220 CMP B,[SI+1],":" ;Check for potential drive specifier +30230 JNZ DEFAULT +30240 CALL GETLET +30250 SUB AL,"@" ;Convert drive letter to binary drive number +30260 JZ NODRV ;Valid drive numbers are 1-15 +30270 INCcifier--back up pointer +30280 DEFAULT: +30290 XOR AL,AL +30300 HAVDRV: +30310 STOB ;Put drive specifier in first byte +30320 MOV CX,8 +30330 CALL GETWORD ;Get 8-letter file name +30340 CMP B,[SI],"." +30350 JNZ NODOT +30360 INC SI ;Skip over dot if present +30370 NODOT: +30380 MOV CX,3 ;Get 3-letter extension +30390 CALL GETWORD +30400 SEG CS +30410 LDS BX,[SPSAVE] +30420 MOV [BX+SISAVE],SI +30430 XOR AX,AX +30440 STOW +30450 STOW +30460 MOV AL,DL +30470 RET +30480 +30490 GETWORD: +30500 CALL GETLET +30510 JZ FILLNAM ;Exit if invalid character +30520 CMP AL," " +30530 JBE FILLNAM +30540 CMP AL,"*" ;Check for ambiguous file specifier +30550 JNZ NOSTAR +30560 MOV AL,"?" +30570 DEC CX +30580 REP +30590 STOB ;Fill rest of word with "?" +30600 INC CX +30610 NOSTAR: +30620 STOB +30630 CMP AL,"?" +30640 JNZ NOTQ +30650 MOV DL,1 ;Flag ambiguous file name +30660 NOTQ: +30670 LOOP GETWORD +30680 INC SI ;Point to "termination" character +30690 FILLNAM: +30700 MOV AL," " +30710 REP +30720 STOB +30730 DEC SI +30740 RET +30750 +30760 GETLET: +30770 LODB +30780 CMP AL,"a" +30790 JB CHK +30800 CMP AL,"z" +30810 JA CHK +30820 SUB AL,20H ;Convert to upper case +30830 CHK: +30840 CMP AL," " +30850 JZ RET +30860 CMP AL,"=" +30870 JZ RET +30880 CMP AL,"," +30890 JZ RET +30900 CMP AL,";" +30910 JZ RET +30920 CMP AL,"." +30930 JZ RET +30940 CMP AL,":" +30950 JZ RET +30960 CMP AL,9 ;Filter out TABs too +30970 RET +30980 +30990 +31000 SETVECT: ; Interrupt call 37 +31010 XOR BX,BX +31020 MOV ES,BX +31030 MOV BL,AL +31040 SHL BX +31050 SHL BX +31060 SEG ES +31070 MOV [BX],DX +31080 SEG ES +31090 MOV [BX+2],DS +31100 RET +31110 +31120 +31130 NEWBASE: ; Interrupt call 38 +31140 MOV ES,DX +31150 SEG CS +31160 MOV DS,[CSLOC] +31170 XOR SI,SI +31180 MOV DI,SI +31190 MOV CX,80H +31200 REP +31210 MOVW +31220 +31230 SETMEM: +31240 +31250 ; Inputs: +31260 ; DX = Segment +31270 ; Function: +31280 ; Completely prepares a program base at the +31290 ; specified segment. +31300 ; Outputs: +31310 ; DS = DX +31320 ; ES = DX +31330 ; [0] has INT 20H +31340 ; [2] = First unavailable segment ([ENDMEM]) +31350 ; [5] to [9] form a long call to the entry point +31360 ; [10] to [13] have exit address (from INT 22H) +31370 ; [14] to [17] have ctrl-C exit address (from INT 23H) +31380 ; AX,DX,BP unchanged. All other registers destroyed. +31390 +31400 XOR CX,CX +31410 MOV DS,CX +31420 MOV ES,DX +31430 MOV SI,EXIT +31440 MOV DI,SAVEXIT +31450 MOVW +31460 MOVW +31470 MOVW +31480 MOVW +31490 SEG CS +31500 MOV CX,[ENDMEM] +31510 SEG ES +31520 MOV [2],CX +31530 SUB CX,DX +31540 CMP CX,MAXDIF +31550 JBE HAVDIF +31560 MOV CX,MAXDIF +31570 HAVDIF: +31580 MOV BX,ENTRYPOINTSEG +31590 SUB BX,CX +31600 SHL CX +31610 SHL CX +31620 SHL CX +31630 SHL CX +31640 MOV DS,DX +31650 MOV [6],CX +31660 MOV [8],BX +31670 MOV [0],20CDH ;"INT INTTAB" +31680 MOV B,[5],LONGCALL +31690 RET +31700 +31710 +31720 SHFTDI7: +31730 SHL DI +31740 SHL DI +31750 SHL DI +31760 SHL DI +31770 SHL DI +31780 SHL DI +31790 SHL DI +31800 RET +31810 +31820 +31830 ; Default handler for division overflow trap +31840 DIVOV: +31850 XOR DX,DX ;Say no remainder +31860 MOV AX,-1 ;But large quotient +31870 IRET +31880 +31890 +31900 ;***** DATA AREA ***** +31910 +31920 BADMES: DB 13,10,"Bad FAT",13,10,"$" +31930 BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$" +31940 RDERRMES:DB 13,10,"Disk read error",13,10,"$" +31950 WRTERRMES:DB 13,10,"Disk write error",13,10,"$" +31960 IONAME: DB "PRN","LST","AUX","CON" +31970 +31980 CARPOS: DB 0 +31990 STARTPOS:DB 0 +32000 PFLAG: DB 0 +32010 DIRTYDIR:DB 0 ;Dirty buffer flag +32020 NUMDRV: DS 1 ;Number of drives +32030 CONTPOS:DW 0 +32040 DMAADD: DW 80H ;User's disk transfer address (disp/seg) +32050 DS 2 +32060 ENDMEM: DS 2 +32070 MAXSEC: DW 0 +32080 BUFFER: DS 2 +32090 BUFSECNO:DW 0 +32100 BUFDRVNO:DB -1 +32110 DIRTYBUF:DB 0 +32120 DIRBUFID:DW -1 +32130 DATE: DS 2 +32140 CURDRVPT:DS 2 +32150 DRVTAB: DS 30 ;Enough for 15 drives +32160 INBUF: DS 15 ;Only the first part +32170 +32180 ; Init code overlaps with data area below +32190 +32200 INITCODE: +32210 +32220 DS 128-15 ;More of INBUF +32230 CONBUF: DS 130 ;The rest of INBUF and console buffer +32240 FUNC: DS 1 ;Currently executing function code +32250 LASTENT:DS 2 +32260 EXITHOLD:DS 4 +32270 FATBASE:DS 2 +32280 NAME1: DS 11 ;File name buffer +32290 NAME2: DS 11 +32300 TEMP: +32310 CSLOC: DS 2 +32320 SPSAVE: DS 2 +32330 SSSAVE: DS 2 +32340 SECCLUSPOS:DS 1 ;Position of first sector within cluster +32350 DSKERR: DS 1 +32360 TRANS: DS 1 +32370 +32380 ALIGN +32390 FCB: DS 2 ;Address of user FCB +32400 NEXTADD:DS 2 +32410 RECPOS: DS 4 +32420 RECCNT: DS 2 +32430 LASTPOS:DS 2 +32440 CLUSNUM:DS 2 +32450 SECPOS: DS 2 ;Position of first sector accessed +32460 VALSEC: DS 2 ;Number of valid (previously written) sectors +32470 BYTSECPOS:DS 2 ;Position of first byte within sector +32480 BYTPOS: DS 4 ;Byte position in file of access +32490 BYTCNT1:DS 2 ;No. of bytes in first sector +32500 BYTCNT2:DS 2 ;No. of bytes in last sector +32510 SECCNT: DS 2 ;No. of whole sectors +32520 +32530 DS 60 ;Stack space +32540 STACK: +32550 +32560 IF DSKTEST +32570 NSS: DS 2 +32580 NSP: DS 2 +32590 DS 60 +32600 TESTSTK: +32610 ENDIF +32620 +32630 DIRBUF: +32640 +32650 ;Init code below overlaps with data area above +32660 +32670 ORG INITCODE +32680 PUT $+100H +32690 +32700 MOVFAT: +32710 ;This section of code is safe from being overwritten by block move +32720 SEG ES +32730 REP +32740 MOVB +32750 UP +32760 FININIT: +32770 CALL SETMEM ;Set up segment +32780 RET L +32790 +32800 DOSINIT: +32810 DI +32820 UP +32830 PUSH CS +32840 POP ES +32850 LODB +32860 SEG ES +32870 MOV [NUMDRV],AL +32880 MOV BX,DRVTAB +32890 MOV DI,MEMSTRT +32900 PERDRV: +32910 SEG ES +32920 MOV [BX],DI +32930 MOV BP,DI +32940 INC BX +32950 INC BX +32960 SEG ES +32970 MOV AL,[DRVCNT] +32980 STOB ;DRVNUM +32990 LODW ;Pointer to DPT +33000 PUSH SI +33010 MOV SI,AX +33020 LODW +33030 STOW ;SECSIZ +33040 MOV DX,AX +33050 SEG ES +33060 CMP AX,[MAXSEC] +33070 JBE NOTMAX +33080 SEG ES +33090 MOV [MAXSEC],AX +33100 NOTMAX: +33110 LODB +33120 DEC AL +33130 STOB ;CLUSMSK +33140 JZ HAVSHFT +33150 CBW +33160 FIGSHFT: +33170 INC AH +33180 SAR AL +33190 JNZ FIGSHFT +33200 MOV AL,AH +33210 HAVSHFT: +33220 STOB ;CLUSSHFT +33230 MOVW ;FIRFAT (= number of reserved sectors) +33240 MOVB ;FATCNT +33250 MOVW ;MAXENT +33260 MOV AX,DX ;SECSIZ again +33270 MOV CL,5 +33280 SHR AX,CL +33290 MOV CX,AX ;Directory entries per sector +33300 DEC AX +33310 SEG ES +33320 ADD AX,[BP+MAXENT] +33330 XOR DX,DX +33340 DIV AX,CX +33350 STOW ;DIRSEC (temporarily) +33360 SHR AX ;Divide by two +33370 ADC AX,0 ;Round up +33380 SEG ES +33390 MOV [SDIRSEC],AX ;Number of directory records for small entries +33400 MOVW ;DSKSIZ (temporarily) +33410 FNDFATSIZ: +33420 MOV AL,1 +33430 MOV DX,1 +33440 GETFATSIZ: +33450 PUSH DX +33460 CALL FIGFATSIZ +33470 POP DX +33480 CMP AL,DL ;Compare newly computed FAT size with trial +33490 JZ HAVFATSIZ ;Has sequence converged? +33500 CMP AL,DH ;Compare with previous trial +33510 MOV DH,DL +33520 MOV DL,AL ;Shuffle trials +33530 JNZ GETFATSIZ ;Continue iterations if not oscillating +33540 SEG ES +33550 DEC [BP+DSKSIZ] ;Damp those oscillations +33560 JP FNDFATSIZ ;Try again +33570 HAVFATSIZ: +33580 STOB ;FATSIZ +33590 SEG ES +33600 MUL AL,[BP+FATCNT] ;Space occupied by all FATs +33610 SEG ES +33620 ADD AX,[BP+FIRFAT] +33630 STOW ;FIRDIR +33640 +33650 IF SMALLDIR-1 +33660 SEG ES +33670 ADD AX,[BP+DIRSEC] +33680 SEG ES +33690 MOV [BP+FIRREC],AX ;Destroys DIRSEC +33700 CALL FIGMAX +33710 SEG ES +33720 MOV [BP+MAXCLUS],CX +33730 ENDIF +33740 +33750 IF SMALLDIR +33760 MOV DX,AX ;Save FIRDIR momentarily +33770 SEG ES +33780 ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry +33790 STOW ;FIRREC1 +33800 XCHG AX,CX ;Previously computed MAXCLUS +33810 STOW ;MAXCLUS1 +33820 XCHG DX,AX +33830 SEG ES +33840 ADD AX,[BP+DIRSEC] ;Add number of dir. sectores for 32-byte entry +33850 STOW ;FIRREC2 +33860 CALL FIGMAX +33870 XCHG AX,CX +33880 STOW ;MAXCLUS2 +33890 ENDIF +33900 +33910 MOV AX,0FFH +33920 STOB ;DIRTYFAT +33930 SEG ES +33940 MOV AL,[BP+FATSIZ] +33950 SEG ES +33960 MUL AX,[BP+SECSIZ] +33970 ADD DI,AX ;Allocate FAT +33980 POP SI ;Restore pointer to init. table +33990 SEG ES +34000 MOV AL,[DRVCNT] +34010 INC AL +34020 SEG ES +34030 MOV [DRVCNT],AL +34040 SEG ES +34050 CMP AL,[NUMDRV] +34060 JAE CONTINIT +34070 JMP PERDRV +34080 CONTINIT: +34090 LODW ;Max. buffer size +34100 SEG ES +34110 MOV BX,[MAXSEC] +34120 MOV AX,DIRBUF +34130 ADD AX,BX +34140 SEG ES +34150 MOV [BUFFER],AX ;Start of buffer +34160 PUSH DI ;Save ending location +34170 ADD DI,BX ;Allocate directory buffer +34180 ADD DI,BX ;Allocate buffer space +34190 ADD DI,ADJFAC+15 ;True start of free space +34200 MOV CL,4 +34210 SHR DI,CL ;First free segment +34220 MOV BP,DI +34230 XOR AX,AX +34240 MOV DS,AX +34250 MOV ES,AX +34260 MOV DI,INTBASE +34270 MOV AX,QUIT +34280 STOW ;Set abort address--displacement +34290 MOV AX,CS +34300 MOV B,[ENTRYPOINT],LONGJUMP +34310 MOV [ENTRYPOINT+1],ENTRY +34320 MOV [ENTRYPOINT+3],AX +34330 MOV [0],DIVOV ;Set default divide trap address +34340 MOV [2],AX +34350 MOV CX,9 +34360 REP +34370 STOW ;Set 5 segments (skip 2 between each) +34380 MOV [INTBASE+4],COMMAND +34390 MOV [INTBASE+12],IRET ;CTRL-C exit +34400 MOV [INTBASE+16],IRET ;Fatal error exit +34410 MOV AX,BIOSREAD +34420 STOW +34430 MOV AX,BIOSSEG +34440 STOW +34450 STOW ;Add 2 to DI +34460 STOW +34470 MOV [INTBASE+18H],BIOSWRITE +34480 MOV DX,CS +34490 MOV DS,DX +34500 ADD DX,BP +34510 MOV [DMAADD],80H +34520 MOV [DMAADD+2],DX +34530 MOV AX,[DRVTAB] +34540 MOV [CURDRVPT],AX +34550 MOV CX,DX +34560 MOV BX,0FH +34570 MEMSCAN: +34580 INC CX +34590 JZ HAVMEM +34600 MOV DS,CX +34610 MOV AL,[BX] +34620 NOT AL +34630 MOV [BX],AL +34640 CMP AL,[BX] +34650 NOT AL +34660 MOV [BX],AL +34670 JZ MEMSCAN +34680 HAVMEM: +34690 SEG CS +34700 MOV [ENDMEM],CX +34710 XOR CX,CX +34720 MOV DS,CX +34730 MOV [EXIT],100H +34740 MOV [EXIT+2],DX +34750 MOV SI,HEADER +34760 CALL OUTMES +34770 PUSH CS +34780 POP DS +34790 PUSH CS +34800 POP ES +34810 PUSH DX +34820 GETDAT: +34830 MOV SI,DATMES +34840 CALL OUTMES +34850 MOV DX,DATBUF +34860 CALL BUFIN +34870 CALL CRLF +34880 MOV SI,DATBUF+2 +34890 MOV DX,12 +34900 CALL MYD +34910 JC GETDAT +34920 MOV CL,5 +34930 SHL AX,CL +34940 MOV [DATE],AX +34950 MOV DX,31 +34960 CALL MYD +34970 JC GETDAT +34980 OR [DATE],AL +34990 MOV DX,2100 +35000 CALL MYD +35010 JC GETDAT +35020 SUB AX,80 +35030 JC GETDAT +35040 CMP AX,19 +35050 JBE SAVYR +35060 SUB AX,1900 +35070 JC GETDAT +35080 SAVYR: +35090 SHL AL +35100 OR [DATE+1],AL +35110 ;Move the FATs into position and adjust the drive pointer table +35120 POP DX +35130 POP SI +35140 MOV AX,[MAXSEC] +35150 SHL AX ;Allocate two buffers +35160 ADD AX,ADJFAC +35170 JZ FINJMP +35180 MOV DI,DRVTAB +35190 MOV CX,15 +35200 ADJLP: +35210 ADD [DI],AX +35220 INC DI +35230 INC DI +35240 LOOP ADJLP +35250 MOV CX,SI +35260 MOV SI,MEMSTRT ;Place to move FATs from +35270 SUB CX,SI ;Total length of FATs +35280 MOV DI,AX +35290 ADD DI,SI ;Place to move FATs to +35300 OR AX,AX +35310 JS MOVJMP +35320 DEC CX +35330 ADD DI,CX +35340 ADD SI,CX +35350 INC CX +35360 DOWN +35370 MOVJMP: +35380 JMP MOVFAT +35390 FINJMP: JMP FININIT +35400 +35410 FIGFATSIZ: +35420 SEG ES +35430 MUL AL,[BP+FATCNT] +35440 SEG ES +35450 ADD AX,[BP+FIRFAT] +35460 SEG ES +35470 ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +35480 FIGMAX: +35490 ;AX has equivalent of FIRREC +35500 SEG ES +35510 SUB AX,[BP+DSKSIZ] +35520 NEG AX +35530 SEG ES +35540 MOV CL,[BP+CLUSSHFT] +35550 SHR AX,CL +35560 INC AX +35570 MOV CX,AX ;MAXCLUS +35580 INC AX +35590 MOV DX,AX +35600 SHR DX +35610 ADC AX,DX ;Size of FAT in bytes +35620 SEG ES +35630 MOV SI,[BP+SECSIZ] +35640 ADD AX,SI +35650 DEC AX +35660 XOR DX,DX +35670 DIV AX,SI +35680 RET +35690 +35700 MYD: +35710 ;SI points to input buffer. Get decimal number < DX and return it +35720 ;in AX. Carry set on error. +35730 XOR BX,BX +35740 MOV AH,0 +35750 GETDIG: +35760 LODB +35770 SUB AL,"0" +35780 JC CHKRET +35790 CMP AL,10 +35800 JNC CHKRET +35810 SHL BX +35820 MOV CX,BX +35830 SHL BX +35840 SHL BX +35850 ADD BX,CX +35860 ADD BX,AX +35870 JP GETDIG +35880 CHKRET: +35890 MOV AX,BX +35900 OR AX,AX +35910 STC +35920 JZ RET +35930 CMP DX,AX +35940 RET +35950 +35960 DRVCNT: DB 0 +35970 +35980 DATMES: DB "Enter today's date (m-d-y): $" +35990 DATBUF: DB 12,8,"04-28-81",13 +36000 DS 5 +36010 +36020 SDIRSEC:DS 2 +36030 +36040 MEMSTRT: +36050 ADJFAC: EQU DIRBUF-MEMSTRT diff --git a/2_printed_files/bundle_05/ASM.PRN b/2_printed_files/bundle_05/ASM.PRN new file mode 100644 index 0000000..f61116f --- /dev/null +++ b/2_printed_files/bundle_05/ASM.PRN @@ -0,0 +1,3754 @@ +0000 0001 ; Seattle Computer Products 8086 Assembler version 2.31 +0000 0002 ; by Tim Paterson +0000 0003 ; Runs on the 8086 under 86-DOS +0000 0004 +0000 0005 ;* * * * * * REVISION HISTORY * * * * * * +0000 0006 ; +0000 0007 ; 12/29/80 2.01 General release with 86-DOS version 0.34 +0000 0008 ; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +0000 0009 ; 03/18/81 2.11 General cleanup and more documentation +0000 0010 ; 03/24/81 2.20 Modify ESC handling for full 8087 operation +0000 0011 ; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +0000 0012 ; 04/03/81 2.22 Fix 2.21 buffer handling +0000 0013 ; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +0000 0014 ; 04/28/81 2.24 Allow nested IFs +0000 0015 ; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +0000 0016 ; 08/02/81 2.30 Re-write pass 2: +0000 0017 ; Always report errors to console +0000 0018 ; Exact byte lengths for HEX and PRN files +0000 0019 ; 08/23/81 2.40 Add 8087 mnemonics +0000 0020 ; +0000 0021 ;* * * * * * * * * * * * * * * * * * * * * +0000 0022 +0000 0023 SYMWID: EQU 10 +0000 0024 FCB: EQU 5CH +0000 0025 BUFSIZ: EQU 1024 ;Source code buffer +0000 0026 LSTBUFSIZ:EQU BUFSIZ ;List file buffer +0000 0027 HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +0000 0028 EOL: EQU 13 ;ASCII carriage return +0000 0029 OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS +0000 0030 +0000 0031 ;System call function codes +0000 0032 PRINTMES: EQU 9 +0000 0033 OPEN: EQU 15 +0000 0034 CLOSE: EQU 16 +0000 0035 READ: EQU 20 +0000 0036 SETDMA: EQU 26 +0000 0037 MAKE: EQU 22 +0000 0038 BLKWRT: EQU 40 +0000 0039 +0000 0040 ;The following equates define some token values returned by GETSYM +0000 0041 UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +0000 0042 CONST: EQU 1 ;Constant (including $) +0000 0043 REG: EQU 2 ;8-bit register +0000 0044 XREG: EQU 3 ;16-bit register (except segment registers) +0000 0045 SREG: EQU 4 ;Segment register +0000 0046 +0000 0047 ;Ouput file record definition +0000 0048 ORG 0 +0000 0049 WRTPT: DS 2 ;Pointer to next byte to be written +0002 0050 BUFEND: DS 2 ;Pointer to end of buffer plus one +0004 0051 BUFSTRT:DS 2 ;Address of start of buffer +0006 0052 BUFFCB: DS 37 ;FCB for the file +002B 0053 +002B 0054 ORG 100H +0100 0055 PUT 100H +0100 0056 +0100 EB 75 0057 JP BEGIN +0102 0058 +0102 0D 0A 53 65 61 74 74 0059 HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.31' + 6C 65 20 43 6F 6D 70 + 75 74 65 72 20 50 72 + 6F 64 75 63 74 73 20 + 38 30 38 36 20 41 73 + 73 65 6D 62 6C 65 72 + 20 56 65 72 73 69 6F + 6E 20 32 2E 33 31 +0139 0D 0A 43 6F 70 79 72 0060 DB 13,10,'Copyright 1979,80,81 by Seattle Computer Products, Inc.' + 69 67 68 74 20 31 39 + 37 39 2C 38 30 2C 38 + 31 20 62 79 20 53 65 + 61 74 74 6C 65 20 43 + 6F 6D 70 75 74 65 72 + 20 50 72 6F 64 75 63 + 74 73 2C 20 49 6E 63 + 2E +0172 0D 0A 0D 0A 24 0061 DB 13,10,13,10,'$' +0177 0062 +0177 0063 BEGIN: +0177 BC 90 24 0064 MOV SP,STACK +017A BA 02 01 0065 MOV DX,HEADER +017D B4 09 0066 MOV AH,PRINTMES +017F CD 21 0067 INT 33 +0181 A0 6D 00 0068 MOV AL,[FCB+17] +0184 A2 D0 1B 0069 MOV [SYMFLG],AL ;Save symbol table request flag +0187 BE 65 00 0070 MOV SI,FCB+9 ;Point to file extension +018A AC 0071 LODB ;Get source drive letter +018B E8 10 01 0072 CALL CHKDSK ;Valid drive? +018E 0A C0 0073 OR AL,AL +0190 74 03 0074 JZ DEFAULT ;If no extension, use existing drive spec +0192 A2 5C 00 0075 MOV [FCB],AL +0195 0076 DEFAULT: +0195 AC 0077 LODB ;Get HEX file drive letter +0196 3C 5A 0078 CMP AL,'Z' ;Suppress HEX file? +0198 74 03 0079 JZ L0000 +019A E8 01 01 0080 CALL CHKDSK +019D 0081 L0000: +019D A2 1B 1B 0082 MOV [HEXFCB],AL +01A0 AC 0083 LODB ;Get PRN file drive letter +01A1 B4 00 0084 MOV AH,0 ;Signal no PRN file +01A3 3C 5A 0085 CMP AL,'Z' ;Suppress PRN file? +01A5 74 15 0086 JZ NOPRN +01A7 3C 59 0087 CMP AL,'Y' ;Print errors only on console? +01A9 74 11 0088 JZ NOPRN +01AB B4 02 0089 MOV AH,2 +01AD 3C 58 0090 CMP AL,'X' ;PRN file to console? +01AF 74 0B 0091 JZ NOPRN +01B1 B4 04 0092 MOV AH,4 +01B3 3C 50 0093 CMP AL,'P' ;PRN file to printer? +01B5 74 05 0094 JZ NOPRN +01B7 E8 E4 00 0095 CALL CHKDSK +01BA B4 80 0096 MOV AH,80H +01BC 0097 NOPRN: +01BC A2 40 1B 0098 MOV [LSTFCB],AL +01BF 88 26 EC 1B 0099 MOV [LSTDEV],AH ;Flag device for list ouput +01C3 BE 0A 1B 0100 MOV SI,EXTEND +01C6 BF 65 00 0101 MOV DI,FCB+9 +01C9 A5 0102 MOVW +01CA A4 0103 MOVB ;Set extension to ASM +01CB A5 0104 MOVW ;Zero extent field +01CC BA 5C 00 0105 MOV DX,FCB +01CF B4 0F 0106 MOV AH,OPEN +01D1 CD 21 0107 INT 33 +01D3 BB AF 1A 0108 MOV BX,NOFILE +01D6 0A C0 0109 OR AL,AL +01D8 74 03 0110 JZ $+5 +01DA E9 97 00 0111 JMP PRERR +01DD BA 1B 1B 0112 MOV DX,HEXFCB +01E0 E8 99 00 0113 CALL MAKFIL +01E3 BA 40 1B 0114 MOV DX,LSTFCB +01E6 E8 93 00 0115 CALL MAKFIL +01E9 C6 06 7C 00 00 0116 MOV B,[FCB+32],0 ;Zero Next Record field +01EE C7 06 6A 00 00 04 0117 MOV [FCB+14],BUFSIZ ;Set record size +01F4 C7 06 3E 20 40 20 0118 MOV [BUFPT],SRCBUF ;Initialize buffer pointer +01FA C7 06 D1 1B 91 24 0119 MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE +0200 C7 06 F2 1B 90 24 0120 MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE +0206 33 C0 0121 XOR AX,AX +0208 A3 65 1B 0122 MOV [PC],AX ;DEFAULT PROGRAM COUNTER +020B A3 CC 1B 0123 MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL +020E A3 EA 1B 0124 MOV [RETPT],AX ;Pointer to last RET record +0211 A2 E4 1B 0125 MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF +0214 A2 E5 1B 0126 MOV [CHKLAB],AL ;LOOKUP ALL LABELS +0217 48 0127 DEC AX +0218 A3 E8 1B 0128 MOV [LSTRET],AX ;Location of last RET +021B A1 06 00 0129 MOV AX,[6] ;HL=END OF MEMORY +021E A3 CE 1B 0130 MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE +0221 C7 06 D5 1B 04 00 0131 MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE +0227 0132 +0227 0133 ;Assemble each line of code +0227 0134 +0227 0135 LOOP: +0227 E8 8A 00 0136 CALL NEXTCHR ;Get first character on line +022A 3C 1A 0137 CMP AL,1AH +022C 74 1E 0138 JZ ENDJ +022E B0 FF 0139 MOV AL,-1 ;Flag that no tokens have been read yet +0230 A2 CB 1B 0140 MOV [SYM],AL +0233 E8 89 06 0141 CALL ASMLIN ;Assemble the line +0236 A0 CB 1B 0142 MOV AL,[SYM] +0239 3C FF 0143 CMP AL,-1 ;Any tokens found on line? +023B 75 03 0144 JNZ L0002 +023D E8 67 03 0145 CALL GETSYM ;If no tokens read yet, read first one +0240 0146 L0002: +0240 3C 3B 0147 CMP AL,';' +0242 74 0B 0148 JZ ENDLN +0244 3C 0D 0149 CMP AL,EOL +0246 74 07 0150 JZ ENDLN +0248 B0 14 0151 MOV AL,14H ;Garbage at end of line error +024A EB 05 0152 JP ENDLIN +024C E9 B9 0D 0153 ENDJ: JMP END +024F 0154 +024F 0155 ENDLN: +024F 32 C0 0156 XOR AL,AL ;Flag no errors on line +0251 0157 ENDLIN: +0251 0158 ;AL = error code for line. Stack depth unknown +0251 BC 90 24 0159 MOV SP,STACK +0254 E8 02 00 0160 CALL NEXLIN +0257 EB CE 0161 JP LOOP +0259 0162 +0259 0163 NEXLIN: +0259 B5 C0 0164 MOV CH,0C0H ;Put end of line marker and error code (AL) +025B E8 00 08 0165 CALL PUTCD +025E E8 C7 07 0166 CALL GEN1 +0261 A0 CA 1B 0167 MOV AL,[CHR] +0264 0168 GETEOL: +0264 3C 0A 0169 CMP AL,10 +0266 74 35 0170 JZ RET +0268 3C 1A 0171 CMP AL,1AH +026A 74 E0 0172 JZ ENDJ +026C E8 45 00 0173 CALL NEXTCHR ;Scan over comments for linefeed +026F EB F3 0174 JP GETEOL +0271 0175 +0271 0176 ABORT: +0271 BB 97 1A 0177 MOV BX,NOMEM +0274 0178 PRERR: +0274 8B D3 0179 MOV DX,BX +0276 B4 09 0180 MOV AH,PRINTMES +0278 CD 21 0181 INT 33 +027A CD 20 0182 INT 32 +027C 0183 +027C 0184 MAKFIL: +027C 8B F2 0185 MOV SI,DX +027E AC 0186 LODB ;Get drive select byte +027F 3C 20 0187 CMP AL,20H ;If not valid, don't make file +0281 73 1A 0188 JNC RET +0283 B9 04 00 0189 MOV CX,4 +0286 8B FE 0190 MOV DI,SI +0288 BE 5D 00 0191 MOV SI,FCB+1 +028B F3 0192 REP +028C A5 0193 MOVW ;Copy source file name +028D B4 16 0194 MOV AH,MAKE +028F CD 21 0195 INT 33 +0291 C7 45 05 01 00 0196 MOV [DI-9+14],1 ;Set record length to 1 byte +0296 BB 7D 1A 0197 MOV BX,NOSPAC +0299 0A C0 0198 OR AL,AL ;Success? +029B 75 D7 0199 JNZ PRERR +029D C3 0200 RET +029E 0201 +029E 0202 CHKDSK: +029E 2C 20 0203 SUB AL,' ' ;If not present, set zero flag +02A0 74 FB 0204 JZ RET +02A2 2C 20 0205 SUB AL,20H +02A4 74 04 0206 JZ DSKERR ;Must be in range A-O +02A6 3C 10 0207 CMP AL,'P'-'@' +02A8 72 F3 0208 JC RET +02AA 0209 DSKERR: +02AA BB D0 1A 0210 MOV BX,BADDSK +02AD EB C5 0211 JP PRERR +02AF 0212 +02AF 0213 ERROR: +02AF 8A C1 0214 MOV AL,CL +02B1 E9 9D FF 0215 JMP ENDLIN +02B4 0216 +02B4 0217 NEXTCHR: +02B4 8B 36 3E 20 0218 MOV SI,[BUFPT] +02B8 81 FE 40 20 0219 CMP SI,SRCBUF +02BC 75 15 0220 JNZ GETCH +02BE 0221 ;Buffer empty so refill it +02BE 52 0222 PUSH DX +02BF 8B D6 0223 MOV DX,SI +02C1 B4 1A 0224 MOV AH,SETDMA +02C3 CD 21 0225 INT 33 +02C5 BA 5C 00 0226 MOV DX,FCB +02C8 B4 14 0227 MOV AH,READ +02CA CD 21 0228 INT 33 +02CC 5A 0229 POP DX +02CD 3C 01 0230 CMP AL,1 +02CF B0 1A 0231 MOV AL,1AH ;Possibly signal End of File +02D1 74 0A 0232 JZ NOMOD ;If nothing read +02D3 0233 GETCH: +02D3 AC 0234 LODB +02D4 81 FE 40 24 0235 CMP SI,SRCBUF+BUFSIZ +02D8 75 03 0236 JNZ NOMOD +02DA BE 40 20 0237 MOV SI,SRCBUF +02DD 0238 NOMOD: +02DD 89 36 3E 20 0239 MOV [BUFPT],SI +02E1 A2 CA 1B 0240 MOV [CHR],AL +02E4 C3 0241 RET +02E5 0242 +02E5 0243 +02E5 0244 MROPS: +02E5 0245 +02E5 0246 ; Get two operands and check for certain types, according to flag byte +02E5 0247 ; in CL. OP code in CH. Returns only if immediate operation. +02E5 0248 +02E5 51 0249 PUSH CX ;Save type flags +02E6 E8 D8 00 0250 CALL GETOP +02E9 52 0251 PUSH DX ;Save first operand +02EA E8 CB 00 0252 CALL GETOP2 +02ED 5B 0253 POP BX ;First op in BX, second op in DX +02EE B0 04 0254 MOV AL,SREG ;Check for a segment register +02F0 3A C7 0255 CMP AL,BH +02F2 74 41 0256 JZ SEGCHK +02F4 3A C6 0257 CMP AL,DH +02F6 74 3D 0258 JZ SEGCHK +02F8 B0 01 0259 MOV AL,CONST ;Check if the first operand is immediate +02FA B1 1A 0260 MOV CL,26 +02FC 3A C7 0261 CMP AL,BH +02FE 74 AF 0262 JZ ERROR ;Error if so +0300 59 0263 POP CX ;Restore type flags +0301 3A C6 0264 CMP AL,DH ;If second operand is immediate, then done +0303 74 DF 0265 JZ RET +0305 B0 00 0266 MOV AL,UNDEFID ;Check for memory reference +0307 3A C7 0267 CMP AL,BH +0309 74 4F 0268 JZ STORE ;Is destination memory? +030B 3A C6 0269 CMP AL,DH +030D 74 55 0270 JZ LOAD ;Is source memory? +030F F6 C1 01 0271 TEST CL,1 ;Check if register-to-register operation OK +0312 B1 1B 0272 MOV CL,27 +0314 74 99 0273 JZ ERROR +0316 8A C6 0274 MOV AL,DH +0318 3A C7 0275 CMP AL,BH ;Registers must be of same length +031A 0276 RR: +031A B1 16 0277 MOV CL,22 +031C 75 91 0278 JNZ ERROR +031E 0279 RR1: +031E 24 01 0280 AND AL,1 ;Get register length (1=16 bits) +0320 0A C5 0281 OR AL,CH ;Or in to OP code +0322 E8 F6 06 0282 CALL PUT ;And write it +0325 59 0283 POP CX ;Dump return address +0326 8A C3 0284 MOV AL,BL +0328 02 C0 0285 ADD AL,AL ;Rotate register number into middle position +032A 02 C0 0286 ADD AL,AL +032C 02 C0 0287 ADD AL,AL +032E 0C C0 0288 OR AL,0C0H ;Set register-to-register mode +0330 0A C2 0289 OR AL,DL ;Combine with other register number +0332 E9 E6 06 0290 JMP PUT +0335 0291 +0335 0292 SEGCHK: +0335 0293 ;Come here if at least one operand is a segment register +0335 59 0294 POP CX ;Restore flags +0336 F6 C1 08 0295 TEST CL,8 ;Check if segment register OK +0339 B1 16 0296 MOV CL,22 +033B 74 78 0297 JZ ERR1 +033D B9 03 8E 0298 MOV CX,8E03H ;Segment register move OP code +0340 B0 00 0299 MOV AL,UNDEFID +0342 3A C6 0300 CMP AL,DH ;Check if source is memory +0344 74 1E 0301 JZ LOAD +0346 3A C7 0302 CMP AL,BH ;Check if destination is memory +0348 74 10 0303 JZ STORE +034A B0 03 0304 MOV AL,XREG +034C 2A C6 0305 SUB AL,DH ;Check if source is 16-bit register +034E 74 CA 0306 JZ RR ;If so, AL must be zero +0350 B5 8C 0307 MOV CH,8CH ;Change direction +0352 87 DA 0308 XCHG DX,BX ;Flip which operand is first and second +0354 B0 03 0309 MOV AL,XREG +0356 2A C6 0310 SUB AL,DH ;Let RR perform finish the test +0358 EB C0 0311 JP RR +035A 0312 +035A 0313 STORE: +035A F6 C1 04 0314 TEST CL,004H ;Check if storing is OK +035D 75 52 0315 JNZ STERR +035F 87 DA 0316 XCHG DX,BX ;If so, flip operands +0361 80 E5 FD 0317 AND CH,0FDH ; and zero direction bit +0364 0318 LOAD: +0364 B6 19 0319 MOV DH,25 +0366 3A C7 0320 CMP AL,BH ;Check if memory-to-memory +0368 74 49 0321 JZ MRERR +036A 8A C7 0322 MOV AL,BH +036C 3C 02 0323 CMP AL,REG ;Check if 8-bit operation +036E 75 07 0324 JNZ XRG +0370 B6 16 0325 MOV DH,22 +0372 F6 C1 01 0326 TEST CL,1 ;See if 8-bit operation is OK +0375 74 3C 0327 JZ MRERR +0377 0328 XRG: +0377 8A C2 0329 MOV AL,DL +0379 2C 06 0330 SUB AL,6 ;Check for R/M mode 6 and register 0 +037B 0A C3 0331 OR AL,BL ; meaning direct load/store of accumulator +037D 75 19 0332 JNZ NOTAC +037F F6 C1 08 0333 TEST CL,8 ;See if direct load/store of accumulator +0382 74 14 0334 JZ NOTAC ; means anything in this case +0384 0335 ; Process direct load/store of accumulator +0384 8A C5 0336 MOV AL,CH +0386 24 02 0337 AND AL,2 ;Preserve direction bit only +0388 34 02 0338 XOR AL,2 ; but flip it +038A 0C A0 0339 OR AL,0A0H ;Combine with OP code +038C 8A E8 0340 MOV CH,AL +038E 8A C7 0341 MOV AL,BH ;Check byte/word operation +0390 24 01 0342 AND AL,1 +0392 0A C5 0343 OR AL,CH +0394 59 0344 POP CX ;Dump return address +0395 E9 47 07 0345 JMP PUTADD ;Write the address +0398 0346 +0398 0347 NOTAC: +0398 8A C7 0348 MOV AL,BH +039A 24 01 0349 AND AL,1 ;Get byte/word bit +039C 22 C1 0350 AND AL,CL ;But don't use it in word-only operations +039E 0A C5 0351 OR AL,CH ;Combine with OP code +03A0 E8 78 06 0352 CALL PUT +03A3 8A C3 0353 MOV AL,BL +03A5 02 C0 0354 ADD AL,AL ;Rotate to middle position +03A7 02 C0 0355 ADD AL,AL +03A9 02 C0 0356 ADD AL,AL +03AB 0A C2 0357 OR AL,DL ;Combine register field +03AD 59 0358 POP CX ;Dump return address +03AE E9 2E 07 0359 JMP PUTADD ;Write the address +03B1 0360 +03B1 0361 STERR: +03B1 B6 1D 0362 MOV DH,29 +03B3 0363 MRERR: +03B3 8A CE 0364 MOV CL,DH +03B5 0365 +03B5 E9 F7 FE 0366 ERR1: JMP ERROR +03B8 0367 +03B8 0368 GETOP2: +03B8 0369 ;Get the second operand: look for a comma and drop into GETOP +03B8 A0 CB 1B 0370 MOV AL,[SYM] +03BB 3C 2C 0371 CMP AL,',' +03BD B1 15 0372 MOV CL,21 +03BF 75 F4 0373 JNZ ERR1 +03C1 0374 +03C1 0375 +03C1 0376 GETOP: +03C1 0377 +03C1 0378 ; Get one operand. Operand may be a memory reference in brackets, a register, +03C1 0379 ; or a constant. If a flag (such as "B" for byte operation) is encountered, +03C1 0380 ; it is noted and processing continues to find the operand. +03C1 0381 ; +03C1 0382 ; On exit, AL (=DH) has the type of operand. Other information depends +03C1 0383 ; on the actual operand: +03C1 0384 ; +03C1 0385 ; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +03C1 0386 ; the 8086 R/M format (middle bits zero). The constant part of the address +03C1 0387 ; is in ADDR. If an undefined label needs to be added to this, a pointer to +03C1 0388 ; its information fields is in ALABEL, otherwise ALABEL is zero. +03C1 0389 ; +03C1 0390 ; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +03C1 0391 ; to be added to this, a pointer to its information fields is in DLABEL, +03C1 0392 ; otherwise DLABEL is zero. "$" and "RET" are in this class. +03C1 0393 ; +03C1 0394 ; AL=DH=2 8-bit Register. DL has the register number. +03C1 0395 ; +03C1 0396 ; AL=DH=3 16-bit Register. DL has the register number. +03C1 0397 ; +03C1 0398 ; AL=DH=4 Segment Register. DL has the register number. +03C1 0399 +03C1 E8 E3 01 0400 CALL GETSYM +03C4 0401 GETOP1: +03C4 0402 ;Enter here if we don't need a GETSYM first +03C4 3C 5B 0403 CMP AL,'[' ;Memory reference? +03C6 74 30 0404 JZ MEM +03C8 3C 05 0405 CMP AL,5 ;Flag ("B", "W", etc.)? +03CA 74 57 0406 JZ FLG +03CC 3C 02 0407 CMP AL,REG ;8-Bit register? +03CE 74 20 0408 JZ NREG +03D0 3C 03 0409 CMP AL,XREG ;16-Bit register? +03D2 74 1C 0410 JZ NREG +03D4 3C 04 0411 CMP AL,SREG ;Segment register? +03D6 74 18 0412 JZ NREG +03D8 0413 VAL: ;Must be immediate +03D8 32 C0 0414 XOR AL,AL ;No addressing modes allowed +03DA 0415 VAL1: +03DA E8 4F 00 0416 CALL GETVAL +03DD A1 75 1B 0417 MOV AX,[CON] ;Defined part +03E0 A3 71 1B 0418 MOV [DATA],AX +03E3 A1 77 1B 0419 MOV AX,[UNDEF] ;Undefined part +03E6 A3 73 1B 0420 MOV [DLABEL],AX +03E9 8A D5 0421 MOV DL,CH +03EB B6 01 0422 MOV DH,CONST +03ED 8A C6 0423 MOV AL,DH +03EF C3 0424 RET +03F0 0425 NREG: +03F0 52 0426 PUSH DX +03F1 E8 B3 01 0427 CALL GETSYM +03F4 5A 0428 POP DX +03F5 8A C6 0429 MOV AL,DH +03F7 C3 0430 RET +03F8 0431 MEM: +03F8 E8 AC 01 0432 CALL GETSYM +03FB B0 01 0433 MOV AL,1 +03FD E8 2C 00 0434 CALL GETVAL +0400 A0 CB 1B 0435 MOV AL,[SYM] +0403 3C 5D 0436 CMP AL,']' +0405 B1 18 0437 MOV CL,24 +0407 75 AC 0438 JNZ ERR1 +0409 E8 9B 01 0439 CALL GETSYM +040C 8B 1E 75 1B 0440 MOV BX,[CON] +0410 89 1E 6D 1B 0441 MOV [ADDR],BX +0414 8B 1E 77 1B 0442 MOV BX,[UNDEF] +0418 89 1E 6F 1B 0443 MOV [ALABEL],BX +041C 8A D5 0444 MOV DL,CH +041E B6 00 0445 MOV DH,UNDEFID +0420 8A C6 0446 MOV AL,DH +0422 C3 0447 RET +0423 0448 FLG: +0423 E8 81 01 0449 CALL GETSYM +0426 3C 2C 0450 CMP AL,',' +0428 74 97 0451 JZ GETOP +042A EB 98 0452 JP GETOP1 +042C 0453 +042C 0454 +042C 0455 GETVAL: +042C 0456 +042C 0457 ; Expression analyzer. On entry, if AL=0 then do not allow base or index +042C 0458 ; registers. If AL=1, we are analyzing a memory reference, so allow base +042C 0459 ; and index registers, and compute addressing mode when done. The constant +042C 0460 ; part of the expression will be found in CON. If an undefined label is to +042C 0461 ; be added to this, a pointer to its information fields will be found in +042C 0462 ; UNDEF. +042C 0463 +042C 95 0464 XCHG AX,BP ;Flag is kept in BP +042D 53 0465 PUSH BX +042E BB 00 00 0466 MOV BX,0 +0431 89 1E 75 1B 0467 MOV [CON],BX +0435 89 1E 77 1B 0468 MOV [UNDEF],BX +0439 5B 0469 POP BX +043A A0 CB 1B 0470 MOV AL,[SYM] +043D 3C 2B 0471 CMP AL,'+' +043F 74 09 0472 JZ PLSMNS +0441 3C 2D 0473 CMP AL,'-' +0443 74 05 0474 JZ PLSMNS +0445 B1 2B 0475 MOV CL,'+' +0447 51 0476 PUSH CX +0448 EB 08 0477 JP OPERATE +044A 0478 PLSMNS: +044A 50 0479 PUSH AX +044B 81 CD 04 00 0480 OR BP,4 ;Flag that a sign was found +044F E8 55 01 0481 CALL GETSYM +0452 0482 OPERATE: +0452 3C 01 0483 CMP AL,CONST +0454 75 03 0484 JNZ $+5 +0456 E9 C3 00 0485 JMP CVAL +0459 3C 00 0486 CMP AL,UNDEFID +045B 75 03 0487 JNZ $+5 +045D E9 CA 00 0488 JMP UVAL +0460 3C 22 0489 CMP AL,'"' +0462 75 03 0490 JNZ $+5 +0464 E9 DE 00 0491 STRINGJ:JMP STRING +0467 3C 27 0492 CMP AL,"'" +0469 74 F9 0493 JZ STRINGJ +046B 3C 03 0494 CMP AL,XREG ;Only 16-bit register may index +046D B1 14 0495 MOV CL,20 +046F 75 20 0496 JNZ ERR2 +0471 F7 C5 01 00 0497 TEST BP,1 ;Check to see if indexing is OK +0475 B1 01 0498 MOV CL,1 +0477 74 18 0499 JZ ERR2 +0479 8A C2 0500 MOV AL,DL +047B B1 03 0501 MOV CL,3 +047D 3C 03 0502 CMP AL,3 ;Check for BX +047F 74 25 0503 JZ BXJ +0481 2C 05 0504 SUB AL,5 ;Check for BP +0483 74 2A 0505 JZ BPJ +0485 FE C8 0506 DEC AL ;Check for SI +0487 B1 04 0507 MOV CL,4 +0489 74 12 0508 JZ SIJ +048B FE C8 0509 DEC AL ;Check for DI +048D 74 05 0510 JZ DIJ +048F B1 02 0511 MOV CL,2 ;Invalid base/index register +0491 E9 1B FE 0512 ERR2: JMP ERROR +0494 0513 DIJ: +0494 95 0514 XCHG AX,BP +0495 A8 10 0515 TEST AL,10H ;Check if already seen index register +0497 75 F8 0516 JNZ ERR2 +0499 0C 30 0517 OR AL,30H ;Flag seeing index register DI +049B EB 19 0518 JP LPCHK +049D 0519 SIJ: +049D 95 0520 XCHG AX,BP +049E A8 10 0521 TEST AL,010H ;Check if already seen index register +04A0 75 EF 0522 JNZ ERR2 +04A2 0C 10 0523 OR AL,010H ;Flag seeing index register SI +04A4 EB 10 0524 JP LPCHK +04A6 0525 BXJ: +04A6 95 0526 XCHG AX,BP +04A7 A8 80 0527 TEST AL,080H ;Check if already seen base register +04A9 75 E6 0528 JNZ ERR2 +04AB 0C 80 0529 OR AL,080H ;Flag seeing base register BX +04AD EB 07 0530 JP LPCHK +04AF 0531 BPJ: +04AF 95 0532 XCHG AX,BP +04B0 A8 80 0533 TEST AL,080H ;Check if already seen base register +04B2 75 DD 0534 JNZ ERR2 +04B4 0C C0 0535 OR AL,0C0H ;Flag seeing base register BP +04B6 0536 LPCHK: +04B6 95 0537 XCHG AX,BP +04B7 58 0538 POP AX ;Get operator +04B8 3C 2D 0539 CMP AL,'-' ;Can't subtract a register +04BA B1 05 0540 MOV CL,5 +04BC 74 D3 0541 JZ ERR2 +04BE 0542 NEXTER: +04BE E8 E6 00 0543 CALL GETSYM +04C1 3C 2B 0544 CMP AL,'+' +04C3 75 03 0545 JNZ $+5 +04C5 E9 82 FF 0546 PJ: JMP PLSMNS +04C8 3C 2D 0547 CMP AL,'-' +04CA 74 F9 0548 JZ PJ +04CC 95 0549 XCHG AX,BP +04CD B5 00 0550 MOV CH,0 +04CF A8 10 0551 TEST AL,010H ;Test INDEX bit +04D1 D0 D0 0552 RCL AL ;BASE bit (zero flag not affected) +04D3 74 3B 0553 JZ NOIND ;Jump if not indexed, with BASE bit in carry +04D5 F5 0554 CMC +04D6 D0 D5 0555 RCL CH +04D8 D0 D0 0556 RCL AL ;BP bit +04DA D0 D5 0557 RCL CH +04DC D0 D0 0558 RCL AL ;DI bit +04DE D0 D5 0559 RCL CH ;The low 3 bits now have indexing mode +04E0 0560 MODE: +04E0 80 CD 80 0561 OR CH,080H ;If undefined label, force 16-bit displacement +04E3 F7 06 77 1B FF FF 0562 TEST [UNDEF],-1 +04E9 75 1E 0563 JNZ RET +04EB 8B 1E 75 1B 0564 MOV BX,[CON] +04EF E8 18 00 0565 CALL SIGNEXT ;Check if 8-bit with sign extended +04F2 75 15 0566 JNZ RET ;If not, use 16-bit displacement +04F4 80 E5 7F 0567 AND CH,07FH ;Reset 16-bit displacement +04F7 80 CD 40 0568 OR CH,040H ;Set 8-bit displacement +04FA 0B DB 0569 OR BX,BX +04FC 75 0B 0570 JNZ RET ;Use it if not zero displacement +04FE 80 E5 07 0571 AND CH,7 ;Specify no displacement +0501 82 FD 06 0572 CMP CH,6 ;Check for BP+0 addressing mode +0504 75 03 0573 JNZ RET +0506 80 CD 40 0574 OR CH,040H ;If BP+0, use 8-bit displacement +0509 C3 0575 RET +050A 0576 +050A 0577 SIGNEXT: +050A 0578 ; Return with zero flag set if value in BX is a valid sign-extended +050A 0579 ; 8-bit value. AX destroyed +050A 8A C3 0580 MOV AL,BL +050C 98 0581 CBW +050D 3B C3 0582 CMP AX,BX +050F C3 0583 RET +0510 0584 +0510 0585 NOIND: +0510 B5 06 0586 MOV CH,6 ;Try direct address mode +0512 73 FB 0587 JNC RET ;If no base register, that's right +0514 D0 D0 0588 RCL AL ;Check BP bit +0516 72 C8 0589 JC MODE +0518 FE C5 0590 INC CH ;If not, must be BX +051A EB C4 0591 JP MODE +051C 0592 +051C 0593 CVAL: +051C 58 0594 POP AX +051D 3C 2D 0595 CMP AL,'-' +051F 75 02 0596 JNZ ADDCON +0521 F7 DA 0597 NEG DX +0523 0598 ADDCON: +0523 01 16 75 1B 0599 ADD [CON],DX +0527 E9 94 FF 0600 JMP NEXTER +052A 0601 +052A 0602 UVAL: +052A 95 0603 XCHG AX,BP +052B B1 06 0604 MOV CL,6 +052D A8 08 0605 TEST AL,008H ;Check if undefined label has been seen +052F 75 11 0606 JNZ ERR30 +0531 0C 08 0607 OR AL,008H ;Flag seeing undefined label +0533 95 0608 XCHG AX,BP +0534 89 1E 77 1B 0609 MOV [UNDEF],BX +0538 58 0610 POP AX +0539 3C 2B 0611 CMP AL,'+' ;Undefined label may only be added +053B B1 05 0612 MOV CL,5 +053D 75 03 0613 JNZ ERR30 +053F E9 7C FF 0614 JMP NEXTER +0542 0615 +0542 E9 6A FD 0616 ERR30: JMP ERROR +0545 0617 +0545 0618 STRING: +0545 8A E8 0619 MOV CH,AL +0547 A0 CA 1B 0620 MOV AL,[CHR] +054A 3A C5 0621 CMP AL,CH +054C B1 23 0622 MOV CL,35 +054E 8A D0 0623 MOV DL,AL +0550 B6 00 0624 MOV DH,0 +0552 75 03 0625 JNZ L0003 +0554 E8 36 00 0626 CALL ZERLEN +0557 0627 L0003: +0557 E8 3B 00 0628 CALL GETCHR +055A 9F 0629 LAHF +055B 95 0630 XCHG AX,BP +055C 9E 0631 SAHF +055D B1 25 0632 MOV CL,37 +055F A8 02 0633 TEST AL,002H +0561 74 DF 0634 JZ ERR30 +0563 A8 04 0635 TEST AL,004H +0565 B1 26 0636 MOV CL,38 +0567 75 D9 0637 JNZ ERR30 +0569 9F 0638 LAHF +056A 95 0639 XCHG AX,BP +056B 9E 0640 SAHF +056C 0641 STRGDAT: +056C 8A C2 0642 MOV AL,DL +056E 3C 0D 0643 CMP AL,EOL +0570 B1 27 0644 MOV CL,39 +0572 74 CE 0645 JZ ERR30 +0574 E8 A4 04 0646 CALL PUT +0577 A0 D3 1B 0647 MOV AL,[DATSIZ] +057A 0A C0 0648 OR AL,AL +057C 75 05 0649 JNZ BYTSIZ +057E 8A C6 0650 MOV AL,DH +0580 E8 98 04 0651 CALL PUT +0583 0652 BYTSIZ: +0583 A0 CA 1B 0653 MOV AL,[CHR] +0586 8A D0 0654 MOV DL,AL +0588 E8 0A 00 0655 CALL GETCHR +058B EB DF 0656 JP STRGDAT +058D 0657 ZERLEN: +058D E8 24 FD 0658 CALL NEXTCHR +0590 3A C5 0659 CMP AL,CH +0592 75 AE 0660 JNZ ERR30 +0594 C3 0661 RET +0595 0662 GETCHR: +0595 E8 1C FD 0663 CALL NEXTCHR +0598 3A C5 0664 CMP AL,CH +059A 75 F8 0665 JNZ RET +059C E8 15 FD 0666 CALL NEXTCHR +059F 3A C5 0667 CMP AL,CH +05A1 74 F1 0668 JZ RET +05A3 5B 0669 POP BX +05A4 E9 75 FF 0670 JMP CVAL +05A7 0671 +05A7 0672 +05A7 0673 GETSYM: +05A7 0674 +05A7 0675 ; The lexical scanner. Used only in the operand field. Returns with the token +05A7 0676 ; in SYM and AL, sometimes with additional info in BX or DX. +05A7 0677 ; +05A7 0678 ; AL=SYM=0 Undefined label. BX has pointer to information fields. +05A7 0679 ; +05A7 0680 ; AL=SYM=1 Constant (or defined label). DX has value. +05A7 0681 ; +05A7 0682 ; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +05A7 0683 ; respectively. DL has register number. +05A7 0684 ; +05A7 0685 ; AL=SYM=5 A mode flag (such as "B" for byte operation). Also stored in +05A7 0686 ; appropriate memory location--FLAG or LONG. +05A7 0687 ; +05A7 0688 ; All other values are the ASCII code of the character. Note that this may +05A7 0689 ; never be a letter or number. +05A7 0690 +05A7 E8 20 00 0691 CALL GETSY +05AA A0 CB 1B 0692 MOV AL,[SYM] +05AD C3 0693 RET +05AE 0694 +05AE 0695 SCANB: +05AE A0 CA 1B 0696 MOV AL,[CHR] +05B1 0697 SCANT: +05B1 3C 20 0698 CMP AL,' ' +05B3 74 04 0699 JZ NEXB +05B5 3C 09 0700 CMP AL,9 +05B7 75 F4 0701 JNZ RET +05B9 0702 NEXB: +05B9 E8 F8 FC 0703 CALL NEXTCHR +05BC EB F3 0704 JP SCANT +05BE 0705 +05BE 0706 DOLLAR: +05BE 8B 16 67 1B 0707 MOV DX,[OLDPC] +05C2 B0 01 0708 MOV AL,CONST +05C4 A2 CB 1B 0709 MOV [SYM],AL +05C7 0710 NEXTCHJ: +05C7 E9 EA FC 0711 JMP NEXTCHR +05CA 0712 +05CA 0713 GETSY: +05CA E8 E1 FF 0714 CALL SCANB +05CD 3C 24 0715 CMP AL,'$' +05CF 74 ED 0716 JZ DOLLAR +05D1 A2 CB 1B 0717 MOV [SYM],AL +05D4 0C 20 0718 OR AL,20H +05D6 3C 7B 0719 CMP AL,'z'+1 +05D8 73 ED 0720 JNC NEXTCHJ +05DA 3C 61 0721 CMP AL,'a' +05DC 72 03 0722 JC $+5 +05DE E9 BF 00 0723 JMP LETTER +05E1 3C 3A 0724 CMP AL,'9'+1 +05E3 73 E2 0725 JNC NEXTCHJ +05E5 3C 30 0726 CMP AL,'0' +05E7 72 DE 0727 JC NEXTCHJ +05E9 BB CB 1B 0728 MOV BX,SYM +05EC C6 07 01 0729 MOV B,[BX],CONST +05EF E8 83 00 0730 CALL READID +05F2 4B 0731 DEC BX +05F3 8A 07 0732 MOV AL,[BX] +05F5 B1 07 0733 MOV CL,7 +05F7 BB 00 00 0734 MOV BX,0 +05FA 3C 68 0735 CMP AL,'h' +05FC 75 03 0736 JNZ $+5 +05FE E9 32 00 0737 JMP HEX +0601 FE C1 0738 INC CL +0603 C7 06 F0 1B 7A 1B 0739 MOV [IX],ID +0609 0740 DEC: +0609 8B 36 F0 1B 0741 MOV SI,[IX] +060D 8A 04 0742 MOV AL,[SI] +060F FF 06 F0 1B 0743 INC [IX] +0613 3C 3A 0744 CMP AL,'9'+1 +0615 72 03 0745 JC $+5 +0617 E9 95 FC 0746 JMP ERROR +061A 2C 30 0747 SUB AL,'0' +061C 8B D3 0748 MOV DX,BX +061E D1 E3 0749 SHL BX +0620 D1 E3 0750 SHL BX +0622 03 DA 0751 ADD BX,DX +0624 D1 E3 0752 SHL BX +0626 8A D0 0753 MOV DL,AL +0628 B6 00 0754 MOV DH,0 +062A 03 DA 0755 ADD BX,DX +062C FE CD 0756 DEC CH +062E 75 D9 0757 JNZ DEC +0630 87 DA 0758 XCHG DX,BX +0632 C3 0759 RET +0633 0760 +0633 0761 HEX: +0633 BA 7A 1B 0762 MOV DX,ID +0636 FE CD 0763 DEC CH +0638 0764 HEX1: +0638 8B F2 0765 MOV SI,DX +063A AC 0766 LODB +063B 42 0767 INC DX +063C 2C 30 0768 SUB AL,'0' +063E 3C 0A 0769 CMP AL,10 +0640 72 06 0770 JC GOTIT +0642 3C 37 0771 CMP AL,'g'-'0' +0644 73 13 0772 JNC ERR4 +0646 2C 27 0773 SUB AL,'a'-10-'0' +0648 0774 GOTIT: +0648 D1 E3 0775 SHL BX +064A D1 E3 0776 SHL BX +064C D1 E3 0777 SHL BX +064E D1 E3 0778 SHL BX +0650 02 D8 0779 ADD BL,AL +0652 FE CD 0780 DEC CH +0654 75 E2 0781 JNZ HEX1 +0656 87 DA 0782 XCHG DX,BX +0658 C3 0783 RET +0659 0784 +0659 E9 53 FC 0785 ERR4: JMP ERROR +065C 0786 +065C 0787 GETLET: +065C E8 4F FF 0788 CALL SCANB +065F 3C 0D 0789 CMP AL,EOL +0661 F9 0790 STC +0662 74 F4 0791 JZ RET +0664 3C 3B 0792 CMP AL,';' +0666 F9 0793 STC +0667 74 EF 0794 JZ RET +0669 B1 0A 0795 MOV CL,10 +066B 0C 20 0796 OR AL,20H +066D 3C 61 0797 CMP AL,'a' +066F 72 E8 0798 JC ERR4 +0671 3C 7B 0799 CMP AL,'z'+1 +0673 73 E4 0800 JNC ERR4 +0675 0801 READID: +0675 BB 7A 1B 0802 MOV BX,ID +0678 B5 00 0803 MOV CH,0 +067A 0804 MOREID: +067A 88 07 0805 MOV [BX],AL +067C FE C5 0806 INC CH +067E 43 0807 INC BX +067F E8 32 FC 0808 CALL NEXTCHR +0682 3C 30 0809 CMP AL,'0' +0684 72 0E 0810 JC NOMORE +0686 0C 20 0811 OR AL,20H +0688 3C 7B 0812 CMP AL,'z'+1 +068A 73 08 0813 JNC NOMORE +068C 3C 3A 0814 CMP AL,'9'+1 +068E 72 EA 0815 JC MOREID +0690 3C 61 0816 CMP AL,'a' +0692 73 E6 0817 JNC MOREID +0694 0818 NOMORE: +0694 8A C8 0819 MOV CL,AL +0696 8A C5 0820 MOV AL,CH +0698 A2 79 1B 0821 MOV [LENID],AL +069B 0A C0 0822 OR AL,AL +069D 8A C1 0823 MOV AL,CL +069F C3 0824 RET +06A0 0825 +06A0 0826 LETTER: +06A0 E8 D2 FF 0827 CALL READID +06A3 8A C5 0828 MOV AL,CH +06A5 FE C8 0829 DEC AL +06A7 75 1B 0830 JNZ NOFLG +06A9 A0 7A 1B 0831 MOV AL,[ID] +06AC 3C 6C 0832 CMP AL,'l' +06AE B1 00 0833 MOV CL,0 +06B0 BA 6C 1B 0834 MOV DX,LONG +06B3 74 23 0835 JZ BWFLAG +06B5 3C 62 0836 CMP AL,'b' +06B7 BA 6B 1B 0837 MOV DX,FLAG +06BA 74 1C 0838 JZ BWFLAG +06BC 3C 77 0839 CMP AL,'w' +06BE B1 01 0840 MOV CL,1 +06C0 74 16 0841 JZ BWFLAG +06C2 32 C0 0842 XOR AL,AL +06C4 0843 NOFLG: +06C4 FE C8 0844 DEC AL +06C6 53 0845 PUSH BX +06C7 75 03 0846 JNZ L0004 +06C9 E8 1F 00 0847 CALL REGCHK +06CC 0848 L0004: +06CC 5B 0849 POP BX +06CD 8A C6 0850 MOV AL,DH +06CF 74 03 0851 JZ SYMSAV +06D1 E8 B6 00 0852 CALL LOOKRET +06D4 0853 SYMSAV: +06D4 A2 CB 1B 0854 MOV [SYM],AL +06D7 C3 0855 RET +06D8 0856 +06D8 0857 BWFLAG: +06D8 87 DA 0858 XCHG DX,BX +06DA 8A 07 0859 MOV AL,[BX] +06DC FE C0 0860 INC AL +06DE 88 0F 0861 MOV [BX],CL +06E0 B1 20 0862 MOV CL,32 +06E2 74 03 0863 JZ $+5 +06E4 E9 C8 FB 0864 JMP ERROR +06E7 B0 05 0865 MOV AL,5 +06E9 EB E9 0866 JP SYMSAV +06EB 0867 +06EB 0868 REGCHK: +06EB BB 7A 1B 0869 MOV BX,ID +06EE 8A 0F 0870 MOV CL,[BX] +06F0 9F 0871 LAHF +06F1 43 0872 INC BX +06F2 9E 0873 SAHF +06F3 8A 07 0874 MOV AL,[BX] +06F5 BB 52 07 0875 MOV BX,REGTAB +06F8 B6 03 0876 MOV DH,XREG +06FA B2 00 0877 MOV DL,0 +06FC 3C 78 0878 CMP AL,'x' +06FE 74 3B 0879 JZ SCANREG +0700 B6 02 0880 MOV DH,REG +0702 3C 6C 0881 CMP AL,'l' +0704 74 35 0882 JZ SCANREG +0706 B2 04 0883 MOV DL,4 +0708 3C 68 0884 CMP AL,'h' +070A 74 2F 0885 JZ SCANREG +070C B6 04 0886 MOV DH,SREG +070E B2 00 0887 MOV DL,0 +0710 BB 56 07 0888 MOV BX,SEGTAB +0713 3C 73 0889 CMP AL,'s' +0715 74 24 0890 JZ SCANREG +0717 B6 03 0891 MOV DH,XREG +0719 3C 70 0892 CMP AL,'p' +071B 74 11 0893 JZ PREG +071D 3C 69 0894 CMP AL,'i' +071F 75 B6 0895 JNZ RET +0721 B2 06 0896 MOV DL,6 +0723 8A C1 0897 MOV AL,CL +0725 3C 73 0898 CMP AL,'s' +0727 74 AE 0899 JZ RET +0729 FE C2 0900 INC DL +072B 3C 64 0901 CMP AL,'d' +072D C3 0902 RET +072E 0903 PREG: +072E B2 04 0904 MOV DL,4 +0730 8A C1 0905 MOV AL,CL +0732 3C 73 0906 CMP AL,'s' +0734 74 F7 0907 JZ RET +0736 FE C2 0908 INC DL +0738 3C 62 0909 CMP AL,'b' +073A C3 0910 RET +073B 0911 SCANREG: +073B 8A C1 0912 MOV AL,CL +073D B9 04 00 0913 MOV CX,4 +0740 FC 0914 UP +0741 8B FB 0915 MOV DI,BX +0743 F2 0916 REPNZ +0744 AE 0917 SCAB +0745 8B DF 0918 MOV BX,DI +0747 75 F1 0919 JNZ RET +0749 8A C1 0920 MOV AL,CL +074B 02 C2 0921 ADD AL,DL +074D 8A D0 0922 MOV DL,AL +074F 32 C0 0923 XOR AL,AL +0751 C3 0924 RET +0752 0925 +0752 62 64 63 61 0926 REGTAB: DB 'bdca' +0756 0927 +0756 64 73 63 65 0928 SEGTAB: DB 'dsce' +075A 0929 +075A 0930 LOOK: +075A 8A 2F 0931 MOV CH,[BX] +075C 43 0932 INC BX +075D BA 7A 1B 0933 MOV DX,ID +0760 E8 F4 00 0934 CALL CPSLP +0763 74 EC 0935 JZ RET +0765 34 80 0936 XOR AL,80H +0767 8A C8 0937 MOV CL,AL +0769 4B 0938 DEC BX +076A 8A 07 0939 MOV AL,[BX] +076C 34 80 0940 XOR AL,80H +076E 3A C1 0941 CMP AL,CL +0770 73 04 0942 JNC SMALL +0772 FE C5 0943 INC CH +0774 FE C5 0944 INC CH +0776 0945 SMALL: +0776 8A D5 0946 MOV DL,CH +0778 B6 00 0947 MOV DH,0 +077A 03 DA 0948 ADD BX,DX +077C 8B 17 0949 MOV DX,[BX] +077E 43 0950 INC BX +077F 8A C2 0951 MOV AL,DL +0781 0A C6 0952 OR AL,DH +0783 F9 0953 STC +0784 74 CB 0954 JZ RET +0786 87 DA 0955 XCHG DX,BX +0788 EB D0 0956 JP LOOK +078A 0957 +078A 0958 LOOKRET: +078A 8A C5 0959 MOV AL,CH +078C 3C 03 0960 CMP AL,3 ;RET has 3 letters +078E 75 4D 0961 JNZ LOOKUP +0790 4B 0962 DEC BX +0791 80 0F 80 0963 OR B,[BX],080H +0794 BA 1A 1B 0964 MOV DX,RETSTR+2 +0797 0965 CHKRET: +0797 8B F2 0966 MOV SI,DX +0799 AC 0967 LODB +079A 3A 07 0968 CMP AL,[BX] +079C 75 43 0969 JNZ LOOKIT +079E 4B 0970 DEC BX +079F 4A 0971 DEC DX +07A0 FE CD 0972 DEC CH +07A2 75 F3 0973 JNZ CHKRET +07A4 8B 16 E8 1B 0974 MOV DX,[LSTRET] +07A8 8A C2 0975 MOV AL,DL +07AA 22 C6 0976 AND AL,DH +07AC FE C0 0977 INC AL +07AE 74 0D 0978 JZ ALLRET +07B0 8B 1E 65 1B 0979 MOV BX,[PC] +07B4 2B DA 0980 SUB BX,DX +07B6 E8 51 FD 0981 CALL SIGNEXT +07B9 B0 01 0982 MOV AL,1 +07BB 74 94 0983 JZ RET +07BD 0984 ALLRET: +07BD 8B 1E EA 1B 0985 MOV BX,[RETPT] +07C1 8A C7 0986 MOV AL,BH +07C3 0A C3 0987 OR AL,BL +07C5 B0 00 0988 MOV AL,0 +07C7 75 88 0989 JNZ RET +07C9 8B 1E CE 1B 0990 MOV BX,[HEAP] +07CD 4B 0991 DEC BX +07CE 4B 0992 DEC BX +07CF 4B 0993 DEC BX +07D0 89 1E CE 1B 0994 MOV [HEAP],BX +07D4 32 C0 0995 XOR AL,AL +07D6 88 07 0996 MOV [BX],AL +07D8 89 1E EA 1B 0997 MOV [RETPT],BX +07DC C3 0998 RET +07DD 0999 +07DD 1000 LOOKUP: +07DD 4B 1001 DEC BX +07DE 80 0F 80 1002 OR B,[BX],080H +07E1 1003 LOOKIT: +07E1 8B 1E CC 1B 1004 MOV BX,[BASE] +07E5 8A C7 1005 MOV AL,BH +07E7 0A C3 1006 OR AL,BL +07E9 74 1E 1007 JZ EMPTY +07EB E8 6C FF 1008 CALL LOOK +07EE 72 10 1009 JC ENTER +07F0 BA 04 00 1010 MOV DX,4 +07F3 03 DA 1011 ADD BX,DX +07F5 8A 07 1012 MOV AL,[BX] +07F7 0A C0 1013 OR AL,AL +07F9 74 E1 1014 JZ RET +07FB 43 1015 INC BX +07FC 8B 17 1016 MOV DX,[BX] +07FE 43 1017 INC BX +07FF C3 1018 RET +0800 1019 +0800 1020 ENTER: +0800 53 1021 PUSH BX ;Save pointer to link field +0801 E8 0D 00 1022 CALL CREATE ;Add the node +0804 5E 1023 POP SI +0805 89 54 FF 1024 MOV [SI-1],DX ;Link new node +0808 C3 1025 RET ;Zero was set by CREATE +0809 1026 +0809 1027 EMPTY: +0809 E8 05 00 1028 CALL CREATE +080C 89 16 CC 1B 1029 MOV [BASE],DX +0810 C3 1030 RET +0811 1031 +0811 1032 +0811 1033 CREATE: +0811 1034 +0811 1035 ; Add a new node to the identifier tree. The identifier is at ID with +0811 1036 ; bit 7 of the last character set to one. The length of the identifier is +0811 1037 ; in LENID, which is ID-1. +0811 1038 ; +0811 1039 ; Node format: +0811 1040 ; 1. Length of identifier (1 byte) +0811 1041 ; 2. Identifier (1-80 bytes) +0811 1042 ; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +0811 1043 ; 4. Right link (0 if none larger) +0811 1044 ; 5. Data field: +0811 1045 ; a. Defined flag (0=undefined, 1=defined) +0811 1046 ; b. Value (2 bytes) +0811 1047 ; +0811 1048 ; This routine returns with AL=zero and zero flag set (which indicates +0811 1049 ; on return from LOOKUP that it has not yet been defined), DX points +0811 1050 ; to start of new node, and BX points to data field of new node. +0811 1051 +0811 A0 79 1B 1052 MOV AL,[LENID] +0814 04 08 1053 ADD AL,8 ;Storage needed for the node +0816 8B 1E CE 1B 1054 MOV BX,[HEAP] +081A 8A D0 1055 MOV DL,AL +081C B6 00 1056 MOV DH,0 +081E 2B DA 1057 SUB BX,DX ;Heap grows downward +0820 89 1E CE 1B 1058 MOV [HEAP],BX +0824 87 DA 1059 XCHG DX,BX +0826 8B 1E D1 1B 1060 MOV BX,[CODE] ;Check to make sure there's enough +082A 3B DA 1061 CMP BX,DX +082C 72 03 1062 JB $+5 +082E E9 40 FA 1063 JMP ABORT +0831 52 1064 PUSH DX +0832 BB 79 1B 1065 MOV BX,LENID +0835 8A 0F 1066 MOV CL,[BX] +0837 FE C1 1067 INC CL +0839 B5 00 1068 MOV CH,0 +083B FC 1069 UP +083C 8B F3 1070 MOV SI,BX +083E 8B FA 1071 MOV DI,DX +0840 F3 1072 REP +0841 A4 1073 MOVB ;Move identifier and length into node +0842 8B D7 1074 MOV DX,DI +0844 8B DE 1075 MOV BX,SI +0846 B5 04 1076 MOV CH,4 +0848 87 DA 1077 XCHG DX,BX +084A 1078 NILIFY: +084A 88 0F 1079 MOV [BX],CL ;Zero left and right links +084C 43 1080 INC BX +084D FE CD 1081 DEC CH +084F 75 F9 1082 JNZ NILIFY +0851 32 C0 1083 XOR AL,AL ;Set zero flag +0853 88 07 1084 MOV [BX],AL ;Zero defined flag +0855 5A 1085 POP DX ;Restore pointer to node +0856 C3 1086 RET +0857 1087 +0857 1088 CPSLP: +0857 8B F2 1089 MOV SI,DX +0859 AC 1090 LODB +085A 3A 07 1091 CMP AL,[BX] +085C 9F 1092 LAHF +085D 42 1093 INC DX +085E 43 1094 INC BX +085F 9E 1095 SAHF +0860 75 F4 1096 JNZ RET +0862 FE CD 1097 DEC CH +0864 75 F1 1098 JNZ CPSLP +0866 C3 1099 RET +0867 1100 +0867 1101 GETLAB: +0867 BB 00 00 1102 MOV BX,0 +086A 89 1E 69 1B 1103 MOV [LABPT],BX +086E B0 FF 1104 MOV AL,-1 +0870 A2 6B 1B 1105 MOV [FLAG],AL +0873 A2 6C 1B 1106 MOV [LONG],AL +0876 B6 00 1107 MOV DH,0 +0878 A0 CA 1B 1108 MOV AL,[CHR] +087B 3C 21 1109 CMP AL,' '+1 +087D 72 03 1110 JC NOT1 +087F 80 CE 01 1111 OR DH,001H +0882 1112 NOT1: +0882 E8 D7 FD 1113 CALL GETLET +0885 72 DF 1114 JC RET +0887 3C 3A 1115 CMP AL,':' +0889 75 05 1116 JNZ LABCHK +088B E8 26 FA 1117 CALL NEXTCHR +088E EB 07 1118 JP LABEL +0890 1119 LABCHK: +0890 0A C0 1120 OR AL,AL +0892 F6 C6 01 1121 TEST DH,001H +0895 74 CF 1122 JZ RET +0897 1123 LABEL: +0897 A0 E5 1B 1124 MOV AL,[CHKLAB] +089A 0A C0 1125 OR AL,AL +089C 74 03 1126 JZ $+5 +089E E9 BB FD 1127 JMP GETLET +08A1 E8 39 FF 1128 CALL LOOKUP +08A4 B1 0B 1129 MOV CL,11 +08A6 75 14 1130 JNZ ERR5 +08A8 8B 16 65 1B 1131 MOV DX,[PC] +08AC C6 07 01 1132 MOV B,[BX],1 +08AF 43 1133 INC BX +08B0 88 17 1134 MOV [BX],DL +08B2 89 1E 69 1B 1135 MOV [LABPT],BX +08B6 43 1136 INC BX +08B7 88 37 1137 MOV [BX],DH +08B9 E9 A0 FD 1138 JMP GETLET +08BC 1139 +08BC E9 F0 F9 1140 ERR5: JMP ERROR +08BF 1141 +08BF 1142 ASMLIN: +08BF 8B 1E 65 1B 1143 MOV BX,[PC] +08C3 89 1E 67 1B 1144 MOV [OLDPC],BX +08C7 E8 9D FF 1145 CALL GETLAB +08CA 73 03 1146 JNC $+5 +08CC E9 80 F9 1147 JMP ENDLN +08CF BB 79 1B 1148 MOV BX,LENID +08D2 8A 07 1149 MOV AL,[BX] +08D4 B1 0C 1150 MOV CL,12 +08D6 2C 02 1151 SUB AL,2 +08D8 8A E8 1152 MOV CH,AL +08DA 72 E0 1153 JC ERR5 +08DC 43 1154 INC BX +08DD 82 3F 66 1155 CMP B,[BX],"f" ;See if an 8087 mnemonic +08E0 74 57 1156 JZ NDPOP +08E2 3C 05 1157 CMP AL,5 +08E4 73 D6 1158 JNC ERR5 +08E6 8A 07 1159 MOV AL,[BX] +08E8 2C 61 1160 SUB AL,'a' +08EA 8A C8 1161 MOV CL,AL +08EC 02 C0 1162 ADD AL,AL +08EE 02 C0 1163 ADD AL,AL +08F0 02 C1 1164 ADD AL,CL +08F2 02 C5 1165 ADD AL,CH +08F4 02 C0 1166 ADD AL,AL +08F6 BB 35 19 1167 MOV BX,OPTAB +08F9 8A D0 1168 MOV DL,AL +08FB B6 00 1169 MOV DH,0 +08FD 03 DA 1170 ADD BX,DX +08FF 8A 17 1171 MOV DL,[BX] +0901 43 1172 INC BX +0902 8A 37 1173 MOV DH,[BX] +0904 87 DA 1174 XCHG DX,BX +0906 FE C5 1175 INC CH +0908 8A CD 1176 MOV CL,CH +090A 8A 07 1177 MOV AL,[BX] +090C 43 1178 INC BX +090D 0A C0 1179 OR AL,AL +090F 74 1E 1180 JZ OPERR +0911 1181 FINDOP: +0911 8A E9 1182 MOV CH,CL +0913 9F 1183 LAHF +0914 95 1184 XCHG AX,BP +0915 9E 1185 SAHF +0916 BA 7B 1B 1186 MOV DX,ID+1 +0919 E8 3B FF 1187 CALL CPSLP +091C 74 16 1188 JZ HAVOP +091E B6 00 1189 MOV DH,0 +0920 8A D5 1190 MOV DL,CH +0922 FE C2 1191 INC DL +0924 FE C2 1192 INC DL +0926 03 DA 1193 ADD BX,DX +0928 9F 1194 LAHF +0929 95 1195 XCHG AX,BP +092A 9E 1196 SAHF +092B FE C8 1197 DEC AL +092D 75 E2 1198 JNZ FINDOP +092F 1199 OPERR: +092F B1 0C 1200 MOV CL,12 +0931 E9 7B F9 1201 JMP ERROR +0934 1202 +0934 1203 HAVOP: +0934 8A 47 02 1204 MOV AL,[BX+2] ;Get opcode +0937 FF 27 1205 JMP [BX] +0939 1206 +0939 1207 NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") +0939 43 1208 INC BX +093A 82 3F 6E 1209 CMP B,[BX],"n" ;"No-wait" form? +093D B4 00 1210 MOV AH,0 +093F 75 05 1211 JNZ SAVNFLG +0941 B4 01 1212 MOV AH,1 +0943 FE C8 1213 DEC AL +0945 43 1214 INC BX ;Skip over the "N" +0946 1215 SAVNFLG: +0946 88 26 EF 1B 1216 MOV [NOWAIT],AH ;0 for wait, 1 for no wait +094A 3C 01 1217 CMP AL,1 +094C 72 E1 1218 JB OPERR ;Not enough char left for valid opcode? +094E 3C 05 1219 CMP AL,5 +0950 77 DD 1220 JA OPERR ;Too many? +0952 98 1221 CBW +0953 92 1222 XCHG AX,DX ;Save length in DX +0954 8B F2 1223 MOV SI,DX +0956 80 08 80 1224 OR B,[SI+BX],80H ;Set high bit of last character +0959 8A 07 1225 MOV AL,[BX] ;Get first char of opcode +095B 43 1226 INC BX +095C 2C 61 1227 SUB AL,"a" +095E 72 28 1228 JB TRY2XM1 ;Go see if opcode starts with "2" +0960 3C 19 1229 CMP AL,"z"-"a" +0962 77 CB 1230 JA OPERR +0964 98 1231 CBW +0965 D1 E0 1232 SHL AX ;Double to index into address table +0967 96 1233 XCHG AX,SI ;Put in index register +0968 8B BC 39 1A 1234 MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +096C 1235 LOOKNDP: +096C 8A 25 1236 MOV AH,[DI] ;Number of opcodes starting with this letter +096E 0A E4 1237 OR AH,AH +0970 74 BD 1238 JZ OPERR ;Any start with this letter? +0972 1239 FNDNDP: +0972 47 1240 INC DI +0973 8B F3 1241 MOV SI,BX ;Pointer to start of opcode +0975 8B CA 1242 MOV CX,DX ;Get length of opcode +0977 F3 1243 REPE +0978 A6 1244 CMPB ;Compare opcode to table entry +0979 74 16 1245 JZ HAVNDP +097B 4F 1246 DEC DI ;Back up in case that was last letter +097C B0 80 1247 MOV AL,80H ;Look for char with high bit set +097E 1248 ENDOP: +097E AE 1249 SCASB +097F 77 FD 1250 JA ENDOP +0981 47 1251 INC DI ;Skip over info about opcode +0982 FE CC 1252 DEC AH +0984 75 EC 1253 JNZ FNDNDP +0986 EB A7 1254 JP OPERR +0988 1255 +0988 1256 TRY2XM1: +0988 3C D1 1257 CMP AL,"2"-"a" +098A 75 A3 1258 JNZ OPERR +098C BF CC 17 1259 MOV DI,XM1 +098F EB DB 1260 JP LOOKNDP +0991 1261 +0991 1262 HAVNDP: +0991 8B F7 1263 MOV SI,DI +0993 82 3E EF 1B 00 1264 CMP B,[NOWAIT],0 +0998 75 05 1265 JNZ NWAIT +099A B0 9B 1266 MOV AL,9BH ;Wait opcode +099C E8 7C 00 1267 CALL PUT +099F 1268 NWAIT: +099F AD 1269 LODW ;Get opcode info +09A0 A8 F8 1270 TEST AL,0F8H ;Any operand bits set? +09A2 74 00 1271 JZ NOOPS ;If no operands, output code +09A4 1272 NOOPS: +09A4 0C D8 1273 OR AL,0D8H ;ESC hook +09A6 E8 72 00 1274 CALL PUT +09A9 8A C4 1275 MOV AL,AH +09AB E9 6D 00 1276 JMP PUT +09AE 1277 +09AE 1278 GRP1: +09AE B9 09 8A 1279 MOV CX,8A09H +09B1 E8 31 F9 1280 CALL MROPS +09B4 B9 C6 00 1281 MOV CX,0C6H +09B7 8A C7 1282 MOV AL,BH +09B9 3C 00 1283 CMP AL,UNDEFID +09BB 75 03 1284 JNZ L0006 +09BD E8 40 00 1285 CALL STIMM +09C0 1286 L0006: +09C0 24 01 1287 AND AL,1 +09C2 74 0A 1288 JZ BYTIMM +09C4 B0 B8 1289 MOV AL,0B8H +09C6 0A C3 1290 OR AL,BL +09C8 E8 50 00 1291 CALL PUT +09CB E9 9A 00 1292 JMP PUTWOR +09CE 1293 +09CE 1294 BYTIMM: +09CE B0 B0 1295 MOV AL,0B0H +09D0 0A C3 1296 OR AL,BL +09D2 E8 46 00 1297 CALL PUT +09D5 E9 97 00 1298 PUTBJ: JMP PUTBYT +09D8 1299 +09D8 1300 IMMED: +09D8 8A C7 1301 MOV AL,BH +09DA 3C 00 1302 CMP AL,UNDEFID +09DC 74 22 1303 JZ STIMM +09DE 8A C3 1304 MOV AL,BL +09E0 0A C0 1305 OR AL,AL +09E2 74 36 1306 JZ RET +09E4 8A C7 1307 MOV AL,BH +09E6 E8 22 00 1308 CALL IMM +09E9 0C C0 1309 OR AL,0C0H +09EB E8 2D 00 1310 CALL PUT +09EE 1311 FINIMM: +09EE 8A C1 1312 MOV AL,CL +09F0 59 1313 POP CX +09F1 D1 DE 1314 RCR SI +09F3 A8 01 1315 TEST AL,001H +09F5 D1 D6 1316 RCL SI +09F7 74 DC 1317 JZ PUTBJ +09F9 3C 83 1318 CMP AL,83H +09FB 74 D8 1319 JZ PUTBJ +09FD E9 68 00 1320 JMP PUTWOR +0A00 1321 +0A00 1322 STIMM: +0A00 A0 6B 1B 1323 MOV AL,[FLAG] +0A03 E8 05 00 1324 CALL IMM +0A06 E8 D6 00 1325 CALL PUTADD +0A09 EB E3 1326 JP FINIMM +0A0B 1327 +0A0B 1328 IMM: +0A0B 24 01 1329 AND AL,1 +0A0D 0A C1 1330 OR AL,CL +0A0F 8A C8 1331 MOV CL,AL +0A11 E8 07 00 1332 CALL PUT +0A14 8A C5 1333 MOV AL,CH +0A16 24 38 1334 AND AL,38H +0A18 0A C3 1335 OR AL,BL +0A1A C3 1336 RET +0A1B 1337 +0A1B 1338 PUT: +0A1B 1339 ;Save byte in AL as pure code, with intermediate code bits 00. AL and +0A1B 1340 ;DI destroyed, no other registers affected. +0A1B 53 1341 PUSH BX +0A1C 51 1342 PUSH CX +0A1D B5 00 1343 MOV CH,0 ;Flag as pure code +0A1F E8 03 00 1344 CALL GEN +0A22 59 1345 POP CX +0A23 5B 1346 POP BX +0A24 C3 1347 RET +0A25 1348 +0A25 1349 GEN: +0A25 1350 ;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. +0A25 E8 32 00 1351 CALL PUTINC ;Save it and bump code pointer +0A28 1352 GEN1: +0A28 8A 0E D4 1B 1353 MOV CL,[RELOC] +0A2C D1 C1 1354 ROL CX +0A2E D1 C1 1355 ROL CX +0A30 88 0E D4 1B 1356 MOV [RELOC],CL +0A34 BB D5 1B 1357 MOV BX,BCOUNT +0A37 FE 0F 1358 DEC B,[BX] +0A39 75 E9 1359 JNZ RET +0A3B C6 07 04 1360 MOV B,[BX],4 +0A3E BB D4 1B 1361 MOV BX,RELOC +0A41 8A 07 1362 MOV AL,[BX] +0A43 C6 07 00 1363 MOV B,[BX],0 +0A46 8B 3E F2 1B 1364 MOV DI,[IY] +0A4A 88 05 1365 MOV [DI],AL +0A4C 8B 1E D1 1B 1366 MOV BX,[CODE] +0A50 89 1E F2 1B 1367 MOV [IY],BX +0A54 43 1368 INC BX +0A55 89 1E D1 1B 1369 MOV [CODE],BX +0A59 C3 1370 RET +0A5A 1371 +0A5A 1372 PUTINC: +0A5A FF 06 65 1B 1373 INC [PC] +0A5E 1374 PUTCD: +0A5E 8B 3E D1 1B 1375 MOV DI,[CODE] +0A62 AA 1376 STOB +0A63 89 3E D1 1B 1377 MOV [CODE],DI +0A67 C3 1378 RET +0A68 1379 +0A68 1380 PUTWOR: +0A68 1381 ;Save the word value described by [DLABEL] and [DATA] as code. If defined, +0A68 1382 ;two bytes of pure code will be produced. Otherwise, appropriate intermediate +0A68 1383 ;code will be generated. +0A68 51 1384 PUSH CX +0A69 B5 80 1385 MOV CH,80H +0A6B 52 1386 PUSH DX +0A6C 53 1387 PUSH BX +0A6D EB 20 1388 JP PUTBW +0A6F 1389 +0A6F 1390 PUTBYT: +0A6F 1391 ;Same as PUTWOR, above, but for byte value. +0A6F 51 1392 PUSH CX +0A70 B5 40 1393 MOV CH,40H +0A72 52 1394 PUSH DX +0A73 53 1395 PUSH BX +0A74 8B 1E 73 1B 1396 MOV BX,[DLABEL] +0A78 8A C7 1397 MOV AL,BH +0A7A 0A C3 1398 OR AL,BL +0A7C 75 11 1399 JNZ PUTBW +0A7E 8B 1E 71 1B 1400 MOV BX,[DATA] +0A82 0A C7 1401 OR AL,BH +0A84 74 09 1402 JZ PUTBW +0A86 FE C7 1403 INC BH +0A88 74 05 1404 JZ PUTBW +0A8A B1 1F 1405 MOV CL,31 +0A8C E9 20 F8 1406 JMP ERROR +0A8F 1407 PUTBW: +0A8F 8B 16 73 1B 1408 MOV DX,[DLABEL] +0A93 8B 1E 71 1B 1409 MOV BX,[DATA] +0A97 1410 PUTCHK: +0A97 8A C6 1411 MOV AL,DH +0A99 0A C2 1412 OR AL,DL +0A9B 74 29 1413 JZ NOUNDEF +0A9D 8A C2 1414 MOV AL,DL +0A9F E8 BC FF 1415 CALL PUTCD +0AA2 8A C6 1416 MOV AL,DH +0AA4 E8 B7 FF 1417 CALL PUTCD +0AA7 8A C3 1418 MOV AL,BL +0AA9 E8 AE FF 1419 CALL PUTINC +0AAC 8A C7 1420 MOV AL,BH +0AAE D1 DE 1421 RCR SI +0AB0 F6 C5 80 1422 TEST CH,080H +0AB3 D1 D6 1423 RCL SI +0AB5 74 05 1424 JZ SMPUT +0AB7 E8 6B FF 1425 CALL GEN +0ABA EB 06 1426 JP PRET +0ABC 1427 SMPUT: +0ABC E8 9F FF 1428 CALL PUTCD +0ABF E8 66 FF 1429 CALL GEN1 +0AC2 1430 PRET: +0AC2 5B 1431 POP BX +0AC3 5A 1432 POP DX +0AC4 59 1433 POP CX +0AC5 C3 1434 RET +0AC6 1435 +0AC6 1436 NOUNDEF: +0AC6 8A C3 1437 MOV AL,BL +0AC8 8A CF 1438 MOV CL,BH +0ACA 51 1439 PUSH CX +0ACB B5 00 1440 MOV CH,0 +0ACD E8 55 FF 1441 CALL GEN +0AD0 59 1442 POP CX +0AD1 8A C1 1443 MOV AL,CL +0AD3 F6 C5 80 1444 TEST CH,080H +0AD6 B5 00 1445 MOV CH,0 +0AD8 74 E8 1446 JZ PRET +0ADA E8 48 FF 1447 CALL GEN +0ADD EB E3 1448 JP PRET +0ADF 1449 +0ADF 1450 PUTADD: +0ADF 1451 ;Save complete addressing mode. Addressing mode is in AL; if this is a register +0ADF 1452 ;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +0ADF 1453 ;the details of the addressing mode will be investigated and the optional one- +0ADF 1454 ;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. +0ADF 51 1455 PUSH CX +0AE0 52 1456 PUSH DX +0AE1 53 1457 PUSH BX +0AE2 B5 00 1458 MOV CH,0 +0AE4 8A C8 1459 MOV CL,AL +0AE6 E8 3C FF 1460 CALL GEN ;Save the addressing mode as pure code +0AE9 8A C1 1461 MOV AL,CL +0AEB B5 80 1462 MOV CH,80H +0AED 24 C7 1463 AND AL,0C7H +0AEF 3C 06 1464 CMP AL,6 +0AF1 74 0A 1465 JZ TWOBT ;Direct address? +0AF3 24 C0 1466 AND AL,0C0H +0AF5 74 CB 1467 JZ PRET ;Indirect through reg, no displacement? +0AF7 3C C0 1468 CMP AL,0C0H +0AF9 74 C7 1469 JZ PRET ;Register to register operation? +0AFB 8A E8 1470 MOV CH,AL ;Save whether one- or two-byte displacement +0AFD 1471 TWOBT: +0AFD 8B 1E 6D 1B 1472 MOV BX,[ADDR] +0B01 8B 16 6F 1B 1473 MOV DX,[ALABEL] +0B05 EB 90 1474 JP PUTCHK +0B07 1475 +0B07 1476 GRP2: +0B07 E8 B7 F8 1477 CALL GETOP +0B0A B9 30 FF 1478 MOV CX,0FF30H +0B0D 3C 00 1479 CMP AL,UNDEFID +0B0F 74 14 1480 JZ PMEM +0B11 B5 50 1481 MOV CH,50H +0B13 3C 03 1482 CMP AL,XREG +0B15 74 1A 1483 JZ PXREG +0B17 B5 06 1484 MOV CH,6 +0B19 3C 04 1485 CMP AL,SREG +0B1B 75 03 1486 JNZ $+5 +0B1D E9 2C 04 1487 JMP PACKREG +0B20 B1 14 1488 MOV CL,20 +0B22 E9 8A F7 1489 JMP ERROR +0B25 1490 +0B25 1491 PMEM: +0B25 8A C5 1492 MOV AL,CH +0B27 E8 F1 FE 1493 CALL PUT +0B2A 8A C1 1494 MOV AL,CL +0B2C 0A C2 1495 OR AL,DL +0B2E E9 AE FF 1496 JMP PUTADD +0B31 1497 +0B31 1498 PXREG: +0B31 8A C5 1499 MOV AL,CH +0B33 0A C2 1500 OR AL,DL +0B35 E9 E3 FE 1501 JMP PUT +0B38 1502 +0B38 1503 GRP3: +0B38 E8 86 F8 1504 CALL GETOP +0B3B 52 1505 PUSH DX +0B3C E8 79 F8 1506 CALL GETOP2 +0B3F 5B 1507 POP BX +0B40 B9 14 86 1508 MOV CX,8614H +0B43 B0 04 1509 MOV AL,SREG +0B45 3A C7 1510 CMP AL,BH +0B47 74 4C 1511 JZ ERR6 +0B49 3A C6 1512 CMP AL,DH +0B4B 74 48 1513 JZ ERR6 +0B4D B0 01 1514 MOV AL,CONST +0B4F 3A C7 1515 CMP AL,BH +0B51 74 42 1516 JZ ERR6 +0B53 3A C6 1517 CMP AL,DH +0B55 74 3E 1518 JZ ERR6 +0B57 B0 00 1519 MOV AL,UNDEFID +0B59 3A C7 1520 CMP AL,BH +0B5B 74 2D 1521 JZ EXMEM +0B5D 3A C6 1522 CMP AL,DH +0B5F 74 2B 1523 JZ EXMEM1 +0B61 8A C7 1524 MOV AL,BH +0B63 3A C6 1525 CMP AL,DH +0B65 B1 16 1526 MOV CL,22 +0B67 75 2C 1527 JNZ ERR6 +0B69 3C 03 1528 CMP AL,XREG +0B6B 74 03 1529 JZ L0008 +0B6D E8 AE F7 1530 CALL RR1 +0B70 1531 L0008: ;RR1 never returns +0B70 8A C3 1532 MOV AL,BL +0B72 0A C0 1533 OR AL,AL +0B74 74 0D 1534 JZ EXACC +0B76 87 DA 1535 XCHG DX,BX +0B78 8A C3 1536 MOV AL,BL +0B7A 0A C0 1537 OR AL,AL +0B7C 8A C7 1538 MOV AL,BH +0B7E 74 03 1539 JZ EXACC +0B80 E8 9B F7 1540 CALL RR1 +0B83 1541 EXACC: +0B83 B0 90 1542 MOV AL,90H +0B85 0A C2 1543 OR AL,DL +0B87 E9 91 FE 1544 JMP PUT +0B8A 1545 +0B8A 1546 EXMEM: +0B8A 87 DA 1547 XCHG DX,BX +0B8C 1548 EXMEM1: +0B8C 3A C7 1549 CMP AL,BH +0B8E 74 05 1550 JZ ERR6 +0B90 B1 01 1551 MOV CL,1 ;Flag word as OK +0B92 E8 03 F8 1552 CALL NOTAC ;NOTAC never returns +0B95 E9 17 F7 1553 ERR6: JMP ERROR +0B98 1554 +0B98 1555 GRP4: +0B98 9F 1556 LAHF +0B99 86 E0 1557 XCHG AH,AL +0B9B 50 1558 PUSH AX +0B9C 86 E0 1559 XCHG AH,AL +0B9E E8 20 F8 1560 CALL GETOP +0BA1 59 1561 POP CX +0BA2 3C 01 1562 CMP AL,CONST +0BA4 74 13 1563 JZ FIXED +0BA6 2C 03 1564 SUB AL,XREG +0BA8 FE CA 1565 DEC DL +0BAA FE CA 1566 DEC DL +0BAC 0A C2 1567 OR AL,DL +0BAE B1 14 1568 MOV CL,20 +0BB0 75 E3 1569 JNZ ERR6 +0BB2 8A C5 1570 MOV AL,CH +0BB4 0C 08 1571 OR AL,8 +0BB6 E9 62 FE 1572 JMP PUT +0BB9 1573 FIXED: +0BB9 8A C5 1574 MOV AL,CH +0BBB E8 5D FE 1575 CALL PUT +0BBE E9 AE FE 1576 JMP PUTBYT +0BC1 1577 +0BC1 1578 GRP5: +0BC1 9F 1579 LAHF +0BC2 86 E0 1580 XCHG AH,AL +0BC4 50 1581 PUSH AX +0BC5 86 E0 1582 XCHG AH,AL +0BC7 E8 F7 F7 1583 CALL GETOP +0BCA 3C 01 1584 CMP AL,CONST +0BCC 75 C7 1585 JNZ ERR6 +0BCE 8B 1E 73 1B 1586 MOV BX,[DLABEL] +0BD2 8A C7 1587 MOV AL,BH +0BD4 0A C3 1588 OR AL,BL +0BD6 B1 1E 1589 MOV CL,30 +0BD8 75 BB 1590 JNZ ERR6 +0BDA 8B 1E 71 1B 1591 MOV BX,[DATA] +0BDE 58 1592 POP AX +0BDF 86 E0 1593 XCHG AH,AL +0BE1 9E 1594 SAHF +0BE2 0A C0 1595 OR AL,AL +0BE4 74 4B 1596 JZ ORG +0BE6 FE C8 1597 DEC AL +0BE8 74 19 1598 JZ DSJ +0BEA FE C8 1599 DEC AL +0BEC 74 2D 1600 JZ EQU +0BEE FE C8 1601 DEC AL +0BF0 74 03 1602 JZ $+5 +0BF2 E9 BA 03 1603 JMP IF +0BF5 1604 PUTOP: +0BF5 B0 FD 1605 MOV AL,-3 +0BF7 EB 3E 1606 JP NEWLOC +0BF9 1607 ALIGN: +0BF9 A0 65 1B 1608 MOV AL,[PC] +0BFC 24 01 1609 AND AL,1 +0BFE 74 30 1610 JZ RET +0C00 BB 01 00 1611 MOV BX,1 +0C03 1612 DSJ: +0C03 87 DA 1613 XCHG DX,BX +0C05 8B 1E 65 1B 1614 MOV BX,[PC] +0C09 9F 1615 LAHF +0C0A 03 DA 1616 ADD BX,DX +0C0C D1 DE 1617 RCR SI +0C0E 9E 1618 SAHF +0C0F D1 D6 1619 RCL SI +0C11 89 1E 65 1B 1620 MOV [PC],BX +0C15 87 DA 1621 XCHG DX,BX +0C17 B0 FC 1622 MOV AL,-4 +0C19 EB 1C 1623 JP NEWLOC +0C1B 1624 EQU: +0C1B 87 DA 1625 XCHG DX,BX +0C1D 8B 1E 69 1B 1626 MOV BX,[LABPT] +0C21 8A C7 1627 MOV AL,BH +0C23 0A C3 1628 OR AL,BL +0C25 B1 22 1629 MOV CL,34 +0C27 74 29 1630 JZ ERR7 +0C29 88 17 1631 MOV [BX],DL +0C2B 9F 1632 LAHF +0C2C 43 1633 INC BX +0C2D 9E 1634 SAHF +0C2E 88 37 1635 MOV [BX],DH +0C30 C3 1636 RET +0C31 1637 ORG: +0C31 89 1E 65 1B 1638 MOV [PC],BX +0C35 B0 FE 1639 MOV AL,-2 +0C37 1640 NEWLOC: +0C37 E8 24 FE 1641 CALL PUTCD +0C3A 8A C3 1642 MOV AL,BL +0C3C E8 1F FE 1643 CALL PUTCD +0C3F 8A C7 1644 MOV AL,BH +0C41 E8 1A FE 1645 CALL PUTCD +0C44 B5 C0 1646 MOV CH,0C0H +0C46 E9 DF FD 1647 JMP GEN1 +0C49 1648 GRP6: +0C49 8A E8 1649 MOV CH,AL +0C4B B1 04 1650 MOV CL,4 +0C4D E8 95 F6 1651 CALL MROPS +0C50 B1 17 1652 MOV CL,23 +0C52 E9 5A F6 1653 ERR7: JMP ERROR +0C55 1654 GRP7: +0C55 8A E8 1655 MOV CH,AL +0C57 B1 01 1656 MOV CL,1 +0C59 E8 89 F6 1657 CALL MROPS +0C5C B1 80 1658 MOV CL,80H +0C5E 8B 16 73 1B 1659 MOV DX,[DLABEL] +0C62 8A C6 1660 MOV AL,DH +0C64 0A C2 1661 OR AL,DL +0C66 75 12 1662 JNZ ACCJ +0C68 87 DA 1663 XCHG DX,BX +0C6A 8B 1E 71 1B 1664 MOV BX,[DATA] +0C6E E8 99 F8 1665 CALL SIGNEXT +0C71 87 DA 1666 XCHG DX,BX +0C73 75 05 1667 JNZ ACCJ +0C75 9F 1668 LAHF +0C76 80 C9 02 1669 OR CL,002H +0C79 9E 1670 SAHF +0C7A E9 C5 00 1671 ACCJ: JMP ACCIMM +0C7D 1672 GRP8: +0C7D 8A C8 1673 MOV CL,AL +0C7F B5 FE 1674 MOV CH,0FEH +0C81 EB 04 1675 JP ONEOP +0C83 1676 GRP9: +0C83 8A C8 1677 MOV CL,AL +0C85 B5 F6 1678 MOV CH,0F6H +0C87 1679 ONEOP: +0C87 51 1680 PUSH CX +0C88 E8 36 F7 1681 CALL GETOP +0C8B 1682 ONE: +0C8B B1 1A 1683 MOV CL,26 +0C8D 3C 01 1684 CMP AL,CONST +0C8F 74 C1 1685 JZ ERR7 +0C91 3C 04 1686 CMP AL,SREG +0C93 B1 16 1687 MOV CL,22 +0C95 74 BB 1688 JZ ERR7 +0C97 59 1689 POP CX +0C98 3C 00 1690 CMP AL,UNDEFID +0C9A 74 16 1691 JZ MOP +0C9C 24 01 1692 AND AL,1 +0C9E 74 25 1693 JZ ROP +0CA0 D1 DE 1694 RCR SI +0CA2 F6 C1 01 1695 TEST CL,001H +0CA5 D1 D6 1696 RCL SI +0CA7 74 1C 1697 JZ ROP +0CA9 8A C1 1698 MOV AL,CL +0CAB 24 F8 1699 AND AL,0F8H +0CAD 0A C2 1700 OR AL,DL +0CAF E9 69 FD 1701 JMP PUT +0CB2 1702 MOP: +0CB2 A0 6B 1B 1703 MOV AL,[FLAG] +0CB5 24 01 1704 AND AL,1 +0CB7 0A C5 1705 OR AL,CH +0CB9 E8 5F FD 1706 CALL PUT +0CBC 8A C1 1707 MOV AL,CL +0CBE 24 38 1708 AND AL,38H +0CC0 0A C2 1709 OR AL,DL +0CC2 E9 1A FE 1710 JMP PUTADD +0CC5 1711 ROP: +0CC5 0A C5 1712 OR AL,CH +0CC7 E8 51 FD 1713 CALL PUT +0CCA 8A C1 1714 MOV AL,CL +0CCC 24 38 1715 AND AL,38H +0CCE 0C C0 1716 OR AL,0C0H +0CD0 0A C2 1717 OR AL,DL +0CD2 E9 46 FD 1718 JMP PUT +0CD5 1719 GRP10: +0CD5 8A C8 1720 MOV CL,AL +0CD7 B5 F6 1721 MOV CH,0F6H +0CD9 51 1722 PUSH CX +0CDA E8 E4 F6 1723 CALL GETOP +0CDD B1 14 1724 MOV CL,20 +0CDF 8A C2 1725 MOV AL,DL +0CE1 0A C0 1726 OR AL,AL +0CE3 75 08 1727 JNZ ERRJ1 +0CE5 8A C6 1728 MOV AL,DH +0CE7 3C 03 1729 CMP AL,XREG +0CE9 74 04 1730 JZ G10 +0CEB 3C 02 1731 CMP AL,REG +0CED 75 77 1732 ERRJ1: JNZ ERR8 +0CEF 1733 G10: +0CEF 9F 1734 LAHF +0CF0 86 E0 1735 XCHG AH,AL +0CF2 50 1736 PUSH AX +0CF3 86 E0 1737 XCHG AH,AL +0CF5 E8 C9 F6 1738 CALL GETOP +0CF8 58 1739 POP AX +0CF9 86 E0 1740 XCHG AH,AL +0CFB 9E 1741 SAHF +0CFC 24 01 1742 AND AL,1 +0CFE A2 6B 1B 1743 MOV [FLAG],AL +0D01 8A C6 1744 MOV AL,DH +0D03 EB 86 1745 ONEJ: JP ONE +0D05 1746 GRP11: +0D05 E8 13 FD 1747 CALL PUT +0D08 B0 0A 1748 MOV AL,0AH +0D0A E9 0E FD 1749 JMP PUT +0D0D 1750 GRP12: +0D0D 8A C8 1751 MOV CL,AL +0D0F B5 D0 1752 MOV CH,0D0H +0D11 51 1753 PUSH CX +0D12 E8 AC F6 1754 CALL GETOP +0D15 A0 CB 1B 1755 MOV AL,[SYM] +0D18 3C 2C 1756 CMP AL,',' +0D1A 8A C6 1757 MOV AL,DH +0D1C 75 E5 1758 JNZ ONEJ +0D1E 52 1759 PUSH DX +0D1F E8 9F F6 1760 CALL GETOP +0D22 2C 02 1761 SUB AL,REG +0D24 B1 14 1762 MOV CL,20 +0D26 FE CA 1763 DEC DL +0D28 0A C2 1764 OR AL,DL +0D2A 75 3A 1765 JNZ ERR8 +0D2C 5A 1766 POP DX +0D2D 8A C6 1767 MOV AL,DH +0D2F 59 1768 POP CX +0D30 9F 1769 LAHF +0D31 80 CD 02 1770 OR CH,002H +0D34 9E 1771 SAHF +0D35 51 1772 PUSH CX +0D36 E9 52 FF 1773 JMP ONE +0D39 1774 GRP13: +0D39 8A E8 1775 MOV CH,AL +0D3B B1 01 1776 MOV CL,1 +0D3D E8 A5 F5 1777 CALL MROPS +0D40 B1 80 1778 MOV CL,80H +0D42 1779 ACCIMM: +0D42 E8 93 FC 1780 CALL IMMED +0D45 80 CD 04 1781 OR CH,004H +0D48 80 E5 FD 1782 AND CH,0FDH +0D4B 1783 AIMM: +0D4B 8A C7 1784 MOV AL,BH +0D4D 24 01 1785 AND AL,1 +0D4F 9F 1786 LAHF +0D50 86 E0 1787 XCHG AH,AL +0D52 50 1788 PUSH AX +0D53 86 E0 1789 XCHG AH,AL +0D55 0A C5 1790 OR AL,CH +0D57 E8 C1 FC 1791 CALL PUT +0D5A 58 1792 POP AX +0D5B 86 E0 1793 XCHG AH,AL +0D5D 9E 1794 SAHF +0D5E 75 03 1795 JNZ $+5 +0D60 E9 0C FD 1796 JMP PUTBYT +0D63 E9 02 FD 1797 JMP PUTWOR +0D66 E9 46 F5 1798 ERR8: JMP ERROR +0D69 1799 GRP14: +0D69 9F 1800 LAHF +0D6A 86 E0 1801 XCHG AH,AL +0D6C 50 1802 PUSH AX +0D6D 86 E0 1803 XCHG AH,AL +0D6F E8 4F F6 1804 CALL GETOP +0D72 3C 01 1805 CMP AL,CONST +0D74 74 31 1806 JZ DIRECT +0D76 B1 14 1807 MOV CL,20 +0D78 3C 02 1808 CMP AL,REG +0D7A 74 EA 1809 JZ ERR8 +0D7C 3C 04 1810 CMP AL,SREG +0D7E 74 E6 1811 JZ ERR8 +0D80 3C 03 1812 CMP AL,XREG +0D82 75 06 1813 JNZ NOTRG +0D84 80 CA 40 1814 OR DL,040H +0D87 80 CA 80 1815 OR DL,080H +0D8A 1816 NOTRG: +0D8A B0 FF 1817 MOV AL,0FFH +0D8C E8 8C FC 1818 CALL PUT +0D8F 58 1819 POP AX +0D90 86 E0 1820 XCHG AH,AL +0D92 9E 1821 SAHF +0D93 24 38 1822 AND AL,38H +0D95 0A C2 1823 OR AL,DL +0D97 8A E8 1824 MOV CH,AL +0D99 A0 6C 1B 1825 MOV AL,[LONG] +0D9C 0A C0 1826 OR AL,AL +0D9E 8A C5 1827 MOV AL,CH +0DA0 74 02 1828 JZ PUTADDJ +0DA2 24 F7 1829 AND AL,0F7H +0DA4 1830 PUTADDJ: +0DA4 E9 38 FD 1831 JMP PUTADD +0DA7 1832 DIRECT: +0DA7 A0 CB 1B 1833 MOV AL,[SYM] +0DAA 3C 2C 1834 CMP AL,',' +0DAC 74 22 1835 JZ LONGJ +0DAE 58 1836 POP AX +0DAF 86 E0 1837 XCHG AH,AL +0DB1 9E 1838 SAHF +0DB2 FE C8 1839 DEC AL +0DB4 3C E9 1840 CMP AL,0E9H +0DB6 74 02 1841 JZ GOTOP +0DB8 B0 E8 1842 MOV AL,0E8H +0DBA 1843 GOTOP: +0DBA E8 5E FC 1844 CALL PUT +0DBD 8B 1E 71 1B 1845 MOV BX,[DATA] +0DC1 8B 16 65 1B 1846 MOV DX,[PC] +0DC5 42 1847 INC DX +0DC6 42 1848 INC DX +0DC7 2B DA 1849 SUB BX,DX +0DC9 89 1E 71 1B 1850 MOV [DATA],BX +0DCD E9 98 FC 1851 JMP PUTWOR +0DD0 1852 LONGJ: +0DD0 58 1853 POP AX +0DD1 86 E0 1854 XCHG AH,AL +0DD3 9E 1855 SAHF +0DD4 E8 44 FC 1856 CALL PUT +0DD7 E8 8E FC 1857 CALL PUTWOR +0DDA E8 E4 F5 1858 CALL GETOP +0DDD B1 14 1859 MOV CL,20 +0DDF 3C 01 1860 CMP AL,CONST +0DE1 75 83 1861 JNZ ERR8 +0DE3 E9 82 FC 1862 JMP PUTWOR +0DE6 1863 GRP16: +0DE6 9F 1864 LAHF +0DE7 86 E0 1865 XCHG AH,AL +0DE9 50 1866 PUSH AX +0DEA 86 E0 1867 XCHG AH,AL +0DEC E8 B8 F7 1868 CALL GETSYM +0DEF 3C 05 1869 CMP AL,5 +0DF1 74 1C 1870 JZ LONGR +0DF3 3C 0D 1871 CMP AL,EOL +0DF5 74 3F 1872 JZ NODEC +0DF7 3C 3B 1873 CMP AL,';' +0DF9 74 3B 1874 JZ NODEC +0DFB 1875 GETSP: +0DFB E8 C6 F5 1876 CALL GETOP1 +0DFE 59 1877 POP CX +0DFF 3C 01 1878 CMP AL,CONST +0E01 B1 14 1879 MOV CL,20 +0E03 75 6A 1880 JNZ ERR9 +0E05 8A C5 1881 MOV AL,CH +0E07 24 FE 1882 AND AL,0FEH +0E09 E8 0F FC 1883 CALL PUT +0E0C E9 59 FC 1884 JMP PUTWOR +0E0F 1885 LONGR: +0E0F A0 6C 1B 1886 MOV AL,[LONG] +0E12 0A C0 1887 OR AL,AL +0E14 75 0C 1888 JNZ NOTLON +0E16 58 1889 POP AX +0E17 86 E0 1890 XCHG AH,AL +0E19 9E 1891 SAHF +0E1A 0C 08 1892 OR AL,8 +0E1C 9F 1893 LAHF +0E1D 86 E0 1894 XCHG AH,AL +0E1F 50 1895 PUSH AX +0E20 86 E0 1896 XCHG AH,AL +0E22 1897 NOTLON: +0E22 E8 82 F7 1898 CALL GETSYM +0E25 3C 0D 1899 CMP AL,EOL +0E27 74 35 1900 JZ DORET +0E29 3C 3B 1901 CMP AL,';' +0E2B 74 31 1902 JZ DORET +0E2D 3C 2C 1903 CMP AL,',' +0E2F 75 03 1904 JNZ L0011 +0E31 E8 73 F7 1905 CALL GETSYM +0E34 1906 L0011: +0E34 EB C5 1907 JP GETSP +0E36 1908 NODEC: +0E36 8B 1E 65 1B 1909 MOV BX,[PC] +0E3A 89 1E E8 1B 1910 MOV [LSTRET],BX +0E3E 87 DA 1911 XCHG DX,BX +0E40 8B 1E EA 1B 1912 MOV BX,[RETPT] +0E44 8A C7 1913 MOV AL,BH +0E46 0A C3 1914 OR AL,BL +0E48 74 14 1915 JZ DORET +0E4A C6 07 01 1916 MOV B,[BX],1 +0E4D 9F 1917 LAHF +0E4E 43 1918 INC BX +0E4F 9E 1919 SAHF +0E50 88 17 1920 MOV [BX],DL +0E52 9F 1921 LAHF +0E53 43 1922 INC BX +0E54 9E 1923 SAHF +0E55 88 37 1924 MOV [BX],DH +0E57 BB 00 00 1925 MOV BX,0 +0E5A 89 1E EA 1B 1926 MOV [RETPT],BX +0E5E 1927 DORET: +0E5E 58 1928 POP AX +0E5F 86 E0 1929 XCHG AH,AL +0E61 9E 1930 SAHF +0E62 E9 B6 FB 1931 JMP PUT +0E65 1932 GRP17: +0E65 E8 B3 FB 1933 CALL PUT +0E68 E8 56 F5 1934 CALL GETOP +0E6B 3C 01 1935 CMP AL,CONST +0E6D B1 14 1936 MOV CL,20 +0E6F 75 29 1937 ERR9: JNZ ERR10 +0E71 8B 1E 71 1B 1938 MOV BX,[DATA] +0E75 8B 16 65 1B 1939 MOV DX,[PC] +0E79 9F 1940 LAHF +0E7A 42 1941 INC DX +0E7B 9E 1942 SAHF +0E7C 1B DA 1943 SBB BX,DX +0E7E 89 1E 71 1B 1944 MOV [DATA],BX +0E82 E8 EA FB 1945 CALL PUTBYT +0E85 8B 1E 73 1B 1946 MOV BX,[DLABEL] +0E89 8A C7 1947 MOV AL,BH +0E8B 0A C3 1948 OR AL,BL +0E8D 75 0E 1949 JNZ RET +0E8F 8B 1E 71 1B 1950 MOV BX,[DATA] +0E93 E8 74 F6 1951 CALL SIGNEXT +0E96 74 05 1952 JZ RET +0E98 B1 1F 1953 MOV CL,31 +0E9A E9 12 F4 1954 ERR10: JMP ERROR +0E9D C3 1955 RET +0E9E 1956 GRP18: +0E9E E8 20 F5 1957 CALL GETOP +0EA1 3C 01 1958 CMP AL,CONST +0EA3 B1 14 1959 MOV CL,20 +0EA5 75 F3 1960 JNZ ERR10 +0EA7 8B 1E 73 1B 1961 MOV BX,[DLABEL] +0EAB 8A C7 1962 MOV AL,BH +0EAD 0A C3 1963 OR AL,BL +0EAF 75 10 1964 JNZ GENINT +0EB1 8B 1E 71 1B 1965 MOV BX,[DATA] +0EB5 BA 03 00 1966 MOV DX,3 +0EB8 1B DA 1967 SBB BX,DX +0EBA 75 05 1968 JNZ GENINT +0EBC B0 CC 1969 MOV AL,0CCH +0EBE E9 5A FB 1970 JMP PUT +0EC1 1971 GENINT: +0EC1 B0 CD 1972 MOV AL,0CDH +0EC3 E8 55 FB 1973 CALL PUT +0EC6 E9 A6 FB 1974 JMP PUTBYT +0EC9 1975 +0EC9 1976 GRP19: ;ESC opcode +0EC9 E8 F5 F4 1977 CALL GETOP +0ECC B1 14 1978 MOV CL,20 +0ECE 3C 01 1979 CMP AL,CONST +0ED0 75 39 1980 JNZ ERRJ ;First operand must be immediate +0ED2 B1 1E 1981 MOV CL,1EH +0ED4 F7 06 73 1B FF FF 1982 TEST [DLABEL],-1 ;See if all labels have been defined +0EDA 75 2F 1983 JNZ ERRJ +0EDC A1 71 1B 1984 MOV AX,[DATA] +0EDF 3D 40 00 1985 CMP AX,64 ;Must only be 6 bits +0EE2 B1 1F 1986 MOV CL,1FH +0EE4 73 25 1987 JNB ERRJ +0EE6 8A D8 1988 MOV BL,AL ;Save for second byte +0EE8 D0 E8 1989 SHR AL +0EEA D0 E8 1990 SHR AL +0EEC D0 E8 1991 SHR AL +0EEE 0C D8 1992 OR AL,0D8H ;ESC opcode +0EF0 E8 28 FB 1993 CALL PUT +0EF3 53 1994 PUSH BX +0EF4 E8 C1 F4 1995 CALL GETOP2 +0EF7 5B 1996 POP BX +0EF8 80 E3 07 1997 AND BL,7 ;Low 3 bits of first operand +0EFB D0 E3 1998 SHL BL +0EFD D0 E3 1999 SHL BL +0EFF D0 E3 2000 SHL BL +0F01 3C 00 2001 CMP AL,UNDEFID ;Check for memory operand +0F03 74 09 2002 JZ ESCMEM +0F05 3C 01 2003 CMP AL,CONST ;Check for another immediate +0F07 74 0C 2004 JZ ESCIMM +0F09 B1 14 2005 MOV CL,20 +0F0B E9 A1 F3 2006 ERRJ: JMP ERROR +0F0E 2007 +0F0E 2008 ESCMEM: +0F0E 0A DA 2009 OR BL,DL ;Combine mode with first operand +0F10 8A C3 2010 MOV AL,BL +0F12 E9 CA FB 2011 JMP PUTADD +0F15 2012 +0F15 2013 ESCIMM: +0F15 B1 1E 2014 MOV CL,1EH +0F17 F7 06 73 1B FF FF 2015 TEST [DLABEL],-1 ;See if second operand is fully defined +0F1D 75 EC 2016 JNZ ERRJ +0F1F A1 71 1B 2017 MOV AX,[DATA] +0F22 B1 1F 2018 MOV CL,1FH +0F24 3D 08 00 2019 CMP AX,8 ;Must only be 3 bit value +0F27 73 E2 2020 JNB ERRJ +0F29 0A C3 2021 OR AL,BL ;Combine first and second operands +0F2B 0C C0 2022 OR AL,0C0H ;Force "register" mode +0F2D E9 EB FA 2023 JMP PUT +0F30 2024 +0F30 2025 GRP20: +0F30 8A E8 2026 MOV CH,AL +0F32 B1 01 2027 MOV CL,1 +0F34 E8 AE F3 2028 CALL MROPS +0F37 B1 F6 2029 MOV CL,0F6H +0F39 E8 9C FA 2030 CALL IMMED +0F3C B5 A8 2031 MOV CH,0A8H +0F3E E9 0A FE 2032 JMP AIMM +0F41 2033 GRP21: +0F41 E8 7D F4 2034 CALL GETOP +0F44 3C 04 2035 CMP AL,SREG +0F46 B1 1C 2036 MOV CL,28 +0F48 75 C1 2037 JNZ ERRJ +0F4A B5 26 2038 MOV CH,26H +0F4C 2039 PACKREG: +0F4C 8A C2 2040 MOV AL,DL +0F4E 02 C0 2041 ADD AL,AL +0F50 02 C0 2042 ADD AL,AL +0F52 02 C0 2043 ADD AL,AL +0F54 0A C5 2044 OR AL,CH +0F56 E9 C2 FA 2045 JMP PUT +0F59 2046 GRP22: +0F59 E8 65 F4 2047 CALL GETOP +0F5C B9 00 8F 2048 MOV CX,8F00H +0F5F 3C 00 2049 CMP AL,UNDEFID +0F61 75 03 2050 JNZ $+5 +0F63 E9 BF FB 2051 JMP PMEM +0F66 B5 58 2052 MOV CH,58H +0F68 3C 03 2053 CMP AL,XREG +0F6A 75 03 2054 JNZ $+5 +0F6C E9 C2 FB 2055 JMP PXREG +0F6F B5 07 2056 MOV CH,7 +0F71 3C 04 2057 CMP AL,SREG +0F73 74 D7 2058 JZ PACKREG +0F75 B1 14 2059 MOV CL,20 +0F77 E9 35 F3 2060 ERR11: JMP ERROR +0F7A 2061 GRP23: +0F7A A2 D3 1B 2062 MOV [DATSIZ],AL +0F7D 2063 GETDAT: +0F7D E8 27 F6 2064 CALL GETSYM +0F80 B0 02 2065 MOV AL,2 +0F82 E8 55 F4 2066 CALL VAL1 +0F85 A0 CB 1B 2067 MOV AL,[SYM] +0F88 3C 2C 2068 CMP AL,',' +0F8A A0 D3 1B 2069 MOV AL,[DATSIZ] +0F8D 75 05 2070 JNZ ENDDAT +0F8F E8 13 00 2071 CALL SAVDAT +0F92 EB E9 2072 JP GETDAT +0F94 2073 ENDDAT: +0F94 3C 02 2074 CMP AL,2 +0F96 75 0D 2075 JNZ SAVDAT +0F98 8B 1E 71 1B 2076 MOV BX,[DATA] +0F9C 9F 2077 LAHF +0F9D 80 CB 80 2078 OR BL,080H +0FA0 9E 2079 SAHF +0FA1 89 1E 71 1B 2080 MOV [DATA],BX +0FA5 2081 SAVDAT: +0FA5 0A C0 2082 OR AL,AL +0FA7 74 03 2083 JZ $+5 +0FA9 E9 C3 FA 2084 JMP PUTBYT +0FAC E9 B9 FA 2085 JMP PUTWOR +0FAF 2086 IF: +0FAF 0B DB 2087 OR BX,BX +0FB1 74 05 2088 JZ SKIPCD +0FB3 FE 06 E4 1B 2089 INC B,[IFFLG] +0FB7 C3 2090 RET +0FB8 2091 +0FB8 2092 SKIPCD: +0FB8 FE 06 E5 1B 2093 INC B,[CHKLAB] +0FBC 2094 SKIPLP: +0FBC 32 C0 2095 XOR AL,AL +0FBE E8 98 F2 2096 CALL NEXLIN +0FC1 E8 F0 F2 2097 CALL NEXTCHR +0FC4 3C 1A 2098 CMP AL,1AH +0FC6 74 40 2099 JZ END +0FC8 E8 9C F8 2100 CALL GETLAB +0FCB 72 EF 2101 JC SKIPLP +0FCD BF 79 1B 2102 MOV DI,LENID +0FD0 BE 0F 1B 2103 MOV SI,IFEND +0FD3 B5 00 2104 MOV CH,0 +0FD5 8A 0D 2105 MOV CL,[DI] +0FD7 FE C1 2106 INC CL +0FD9 F3 2107 REPE +0FDA A6 2108 CMPB +0FDB 74 14 2109 JZ ENDCOND +0FDD BF 79 1B 2110 MOV DI,LENID +0FE0 BE 15 1B 2111 MOV SI,IFNEST +0FE3 8A 0D 2112 MOV CL,[DI] +0FE5 FE C1 2113 INC CL +0FE7 F3 2114 REPE +0FE8 A6 2115 CMPB +0FE9 75 D1 2116 JNZ SKIPLP +0FEB FE 06 E5 1B 2117 INC B,[CHKLAB] +0FEF EB CB 2118 JP SKIPLP +0FF1 2119 +0FF1 2120 ENDCOND: +0FF1 FE 0E E5 1B 2121 DEC B,[CHKLAB] +0FF5 75 C5 2122 JNZ SKIPLP +0FF7 C3 2123 RET +0FF8 2124 +0FF8 2125 ENDIF: +0FF8 A0 E4 1B 2126 MOV AL,[IFFLG] +0FFB B1 24 2127 MOV CL,36 +0FFD FE C8 2128 DEC AL +0FFF 78 04 2129 JS ERRJMP +1001 A2 E4 1B 2130 MOV [IFFLG],AL +1004 C3 2131 RET +1005 2132 +1005 E9 A7 F2 2133 ERRJMP: JMP ERROR +1008 2134 +1008 2135 ;********************************************************************* +1008 2136 ; +1008 2137 ; PASS 2 +1008 2138 ; +1008 2139 ;********************************************************************* +1008 2140 +1008 2141 END: +1008 B2 04 2142 MOV DL,4 +100A 2143 WREND: +100A B5 FF 2144 MOV CH,0FFH +100C 8A C5 2145 MOV AL,CH +100E E8 14 FA 2146 CALL GEN +1011 FE CA 2147 DEC DL +1013 75 F5 2148 JNZ WREND +1015 C7 06 3E 20 40 20 2149 MOV [BUFPT],SRCBUF +101B C6 06 E0 1B FB 2150 MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY +1020 C7 06 F6 1B 3E 1C 2151 MOV [LSTPNT],LSTBUF +1026 C7 06 F4 1B F8 1B 2152 MOV [HEXPNT],HEXBUF +102C 33 C0 2153 XOR AX,AX +102E A3 E6 1B 2154 MOV [ERRCNT],AX +1031 A3 65 1B 2155 MOV [PC],AX +1034 A3 D8 1B 2156 MOV [LINE],AX ;Current line number +1037 C7 06 DC 1B 00 01 2157 MOV [HEXADD],OBJECT +103D BA 5C 00 2158 MOV DX,FCB +1040 B4 0F 2159 MOV AH,OPEN +1042 CD 21 2160 INT 33 ;Re-open source file +1044 32 C0 2161 XOR AL,AL +1046 A2 7C 00 2162 MOV [FCB+20H],AL +1049 C7 06 6A 00 00 04 2163 MOV [FCB+14],BUFSIZ +104F A2 D6 1B 2164 MOV [COUNT],AL +1052 B5 01 2165 MOV CH,1 +1054 BE 90 24 2166 MOV SI,START +1057 2167 FIXLINE: +1057 BF 90 24 2168 MOV DI,START ;Store code over used up intermediate code +105A 32 C0 2169 XOR AL,AL +105C A2 EE 1B 2170 MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) +105F A2 D7 1B 2171 MOV [ERR],AL ;No second pass errors yet +1062 2172 NEXBT: +1062 D0 E1 2173 SHL CL ;Shift out last bit of previous code +1064 FE CD 2174 DEC CH ;Still have codes left? +1066 75 05 2175 JNZ TESTTYP +1068 AC 2176 LODB ;Get next flag byte +1069 8A C8 2177 MOV CL,AL +106B B5 04 2178 MOV CH,4 +106D 2179 TESTTYP: +106D D0 E1 2180 SHL CL ;Set flags based on two bits +106F 70 06 2181 JO FIXUP +1071 AC 2182 LODB +1072 72 4E 2183 JC EMARK +1074 2184 OBJBT: +1074 AA 2185 STOB +1075 EB EB 2186 JP NEXBT +1077 2187 +1077 2188 FIXUP: +1077 2189 ;Either a word or byte fixup is needed from a forward reference +1077 AD 2190 LODW ;Get pointer to symbol +1078 93 2191 XCHG AX,BX +1079 AD 2192 LODW ;Get constant part +107A 03 47 01 2193 ADD AX,[BX+1] ;Add symbol value to constant part +107D 82 3F 00 2194 CMP B,[BX],0 ;See if symbol got defined +1080 75 07 2195 JNZ HAVDEF +1082 C6 06 D7 1B 64 2196 MOV B,[ERR],100 ;Undefined - flag error +1087 33 C0 2197 XOR AX,AX +1089 2198 HAVDEF: +1089 0A C9 2199 OR CL,CL ;See if word or byte fixup +108B 78 03 2200 JS DEFBYT +108D AB 2201 STOW +108E EB D2 2202 JP NEXBT +1090 2203 +1090 2204 DEFBYT: +1090 8B D0 2205 MOV DX,AX +1092 98 2206 CBW ;Extend sign +1093 3B C2 2207 CMP AX,DX ;See if in range +127 to -128 +1095 74 DD 2208 JZ OBJBT ;If so, it's always OK +1097 F6 D4 2209 NOT AH ;Check for range +255 to -256 +1099 3A E6 2210 CMP AH,DH +109B 75 1B 2211 JNZ RNGERR ;Must always be in this range +109D 2212 ;Check for short jump. If so, we're out of range; otherwise we're OK +109D 81 FF 91 24 2213 CMP DI,START+1 ;Only one other byte on line? +10A1 75 D1 2214 JNZ OBJBT ;Can't be short jump if not +10A3 A0 90 24 2215 MOV AL,[START] ;Get the first byte of this line +10A6 3C EB 2216 CMP AL,0EBH ;Direct short jump? +10A8 74 0E 2217 JZ RNGERR +10AA 24 FC 2218 AND AL,0FCH +10AC 3C E0 2219 CMP AL,0E0H ;LOOP or JCXZ instruction? +10AE 74 08 2220 JZ RNGERR +10B0 24 F0 2221 AND AL,0F0H +10B2 3C 70 2222 CMP AL,70H ;Conditional jump? +10B4 8A C2 2223 MOV AL,DL ;Get code byte in AL +10B6 75 BC 2224 JNZ OBJBT ;If not, we're OK +10B8 2225 RNGERR: +10B8 C6 06 D7 1B 65 2226 MOV B,[ERR],101 ;Value out of range +10BD EB B5 2227 JP OBJBT +10BF 2228 +10BF E9 7A 01 2229 FINIJ: JMP FINI +10C2 2230 +10C2 2231 EMARK: +10C2 3C FF 2232 CMP AL,-1 ;End of file? +10C4 74 F9 2233 JZ FINIJ +10C6 3C F6 2234 CMP AL,-10 ;Special item? +10C8 77 5C 2235 JA SPEND +10CA 51 2236 PUSH CX +10CB 56 2237 PUSH SI +10CC 50 2238 PUSH AX ;Save error code +10CD 8A 26 EC 1B 2239 MOV AH,[LSTDEV] +10D1 80 E4 FE 2240 AND AH,0FEH ;Reset error indicator +10D4 0A 06 D7 1B 2241 OR AL,[ERR] ;See if any errors on this line +10D8 74 03 2242 JZ NOERR +10DA 80 CC 01 2243 OR AH,1 ;Send line to console if error occured +10DD 2244 NOERR: +10DD 88 26 EC 1B 2245 MOV [LSTDEV],AH +10E1 8B CF 2246 MOV CX,DI +10E3 E8 EE 00 2247 CALL STRTLIN ;Print address of line +10E6 BE 90 24 2248 MOV SI,START +10E9 2B CE 2249 SUB CX,SI ;Get count of bytes of code +10EB 74 06 2250 JZ SHOLIN +10ED 2251 CODLP: +10ED AC 2252 LODB +10EE E8 33 02 2253 CALL SAVCD ;Ouput code to HEX and PRN files +10F1 E2 FA 2254 LOOP CODLP +10F3 2255 SHOLIN: +10F3 B0 00 2256 MOV AL,0 +10F5 86 06 D6 1B 2257 XCHG AL,[COUNT] +10F9 B9 07 00 2258 MOV CX,7 ;Allow 7 bytes of code per line +10FC 2A C8 2259 SUB CL,AL +10FE B0 20 2260 MOV AL,' ' +1100 74 0B 2261 JZ NOFIL +1102 2262 BLNK: ;Put in 3 blanks for each byte not present +1102 E8 E4 00 2263 CALL LIST +1105 E8 E1 00 2264 CALL LIST +1108 E8 DE 00 2265 CALL LIST +110B E2 F5 2266 LOOP BLNK +110D 2267 NOFIL: +110D E8 45 00 2268 CALL OUTLIN +1110 58 2269 POP AX ;Restore error code +1111 E8 46 02 2270 CALL REPERR +1114 A0 D7 1B 2271 MOV AL,[ERR] +1117 E8 40 02 2272 CALL REPERR +111A 5E 2273 POP SI +111B 59 2274 POP CX +111C A0 EE 1B 2275 MOV AL,[SPC] ;Any special funtion? +111F 0A C0 2276 OR AL,AL +1121 75 0D 2277 JNZ SPCFUN +1123 E9 31 FF 2278 JMP FIXLINE +1126 2279 +1126 2280 SPEND: +1126 A2 EE 1B 2281 MOV [SPC],AL ;Record special function +1129 AD 2282 LODW ;Get it's data +112A A3 71 1B 2283 MOV [DATA],AX +112D E9 32 FF 2284 JMP NEXBT +1130 2285 +1130 2286 SPCFUN: +1130 8B 16 71 1B 2287 MOV DX,[DATA] +1134 3C FE 2288 CMP AL,-2 +1136 74 0F 2289 JZ DORG +1138 3C FD 2290 CMP AL,-3 +113A 74 12 2291 JZ DPUT +113C 2292 DDS: +113C 2293 ;Handle DS pseudo-op +113C 01 16 65 1B 2294 ADD [PC],DX +1140 01 16 DC 1B 2295 ADD [HEXADD],DX +1144 E9 10 FF 2296 JMP FIXLINE +1147 2297 +1147 2298 DORG: +1147 2299 ;Handle ORG pseudo-op +1147 89 16 65 1B 2300 MOV [PC],DX +114B E9 09 FF 2301 JMP FIXLINE +114E 2302 +114E 2303 DPUT: +114E 2304 ;Handle PUT pseudo-op +114E 89 16 DC 1B 2305 MOV [HEXADD],DX +1152 E9 02 FF 2306 JMP FIXLINE +1155 2307 +1155 2308 OUTLIN: +1155 2309 ;Copy the source line to the ouput device. Line will be preceded by +1155 2310 ;assembler-generated line number. This routine may be called several times +1155 2311 ;on one line (once for each line of object code bytes), so it sets a flag +1155 2312 ;so the line will only be output on the first call. +1155 B0 FF 2313 MOV AL,-1 +1157 86 06 E2 1B 2314 XCHG AL,[LINFLG] +115B 0A C0 2315 OR AL,AL +115D 75 33 2316 JNZ CRLF ;Output line only if first time +115F A1 D8 1B 2317 MOV AX,[LINE] +1162 40 2318 INC AX +1163 A3 D8 1B 2319 MOV [LINE],AX +1166 B7 00 2320 MOV BH,0 ;No leading zero suppression +1168 E8 30 00 2321 CALL OUT10 +116B B0 20 2322 MOV AL," " +116D E8 79 00 2323 CALL LIST +1170 A0 40 1B 2324 MOV AL,[LSTFCB] +1173 3C 5A 2325 CMP AL,'Z' +1175 74 1B 2326 JZ CRLF ;Don't call NEXTCHR if listing suppressed +1177 56 2327 PUSH SI ;Save the only register destroyed by NEXTCHR +1178 2328 OUTLN: +1178 E8 39 F1 2329 CALL NEXTCHR +117B E8 6B 00 2330 CALL LIST +117E 3C 0A 2331 CMP AL,10 ;Output until linefeed found +1180 75 F6 2332 JNZ OUTLN +1182 5E 2333 POP SI +1183 C3 2334 RET +1184 2335 +1184 2336 PRTCNT: +1184 BB E7 1A 2337 MOV BX,ERCNTM +1187 E8 E6 01 2338 CALL PRINT +118A A1 E6 1B 2339 MOV AX,[ERRCNT] +118D B7 10 2340 MOV BH,"0"-" " ;Enable leading zero suppression +118F E8 09 00 2341 CALL OUT10 +1192 2342 CRLF: +1192 B0 0D 2343 MOV AL,13 +1194 E8 52 00 2344 CALL LIST +1197 B0 0A 2345 MOV AL,10 +1199 EB 4E 2346 JP LIST +119B 2347 +119B 2348 OUT10: +119B 33 D2 2349 XOR DX,DX +119D BF 10 27 2350 MOV DI,10000 +11A0 F7 F7 2351 DIV AX,DI +11A2 0A C0 2352 OR AL,AL ;>10,000? +11A4 75 02 2353 JNZ LEAD +11A6 2C 10 2354 SUB AL,"0"-" " ;Convert leading zero to blank +11A8 2355 LEAD: +11A8 04 30 2356 ADD AL,"0" +11AA E8 3C 00 2357 CALL LIST +11AD 92 2358 XCHG AX,DX +11AE B3 64 2359 MOV BL,100 +11B0 F6 F3 2360 DIV AL,BL +11B2 8A DC 2361 MOV BL,AH +11B4 E8 0C 00 2362 CALL HIDIG ;Convert to decimal and print 1000s digit +11B7 E8 0E 00 2363 CALL DIGIT ;Print 100s digit +11BA 8A C3 2364 MOV AL,BL +11BC E8 04 00 2365 CALL HIDIG ;Convert to decimal and print 10s digit +11BF B7 00 2366 MOV BH,0 ;Ensure leading zero suppression is off +11C1 EB 05 2367 JP DIGIT +11C3 2368 +11C3 2369 HIDIG: +11C3 D4 0A 2370 AAM ;Convert binary to unpacked BCD +11C5 0D 30 30 2371 OR AX,3030H ;Add "0" bias +11C8 2372 DIGIT: +11C8 86 C4 2373 XCHG AL,AH +11CA 3C 30 2374 CMP AL,"0" +11CC 74 02 2375 JZ SUPZ +11CE B7 00 2376 MOV BH,0 ;Turn off zero suppression if not zero +11D0 2377 SUPZ: +11D0 2A C7 2378 SUB AL,BH ;Convert leading zeros to blanks +11D2 EB 15 2379 JP LIST +11D4 2380 +11D4 2381 STRTLIN: +11D4 C6 06 E2 1B 00 2382 MOV B,[LINFLG],0 +11D9 8B 1E 65 1B 2383 MOV BX,[PC] +11DD 8A C7 2384 MOV AL,BH +11DF E8 4D 00 2385 CALL PHEX +11E2 8A C3 2386 MOV AL,BL +11E4 2387 PHEXB: +11E4 E8 48 00 2388 CALL PHEX +11E7 B0 20 2389 MOV AL,' ' +11E9 2390 LIST: +11E9 50 2391 PUSH AX +11EA 52 2392 PUSH DX +11EB 24 7F 2393 AND AL,7FH +11ED 8A D0 2394 MOV DL,AL +11EF F6 06 EC 1B 03 2395 TEST B,[LSTDEV],3 ;See if output goes to console +11F4 74 04 2396 JZ PRNCHK +11F6 B4 02 2397 MOV AH,2 +11F8 CD 21 2398 INT 33 ;Output to console +11FA 2399 PRNCHK: +11FA F6 06 EC 1B 04 2400 TEST B,[LSTDEV],4 ;See if output goes to printer +11FF 74 04 2401 JZ FILCHK +1201 B4 04 2402 MOV AH,4 +1203 CD 21 2403 INT 33 ;Output to printer +1205 2404 FILCHK: +1205 8A C2 2405 MOV AL,DL +1207 5A 2406 POP DX +1208 F6 06 EC 1B 80 2407 TEST B,[LSTDEV],80H ;See if output goes to a file +120D 74 03 2408 JZ LISTRET +120F E8 02 00 2409 CALL WRTBUF +1212 2410 LISTRET: +1212 58 2411 POP AX +1213 C3 2412 RET +1214 2413 +1214 2414 WRTBUF: +1214 57 2415 PUSH DI +1215 8B 3E F6 1B 2416 MOV DI,[LSTPNT] +1219 AA 2417 STOB +121A 81 FF 3E 20 2418 CMP DI,LSTBUF+LSTBUFSIZ +121E 75 09 2419 JNZ SAVPT +1220 50 2420 PUSH AX +1221 51 2421 PUSH CX +1222 52 2422 PUSH DX +1223 E8 22 02 2423 CALL FLUSHBUF +1226 5A 2424 POP DX +1227 59 2425 POP CX +1228 58 2426 POP AX +1229 2427 SAVPT: +1229 89 3E F6 1B 2428 MOV [LSTPNT],DI +122D 5F 2429 POP DI +122E C3 2430 RET +122F 2431 +122F 2432 PHEX: +122F 50 2433 PUSH AX +1230 E8 37 02 2434 CALL UHALF +1233 E8 B3 FF 2435 CALL LIST +1236 58 2436 POP AX +1237 E8 38 02 2437 CALL LHALF +123A EB AD 2438 JP LIST +123C 2439 +123C 2440 FINI: +123C 80 0E EC 1B 01 2441 OR B,[LSTDEV],1 +1241 E8 40 FF 2442 CALL PRTCNT +1244 80 26 EC 1B FE 2443 AND B,[LSTDEV],0FEH +1249 A0 1B 1B 2444 MOV AL,[HEXFCB] +124C 3C 5A 2445 CMP AL,'Z' +124E 74 3B 2446 JZ SYMDMP +1250 A0 E0 1B 2447 MOV AL,[HEXCNT] +1253 3C FB 2448 CMP AL,-5 +1255 74 03 2449 JZ L0012 +1257 E8 A0 01 2450 CALL ENHEXL +125A 2451 L0012: +125A B0 3A 2452 MOV AL,':' +125C E8 DF 01 2453 CALL PUTCHR +125F B5 0A 2454 MOV CH,10 +1261 2455 HEXEND: +1261 51 2456 PUSH CX +1262 B0 30 2457 MOV AL,'0' +1264 E8 D7 01 2458 CALL PUTCHR +1267 59 2459 POP CX +1268 FE CD 2460 DEC CH +126A 75 F5 2461 JNZ HEXEND +126C B0 0D 2462 MOV AL,13 +126E E8 CD 01 2463 CALL PUTCHR +1271 B0 0A 2464 MOV AL,10 +1273 E8 C8 01 2465 CALL PUTCHR +1276 B0 1A 2466 MOV AL,1AH +1278 E8 C3 01 2467 CALL PUTCHR +127B E8 A5 01 2468 CALL WRTHEX ;Flush HEX file buffer +127E A1 70 00 2469 MOV AX,[FCB+20] +1281 A3 2F 1B 2470 MOV [HEXFCB+20],AX ;Copy date to hex file +1284 BA 1B 1B 2471 MOV DX,HEXFCB +1287 B4 10 2472 MOV AH,CLOSE +1289 CD 21 2473 INT 33 +128B 2474 SYMDMP: +128B A0 D0 1B 2475 MOV AL,[SYMFLG] +128E 3C 53 2476 CMP AL,'S' +1290 75 19 2477 JNZ ENDSYM +1292 BB F8 1A 2478 MOV BX,SYMMES +1295 E8 D8 00 2479 CALL PRINT +1298 8B 16 CC 1B 2480 MOV DX,[BASE] +129C 8A C6 2481 MOV AL,DH +129E 0A C2 2482 OR AL,DL +12A0 74 22 2483 JZ EXIT +12A2 8B 1E CE 1B 2484 MOV BX,[HEAP] +12A6 8B E3 2485 MOV SP,BX +12A8 E8 1C 00 2486 CALL NODE +12AB 2487 ENDSYM: +12AB F6 06 EC 1B 80 2488 TEST B,[LSTDEV],80H ;Print listing to file? +12B0 74 12 2489 JZ EXIT +12B2 B0 1A 2490 MOV AL,1AH +12B4 E8 5D FF 2491 CALL WRTBUF ;Write end-of-file mark +12B7 E8 8E 01 2492 CALL FLUSHBUF +12BA A1 70 00 2493 MOV AX,[FCB+20] ;Get date of source file +12BD A3 54 1B 2494 MOV [LSTFCB+20],AX +12C0 B4 10 2495 MOV AH,CLOSE +12C2 CD 21 2496 INT 33 +12C4 E9 39 ED 2497 EXIT: JMP 0 +12C7 2498 +12C7 2499 NODE: +12C7 87 DA 2500 XCHG DX,BX +12C9 53 2501 PUSH BX +12CA 8A 17 2502 MOV DL,[BX] +12CC B6 00 2503 MOV DH,0 +12CE 43 2504 INC BX +12CF 03 DA 2505 ADD BX,DX +12D1 8A 17 2506 MOV DL,[BX] +12D3 43 2507 INC BX +12D4 8A 37 2508 MOV DH,[BX] +12D6 8A C2 2509 MOV AL,DL +12D8 0A C6 2510 OR AL,DH +12DA 74 03 2511 JZ L0014 +12DC E8 E8 FF 2512 CALL NODE +12DF 2513 L0014: +12DF 5B 2514 POP BX +12E0 8A 2F 2515 MOV CH,[BX] +12E2 43 2516 INC BX +12E3 B0 0A 2517 MOV AL,SYMWID +12E5 2A C5 2518 SUB AL,CH +12E7 73 02 2519 JNC LENOK +12E9 B0 01 2520 MOV AL,1 +12EB 2521 LENOK: +12EB 8A F0 2522 MOV DH,AL +12ED 2523 WRTSYM: +12ED 8A 07 2524 MOV AL,[BX] +12EF 43 2525 INC BX +12F0 E8 F6 FE 2526 CALL LIST +12F3 FE CD 2527 DEC CH +12F5 75 F6 2528 JNZ WRTSYM +12F7 8A EE 2529 MOV CH,DH +12F9 FE C5 2530 INC CH +12FB B0 20 2531 MOV AL,' ' +12FD 2532 OUTB: +12FD E8 E9 FE 2533 CALL LIST +1300 FE CD 2534 DEC CH +1302 75 F9 2535 JNZ OUTB +1304 43 2536 INC BX +1305 43 2537 INC BX +1306 53 2538 PUSH BX +1307 43 2539 INC BX +1308 43 2540 INC BX +1309 43 2541 INC BX +130A 43 2542 INC BX +130B 8A 07 2543 MOV AL,[BX] +130D E8 1F FF 2544 CALL PHEX +1310 4B 2545 DEC BX +1311 8A 07 2546 MOV AL,[BX] +1313 E8 19 FF 2547 CALL PHEX +1316 E8 79 FE 2548 CALL CRLF +1319 5B 2549 POP BX +131A 8B 17 2550 MOV DX,[BX] +131C 43 2551 INC BX +131D 8A C6 2552 MOV AL,DH +131F 0A C2 2553 OR AL,DL +1321 75 A4 2554 JNZ NODE +1323 C3 2555 RET +1324 2556 +1324 2557 SAVCD: +1324 A2 E3 1B 2558 MOV [PREV],AL +1327 53 2559 PUSH BX +1328 51 2560 PUSH CX +1329 50 2561 PUSH AX +132A 52 2562 PUSH DX +132B E8 59 00 2563 CALL CODBYT +132E 5A 2564 POP DX +132F BB D6 1B 2565 MOV BX,COUNT +1332 FE 07 2566 INC B,[BX] +1334 8A 07 2567 MOV AL,[BX] +1336 3C 08 2568 CMP AL,8 +1338 75 11 2569 JNZ NOEXT +133A C6 07 01 2570 MOV B,[BX],1 +133D E8 15 FE 2571 CALL OUTLIN +1340 B0 20 2572 MOV AL,' ' +1342 B5 05 2573 MOV CH,5 +1344 2574 TAB: +1344 E8 A2 FE 2575 CALL LIST +1347 FE CD 2576 DEC CH +1349 75 F9 2577 JNZ TAB +134B 2578 NOEXT: +134B 58 2579 POP AX +134C E8 95 FE 2580 CALL PHEXB +134F 59 2581 POP CX +1350 FF 06 65 1B 2582 INC [PC] +1354 FF 06 DC 1B 2583 INC [HEXADD] +1358 5B 2584 POP BX +1359 C3 2585 RET +135A 2586 +135A 2587 REPERR: +135A 0A C0 2588 OR AL,AL +135C 74 FB 2589 JZ RET +135E 50 2590 PUSH AX +135F BB 6D 1A 2591 MOV BX,ERRMES +1362 E8 0B 00 2592 CALL PRINT +1365 58 2593 POP AX +1366 E8 C6 FE 2594 CALL PHEX +1369 BB 94 1A 2595 MOV BX,ENDMES +136C FF 06 E6 1B 2596 INC [ERRCNT] +1370 2597 PRINT: +1370 8A 07 2598 MOV AL,[BX] +1372 E8 74 FE 2599 CALL LIST +1375 0A C0 2600 OR AL,AL +1377 78 E0 2601 JS RET +1379 43 2602 INC BX +137A EB F4 2603 JP PRINT +137C 2604 +137C 2605 OUTA: +137C 8A D0 2606 MOV DL,AL +137E 2607 OUT: +137E 80 E2 7F 2608 AND DL,7FH +1381 B1 02 2609 MOV CL,2 +1383 2610 SYSTEM: +1383 E8 7F EC 2611 CALL 5 +1386 C3 2612 RET +1387 2613 +1387 2614 CODBYT: +1387 82 3E 1B 1B 5A 2615 CMP B,[HEXFCB],"Z" +138C 74 F8 2616 JZ RET +138E 50 2617 PUSH AX +138F 8B 16 DE 1B 2618 MOV DX,[LASTAD] +1393 8B 1E DC 1B 2619 MOV BX,[HEXADD] +1397 89 1E DE 1B 2620 MOV [LASTAD],BX +139B 42 2621 INC DX +139C A0 E0 1B 2622 MOV AL,[HEXCNT] +139F 3C FB 2623 CMP AL,-5 +13A1 74 07 2624 JZ NEWLIN +13A3 3B DA 2625 CMP BX,DX +13A5 74 2E 2626 JZ AFHEX +13A7 E8 50 00 2627 CALL ENHEXL +13AA 2628 NEWLIN: +13AA B0 3A 2629 MOV AL,':' +13AC E8 8F 00 2630 CALL PUTCHR +13AF B0 FC 2631 MOV AL,-4 +13B1 A2 E0 1B 2632 MOV [HEXCNT],AL +13B4 32 C0 2633 XOR AL,AL +13B6 A2 E1 1B 2634 MOV [CHKSUM],AL +13B9 8B 1E F4 1B 2635 MOV BX,[HEXPNT] +13BD 89 1E DA 1B 2636 MOV [HEXLEN],BX +13C1 E8 12 00 2637 CALL HEXBYT +13C4 A0 DD 1B 2638 MOV AL,[HEXADD+1] +13C7 E8 0C 00 2639 CALL HEXBYT +13CA A0 DC 1B 2640 MOV AL,[HEXADD] +13CD E8 06 00 2641 CALL HEXBYT +13D0 32 C0 2642 XOR AL,AL +13D2 E8 01 00 2643 CALL HEXBYT +13D5 2644 AFHEX: +13D5 58 2645 POP AX +13D6 2646 HEXBYT: +13D6 8A E8 2647 MOV CH,AL +13D8 BB E1 1B 2648 MOV BX,CHKSUM +13DB 02 07 2649 ADD AL,[BX] +13DD 88 07 2650 MOV [BX],AL +13DF 8A C5 2651 MOV AL,CH +13E1 E8 86 00 2652 CALL UHALF +13E4 E8 57 00 2653 CALL PUTCHR +13E7 8A C5 2654 MOV AL,CH +13E9 E8 86 00 2655 CALL LHALF +13EC E8 4F 00 2656 CALL PUTCHR +13EF BB E0 1B 2657 MOV BX,HEXCNT +13F2 FE 07 2658 INC B,[BX] +13F4 8A 07 2659 MOV AL,[BX] +13F6 3C 1A 2660 CMP AL,26 +13F8 75 8C 2661 JNZ RET +13FA 2662 ENHEXL: +13FA 8B 3E DA 1B 2663 MOV DI,[HEXLEN] +13FE 8A E8 2664 MOV CH,AL +1400 E8 67 00 2665 CALL UHALF +1403 AA 2666 STOB +1404 8A C5 2667 MOV AL,CH +1406 E8 69 00 2668 CALL LHALF +1409 AA 2669 STOB +140A B0 FA 2670 MOV AL,-6 +140C A2 E0 1B 2671 MOV [HEXCNT],AL +140F A0 E1 1B 2672 MOV AL,[CHKSUM] +1412 02 C5 2673 ADD AL,CH +1414 F6 D8 2674 NEG AL +1416 E8 BD FF 2675 CALL HEXBYT +1419 B0 0D 2676 MOV AL,13 +141B E8 20 00 2677 CALL PUTCHR +141E B0 0A 2678 MOV AL,10 +1420 E8 1B 00 2679 CALL PUTCHR +1423 2680 WRTHEX: +1423 2681 ;Write out the line +1423 BA F8 1B 2682 MOV DX,HEXBUF +1426 89 16 F4 1B 2683 MOV [HEXPNT],DX +142A B4 1A 2684 MOV AH,SETDMA +142C CD 21 2685 INT 33 +142E 2B FA 2686 SUB DI,DX ;Length of buffer +1430 8B CF 2687 MOV CX,DI +1432 BA 1B 1B 2688 MOV DX,HEXFCB +1435 B4 28 2689 MOV AH,BLKWRT +1437 CD 21 2690 INT 33 +1439 0A C0 2691 OR AL,AL +143B 75 27 2692 JNZ DSKFUL +143D C3 2693 RET +143E 2694 +143E 2695 PUTCHR: +143E 8B 3E F4 1B 2696 MOV DI,[HEXPNT] +1442 AA 2697 STOB +1443 89 3E F4 1B 2698 MOV [HEXPNT],DI +1447 C3 2699 RET +1448 2700 +1448 2701 FLUSHBUF: +1448 8B 0E F6 1B 2702 MOV CX,[LSTPNT] +144C BA 3E 1C 2703 MOV DX,LSTBUF +144F 8B FA 2704 MOV DI,DX +1451 2B CA 2705 SUB CX,DX +1453 74 F2 2706 JZ RET ;Buffer empty? +1455 B4 1A 2707 MOV AH,SETDMA +1457 CD 21 2708 INT 33 +1459 BA 40 1B 2709 MOV DX,LSTFCB +145C B4 28 2710 MOV AH,BLKWRT +145E CD 21 2711 INT 33 +1460 0A C0 2712 OR AL,AL +1462 74 E3 2713 JZ RET +1464 2714 DSKFUL: +1464 BB C2 1A 2715 MOV BX,WRTERR +1467 E9 0A EE 2716 JMP PRERR +146A 2717 +146A 2718 UHALF: +146A D0 D8 2719 RCR AL +146C D0 D8 2720 RCR AL +146E D0 D8 2721 RCR AL +1470 D0 D8 2722 RCR AL +1472 2723 LHALF: +1472 24 0F 2724 AND AL,0FH +1474 0C 30 2725 OR AL,30H +1476 3C 3A 2726 CMP AL,'9'+1 +1478 72 CD 2727 JC RET +147A 04 07 2728 ADD AL,7 +147C C3 2729 RET +147D 2730 +147D 00 2731 NONE: DB 0 +147E 2732 +147E 2733 ; 8086 MNEMONIC TABLE +147E 2734 +147E 2735 ; This table is actually a sequence of subtables, each starting with a label. +147E 2736 ; The label signifies which mnemonics the subtable applies to--A3, for example, +147E 2737 ; means all 3-letter mnemonics beginning with A. +147E 2738 +147E 2739 A3: +147E 07 2740 DB 7 +147F 64 64 2741 DB 'dd' +1481 55 0C 2742 DW GRP7 +1483 02 2743 DB 2 +1484 6E 64 2744 DB 'nd' +1486 39 0D 2745 DW GRP13 +1488 22 2746 DB 22H +1489 64 63 2747 DB 'dc' +148B 55 0C 2748 DW GRP7 +148D 12 2749 DB 12H +148E 61 61 2750 DB 'aa' +1490 1B 0A 2751 DW PUT +1492 37 2752 DB 37H +1493 61 73 2753 DB 'as' +1495 1B 0A 2754 DW PUT +1497 3F 2755 DB 3FH +1498 61 6D 2756 DB 'am' +149A 05 0D 2757 DW GRP11 +149C D4 2758 DB 0D4H +149D 61 64 2759 DB 'ad' +149F 05 0D 2760 DW GRP11 +14A1 D5 2761 DB 0D5H +14A2 2762 A5: +14A2 01 2763 DB 1 +14A3 6C 69 67 6E 2764 DB 'lign' +14A7 F9 0B 2765 DW ALIGN +14A9 00 2766 DB 0 +14AA 2767 C3: +14AA 07 2768 DB 7 +14AB 6D 70 2769 DB 'mp' +14AD 55 0C 2770 DW GRP7 +14AF 3A 2771 DB 3AH +14B0 6C 63 2772 DB 'lc' +14B2 1B 0A 2773 DW PUT +14B4 F8 2774 DB 0F8H +14B5 6C 64 2775 DB 'ld' +14B7 1B 0A 2776 DW PUT +14B9 FC 2777 DB 0FCH +14BA 6C 69 2778 DB 'li' +14BC 1B 0A 2779 DW PUT +14BE FA 2780 DB 0FAH +14BF 6D 63 2781 DB 'mc' +14C1 1B 0A 2782 DW PUT +14C3 F5 2783 DB 0F5H +14C4 62 77 2784 DB 'bw' +14C6 1B 0A 2785 DW PUT +14C8 98 2786 DB 98H +14C9 77 64 2787 DB 'wd' +14CB 1B 0A 2788 DW PUT +14CD 99 2789 DB 99H +14CE 2790 C4: +14CE 03 2791 DB 3 +14CF 61 6C 6C 2792 DB 'all' +14D2 69 0D 2793 DW GRP14 +14D4 9A 2794 DB 9AH +14D5 6D 70 62 2795 DB 'mpb' +14D8 1B 0A 2796 DW PUT +14DA A6 2797 DB 0A6H +14DB 6D 70 77 2798 DB 'mpw' +14DE 1B 0A 2799 DW PUT +14E0 A7 2800 DB 0A7H +14E1 2801 C5: +14E1 02 2802 DB 2 +14E2 6D 70 73 62 2803 DB 'mpsb' +14E6 1B 0A 2804 DW PUT +14E8 A6 2805 DB 0A6H +14E9 6D 70 73 77 2806 DB 'mpsw' +14ED 1B 0A 2807 DW PUT +14EF A7 2808 DB 0A7H +14F0 2809 D2: +14F0 05 2810 DB 5 +14F1 62 2811 DB 'b' +14F2 7A 0F 2812 DW GRP23 +14F4 01 2813 DB 1 +14F5 77 2814 DB 'w' +14F6 7A 0F 2815 DW GRP23 +14F8 00 2816 DB 0 +14F9 6D 2817 DB 'm' +14FA 7A 0F 2818 DW GRP23 +14FC 02 2819 DB 2 +14FD 73 2820 DB 's' +14FE C1 0B 2821 DW GRP5 +1500 01 2822 DB 1 +1501 69 2823 DB 'i' +1502 1B 0A 2824 DW PUT +1504 FA 2825 DB 0FAH +1505 2826 D3: +1505 04 2827 DB 4 +1506 65 63 2828 DB 'ec' +1508 7D 0C 2829 DW GRP8 +150A 49 2830 DB 49H +150B 69 76 2831 DB 'iv' +150D D5 0C 2832 DW GRP10 +150F 30 2833 DB 30H +1510 61 61 2834 DB 'aa' +1512 1B 0A 2835 DW PUT +1514 27 2836 DB 27H +1515 61 73 2837 DB 'as' +1517 1B 0A 2838 DW PUT +1519 2F 2839 DB 2FH +151A 2840 D4: +151A 01 2841 DB 1 +151B 6F 77 6E 2842 DB 'own' +151E 1B 0A 2843 DW PUT +1520 FD 2844 DB 0FDH +1521 2845 E2: +1521 01 2846 DB 1 +1522 69 2847 DB 'i' +1523 1B 0A 2848 DW PUT +1525 FB 2849 DB 0FBH +1526 2850 E3: +1526 03 2851 DB 3 +1527 71 75 2852 DB 'qu' +1529 C1 0B 2853 DW GRP5 +152B 02 2854 DB 2 +152C 73 63 2855 DB 'sc' +152E C9 0E 2856 DW GRP19 +1530 D8 2857 DB 0D8H +1531 6E 64 2858 DB 'nd' +1533 08 10 2859 DW END +1535 00 2860 DB 0 +1536 2861 E5: +1536 01 2862 DB 1 +1537 6E 64 69 66 2863 DB 'ndif' +153B F8 0F 2864 DW ENDIF +153D 00 2865 DB 0 +153E 2866 H3: +153E 01 2867 DB 1 +153F 6C 74 2868 DB 'lt' +1541 1B 0A 2869 DW PUT +1543 F4 2870 DB 0F4H +1544 2871 H4: +1544 01 2872 DB 1 +1545 61 6C 74 2873 DB 'alt' +1548 1B 0A 2874 DW PUT +154A F4 2875 DB 0F4H +154B 2876 I2: +154B 02 2877 DB 2 +154C 6E 2878 DB 'n' +154D 98 0B 2879 DW GRP4 +154F E4 2880 DB 0E4H +1550 66 2881 DB 'f' +1551 C1 0B 2882 DW GRP5 +1553 04 2883 DB 4 +1554 2884 I3: +1554 04 2885 DB 4 +1555 6E 63 2886 DB 'nc' +1557 7D 0C 2887 DW GRP8 +1559 41 2888 DB 41H +155A 6E 62 2889 DB 'nb' +155C 98 0B 2890 DW GRP4 +155E E4 2891 DB 0E4H +155F 6E 77 2892 DB 'nw' +1561 98 0B 2893 DW GRP4 +1563 E5 2894 DB 0E5H +1564 6E 74 2895 DB 'nt' +1566 9E 0E 2896 DW GRP18 +1568 CC 2897 DB 0CCH +1569 2898 I4: +1569 04 2899 DB 4 +156A 6D 75 6C 2900 DB 'mul' +156D D5 0C 2901 DW GRP10 +156F 28 2902 DB 28H +1570 64 69 76 2903 DB 'div' +1573 D5 0C 2904 DW GRP10 +1575 38 2905 DB 38H +1576 72 65 74 2906 DB 'ret' +1579 1B 0A 2907 DW PUT +157B CF 2908 DB 0CFH +157C 6E 74 6F 2909 DB 'nto' +157F 1B 0A 2910 DW PUT +1581 CE 2911 DB 0CEH +1582 2912 J2: +1582 0A 2913 DB 10 +1583 70 2914 DB 'p' +1584 65 0E 2915 DW GRP17 +1586 EB 2916 DB 0EBH +1587 7A 2917 DB 'z' +1588 65 0E 2918 DW GRP17 +158A 74 2919 DB 74H +158B 65 2920 DB 'e' +158C 65 0E 2921 DW GRP17 +158E 74 2922 DB 74H +158F 6C 2923 DB 'l' +1590 65 0E 2924 DW GRP17 +1592 7C 2925 DB 7CH +1593 62 2926 DB 'b' +1594 65 0E 2927 DW GRP17 +1596 72 2928 DB 72H +1597 61 2929 DB 'a' +1598 65 0E 2930 DW GRP17 +159A 77 2931 DB 77H +159B 67 2932 DB 'g' +159C 65 0E 2933 DW GRP17 +159E 7F 2934 DB 7FH +159F 6F 2935 DB 'o' +15A0 65 0E 2936 DW GRP17 +15A2 70 2937 DB 70H +15A3 73 2938 DB 's' +15A4 65 0E 2939 DW GRP17 +15A6 78 2940 DB 78H +15A7 63 2941 DB 'c' +15A8 65 0E 2942 DW GRP17 +15AA 72 2943 DB 72H +15AB 2944 J3: +15AB 11 2945 DB 17 +15AC 6D 70 2946 DB 'mp' +15AE 69 0D 2947 DW GRP14 +15B0 EA 2948 DB 0EAH +15B1 6E 7A 2949 DB 'nz' +15B3 65 0E 2950 DW GRP17 +15B5 75 2951 DB 75H +15B6 6E 65 2952 DB 'ne' +15B8 65 0E 2953 DW GRP17 +15BA 75 2954 DB 75H +15BB 6E 6C 2955 DB 'nl' +15BD 65 0E 2956 DW GRP17 +15BF 7D 2957 DB 7DH +15C0 67 65 2958 DB 'ge' +15C2 65 0E 2959 DW GRP17 +15C4 7D 2960 DB 7DH +15C5 6E 62 2961 DB 'nb' +15C7 65 0E 2962 DW GRP17 +15C9 73 2963 DB 73H +15CA 61 65 2964 DB 'ae' +15CC 65 0E 2965 DW GRP17 +15CE 73 2966 DB 73H +15CF 6E 63 2967 DB 'nc' +15D1 65 0E 2968 DW GRP17 +15D3 73 2969 DB 73H +15D4 6E 67 2970 DB 'ng' +15D6 65 0E 2971 DW GRP17 +15D8 7E 2972 DB 7EH +15D9 6C 65 2973 DB 'le' +15DB 65 0E 2974 DW GRP17 +15DD 7E 2975 DB 7EH +15DE 6E 61 2976 DB 'na' +15E0 65 0E 2977 DW GRP17 +15E2 76 2978 DB 76H +15E3 62 65 2979 DB 'be' +15E5 65 0E 2980 DW GRP17 +15E7 76 2981 DB 76H +15E8 70 65 2982 DB 'pe' +15EA 65 0E 2983 DW GRP17 +15EC 7A 2984 DB 7AH +15ED 6E 70 2985 DB 'np' +15EF 65 0E 2986 DW GRP17 +15F1 7B 2987 DB 7BH +15F2 70 6F 2988 DB 'po' +15F4 65 0E 2989 DW GRP17 +15F6 7B 2990 DB 7BH +15F7 6E 6F 2991 DB 'no' +15F9 65 0E 2992 DW GRP17 +15FB 71 2993 DB 71H +15FC 6E 73 2994 DB 'ns' +15FE 65 0E 2995 DW GRP17 +1600 79 2996 DB 79H +1601 2997 J4: +1601 06 2998 DB 6 +1602 6D 70 73 2999 DB 'mps' +1605 65 0E 3000 DW GRP17 +1607 EB 3001 DB 0EBH +1608 63 78 7A 3002 DB 'cxz' +160B 65 0E 3003 DW GRP17 +160D E3 3004 DB 0E3H +160E 6E 67 65 3005 DB 'nge' +1611 65 0E 3006 DW GRP17 +1613 7C 3007 DB 7CH +1614 6E 61 65 3008 DB 'nae' +1617 65 0E 3009 DW GRP17 +1619 72 3010 DB 72H +161A 6E 62 65 3011 DB 'nbe' +161D 65 0E 3012 DW GRP17 +161F 77 3013 DB 77H +1620 6E 6C 65 3014 DB 'nle' +1623 65 0E 3015 DW GRP17 +1625 7F 3016 DB 7FH +1626 3017 L3: +1626 03 3018 DB 3 +1627 65 61 3019 DB 'ea' +1629 49 0C 3020 DW GRP6 +162B 8D 3021 DB 8DH +162C 64 73 3022 DB 'ds' +162E 49 0C 3023 DW GRP6 +1630 C5 3024 DB 0C5H +1631 65 73 3025 DB 'es' +1633 49 0C 3026 DW GRP6 +1635 C4 3027 DB 0C4H +1636 3028 L4: +1636 05 3029 DB 5 +1637 6F 6F 70 3030 DB 'oop' +163A 65 0E 3031 DW GRP17 +163C E2 3032 DB 0E2H +163D 6F 64 62 3033 DB 'odb' +1640 1B 0A 3034 DW PUT +1642 AC 3035 DB 0ACH +1643 6F 64 77 3036 DB 'odw' +1646 1B 0A 3037 DW PUT +1648 AD 3038 DB 0ADH +1649 61 68 66 3039 DB 'ahf' +164C 1B 0A 3040 DW PUT +164E 9F 3041 DB 9FH +164F 6F 63 6B 3042 DB 'ock' +1652 1B 0A 3043 DW PUT +1654 F0 3044 DB 0F0H +1655 3045 L5: +1655 04 3046 DB 4 +1656 6F 6F 70 65 3047 DB 'oope' +165A 65 0E 3048 DW GRP17 +165C E1 3049 DB 0E1H +165D 6F 6F 70 7A 3050 DB 'oopz' +1661 65 0E 3051 DW GRP17 +1663 E1 3052 DB 0E1H +1664 6F 64 73 62 3053 DB 'odsb' +1668 1B 0A 3054 DW PUT +166A AC 3055 DB 0ACH +166B 6F 64 73 77 3056 DB 'odsw' +166F 1B 0A 3057 DW PUT +1671 AD 3058 DB 0ADH +1672 3059 L6: +1672 02 3060 DB 2 +1673 6F 6F 70 6E 65 3061 DB 'oopne' +1678 65 0E 3062 DW GRP17 +167A E0 3063 DB 0E0H +167B 6F 6F 70 6E 7A 3064 DB 'oopnz' +1680 65 0E 3065 DW GRP17 +1682 E0 3066 DB 0E0H +1683 3067 M3: +1683 02 3068 DB 2 +1684 6F 76 3069 DB 'ov' +1686 AE 09 3070 DW GRP1 +1688 88 3071 DB 88H +1689 75 6C 3072 DB 'ul' +168B D5 0C 3073 DW GRP10 +168D 20 3074 DB 20H +168E 3075 M4: +168E 02 3076 DB 2 +168F 6F 76 62 3077 DB 'ovb' +1692 1B 0A 3078 DW PUT +1694 A4 3079 DB 0A4H +1695 6F 76 77 3080 DB 'ovw' +1698 1B 0A 3081 DW PUT +169A A5 3082 DB 0A5H +169B 3083 M5: +169B 02 3084 DB 2 +169C 6F 76 73 62 3085 DB 'ovsb' +16A0 1B 0A 3086 DW PUT +16A2 A4 3087 DB 0A4H +16A3 6F 76 73 77 3088 DB 'ovsw' +16A7 1B 0A 3089 DW PUT +16A9 A5 3090 DB 0A5H +16AA 3091 N3: +16AA 03 3092 DB 3 +16AB 6F 74 3093 DB 'ot' +16AD 83 0C 3094 DW GRP9 +16AF 10 3095 DB 10H +16B0 65 67 3096 DB 'eg' +16B2 83 0C 3097 DW GRP9 +16B4 18 3098 DB 18H +16B5 6F 70 3099 DB 'op' +16B7 1B 0A 3100 DW PUT +16B9 90 3101 DB 90H +16BA 3102 O2: +16BA 01 3103 DB 1 +16BB 72 3104 DB 'r' +16BC 39 0D 3105 DW GRP13 +16BE 0A 3106 DB 0AH +16BF 3107 O3: +16BF 02 3108 DB 2 +16C0 75 74 3109 DB 'ut' +16C2 98 0B 3110 DW GRP4 +16C4 E6 3111 DB 0E6H +16C5 72 67 3112 DB 'rg' +16C7 C1 0B 3113 DW GRP5 +16C9 00 3114 DB 0 +16CA 3115 O4: +16CA 02 3116 DB 2 +16CB 75 74 62 3117 DB 'utb' +16CE 98 0B 3118 DW GRP4 +16D0 E6 3119 DB 0E6H +16D1 75 74 77 3120 DB 'utw' +16D4 98 0B 3121 DW GRP4 +16D6 E7 3122 DB 0E7H +16D7 3123 P3: +16D7 02 3124 DB 2 +16D8 6F 70 3125 DB 'op' +16DA 59 0F 3126 DW GRP22 +16DC 8F 3127 DB 8FH +16DD 75 74 3128 DB 'ut' +16DF C1 0B 3129 DW GRP5 +16E1 03 3130 DB 3 +16E2 3131 P4: +16E2 02 3132 DB 2 +16E3 75 73 68 3133 DB 'ush' +16E6 07 0B 3134 DW GRP2 +16E8 FF 3135 DB 0FFH +16E9 6F 70 66 3136 DB 'opf' +16EC 1B 0A 3137 DW PUT +16EE 9D 3138 DB 9DH +16EF 3139 P5: +16EF 01 3140 DB 1 +16F0 75 73 68 66 3141 DB 'ushf' +16F4 1B 0A 3142 DW PUT +16F6 9C 3143 DB 9CH +16F7 3144 R3: +16F7 06 3145 DB 6 +16F8 65 74 3146 DB 'et' +16FA E6 0D 3147 DW GRP16 +16FC C3 3148 DB 0C3H +16FD 65 70 3149 DB 'ep' +16FF 1B 0A 3150 DW PUT +1701 F3 3151 DB 0F3H +1702 6F 6C 3152 DB 'ol' +1704 0D 0D 3153 DW GRP12 +1706 00 3154 DB 0 +1707 6F 72 3155 DB 'or' +1709 0D 0D 3156 DW GRP12 +170B 08 3157 DB 8 +170C 63 6C 3158 DB 'cl' +170E 0D 0D 3159 DW GRP12 +1710 10 3160 DB 10H +1711 63 72 3161 DB 'cr' +1713 0D 0D 3162 DW GRP12 +1715 18 3163 DB 18H +1716 3164 R4: +1716 02 3165 DB 2 +1717 65 70 7A 3166 DB 'epz' +171A 1B 0A 3167 DW PUT +171C F3 3168 DB 0F3H +171D 65 70 65 3169 DB 'epe' +1720 1B 0A 3170 DW PUT +1722 F3 3171 DB 0F3H +1723 3172 R5: +1723 02 3173 DB 2 +1724 65 70 6E 7A 3174 DB 'epnz' +1728 1B 0A 3175 DW PUT +172A F2 3176 DB 0F2H +172B 65 70 6E 65 3177 DB 'epne' +172F 1B 0A 3178 DW PUT +1731 F2 3179 DB 0F2H +1732 3180 S3: +1732 0B 3181 DB 11 +1733 75 62 3182 DB 'ub' +1735 55 0C 3183 DW GRP7 +1737 2A 3184 DB 2AH +1738 62 62 3185 DB 'bb' +173A 55 0C 3186 DW GRP7 +173C 1A 3187 DB 1AH +173D 62 63 3188 DB 'bc' +173F 55 0C 3189 DW GRP7 +1741 1A 3190 DB 1AH +1742 74 63 3191 DB 'tc' +1744 1B 0A 3192 DW PUT +1746 F9 3193 DB 0F9H +1747 74 64 3194 DB 'td' +1749 1B 0A 3195 DW PUT +174B FD 3196 DB 0FDH +174C 74 69 3197 DB 'ti' +174E 1B 0A 3198 DW PUT +1750 FB 3199 DB 0FBH +1751 68 6C 3200 DB 'hl' +1753 0D 0D 3201 DW GRP12 +1755 20 3202 DB 20H +1756 68 72 3203 DB 'hr' +1758 0D 0D 3204 DW GRP12 +175A 28 3205 DB 28H +175B 61 6C 3206 DB 'al' +175D 0D 0D 3207 DW GRP12 +175F 20 3208 DB 20H +1760 61 72 3209 DB 'ar' +1762 0D 0D 3210 DW GRP12 +1764 38 3211 DB 38H +1765 65 67 3212 DB 'eg' +1767 41 0F 3213 DW GRP21 +1769 26 3214 DB 26H +176A 3215 S4: +176A 05 3216 DB 5 +176B 63 61 62 3217 DB 'cab' +176E 1B 0A 3218 DW PUT +1770 AE 3219 DB 0AEH +1771 63 61 77 3220 DB 'caw' +1774 1B 0A 3221 DW PUT +1776 AF 3222 DB 0AFH +1777 74 6F 62 3223 DB 'tob' +177A 1B 0A 3224 DW PUT +177C AA 3225 DB 0AAH +177D 74 6F 77 3226 DB 'tow' +1780 1B 0A 3227 DW PUT +1782 AB 3228 DB 0ABH +1783 61 68 66 3229 DB 'ahf' +1786 1B 0A 3230 DW PUT +1788 9E 3231 DB 9EH +1789 3232 S5: +1789 04 3233 DB 4 +178A 63 61 73 62 3234 DB 'casb' +178E 1B 0A 3235 DW PUT +1790 AE 3236 DB 0AEH +1791 63 61 73 77 3237 DB 'casw' +1795 1B 0A 3238 DW PUT +1797 AF 3239 DB 0AFH +1798 74 6F 73 62 3240 DB 'tosb' +179C 1B 0A 3241 DW PUT +179E AA 3242 DB 0AAH +179F 74 6F 73 77 3243 DB 'tosw' +17A3 1B 0A 3244 DW PUT +17A5 AB 3245 DB 0ABH +17A6 3246 T4: +17A6 01 3247 DB 1 +17A7 65 73 74 3248 DB 'est' +17AA 30 0F 3249 DW GRP20 +17AC 84 3250 DB 84H +17AD 3251 U2: +17AD 01 3252 DB 1 +17AE 70 3253 DB 'p' +17AF 1B 0A 3254 DW PUT +17B1 FC 3255 DB 0FCH +17B2 3256 W4: +17B2 01 3257 DB 1 +17B3 61 69 74 3258 DB 'ait' +17B6 1B 0A 3259 DW PUT +17B8 9B 3260 DB 9BH +17B9 3261 X3: +17B9 01 3262 DB 1 +17BA 6F 72 3263 DB 'or' +17BC 39 0D 3264 DW GRP13 +17BE 32 3265 DB 32H +17BF 3266 X4: +17BF 02 3267 DB 2 +17C0 63 68 67 3268 DB 'chg' +17C3 38 0B 3269 DW GRP3 +17C5 86 3270 DB 86H +17C6 6C 61 74 3271 DB 'lat' +17C9 1B 0A 3272 DW PUT +17CB D7 3273 DB 0D7H +17CC 3274 +17CC 3275 +17CC 3276 ; 8087 MNEMONIC TABLE +17CC 3277 ; Similar to 8086 table above, except NOT distinguished by opcode length +17CC 3278 +17CC 3279 XM1: ;F2XM1 +17CC 01 3280 DB 1 ;One opcode +17CD 78 6D B1 3281 DM "xm1" +17D0 01 F0 3282 DB 1,0F0H +17D2 3283 +17D2 3284 NDPA: +17D2 03 3285 DB 3 +17D3 64 E4 3286 DM "dd" +17D5 00 C0 3287 DB 0,0C0H +17D7 64 64 F0 3288 DM "ddp" +17DA 06 C0 3289 DB 6,0C0H +17DC 62 F3 3290 DM "bs" +17DE 01 E0 3291 DB 1,0E0H +17E0 3292 +17E0 3293 NDPB: +17E0 02 3294 DB 2 +17E1 6C E4 3295 DM "ld" +17E3 07 20 3296 DB 7,20H +17E5 73 74 F0 3297 DM "stp" +17E8 07 30 3298 DB 7,30H +17EA 3299 +17EA 3300 NDPC: +17EA 05 3301 DB 5 +17EB 6F ED 3302 DM "om" +17ED 00 D0 3303 DB 0,0D0H +17EF 6F 6D F0 3304 DM "omp" +17F2 00 18 3305 DB 0,18H +17F4 68 F3 3306 DM "hs" +17F6 01 E0 3307 DB 1,0E0H +17F8 6F 6D 70 F0 3308 DM "ompp" +17FC 06 D9 3309 DB 6,0D9H +17FE 6C 65 F8 3310 DM "lex" +1801 03 E2 3311 DB 3,0E2H +1803 3312 +1803 3313 NDPD: +1803 06 3314 DB 6 +1804 69 F6 3315 DM "iv" +1806 00 30 3316 DB 0,30H +1808 69 76 F0 3317 DM "ivp" +180B 06 F0 3318 DB 6,0F0H +180D 69 76 F2 3319 DM "ivr" +1810 00 38 3320 DB 0,38H +1812 69 76 72 F0 3321 DM "ivrp" +1816 06 F8 3322 DB 6,0F8H +1818 65 63 73 74 F0 3323 DM "ecstp" +181D 01 F6 3324 DB 1,0F6H +181F 69 73 E9 3325 DM "isi" +1822 03 E1 3326 DB 3,0E1H +1824 3327 +1824 3328 NDPE: +1824 01 3329 DB 1 +1825 6E E9 3330 DM "ni" +1827 03 E0 3331 DB 3,0E0H +1829 3332 +1829 3333 NDPF: +1829 01 3334 DB 1 +182A 72 65 E5 3335 DM "ree" +182D 05 C0 3336 DB 5,0C0H +182F 3337 +182F 3338 NDPI: +182F 0D 3339 DB 13 +1830 61 64 E4 3340 DM "add" +1833 00 00 3341 DB 0,0 +1835 6C E4 3342 DM "ld" +1837 00 00 3343 DB 0,0 +1839 73 75 E2 3344 DM "sub" +183C 00 00 3345 DB 0,0 +183E 73 74 F0 3346 DM "stp" +1841 00 00 3347 DB 0,0 +1843 73 F4 3348 DM "st" +1845 00 00 3349 DB 0,0 +1847 6D 75 EC 3350 DM "mul" +184A 00 00 3351 DB 0,0 +184C 64 69 F6 3352 DM "div" +184F 00 00 3353 DB 0,0 +1851 73 75 62 F2 3354 DM "subr" +1855 00 00 3355 DB 0,0 +1857 64 69 76 F2 3356 DM "divr" +185B 00 00 3357 DB 0,0 +185D 63 6F ED 3358 DM "com" +1860 00 00 3359 DB 0,0 +1862 63 6F 6D F0 3360 DM "comp" +1866 00 00 3361 DB 0,0 +1868 6E 63 73 74 F0 3362 DM "ncstp" +186D 01 F7 3363 DB 1,0F7H +186F 6E 69 F4 3364 DM "nit" +1872 03 E3 3365 DB 3,0E3H +1874 3366 +1874 3367 NDPL: +1874 0A 3368 DB 10 +1875 E4 3369 DM "d" +1876 00 00 3370 DB 0,0 +1878 64 FA 3371 DM "dz" +187A 01 EE 3372 DB 1,0EEH +187C 64 B1 3373 DM "d1" +187E 01 E8 3374 DB 1,0E8H +1880 64 70 E9 3375 DM "dpi" +1883 01 EB 3376 DB 1,0EBH +1885 64 6C 32 F4 3377 DM "dl2t" +1889 01 E9 3378 DB 1,0E9H +188B 64 6C 32 E5 3379 DM "dl2e" +188F 01 EA 3380 DB 1,0EAH +1891 64 6C 67 B2 3381 DM "dlg2" +1895 01 EC 3382 DB 1,0ECH +1897 64 6C 6E B2 3383 DM "dln2" +189B 01 EB 3384 DB 1,0EBH +189D 64 63 F7 3385 DM "dcw" +18A0 01 00 3386 DB 1,0 +18A2 64 65 6E F6 3387 DM "denv" +18A6 00 00 3388 DB 0,0 +18A8 3389 +18A8 3390 NDPM: +18A8 02 3391 DB 2 +18A9 75 EC 3392 DM "ul" +18AB 00 00 3393 DB 0,0 +18AD 75 6C F0 3394 DM "ulp" +18B0 00 00 3395 DB 0,0 +18B2 3396 +18B2 3397 NDPP: +18B2 03 3398 DB 3 +18B3 72 65 ED 3399 DM "rem" +18B6 01 F8 3400 DB 1,0F8H +18B8 74 61 EE 3401 DM "tan" +18BB 01 F2 3402 DB 1,0F2H +18BD 61 74 61 EE 3403 DM "atan" +18C1 01 F3 3404 DB 1,0F3H +18C3 3405 +18C3 3406 NDPR: +18C3 02 3407 DB 2 +18C4 6E 64 69 6E F4 3408 DM "ndint" +18C9 01 FC 3409 DB 1,0FCH +18CB 73 74 6F F2 3410 DM "stor" +18CF 05 00 3411 DB 5,0 +18D1 3412 +18D1 3413 NDPS: +18D1 0C 3414 DB 12 +18D2 F4 3415 DM "t" +18D3 00 00 3416 DB 0,0 +18D5 74 F0 3417 DM "tp" +18D7 00 00 3418 DB 0,0 +18D9 75 E2 3419 DM "ub" +18DB 00 00 3420 DB 0,0 +18DD 75 62 F0 3421 DM "ubp" +18E0 00 00 3422 DB 0,0 +18E2 75 62 F2 3423 DM "ubr" +18E5 00 00 3424 DB 0,0 +18E7 75 62 72 F0 3425 DM "ubrp" +18EB 00 00 3426 DB 0,0 +18ED 71 72 F4 3427 DM "qrt" +18F0 01 FA 3428 DB 1,0FAH +18F2 63 61 6C E5 3429 DM "cale" +18F6 01 FD 3430 DB 1,0FDH +18F8 61 76 E5 3431 DM "ave" +18FB 05 00 3432 DB 5,0 +18FD 74 63 F7 3433 DM "tcw" +1900 05 00 3434 DB 5,0 +1902 74 65 6E F6 3435 DM "tenv" +1906 05 00 3436 DB 5,0 +1908 74 73 F7 3437 DM "tsw" +190B 05 00 3438 DB 5,0 +190D 3439 +190D 3440 NDPT: +190D 01 3441 DB 1 +190E 73 F4 3442 DM "st" +1910 01 E4 3443 DB 1,0E4H +1912 3444 +1912 3445 NDPW: +1912 01 3446 DB 1 +1913 61 69 F4 3447 DM "ait" +1916 00 00 3448 DB 0,0 +1918 3449 +1918 3450 NDPX: +1918 03 3451 DB 3 +1919 63 E8 3452 DM "ch" +191B 01 C4 3453 DB 1,0C4H +191D 61 ED 3454 DM "am" +191F 01 E5 3455 DB 1,0E5H +1921 74 72 61 63 F4 3456 DM "tract" +1926 01 F4 3457 DB 1,0F4H +1928 3458 +1928 3459 NDPY: +1928 02 3460 DB 2 +1929 6C 32 F8 3461 DM "l2x" +192C 01 F1 3462 DB 1,0F1H +192E 6C 32 78 70 B1 3463 DM "l2xp1" +1933 01 F9 3464 DB 1,0F9H +1935 3465 +1935 3466 +1935 3467 OPTAB: +1935 3468 ; Table of pointers to mnemonics. For each letter of the alphabet (the +1935 3469 ; starting letter of the mnemonic), there are 5 entries. Each entry +1935 3470 ; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +1935 3471 ; long, respectively. If there are no mnemonics for a given combination +1935 3472 ; of first letter and length (such as A-2), then the corresponding entry +1935 3473 ; points to NONE. Otherwise, it points to a place in the mnemonic table +1935 3474 ; for that type. +1935 3475 +1935 3476 ; This table only needs to be modified if a mnemonic is added to a group +1935 3477 ; previously marked NONE. Change the NONE to a label made up of the first +1935 3478 ; letter of the mnemonic and its length, then add a new subsection to +1935 3479 ; the mnemonic table in alphabetical order. +1935 3480 +1935 7D 14 3481 DW NONE +1937 7E 14 3482 DW A3 +1939 7D 14 3483 DW NONE +193B A2 14 3484 DW A5 +193D 7D 14 3485 DW NONE +193F 7D 14 3486 DW NONE ;B +1941 7D 14 3487 DW NONE +1943 7D 14 3488 DW NONE +1945 7D 14 3489 DW NONE +1947 7D 14 3490 DW NONE +1949 7D 14 3491 DW NONE ;C +194B AA 14 3492 DW C3 +194D CE 14 3493 DW C4 +194F E1 14 3494 DW C5 +1951 7D 14 3495 DW NONE +1953 F0 14 3496 DW D2 ;D +1955 05 15 3497 DW D3 +1957 1A 15 3498 DW D4 +1959 7D 14 3499 DW NONE +195B 7D 14 3500 DW NONE +195D 21 15 3501 DW E2 ;E +195F 26 15 3502 DW E3 +1961 7D 14 3503 DW NONE +1963 36 15 3504 DW E5 +1965 7D 14 3505 DW NONE +1967 7D 14 3506 DW NONE ;F +1969 7D 14 3507 DW NONE +196B 7D 14 3508 DW NONE +196D 7D 14 3509 DW NONE +196F 7D 14 3510 DW NONE +1971 7D 14 3511 DW NONE ;G +1973 7D 14 3512 DW NONE +1975 7D 14 3513 DW NONE +1977 7D 14 3514 DW NONE +1979 7D 14 3515 DW NONE +197B 7D 14 3516 DW NONE ;H +197D 3E 15 3517 DW H3 +197F 44 15 3518 DW H4 +1981 7D 14 3519 DW NONE +1983 7D 14 3520 DW NONE +1985 4B 15 3521 DW I2 ;I +1987 54 15 3522 DW I3 +1989 69 15 3523 DW I4 +198B 7D 14 3524 DW NONE +198D 7D 14 3525 DW NONE +198F 82 15 3526 DW J2 ;J +1991 AB 15 3527 DW J3 +1993 01 16 3528 DW J4 +1995 7D 14 3529 DW NONE +1997 7D 14 3530 DW NONE +1999 7D 14 3531 DW NONE ;K +199B 7D 14 3532 DW NONE +199D 7D 14 3533 DW NONE +199F 7D 14 3534 DW NONE +19A1 7D 14 3535 DW NONE +19A3 7D 14 3536 DW NONE ;L +19A5 26 16 3537 DW L3 +19A7 36 16 3538 DW L4 +19A9 55 16 3539 DW L5 +19AB 72 16 3540 DW L6 +19AD 7D 14 3541 DW NONE ;M +19AF 83 16 3542 DW M3 +19B1 8E 16 3543 DW M4 +19B3 9B 16 3544 DW M5 +19B5 7D 14 3545 DW NONE +19B7 7D 14 3546 DW NONE ;N +19B9 AA 16 3547 DW N3 +19BB 7D 14 3548 DW NONE +19BD 7D 14 3549 DW NONE +19BF 7D 14 3550 DW NONE +19C1 BA 16 3551 DW O2 ;O +19C3 BF 16 3552 DW O3 +19C5 CA 16 3553 DW O4 +19C7 7D 14 3554 DW NONE +19C9 7D 14 3555 DW NONE +19CB 7D 14 3556 DW NONE ;P +19CD D7 16 3557 DW P3 +19CF E2 16 3558 DW P4 +19D1 EF 16 3559 DW P5 +19D3 7D 14 3560 DW NONE +19D5 7D 14 3561 DW NONE ;Q +19D7 7D 14 3562 DW NONE +19D9 7D 14 3563 DW NONE +19DB 7D 14 3564 DW NONE +19DD 7D 14 3565 DW NONE +19DF 7D 14 3566 DW NONE ;R +19E1 F7 16 3567 DW R3 +19E3 16 17 3568 DW R4 +19E5 23 17 3569 DW R5 +19E7 7D 14 3570 DW NONE +19E9 7D 14 3571 DW NONE ;S +19EB 32 17 3572 DW S3 +19ED 6A 17 3573 DW S4 +19EF 89 17 3574 DW S5 +19F1 7D 14 3575 DW NONE +19F3 7D 14 3576 DW NONE ;T +19F5 7D 14 3577 DW NONE +19F7 A6 17 3578 DW T4 +19F9 7D 14 3579 DW NONE +19FB 7D 14 3580 DW NONE +19FD AD 17 3581 DW U2 ;U +19FF 7D 14 3582 DW NONE +1A01 7D 14 3583 DW NONE +1A03 7D 14 3584 DW NONE +1A05 7D 14 3585 DW NONE +1A07 7D 14 3586 DW NONE ;V +1A09 7D 14 3587 DW NONE +1A0B 7D 14 3588 DW NONE +1A0D 7D 14 3589 DW NONE +1A0F 7D 14 3590 DW NONE +1A11 7D 14 3591 DW NONE ;W +1A13 7D 14 3592 DW NONE +1A15 B2 17 3593 DW W4 +1A17 7D 14 3594 DW NONE +1A19 7D 14 3595 DW NONE +1A1B 7D 14 3596 DW NONE ;X +1A1D B9 17 3597 DW X3 +1A1F BF 17 3598 DW X4 +1A21 7D 14 3599 DW NONE +1A23 7D 14 3600 DW NONE +1A25 7D 14 3601 DW NONE ;Y +1A27 7D 14 3602 DW NONE +1A29 7D 14 3603 DW NONE +1A2B 7D 14 3604 DW NONE +1A2D 7D 14 3605 DW NONE +1A2F 7D 14 3606 DW NONE ;Z +1A31 7D 14 3607 DW NONE +1A33 7D 14 3608 DW NONE +1A35 7D 14 3609 DW NONE +1A37 7D 14 3610 DW NONE +1A39 3611 +1A39 3612 NDPTAB: +1A39 3613 ;Lookup table for 8087 mnemonics. There is one entry for each letter of the +1A39 3614 ;alphabet +1A39 D2 17 3615 DW NDPA +1A3B E0 17 3616 DW NDPB +1A3D EA 17 3617 DW NDPC +1A3F 03 18 3618 DW NDPD +1A41 24 18 3619 DW NDPE +1A43 29 18 3620 DW NDPF +1A45 7D 14 3621 DW NONE ;G +1A47 7D 14 3622 DW NONE ;H +1A49 2F 18 3623 DW NDPI +1A4B 7D 14 3624 DW NONE ;J +1A4D 7D 14 3625 DW NONE ;K +1A4F 74 18 3626 DW NDPL +1A51 A8 18 3627 DW NDPM +1A53 7D 14 3628 DW NONE ;N +1A55 7D 14 3629 DW NONE ;O +1A57 B2 18 3630 DW NDPP +1A59 7D 14 3631 DW NONE ;Q +1A5B C3 18 3632 DW NDPR +1A5D D1 18 3633 DW NDPS +1A5F 0D 19 3634 DW NDPT +1A61 7D 14 3635 DW NONE ;U +1A63 7D 14 3636 DW NONE ;V +1A65 12 19 3637 DW NDPW +1A67 18 19 3638 DW NDPX +1A69 28 19 3639 DW NDPY +1A6B 7D 14 3640 DW NONE ;Z +1A6D 3641 +1A6D 3642 +1A6D 2A 2A 2A 2A 2A 20 45 3643 ERRMES: DM '***** ERROR no. ' + 52 52 4F 52 20 6E 6F + 2E A0 +1A7D 0D 0A 4E 6F 20 64 69 3644 NOSPAC: DB 13,10,'No directory space',13,10,24H + 72 65 63 74 6F 72 79 + 20 73 70 61 63 65 0D + 0A 24 +1A94 48 0D 8A 3645 ENDMES: DM 'H',13,10 +1A97 0D 0A 49 6E 73 75 66 3646 NOMEM: DB 13,10,'Insufficient memory',13,10,'$' + 66 69 63 69 65 6E 74 + 20 6D 65 6D 6F 72 79 + 0D 0A 24 +1AAF 0D 0A 46 69 6C 65 20 3647 NOFILE: DB 13,10,'File not found',13,10,'$' + 6E 6F 74 20 66 6F 75 + 6E 64 0D 0A 24 +1AC2 0D 0A 44 69 73 6B 20 3648 WRTERR: DB 13,10,'Disk full',13,10,'$' + 66 75 6C 6C 0D 0A 24 +1AD0 0D 0A 42 61 64 20 64 3649 BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' + 69 73 6B 20 73 70 65 + 63 69 66 69 65 72 0D + 0A 24 +1AE7 0D 0A 0D 0A 45 72 72 3650 ERCNTM: DM 13,10,13,10,'Error Count =' + 6F 72 20 43 6F 75 6E + 74 20 BD +1AF8 0D 0A 53 79 6D 62 6F 3651 SYMMES: DM 13,10,'Symbol Table',13,10,13,10 + 6C 20 54 61 62 6C 65 + 0D 0A 0D 8A +1B0A 41 53 4D 00 00 3652 EXTEND: DB 'ASM',0,0 +1B0F 05 65 6E 64 69 66 3653 IFEND: DB 5,'endif' +1B15 02 69 66 3654 IFNEST: DB 2,'if' +1B18 72 65 F4 3655 RETSTR: DM 'ret' +1B1B 00 20 20 20 20 20 20 3656 HEXFCB: DB 0,' HEX',0,0,0,0 + 20 20 48 45 58 00 00 + 00 00 +1B2B 3657 DS 16 +1B3B 00 00 00 00 00 3658 DB 0,0,0,0,0 +1B40 00 20 20 20 20 20 20 3659 LSTFCB: DB 0,' PRN',0,0,0,0 + 20 20 50 52 4E 00 00 + 00 00 +1B50 3660 DS 16 +1B60 00 00 00 00 00 3661 DB 0,0,0,0,0 +1B65 3662 PC: DS 2 +1B67 3663 OLDPC: DS 2 +1B69 3664 LABPT: DS 2 +1B6B 3665 FLAG: DS 1 +1B6C 3666 LONG: DS 1 +1B6D 3667 ADDR: DS 2 +1B6F 3668 ALABEL: DS 2 +1B71 3669 DATA: DS 2 +1B73 3670 DLABEL: DS 2 +1B75 3671 CON: DS 2 +1B77 3672 UNDEF: DS 2 +1B79 3673 LENID: DS 1 +1B7A 3674 ID: DS 80 +1BCA 3675 CHR: DS 1 +1BCB 3676 SYM: DS 1 +1BCC 3677 BASE: DS 2 +1BCE 3678 HEAP: DS 2 +1BD0 3679 SYMFLG: DS 1 +1BD1 3680 CODE: DS 2 +1BD3 3681 DATSIZ: DS 1 +1BD4 3682 RELOC: DS 1 +1BD5 3683 BCOUNT: DS 1 +1BD6 3684 COUNT: DS 1 +1BD7 3685 ERR: DS 1 +1BD8 3686 LINE: DS 2 +1BDA 3687 HEXLEN: DS 2 +1BDC 3688 HEXADD: DS 2 +1BDE 3689 LASTAD: DS 2 +1BE0 3690 HEXCNT: DS 1 +1BE1 3691 CHKSUM: DS 1 +1BE2 3692 LINFLG: DS 1 +1BE3 3693 PREV: DS 1 +1BE4 3694 IFFLG: DS 1 +1BE5 3695 CHKLAB: DS 1 +1BE6 3696 ERRCNT: DS 2 +1BE8 3697 LSTRET: DS 2 +1BEA 3698 RETPT: DS 2 +1BEC 3699 LSTDEV: DS 2 +1BEE 3700 SPC: DS 1 +1BEF 3701 NOWAIT: DS 1 +1BF0 3702 IX: DS 2 +1BF2 3703 IY: DS 2 +1BF4 3704 HEXPNT: DS 2 +1BF6 3705 LSTPNT: DS 2 +1BF8 3706 HEXBUF: DS HEXBUFSIZ +1C3E 3707 LSTBUF: DS LSTBUFSIZ +203E 3708 BUFPT: DS 2 +2040 3709 SRCBUF: DS BUFSIZ +2440 3710 DS 80 +2490 3711 ALIGN +2490 3712 STACK: EQU $ +2490 3713 START: EQU $ + + +Error Count = 0 + \ No newline at end of file diff --git a/2_printed_files/bundle_06/ASM.PRN b/2_printed_files/bundle_06/ASM.PRN new file mode 100644 index 0000000..6b102da --- /dev/null +++ b/2_printed_files/bundle_06/ASM.PRN @@ -0,0 +1,4253 @@ +0000 0001 ; Seattle Computer Products 8086 Assembler version 2.43 +0000 0002 ; by Tim Paterson +0000 0003 ; Runs on the 8086 under MS-DOS +0000 0004 +0000 0005 ;* * * * * * REVISION HISTORY * * * * * * +0000 0006 ; +0000 0007 ; 12/29/80 2.01 General release with 86-DOS version 0.34 +0000 0008 ; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +0000 0009 ; 03/18/81 2.11 General cleanup and more documentation +0000 0010 ; 03/24/81 2.20 Modify ESC handling for full 8087 operation +0000 0011 ; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +0000 0012 ; 04/03/81 2.22 Fix 2.21 buffer handling +0000 0013 ; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +0000 0014 ; 04/28/81 2.24 Allow nested IFs +0000 0015 ; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +0000 0016 ; 08/02/81 2.30 Re-write pass 2: +0000 0017 ; Always report errors to console +0000 0018 ; Exact byte lengths for HEX and PRN files +0000 0019 ; 11/08/81 2.40 Add 8087 mnemonics; print full error messages; +0000 0020 ; allow expressions with *, /, and () +0000 0021 ; 07/04/82 2.41 Fix Intel's 8087 "reverse-bit" bug; don't copy date +0000 0022 ; 08/18/82 2.42 Increase stack from 80 to 256 (Damn! Overflowed again!) +0000 0023 ; 01/05/82 2.43 Correct over-zealous optimization in 2.42 +0000 0024 ; +0000 0025 ;* * * * * * * * * * * * * * * * * * * * * +0000 0026 +0000 0027 SYMWID: EQU 5 ;5 symbols per line in dump +0000 0028 FCB: EQU 5CH +0000 0029 BUFSIZ: EQU 1024 ;Source code buffer +0000 0030 LSTBUFSIZ:EQU BUFSIZ ;List file buffer +0000 0031 HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +0000 0032 EOL: EQU 13 ;ASCII carriage return +0000 0033 OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS +0000 0034 +0000 0035 ;System call function codes +0000 0036 PRINTMES: EQU 9 +0000 0037 OPEN: EQU 15 +0000 0038 CLOSE: EQU 16 +0000 0039 READ: EQU 20 +0000 0040 SETDMA: EQU 26 +0000 0041 MAKE: EQU 22 +0000 0042 BLKWRT: EQU 40 +0000 0043 +0000 0044 ;The following equates define some token values returned by GETSYM +0000 0045 UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +0000 0046 CONST: EQU 1 ;Constant (including $) +0000 0047 REG: EQU 2 ;8-bit register +0000 0048 XREG: EQU 3 ;16-bit register (except segment registers) +0000 0049 SREG: EQU 4 ;Segment register +0000 0050 FREG: EQU 6 ;8087 floating point register +0000 0051 +0000 0052 ;Bits to build 8087 opcode table entries +0000 0053 ONEREG: EQU 40H ;Single ST register OK as operand +0000 0054 NEEDOP: EQU 80H ;Must have an operand +0000 0055 INTEGER:EQU 20H ;For integer operations +0000 0056 REAL: EQU 28H ;For real operations +0000 0057 EXTENDED EQU 10H ;For Long integers or Temporary real +0000 0058 MEMORY: EQU 18H ;For general memory operations +0000 0059 STACKOP:EQU 10H ;Two register arithmetic with pop +0000 0060 ARITH: EQU 8 ;Non-pop arithmetic operations +0000 0061 +0000 0062 ORG 100H +0100 0063 PUT 100H +0100 0064 +0100 EB 74 0065 JMPS BEGIN +0102 0066 +0102 0D 0A 53 65 61 74 74 0067 HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.43' + 6C 65 20 43 6F 6D 70 + 75 74 65 72 20 50 72 + 6F 64 75 63 74 73 20 + 38 30 38 36 20 41 73 + 73 65 6D 62 6C 65 72 + 20 56 65 72 73 69 6F + 6E 20 32 2E 34 33 +0139 0D 0A 43 6F 70 79 72 0068 DB 13,10,'Copyright 1979-1982 by Seattle Computer Products, Inc.' + 69 67 68 74 20 31 39 + 37 39 2D 31 39 38 32 + 20 62 79 20 53 65 61 + 74 74 6C 65 20 43 6F + 6D 70 75 74 65 72 20 + 50 72 6F 64 75 63 74 + 73 2C 20 49 6E 63 2E +0171 0D 0A 0D 0A 24 0069 DB 13,10,13,10,'$' +0176 0070 +0176 0071 BEGIN: +0176 BC A6 2A 0072 MOV SP,STACK +0179 BA 02 01 0073 MOV DX,HEADER +017C B4 09 0074 MOV AH,PRINTMES +017E CD 21 0075 INT 33 +0180 A0 6D 00 0076 MOV AL,[FCB+17] +0183 A2 35 21 0077 MOV [SYMFLG],AL ;Save symbol table request flag +0186 BE 65 00 0078 MOV SI,FCB+9 ;Point to file extension +0189 AC 0079 LODB ;Get source drive letter +018A E8 13 01 0080 CALL CHKDSK ;Valid drive? +018D 0A C0 0081 OR AL,AL +018F 74 03 0082 JZ DEFAULT ;If no extension, use existing drive spec +0191 A2 5C 00 0083 MOV [FCB],AL +0194 0084 DEFAULT: +0194 AC 0085 LODB ;Get HEX file drive letter +0195 3C 5A 0086 CMP AL,'Z' ;Suppress HEX file? +0197 74 03 0087 JZ L0000 +0199 E8 04 01 0088 CALL CHKDSK +019C 0089 L0000: +019C A2 80 20 0090 MOV [HEXFCB],AL +019F AC 0091 LODB ;Get PRN file drive letter +01A0 B4 00 0092 MOV AH,0 ;Signal no PRN file +01A2 3C 5A 0093 CMP AL,'Z' ;Suppress PRN file? +01A4 74 15 0094 JZ NOPRN +01A6 3C 59 0095 CMP AL,'Y' ;Print errors only on console? +01A8 74 11 0096 JZ NOPRN +01AA B4 02 0097 MOV AH,2 +01AC 3C 58 0098 CMP AL,'X' ;PRN file to console? +01AE 74 0B 0099 JZ NOPRN +01B0 B4 04 0100 MOV AH,4 +01B2 3C 50 0101 CMP AL,'P' ;PRN file to printer? +01B4 74 05 0102 JZ NOPRN +01B6 E8 E7 00 0103 CALL CHKDSK +01B9 B4 80 0104 MOV AH,80H +01BB 0105 NOPRN: +01BB A2 A5 20 0106 MOV [LSTFCB],AL +01BE 88 26 52 21 0107 MOV [LSTDEV],AH ;Flag device for list ouput +01C2 BE 6F 20 0108 MOV SI,EXTEND +01C5 BF 65 00 0109 MOV DI,FCB+9 +01C8 A5 0110 MOVW +01C9 A4 0111 MOVB ;Set extension to ASM +01CA A5 0112 MOVW ;Zero extent field +01CB BA 5C 00 0113 MOV DX,FCB +01CE B4 0F 0114 MOV AH,OPEN +01D0 CD 21 0115 INT 33 +01D2 BB 14 20 0116 MOV BX,NOFILE +01D5 0A C0 0117 OR AL,AL +01D7 74 03 0118 JZ $+5 +01D9 E9 9A 00 0119 JMP PRERR +01DC BA 80 20 0120 MOV DX,HEXFCB +01DF E8 9C 00 0121 CALL MAKFIL +01E2 BA A5 20 0122 MOV DX,LSTFCB +01E5 E8 96 00 0123 CALL MAKFIL +01E8 33 C0 0124 XOR AX,AX +01EA A3 68 00 0125 MOV [FCB+12],AX ;Zero CURRENT BLOCK field +01ED A2 7C 00 0126 MOV [FCB+32],AL ;Zero Next Record field +01F0 C7 06 6A 00 00 04 0127 MOV [FCB+14],BUFSIZ ;Set record size +01F6 C7 06 A4 25 A6 25 0128 MOV [BUFPT],SRCBUF ;Initialize buffer pointer +01FC C7 06 37 21 A7 2A 0129 MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE +0202 C7 06 58 21 A6 2A 0130 MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE +0208 33 C0 0131 XOR AX,AX +020A A3 CA 20 0132 MOV [PC],AX ;DEFAULT PROGRAM COUNTER +020D A3 31 21 0133 MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL +0210 A3 50 21 0134 MOV [RETPT],AX ;Pointer to last RET record +0213 A2 4A 21 0135 MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF +0216 A2 4B 21 0136 MOV [CHKLAB],AL ;LOOKUP ALL LABELS +0219 48 0137 DEC AX +021A A3 4E 21 0138 MOV [LSTRET],AX ;Location of last RET +021D A1 06 00 0139 MOV AX,[6] ;HL=END OF MEMORY +0220 A3 33 21 0140 MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE +0223 C7 06 3B 21 04 00 0141 MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE +0229 0142 +0229 0143 ;Assemble each line of code +0229 0144 +0229 0145 LOOP: +0229 E8 8A 00 0146 CALL NEXTCHR ;Get first character on line +022C 3C 1A 0147 CMP AL,1AH +022E 74 1E 0148 JZ ENDJ +0230 B0 FF 0149 MOV AL,-1 ;Flag that no tokens have been read yet +0232 A2 30 21 0150 MOV [SYM],AL +0235 E8 1C 07 0151 CALL ASMLIN ;Assemble the line +0238 A0 30 21 0152 MOV AL,[SYM] +023B 3C FF 0153 CMP AL,-1 ;Any tokens found on line? +023D 75 03 0154 JNZ L0002 +023F E8 C0 03 0155 CALL GETSYM ;If no tokens read yet, read first one +0242 0156 L0002: +0242 3C 3B 0157 CMP AL,';' +0244 74 0B 0158 JZ ENDLN +0246 3C 0D 0159 CMP AL,EOL +0248 74 07 0160 JZ ENDLN +024A B0 14 0161 MOV AL,14H ;Garbage at end of line error +024C EB 05 0162 JP ENDLIN +024E E9 09 0F 0163 ENDJ: JMP END +0251 0164 +0251 0165 ENDLN: +0251 32 C0 0166 XOR AL,AL ;Flag no errors on line +0253 0167 ENDLIN: +0253 0168 ;AL = error code for line. Stack depth unknown +0253 BC A6 2A 0169 MOV SP,STACK +0256 E8 02 00 0170 CALL NEXLIN +0259 EB CE 0171 JP LOOP +025B 0172 +025B 0173 NEXLIN: +025B B5 C0 0174 MOV CH,0C0H ;Put end of line marker and error code (AL) +025D E8 81 09 0175 CALL PUTCD +0260 E8 46 09 0176 CALL GEN1 +0263 A0 2F 21 0177 MOV AL,[CHR] +0266 0178 GETEOL: +0266 3C 0A 0179 CMP AL,10 +0268 74 35 0180 JZ RET +026A 3C 1A 0181 CMP AL,1AH +026C 74 E0 0182 JZ ENDJ +026E E8 45 00 0183 CALL NEXTCHR ;Scan over comments for linefeed +0271 EB F3 0184 JP GETEOL +0273 0185 +0273 0186 ABORT: +0273 BB FC 1F 0187 MOV BX,NOMEM +0276 0188 PRERR: +0276 8B D3 0189 MOV DX,BX +0278 B4 09 0190 MOV AH,PRINTMES +027A CD 21 0191 INT 33 +027C CD 20 0192 INT 32 +027E 0193 +027E 0194 MAKFIL: +027E 8B F2 0195 MOV SI,DX +0280 AC 0196 LODB ;Get drive select byte +0281 3C 20 0197 CMP AL,20H ;If not valid, don't make file +0283 73 1A 0198 JNC RET +0285 B9 04 00 0199 MOV CX,4 +0288 8B FE 0200 MOV DI,SI +028A BE 5D 00 0201 MOV SI,FCB+1 +028D F3 0202 REP +028E A5 0203 MOVW ;Copy source file name +028F B4 16 0204 MOV AH,MAKE +0291 CD 21 0205 INT 33 +0293 C7 45 05 01 00 0206 MOV [DI-9+14],1 ;Set record length to 1 byte +0298 BB E4 1F 0207 MOV BX,NOSPAC +029B 0A C0 0208 OR AL,AL ;Success? +029D 75 D7 0209 JNZ PRERR +029F C3 0210 RET +02A0 0211 +02A0 0212 CHKDSK: +02A0 2C 20 0213 SUB AL,' ' ;If not present, set zero flag +02A2 74 FB 0214 JZ RET +02A4 2C 20 0215 SUB AL,20H +02A6 74 04 0216 JZ DSKERR ;Must be in range A-O +02A8 3C 10 0217 CMP AL,'P'-'@' +02AA 72 F3 0218 JC RET +02AC 0219 DSKERR: +02AC BB 35 20 0220 MOV BX,BADDSK +02AF EB C5 0221 JP PRERR +02B1 0222 +02B1 0223 ERROR: +02B1 8A C1 0224 MOV AL,CL +02B3 E9 9D FF 0225 JMP ENDLIN +02B6 0226 +02B6 0227 NEXTCHR: +02B6 8B 36 A4 25 0228 MOV SI,[BUFPT] +02BA 81 FE A6 25 0229 CMP SI,SRCBUF +02BE 75 1A 0230 JNZ GETCH +02C0 0231 ;Buffer empty so refill it +02C0 52 0232 PUSH DX +02C1 50 0233 PUSH AX ;AH must be saved +02C2 8B D6 0234 MOV DX,SI +02C4 B4 1A 0235 MOV AH,SETDMA +02C6 CD 21 0236 INT 33 +02C8 BA 5C 00 0237 MOV DX,FCB +02CB B4 14 0238 MOV AH,READ +02CD CD 21 0239 INT 33 +02CF 92 0240 XCHG AX,DX ;Put error code in DL +02D0 58 0241 POP AX ;Restore AH +02D1 8A C2 0242 MOV AL,DL ;Error code back in AL +02D3 5A 0243 POP DX +02D4 3C 01 0244 CMP AL,1 +02D6 B0 1A 0245 MOV AL,1AH ;Possibly signal End of File +02D8 74 0A 0246 JZ NOMOD ;If nothing read +02DA 0247 GETCH: +02DA AC 0248 LODB +02DB 81 FE A6 29 0249 CMP SI,SRCBUF+BUFSIZ +02DF 75 03 0250 JNZ NOMOD +02E1 BE A6 25 0251 MOV SI,SRCBUF +02E4 0252 NOMOD: +02E4 89 36 A4 25 0253 MOV [BUFPT],SI +02E8 A2 2F 21 0254 MOV [CHR],AL +02EB C3 0255 RET +02EC 0256 +02EC 0257 +02EC 0258 MROPS: +02EC 0259 +02EC 0260 ; Get two operands and check for certain types, according to flag byte +02EC 0261 ; in CL. OP code in CH. Returns only if immediate operation. +02EC 0262 +02EC 51 0263 PUSH CX ;Save type flags +02ED E8 D8 00 0264 CALL GETOP +02F0 52 0265 PUSH DX ;Save first operand +02F1 E8 CB 00 0266 CALL GETOP2 +02F4 5B 0267 POP BX ;First op in BX, second op in DX +02F5 B0 04 0268 MOV AL,SREG ;Check for a segment register +02F7 3A C7 0269 CMP AL,BH +02F9 74 41 0270 JZ SEGCHK +02FB 3A C6 0271 CMP AL,DH +02FD 74 3D 0272 JZ SEGCHK +02FF B0 01 0273 MOV AL,CONST ;Check if the first operand is immediate +0301 B1 1A 0274 MOV CL,26 +0303 3A C7 0275 CMP AL,BH +0305 74 AA 0276 JZ ERROR ;Error if so +0307 59 0277 POP CX ;Restore type flags +0308 3A C6 0278 CMP AL,DH ;If second operand is immediate, then done +030A 74 DF 0279 JZ RET +030C B0 00 0280 MOV AL,UNDEFID ;Check for memory reference +030E 3A C7 0281 CMP AL,BH +0310 74 4F 0282 JZ STORE ;Is destination memory? +0312 3A C6 0283 CMP AL,DH +0314 74 55 0284 JZ LOAD ;Is source memory? +0316 F6 C1 01 0285 TEST CL,1 ;Check if register-to-register operation OK +0319 B1 1B 0286 MOV CL,27 +031B 74 94 0287 JZ ERROR +031D 8A C6 0288 MOV AL,DH +031F 3A C7 0289 CMP AL,BH ;Registers must be of same length +0321 0290 RR: +0321 B1 16 0291 MOV CL,22 +0323 75 8C 0292 JNZ ERROR +0325 0293 RR1: +0325 24 01 0294 AND AL,1 ;Get register length (1=16 bits) +0327 0A C5 0295 OR AL,CH ;Or in to OP code +0329 E8 70 08 0296 CALL PUT ;And write it +032C 59 0297 POP CX ;Dump return address +032D 8A C3 0298 MOV AL,BL +032F 02 C0 0299 ADD AL,AL ;Rotate register number into middle position +0331 02 C0 0300 ADD AL,AL +0333 02 C0 0301 ADD AL,AL +0335 0C C0 0302 OR AL,0C0H ;Set register-to-register mode +0337 0A C2 0303 OR AL,DL ;Combine with other register number +0339 E9 60 08 0304 JMP PUT +033C 0305 +033C 0306 SEGCHK: +033C 0307 ;Come here if at least one operand is a segment register +033C 59 0308 POP CX ;Restore flags +033D F6 C1 08 0309 TEST CL,8 ;Check if segment register OK +0340 B1 16 0310 MOV CL,22 +0342 74 78 0311 JZ ERR1 +0344 B9 03 8E 0312 MOV CX,8E03H ;Segment register move OP code +0347 B0 00 0313 MOV AL,UNDEFID +0349 3A C6 0314 CMP AL,DH ;Check if source is memory +034B 74 1E 0315 JZ LOAD +034D 3A C7 0316 CMP AL,BH ;Check if destination is memory +034F 74 10 0317 JZ STORE +0351 B0 03 0318 MOV AL,XREG +0353 2A C6 0319 SUB AL,DH ;Check if source is 16-bit register +0355 74 CA 0320 JZ RR ;If so, AL must be zero +0357 B5 8C 0321 MOV CH,8CH ;Change direction +0359 87 DA 0322 XCHG DX,BX ;Flip which operand is first and second +035B B0 03 0323 MOV AL,XREG +035D 2A C6 0324 SUB AL,DH ;Let RR perform finish the test +035F EB C0 0325 JP RR +0361 0326 +0361 0327 STORE: +0361 F6 C1 04 0328 TEST CL,004H ;Check if storing is OK +0364 75 52 0329 JNZ STERR +0366 87 DA 0330 XCHG DX,BX ;If so, flip operands +0368 80 E5 FD 0331 AND CH,0FDH ; and zero direction bit +036B 0332 LOAD: +036B B6 19 0333 MOV DH,25 +036D 3A C7 0334 CMP AL,BH ;Check if memory-to-memory +036F 74 49 0335 JZ MRERR +0371 8A C7 0336 MOV AL,BH +0373 3C 02 0337 CMP AL,REG ;Check if 8-bit operation +0375 75 07 0338 JNZ XRG +0377 B6 16 0339 MOV DH,22 +0379 F6 C1 01 0340 TEST CL,1 ;See if 8-bit operation is OK +037C 74 3C 0341 JZ MRERR +037E 0342 XRG: +037E 8A C2 0343 MOV AL,DL +0380 2C 06 0344 SUB AL,6 ;Check for R/M mode 6 and register 0 +0382 0A C3 0345 OR AL,BL ; meaning direct load/store of accumulator +0384 75 19 0346 JNZ NOTAC +0386 F6 C1 08 0347 TEST CL,8 ;See if direct load/store of accumulator +0389 74 14 0348 JZ NOTAC ; means anything in this case +038B 0349 ; Process direct load/store of accumulator +038B 8A C5 0350 MOV AL,CH +038D 24 02 0351 AND AL,2 ;Preserve direction bit only +038F 34 02 0352 XOR AL,2 ; but flip it +0391 0C A0 0353 OR AL,0A0H ;Combine with OP code +0393 8A E8 0354 MOV CH,AL +0395 8A C7 0355 MOV AL,BH ;Check byte/word operation +0397 24 01 0356 AND AL,1 +0399 0A C5 0357 OR AL,CH +039B 59 0358 POP CX ;Dump return address +039C E9 BD 08 0359 JMP PUTADD ;Write the address +039F 0360 +039F 0361 NOTAC: +039F 8A C7 0362 MOV AL,BH +03A1 24 01 0363 AND AL,1 ;Get byte/word bit +03A3 22 C1 0364 AND AL,CL ;But don't use it in word-only operations +03A5 0A C5 0365 OR AL,CH ;Combine with OP code +03A7 E8 F2 07 0366 CALL PUT +03AA 8A C3 0367 MOV AL,BL +03AC 02 C0 0368 ADD AL,AL ;Rotate to middle position +03AE 02 C0 0369 ADD AL,AL +03B0 02 C0 0370 ADD AL,AL +03B2 0A C2 0371 OR AL,DL ;Combine register field +03B4 59 0372 POP CX ;Dump return address +03B5 E9 A4 08 0373 JMP PUTADD ;Write the address +03B8 0374 +03B8 0375 STERR: +03B8 B6 1D 0376 MOV DH,29 +03BA 0377 MRERR: +03BA 8A CE 0378 MOV CL,DH +03BC 0379 +03BC E9 F2 FE 0380 ERR1: JMP ERROR +03BF 0381 +03BF 0382 GETOP2: +03BF 0383 ;Get the second operand: look for a comma and drop into GETOP +03BF A0 30 21 0384 MOV AL,[SYM] +03C2 3C 2C 0385 CMP AL,',' +03C4 B1 15 0386 MOV CL,21 +03C6 75 F4 0387 JNZ ERR1 +03C8 0388 +03C8 0389 +03C8 0390 GETOP: +03C8 0391 +03C8 0392 ; Get one operand. Operand may be a memory reference in brackets, a register, +03C8 0393 ; or a constant. If a flag (such as "B" for byte operation) is encountered, +03C8 0394 ; it is noted and processing continues to find the operand. +03C8 0395 ; +03C8 0396 ; On exit, AL (=DH) has the type of operand. Other information depends +03C8 0397 ; on the actual operand: +03C8 0398 ; +03C8 0399 ; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +03C8 0400 ; the 8086 R/M format (middle bits zero). The constant part of the address +03C8 0401 ; is in ADDR. If an undefined label needs to be added to this, a pointer to +03C8 0402 ; its information fields is in ALABEL, otherwise ALABEL is zero. +03C8 0403 ; +03C8 0404 ; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +03C8 0405 ; to be added to this, a pointer to its information fields is in DLABEL, +03C8 0406 ; otherwise DLABEL is zero. "$" and "RET" are in this class. +03C8 0407 ; +03C8 0408 ; AL=DH=2 8-bit Register. DL has the register number. +03C8 0409 ; +03C8 0410 ; AL=DH=3 16-bit Register. DL has the register number. +03C8 0411 ; +03C8 0412 ; AL=DH=4 Segment Register. DL has the register number. +03C8 0413 +03C8 E8 37 02 0414 CALL GETSYM +03CB 0415 GETOP1: +03CB 0416 ;Enter here if we don't need a GETSYM first +03CB 3C 5B 0417 CMP AL,'[' ;Memory reference? +03CD 74 30 0418 JZ MEM +03CF 3C 05 0419 CMP AL,5 ;Flag ("B", "W", etc.)? +03D1 74 57 0420 JZ FLG +03D3 3C 02 0421 CMP AL,REG ;8-Bit register? +03D5 74 20 0422 JZ NREG +03D7 3C 03 0423 CMP AL,XREG ;16-Bit register? +03D9 74 1C 0424 JZ NREG +03DB 3C 04 0425 CMP AL,SREG ;Segment register? +03DD 74 18 0426 JZ NREG +03DF 0427 VAL: ;Must be immediate +03DF 32 C0 0428 XOR AL,AL ;No addressing modes allowed +03E1 0429 VAL1: +03E1 E8 57 00 0430 CALL GETVAL +03E4 A1 DA 20 0431 MOV AX,[CON] ;Defined part +03E7 A3 D6 20 0432 MOV [DATA],AX +03EA A1 DC 20 0433 MOV AX,[UNDEF] ;Undefined part +03ED A3 D8 20 0434 MOV [DLABEL],AX +03F0 8A D5 0435 MOV DL,CH +03F2 B6 01 0436 MOV DH,CONST +03F4 8A C6 0437 MOV AL,DH +03F6 C3 0438 RET +03F7 0439 NREG: +03F7 52 0440 PUSH DX +03F8 E8 07 02 0441 CALL GETSYM +03FB 5A 0442 POP DX +03FC 8A C6 0443 MOV AL,DH +03FE C3 0444 RET +03FF 0445 MEM: +03FF E8 00 02 0446 CALL GETSYM +0402 B0 01 0447 MOV AL,1 +0404 E8 34 00 0448 CALL GETVAL +0407 A0 30 21 0449 MOV AL,[SYM] +040A 3C 5D 0450 CMP AL,']' +040C B1 18 0451 MOV CL,24 +040E 75 AC 0452 JNZ ERR1 +0410 E8 EF 01 0453 CALL GETSYM +0413 8B 1E DA 20 0454 MOV BX,[CON] +0417 89 1E D2 20 0455 MOV [ADDR],BX +041B 8B 1E DC 20 0456 MOV BX,[UNDEF] +041F 89 1E D4 20 0457 MOV [ALABEL],BX +0423 8A D5 0458 MOV DL,CH +0425 B6 00 0459 MOV DH,UNDEFID +0427 8A C6 0460 MOV AL,DH +0429 C3 0461 RET +042A 0462 FLG: +042A 3A 16 D1 20 0463 CMP DL,[MAXFLG] ;Invalid flag for this operation? +042E B1 27 0464 MOV CL,27H +0430 7F 8A 0465 JG ERR1 +0432 E8 CD 01 0466 CALL GETSYM +0435 3C 2C 0467 CMP AL,',' +0437 74 8F 0468 JZ GETOP +0439 EB 90 0469 JP GETOP1 +043B 0470 +043B 0471 +043B 0472 GETVAL: +043B 0473 +043B 0474 ; Expression analyzer. On entry, if AL=0 then do not allow base or index +043B 0475 ; registers. If AL=1, we are analyzing a memory reference, so allow base +043B 0476 ; and index registers, and compute addressing mode when done. The constant +043B 0477 ; part of the expression will be found in CON. If an undefined label is to +043B 0478 ; be added to this, a pointer to its information fields will be found in +043B 0479 ; UNDEF. +043B 0480 +043B 8A E0 0481 MOV AH,AL ;Flag is kept in AH +043D C7 06 DC 20 00 00 0482 MOV [UNDEF],0 +0443 A0 30 21 0483 MOV AL,[SYM] +0446 E8 51 00 0484 CALL EXPRESSION +0449 89 16 DA 20 0485 MOV [CON],DX +044D 8A C4 0486 MOV AL,AH +044F B5 00 0487 MOV CH,0 ;Initial mode +0451 A8 10 0488 TEST AL,10H ;Test INDEX bit +0453 D0 D0 0489 RCL AL ;BASE bit (zero flag not affected) +0455 74 37 0490 JZ NOIND ;Jump if not indexed, with BASE bit in carry +0457 F5 0491 CMC +0458 D0 D5 0492 RCL CH ;Rotate in BASE bit +045A D0 D0 0493 RCL AL ;BP bit +045C D0 D5 0494 RCL CH +045E D0 D0 0495 RCL AL ;DI bit +0460 D0 D5 0496 RCL CH ;The low 3 bits now have indexing mode +0462 0497 MODE: +0462 80 CD 80 0498 OR CH,080H ;If undefined label, force 16-bit displacement +0465 F7 06 DC 20 FF FF 0499 TEST [UNDEF],-1 +046B 75 BC 0500 JNZ RET +046D 8B 1E DA 20 0501 MOV BX,[CON] +0471 8A C3 0502 MOV AL,BL +0473 98 0503 CBW ;Extend sign +0474 3B C3 0504 CMP AX,BX ;Is it a signed 8-bit number? +0476 75 B1 0505 JNZ RET ;If not, use 16-bit displacement +0478 80 E5 7F 0506 AND CH,07FH ;Reset 16-bit displacement +047B 80 CD 40 0507 OR CH,040H ;Set 8-bit displacement +047E 0B DB 0508 OR BX,BX +0480 75 A7 0509 JNZ RET ;Use it if not zero displacement +0482 80 E5 07 0510 AND CH,7 ;Specify no displacement +0485 82 FD 06 0511 CMP CH,6 ;Check for BP+0 addressing mode +0488 75 9F 0512 JNZ RET +048A 80 CD 40 0513 OR CH,040H ;If BP+0, use 8-bit displacement +048D C3 0514 RET +048E 0515 +048E 0516 NOIND: +048E B5 06 0517 MOV CH,6 ;Try direct address mode +0490 73 FB 0518 JNC RET ;If no base register, that's right +0492 D0 D0 0519 RCL AL ;Check BP bit +0494 72 CC 0520 JC MODE +0496 FE C5 0521 INC CH ;If not, must be BX +0498 EB C8 0522 JP MODE +049A 0523 +049A 0524 EXPRESSION: +049A 0525 ;Analyze arbitrary expression. Flag byte in AH. +049A 0526 ;On exit, AL has type byte: 0=register or undefined label +049A B5 FF 0527 MOV CH,-1 ;Initial type +049C 8B FA 0528 MOV DI,DX +049E 33 D2 0529 XOR DX,DX ;Initial value +04A0 3C 2B 0530 CMP AL,'+' +04A2 74 0C 0531 JZ PLSMNS +04A4 3C 2D 0532 CMP AL,'-' +04A6 74 08 0533 JZ PLSMNS +04A8 B1 2B 0534 MOV CL,'+' +04AA 52 0535 PUSH DX +04AB 51 0536 PUSH CX +04AC 8B D7 0537 MOV DX,DI +04AE EB 0A 0538 JP OPERATE +04B0 0539 PLSMNS: +04B0 8A C8 0540 MOV CL,AL +04B2 52 0541 PUSH DX +04B3 51 0542 PUSH CX +04B4 80 CC 04 0543 OR AH,4 ;Flag that a sign was found +04B7 E8 48 01 0544 CALL GETSYM +04BA 0545 OPERATE: +04BA E8 2B 00 0546 CALL TERM +04BD 59 0547 POP CX ;Recover operator +04BE 5B 0548 POP BX ;Recover current value +04BF 87 DA 0549 XCHG DX,BX +04C1 22 E8 0550 AND CH,AL +04C3 0A C0 0551 OR AL,AL ;Is it register or undefined label? +04C5 74 17 0552 JZ NOCON ;If so, then no constant part +04C7 82 F9 2D 0553 CMP CL,"-" ;Subtract it? +04CA 75 02 0554 JNZ ADD +04CC F7 DB 0555 NEG BX +04CE 0556 ADD: +04CE 03 D3 0557 ADD DX,BX +04D0 0558 NEXTERM: +04D0 A0 30 21 0559 MOV AL,[SYM] +04D3 3C 2B 0560 CMP AL,'+' +04D5 74 D9 0561 JZ PLSMNS +04D7 3C 2D 0562 CMP AL,'-' +04D9 74 D5 0563 JZ PLSMNS +04DB 8A C5 0564 MOV AL,CH +04DD C3 0565 RET +04DE 0566 NOCON: +04DE 82 F9 2D 0567 CMP CL,"-" +04E1 75 ED 0568 JNZ NEXTERM +04E3 0569 BADOP: +04E3 B1 05 0570 MOV CL,5 +04E5 E9 C9 FD 0571 JMP ERROR +04E8 0572 +04E8 0573 TERM: +04E8 E8 40 00 0574 CALL FACTOR +04EB 0575 MULOP: +04EB 52 0576 PUSH DX ;Save value +04EC 50 0577 PUSH AX ;Save type +04ED E8 12 01 0578 CALL GETSYM +04F0 59 0579 POP CX +04F1 3C 2A 0580 CMP AL,"*" +04F3 74 04 0581 JZ GETFACT +04F5 3C 2F 0582 CMP AL,"/" +04F7 75 2E 0583 JNZ ENDTERM +04F9 0584 GETFACT: +04F9 0A C9 0585 OR CL,CL ;Can we operate on this type? +04FB 74 E6 0586 JZ BADOP +04FD 50 0587 PUSH AX ;Save operator +04FE E8 01 01 0588 CALL GETSYM ;Get past operator +0501 E8 27 00 0589 CALL FACTOR +0504 0A C0 0590 OR AL,AL +0506 74 DB 0591 JZ BADOP +0508 59 0592 POP CX ;Recover operator +0509 5D 0593 POP BP ;And current value +050A 95 0594 XCHG AX,BP ;Save AH in BP +050B 82 F9 2F 0595 CMP CL,"/" ;Do we divide? +050E 75 0E 0596 JNZ DOMUL +0510 0B D2 0597 OR DX,DX ;Dividing by zero? +0512 B1 29 0598 MOV CL,29H +0514 74 51 0599 JZ ERR2 +0516 8B DA 0600 MOV BX,DX +0518 33 D2 0601 XOR DX,DX ;Make 32-bit dividend +051A F7 F3 0602 DIV AX,BX +051C EB 02 0603 JMPS NEXFACT +051E 0604 DOMUL: +051E F7 E2 0605 MUL AX,DX +0520 0606 NEXFACT: +0520 8B D0 0607 MOV DX,AX ;Result in DX +0522 95 0608 XCHG AX,BP ;Restore flags to AH +0523 B0 FF 0609 MOV AL,-1 ;Indicate a number +0525 EB C4 0610 JMPS MULOP +0527 0611 ENDTERM: +0527 5A 0612 POP DX +0528 8A C1 0613 MOV AL,CL +052A C3 0614 RET +052B 0615 +052B 0616 FACTOR: +052B A0 30 21 0617 MOV AL,[SYM] +052E 3C 01 0618 CMP AL,CONST +0530 74 F8 0619 JZ RET +0532 3C 00 0620 CMP AL,UNDEFID +0534 74 5C 0621 JZ UVAL +0536 3C 28 0622 CMP AL,"(" +0538 74 48 0623 JZ PAREN +053A 3C 22 0624 CMP AL,'"' +053C 74 66 0625 JZ STRING +053E 3C 27 0626 CMP AL,"'" +0540 74 62 0627 JZ STRING +0542 3C 03 0628 CMP AL,XREG ;Only 16-bit register may index +0544 B1 14 0629 MOV CL,20 +0546 75 1F 0630 JNZ ERR2 +0548 F6 C4 01 0631 TEST AH,1 ;Check to see if indexing is OK +054B B1 01 0632 MOV CL,1 +054D 74 18 0633 JZ ERR2 +054F 8A C2 0634 MOV AL,DL +0551 B1 03 0635 MOV CL,3 +0553 2C 03 0636 SUB AL,3 ;Check for BX +0555 74 22 0637 JZ BXJ +0557 2C 02 0638 SUB AL,2 ;Check for BP +0559 74 1B 0639 JZ BPJ +055B FE C8 0640 DEC AL ;Check for SI +055D B1 04 0641 MOV CL,4 +055F 74 0C 0642 JZ SIJ +0561 FE C8 0643 DEC AL ;Check for DI +0563 74 05 0644 JZ DIJ +0565 B1 02 0645 MOV CL,2 ;Invalid base/index register +0567 E9 47 FD 0646 ERR2: JMP ERROR +056A 0647 +056A 0648 DIJ: +056A 80 CC 20 0649 OR AH,20H ;Flag seeing index register DI +056D 0650 SIJ: +056D F6 C4 10 0651 TEST AH,10H ;Check if already seen index register +0570 75 F5 0652 JNZ ERR2 +0572 80 CC 10 0653 OR AH,10H ;Flag seeing index register +0575 C3 0654 RET +0576 0655 +0576 0656 BPJ: +0576 80 CC 40 0657 OR AH,40H ;Flag seeing base register BP +0579 0658 BXJ: +0579 F6 C4 80 0659 TEST AH,80H ;Check if already seen base register +057C 75 E9 0660 JNZ ERR2 +057E 80 CC 80 0661 OR AH,80H ;Flag seeing base register +0581 C3 0662 RET +0582 0663 +0582 0664 PAREN: +0582 E8 7D 00 0665 CALL GETSYM ;Eat the "(" +0585 E8 12 FF 0666 CALL EXPRESSION +0588 82 3E 30 21 29 0667 CMP B,[SYM],")" ;Better have closing paren +058D B1 14 0668 MOV CL,20 +058F 75 10 0669 JNZ ERR30 +0591 C3 0670 RET +0592 0671 +0592 0672 UVAL: +0592 B1 06 0673 MOV CL,6 +0594 F6 C4 08 0674 TEST AH,8 ;Check if undefined label has been seen +0597 75 08 0675 JNZ ERR30 +0599 80 CC 08 0676 OR AH,8 ;Flag seeing undefined label +059C 89 1E DC 20 0677 MOV [UNDEF],BX +05A0 C3 0678 RET +05A1 0679 +05A1 E9 0D FD 0680 ERR30: JMP ERROR +05A4 0681 +05A4 0682 STRING: +05A4 8A E8 0683 MOV CH,AL +05A6 A0 2F 21 0684 MOV AL,[CHR] +05A9 3A C5 0685 CMP AL,CH +05AB B1 23 0686 MOV CL,35 +05AD 8A D0 0687 MOV DL,AL +05AF B6 00 0688 MOV DH,0 +05B1 75 03 0689 JNZ L0003 +05B3 E8 32 00 0690 CALL ZERLEN +05B6 0691 L0003: +05B6 E8 37 00 0692 CALL GETCHR +05B9 B1 25 0693 MOV CL,37 +05BB F6 C4 02 0694 TEST AH,2 +05BE 74 E1 0695 JZ ERR30 +05C0 F6 C4 04 0696 TEST AH,4 +05C3 B1 26 0697 MOV CL,38 +05C5 75 DA 0698 JNZ ERR30 +05C7 0699 STRGDAT: +05C7 8A C2 0700 MOV AL,DL +05C9 3C 0D 0701 CMP AL,EOL +05CB B1 27 0702 MOV CL,39 +05CD 74 D2 0703 JZ ERR30 +05CF E8 CA 05 0704 CALL PUT +05D2 A0 39 21 0705 MOV AL,[DATSIZ] +05D5 0A C0 0706 OR AL,AL +05D7 75 05 0707 JNZ BYTSIZ +05D9 8A C6 0708 MOV AL,DH +05DB E8 BE 05 0709 CALL PUT +05DE 0710 BYTSIZ: +05DE A0 2F 21 0711 MOV AL,[CHR] +05E1 8A D0 0712 MOV DL,AL +05E3 E8 0A 00 0713 CALL GETCHR +05E6 EB DF 0714 JP STRGDAT +05E8 0715 +05E8 0716 ZERLEN: +05E8 E8 CB FC 0717 CALL NEXTCHR +05EB 3A C5 0718 CMP AL,CH +05ED 75 B2 0719 JNZ ERR30 +05EF C3 0720 RET +05F0 0721 +05F0 0722 GETCHR: +05F0 E8 C3 FC 0723 CALL NEXTCHR +05F3 3A C5 0724 CMP AL,CH +05F5 75 F8 0725 JNZ RET +05F7 E8 BC FC 0726 CALL NEXTCHR +05FA 3A C5 0727 CMP AL,CH +05FC 74 F1 0728 JZ RET +05FE 5B 0729 POP BX ;Kill return address to STRGDAT loop +05FF B0 FF 0730 MOV AL,-1 ;Flag type as constant +0601 C3 0731 RET +0602 0732 +0602 0733 +0602 0734 GETSYM: +0602 0735 +0602 0736 ; The lexical scanner. Used only in the operand field. Returns with the token +0602 0737 ; in SYM and AL, sometimes with additional info in BX or DX. +0602 0738 ; +0602 0739 ; AL=SYM=0 Undefined label. BX has pointer to information fields. +0602 0740 ; +0602 0741 ; AL=SYM=1 Constant (or defined label). DX has value. +0602 0742 ; +0602 0743 ; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +0602 0744 ; respectively. DL has register number. +0602 0745 ; +0602 0746 ; AL=SYM=5 A mode flag (such as "B" for byte operation). Type of flag in DL +0602 0747 ; and also stored in FLAG: -1=no flags, 0=B, 1=W, 2=S, 3=L, 4=T. +0602 0748 ; +0602 0749 ; AL=SYM=6 8087 floating point register, ST(n) or ST. DL has register number. +0602 0750 ; +0602 0751 ; All other values are the ASCII code of the character. Note that this may +0602 0752 ; never be a letter or number. +0602 0753 +0602 50 0754 PUSH AX ;Save AH +0603 E8 21 00 0755 CALL GETSY +0606 58 0756 POP AX +0607 A0 30 21 0757 MOV AL,[SYM] +060A C3 0758 RET +060B 0759 +060B 0760 SCANB: +060B A0 2F 21 0761 MOV AL,[CHR] +060E 0762 SCANT: +060E 3C 20 0763 CMP AL,' ' +0610 74 04 0764 JZ NEXB +0612 3C 09 0765 CMP AL,9 +0614 75 F4 0766 JNZ RET +0616 0767 NEXB: +0616 E8 9D FC 0768 CALL NEXTCHR +0619 EB F3 0769 JP SCANT +061B 0770 +061B 0771 DOLLAR: +061B 8B 16 CC 20 0772 MOV DX,[OLDPC] +061F B0 01 0773 MOV AL,CONST +0621 A2 30 21 0774 MOV [SYM],AL +0624 0775 NEXTCHJ: +0624 E9 8F FC 0776 JMP NEXTCHR +0627 0777 +0627 0778 GETSY: +0627 E8 E1 FF 0779 CALL SCANB +062A 3C 24 0780 CMP AL,'$' +062C 74 ED 0781 JZ DOLLAR +062E A2 30 21 0782 MOV [SYM],AL +0631 0C 20 0783 OR AL,20H +0633 3C 7B 0784 CMP AL,'z'+1 +0635 73 ED 0785 JNC NEXTCHJ +0637 3C 61 0786 CMP AL,'a' +0639 72 03 0787 JC $+5 +063B E9 BF 00 0788 JMP LETTER +063E 3C 3A 0789 CMP AL,'9'+1 +0640 73 E2 0790 JNC NEXTCHJ +0642 3C 30 0791 CMP AL,'0' +0644 72 DE 0792 JC NEXTCHJ +0646 BB 30 21 0793 MOV BX,SYM +0649 C6 07 01 0794 MOV B,[BX],CONST +064C E8 83 00 0795 CALL READID +064F 4B 0796 DEC BX +0650 8A 07 0797 MOV AL,[BX] +0652 B1 07 0798 MOV CL,7 +0654 BB 00 00 0799 MOV BX,0 +0657 3C 68 0800 CMP AL,'h' +0659 75 03 0801 JNZ $+5 +065B E9 32 00 0802 JMP HEX +065E FE C1 0803 INC CL +0660 C7 06 56 21 DF 20 0804 MOV [IX],ID +0666 0805 DEC: +0666 8B 36 56 21 0806 MOV SI,[IX] +066A 8A 04 0807 MOV AL,[SI] +066C FF 06 56 21 0808 INC [IX] +0670 3C 3A 0809 CMP AL,'9'+1 +0672 72 03 0810 JC $+5 +0674 E9 3A FC 0811 JMP ERROR +0677 2C 30 0812 SUB AL,'0' +0679 8B D3 0813 MOV DX,BX +067B D1 E3 0814 SHL BX +067D D1 E3 0815 SHL BX +067F 03 DA 0816 ADD BX,DX +0681 D1 E3 0817 SHL BX +0683 8A D0 0818 MOV DL,AL +0685 B6 00 0819 MOV DH,0 +0687 03 DA 0820 ADD BX,DX +0689 FE CD 0821 DEC CH +068B 75 D9 0822 JNZ DEC +068D 87 DA 0823 XCHG DX,BX +068F C3 0824 RET +0690 0825 +0690 0826 HEX: +0690 BA DF 20 0827 MOV DX,ID +0693 FE CD 0828 DEC CH +0695 0829 HEX1: +0695 8B F2 0830 MOV SI,DX +0697 AC 0831 LODB +0698 42 0832 INC DX +0699 2C 30 0833 SUB AL,'0' +069B 3C 0A 0834 CMP AL,10 +069D 72 06 0835 JC GOTIT +069F 3C 37 0836 CMP AL,'g'-'0' +06A1 73 13 0837 JNC ERR4 +06A3 2C 27 0838 SUB AL,'a'-10-'0' +06A5 0839 GOTIT: +06A5 D1 E3 0840 SHL BX +06A7 D1 E3 0841 SHL BX +06A9 D1 E3 0842 SHL BX +06AB D1 E3 0843 SHL BX +06AD 02 D8 0844 ADD BL,AL +06AF FE CD 0845 DEC CH +06B1 75 E2 0846 JNZ HEX1 +06B3 87 DA 0847 XCHG DX,BX +06B5 C3 0848 RET +06B6 0849 +06B6 E9 F8 FB 0850 ERR4: JMP ERROR +06B9 0851 +06B9 0852 GETLET: +06B9 E8 4F FF 0853 CALL SCANB +06BC 3C 0D 0854 CMP AL,EOL +06BE F9 0855 STC +06BF 74 F4 0856 JZ RET +06C1 3C 3B 0857 CMP AL,';' +06C3 F9 0858 STC +06C4 74 EF 0859 JZ RET +06C6 B1 0A 0860 MOV CL,10 +06C8 0C 20 0861 OR AL,20H +06CA 3C 61 0862 CMP AL,'a' +06CC 72 E8 0863 JC ERR4 +06CE 3C 7B 0864 CMP AL,'z'+1 +06D0 73 E4 0865 JNC ERR4 +06D2 0866 READID: +06D2 BB DF 20 0867 MOV BX,ID +06D5 B5 00 0868 MOV CH,0 +06D7 0869 MOREID: +06D7 88 07 0870 MOV [BX],AL +06D9 FE C5 0871 INC CH +06DB 43 0872 INC BX +06DC E8 D7 FB 0873 CALL NEXTCHR +06DF 3C 30 0874 CMP AL,'0' +06E1 72 0E 0875 JC NOMORE +06E3 0C 20 0876 OR AL,20H +06E5 3C 7B 0877 CMP AL,'z'+1 +06E7 73 08 0878 JNC NOMORE +06E9 3C 3A 0879 CMP AL,'9'+1 +06EB 72 EA 0880 JC MOREID +06ED 3C 61 0881 CMP AL,'a' +06EF 73 E6 0882 JNC MOREID +06F1 0883 NOMORE: +06F1 8A C8 0884 MOV CL,AL +06F3 8A C5 0885 MOV AL,CH +06F5 A2 DE 20 0886 MOV [LENID],AL +06F8 0A C0 0887 OR AL,AL +06FA 8A C1 0888 MOV AL,CL +06FC C3 0889 RET +06FD 0890 +06FD 0891 LETTER: +06FD E8 D2 FF 0892 CALL READID +0700 8A C5 0893 MOV AL,CH +0702 FE C8 0894 DEC AL +0704 75 14 0895 JNZ NOFLG +0706 A0 DF 20 0896 MOV AL,[ID] +0709 B9 05 00 0897 MOV CX,5 +070C BF 40 07 0898 MOV DI,FLGTAB +070F FC 0899 UP +0710 F2 0900 REPNE +0711 AE 0901 SCAB ;See if one of B,W,S,L,T +0712 74 1A 0902 JZ SAVFLG ;Go save flag +0714 32 C0 0903 XOR AL,AL +0716 8A 2E DE 20 0904 MOV CH,[LENID] +071A 0905 NOFLG: +071A FE C8 0906 DEC AL +071C 53 0907 PUSH BX +071D 75 03 0908 JNZ L0004 +071F E8 5A 00 0909 CALL REGCHK +0722 0910 L0004: +0722 5B 0911 POP BX +0723 8A C6 0912 MOV AL,DH +0725 74 03 0913 JZ SYMSAV +0727 E8 F9 00 0914 CALL LOOKRET +072A 0915 SYMSAV: +072A A2 30 21 0916 MOV [SYM],AL +072D C3 0917 RET +072E 0918 +072E 0919 SAVFLG: +072E 8A D1 0920 MOV DL,CL ;Need flag type in DL +0730 86 0E D0 20 0921 XCHG [FLAG],CL +0734 82 F9 FF 0922 CMP CL,-1 +0737 B1 20 0923 MOV CL,32 +0739 B0 05 0924 MOV AL,5 +073B 74 ED 0925 JZ SYMSAV +073D E9 71 FB 0926 ERRJ3: JMP ERROR +0740 0927 +0740 74 6C 73 77 62 0928 FLGTAB: DB "tlswb" +0745 0929 +0745 0930 FPREG: +0745 0931 ;Have detected "ST" for 8087 floating point stack register +0745 B2 00 0932 MOV DL,0 ;Default is ST(0) +0747 E8 C1 FE 0933 CALL SCANB ;Get next character +074A 3C 28 0934 CMP AL,"(" ;Specifying register number? +074C 75 29 0935 JNZ HAVREG +074E 0936 ;Get register number +074E E8 65 FB 0937 CALL NEXTCHR ;Skip over the "(" +0751 E8 74 FC 0938 CALL GETOP ;A little recursion never hurt anybody +0754 3C 01 0939 CMP AL,CONST ;Better have found a constant +0756 B1 14 0940 MOV CL,20 ;Operand error if not +0758 75 E3 0941 JNZ ERRJ3 +075A 83 3E D8 20 00 0942 CMP [DLABEL],0 ;Constant must be defined +075F B1 1E 0943 MOV CL,30 +0761 75 DA 0944 JNZ ERRJ3 +0763 8B 16 D6 20 0945 MOV DX,[DATA] ;Get constant +0767 83 FA 07 0946 CMP DX,7 ;Constant must be in range 0-7 +076A B1 1F 0947 MOV CL,31 +076C 77 CF 0948 JA ERRJ3 +076E A0 30 21 0949 MOV AL,[SYM] +0771 3C 29 0950 CMP AL,")" +0773 B1 18 0951 MOV CL,24 +0775 75 C6 0952 JNZ ERRJ3 +0777 0953 HAVREG: +0777 B6 06 0954 MOV DH,FREG +0779 32 C0 0955 XOR AL,AL ;Zero set means register found +077B C3 0956 RET +077C 0957 +077C 0958 REGCHK: +077C BB DF 20 0959 MOV BX,ID +077F 81 3F 73 74 0960 CMP [BX],"s"+7400H ;"st" +0783 74 C0 0961 JZ FPREG +0785 8A 0F 0962 MOV CL,[BX] +0787 43 0963 INC BX +0788 8A 07 0964 MOV AL,[BX] +078A BB E7 07 0965 MOV BX,REGTAB +078D B6 03 0966 MOV DH,XREG +078F B2 00 0967 MOV DL,0 +0791 3C 78 0968 CMP AL,'x' +0793 74 3B 0969 JZ SCANREG +0795 B6 02 0970 MOV DH,REG +0797 3C 6C 0971 CMP AL,'l' +0799 74 35 0972 JZ SCANREG +079B B2 04 0973 MOV DL,4 +079D 3C 68 0974 CMP AL,'h' +079F 74 2F 0975 JZ SCANREG +07A1 B6 04 0976 MOV DH,SREG +07A3 B2 00 0977 MOV DL,0 +07A5 BB EB 07 0978 MOV BX,SEGTAB +07A8 3C 73 0979 CMP AL,'s' +07AA 74 24 0980 JZ SCANREG +07AC B6 03 0981 MOV DH,XREG +07AE 3C 70 0982 CMP AL,'p' +07B0 74 11 0983 JZ PREG +07B2 3C 69 0984 CMP AL,'i' +07B4 75 C5 0985 JNZ RET +07B6 B2 06 0986 MOV DL,6 +07B8 8A C1 0987 MOV AL,CL +07BA 3C 73 0988 CMP AL,'s' +07BC 74 BD 0989 JZ RET +07BE FE C2 0990 INC DL +07C0 3C 64 0991 CMP AL,'d' +07C2 C3 0992 RET +07C3 0993 PREG: +07C3 B2 04 0994 MOV DL,4 +07C5 8A C1 0995 MOV AL,CL +07C7 3C 73 0996 CMP AL,'s' +07C9 74 F7 0997 JZ RET +07CB FE C2 0998 INC DL +07CD 3C 62 0999 CMP AL,'b' +07CF C3 1000 RET +07D0 1001 SCANREG: +07D0 8A C1 1002 MOV AL,CL +07D2 B9 04 00 1003 MOV CX,4 +07D5 FC 1004 UP +07D6 8B FB 1005 MOV DI,BX +07D8 F2 1006 REPNZ +07D9 AE 1007 SCAB +07DA 8B DF 1008 MOV BX,DI +07DC 75 F1 1009 JNZ RET +07DE 8A C1 1010 MOV AL,CL +07E0 02 C2 1011 ADD AL,DL +07E2 8A D0 1012 MOV DL,AL +07E4 32 C0 1013 XOR AL,AL +07E6 C3 1014 RET +07E7 1015 +07E7 62 64 63 61 1016 REGTAB: DB 'bdca' +07EB 1017 +07EB 64 73 63 65 1018 SEGTAB: DB 'dsce' +07EF 1019 +07EF 1020 LOOK: +07EF 8A 2F 1021 MOV CH,[BX] +07F1 43 1022 INC BX +07F2 BA DF 20 1023 MOV DX,ID +07F5 E8 FA 00 1024 CALL CPSLP +07F8 74 EC 1025 JZ RET +07FA 34 80 1026 XOR AL,80H +07FC D0 C0 1027 ROL AL ;Make end-of-symbol bit least significant +07FE 8A C8 1028 MOV CL,AL +0800 4B 1029 DEC BX +0801 8A 07 1030 MOV AL,[BX] +0803 34 80 1031 XOR AL,80H +0805 D0 C0 1032 ROL AL +0807 3A C1 1033 CMP AL,CL +0809 73 04 1034 JNC SMALL +080B FE C5 1035 INC CH +080D FE C5 1036 INC CH +080F 1037 SMALL: +080F 8A D5 1038 MOV DL,CH +0811 B6 00 1039 MOV DH,0 +0813 03 DA 1040 ADD BX,DX +0815 8B 17 1041 MOV DX,[BX] +0817 43 1042 INC BX +0818 8A C2 1043 MOV AL,DL +081A 0A C6 1044 OR AL,DH +081C F9 1045 STC +081D 74 C7 1046 JZ RET +081F 87 DA 1047 XCHG DX,BX +0821 EB CC 1048 JP LOOK +0823 1049 +0823 1050 LOOKRET: +0823 8A C5 1051 MOV AL,CH +0825 3C 03 1052 CMP AL,3 ;RET has 3 letters +0827 75 4F 1053 JNZ LOOKUP +0829 4B 1054 DEC BX +082A 80 0F 80 1055 OR B,[BX],080H +082D BA 7F 20 1056 MOV DX,RETSTR+2 +0830 1057 CHKRET: +0830 8B F2 1058 MOV SI,DX +0832 AC 1059 LODB +0833 3A 07 1060 CMP AL,[BX] +0835 75 45 1061 JNZ LOOKIT +0837 4B 1062 DEC BX +0838 4A 1063 DEC DX +0839 FE CD 1064 DEC CH +083B 75 F3 1065 JNZ CHKRET +083D 8B 16 4E 21 1066 MOV DX,[LSTRET] +0841 8A C2 1067 MOV AL,DL +0843 22 C6 1068 AND AL,DH +0845 FE C0 1069 INC AL +0847 74 0F 1070 JZ ALLRET +0849 8B 1E CA 20 1071 MOV BX,[PC] +084D 2B DA 1072 SUB BX,DX +084F 8A C3 1073 MOV AL,BL +0851 98 1074 CBW +0852 3B C3 1075 CMP AX,BX ;Signed 8-bit number? +0854 B0 01 1076 MOV AL,1 +0856 74 8E 1077 JZ RET +0858 1078 ALLRET: +0858 8B 1E 50 21 1079 MOV BX,[RETPT] +085C 8A C7 1080 MOV AL,BH +085E 0A C3 1081 OR AL,BL +0860 B0 00 1082 MOV AL,0 +0862 75 82 1083 JNZ RET +0864 8B 1E 33 21 1084 MOV BX,[HEAP] +0868 4B 1085 DEC BX +0869 4B 1086 DEC BX +086A 4B 1087 DEC BX +086B 89 1E 33 21 1088 MOV [HEAP],BX +086F 32 C0 1089 XOR AL,AL +0871 88 07 1090 MOV [BX],AL +0873 89 1E 50 21 1091 MOV [RETPT],BX +0877 C3 1092 RET +0878 1093 +0878 1094 LOOKUP: +0878 4B 1095 DEC BX +0879 80 0F 80 1096 OR B,[BX],080H +087C 1097 LOOKIT: +087C 8B 1E 31 21 1098 MOV BX,[BASE] +0880 8A C7 1099 MOV AL,BH +0882 0A C3 1100 OR AL,BL +0884 74 1E 1101 JZ EMPTY +0886 E8 66 FF 1102 CALL LOOK +0889 72 10 1103 JC ENTER +088B BA 04 00 1104 MOV DX,4 +088E 03 DA 1105 ADD BX,DX +0890 8A 07 1106 MOV AL,[BX] +0892 0A C0 1107 OR AL,AL +0894 74 E1 1108 JZ RET +0896 43 1109 INC BX +0897 8B 17 1110 MOV DX,[BX] +0899 43 1111 INC BX +089A C3 1112 RET +089B 1113 +089B 1114 ENTER: +089B 53 1115 PUSH BX ;Save pointer to link field +089C E8 0D 00 1116 CALL CREATE ;Add the node +089F 5E 1117 POP SI +08A0 89 54 FF 1118 MOV [SI-1],DX ;Link new node +08A3 C3 1119 RET ;Zero was set by CREATE +08A4 1120 +08A4 1121 EMPTY: +08A4 E8 05 00 1122 CALL CREATE +08A7 89 16 31 21 1123 MOV [BASE],DX +08AB C3 1124 RET +08AC 1125 +08AC 1126 +08AC 1127 CREATE: +08AC 1128 +08AC 1129 ; Add a new node to the identifier tree. The identifier is at ID with +08AC 1130 ; bit 7 of the last character set to one. The length of the identifier is +08AC 1131 ; in LENID, which is ID-1. +08AC 1132 ; +08AC 1133 ; Node format: +08AC 1134 ; 1. Length of identifier (1 byte) +08AC 1135 ; 2. Identifier (1-80 bytes) +08AC 1136 ; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +08AC 1137 ; 4. Right link (0 if none larger) +08AC 1138 ; 5. Data field: +08AC 1139 ; a. Defined flag (0=undefined, 1=defined) +08AC 1140 ; b. Value (2 bytes) +08AC 1141 ; +08AC 1142 ; This routine returns with AL=zero and zero flag set (which indicates +08AC 1143 ; on return from LOOKUP that it has not yet been defined), DX points +08AC 1144 ; to start of new node, and BX points to data field of new node. +08AC 1145 +08AC A0 DE 20 1146 MOV AL,[LENID] +08AF 04 08 1147 ADD AL,8 ;Storage needed for the node +08B1 8B 1E 33 21 1148 MOV BX,[HEAP] +08B5 8A D0 1149 MOV DL,AL +08B7 B6 00 1150 MOV DH,0 +08B9 2B DA 1151 SUB BX,DX ;Heap grows downward +08BB 89 1E 33 21 1152 MOV [HEAP],BX +08BF 87 DA 1153 XCHG DX,BX +08C1 8B 1E 37 21 1154 MOV BX,[CODE] ;Check to make sure there's enough +08C5 3B DA 1155 CMP BX,DX +08C7 72 03 1156 JB $+5 +08C9 E9 A7 F9 1157 JMP ABORT +08CC 52 1158 PUSH DX +08CD BB DE 20 1159 MOV BX,LENID +08D0 8A 0F 1160 MOV CL,[BX] +08D2 FE C1 1161 INC CL +08D4 B5 00 1162 MOV CH,0 +08D6 FC 1163 UP +08D7 8B F3 1164 MOV SI,BX +08D9 8B FA 1165 MOV DI,DX +08DB F3 1166 REP +08DC A4 1167 MOVB ;Move identifier and length into node +08DD 8B D7 1168 MOV DX,DI +08DF 8B DE 1169 MOV BX,SI +08E1 B5 04 1170 MOV CH,4 +08E3 87 DA 1171 XCHG DX,BX +08E5 1172 NILIFY: +08E5 88 0F 1173 MOV [BX],CL ;Zero left and right links +08E7 43 1174 INC BX +08E8 FE CD 1175 DEC CH +08EA 75 F9 1176 JNZ NILIFY +08EC 32 C0 1177 XOR AL,AL ;Set zero flag +08EE 88 07 1178 MOV [BX],AL ;Zero defined flag +08F0 5A 1179 POP DX ;Restore pointer to node +08F1 C3 1180 RET +08F2 1181 +08F2 1182 CPSLP: +08F2 8B F2 1183 MOV SI,DX +08F4 AC 1184 LODB +08F5 3A 07 1185 CMP AL,[BX] +08F7 9F 1186 LAHF +08F8 42 1187 INC DX +08F9 43 1188 INC BX +08FA 9E 1189 SAHF +08FB 75 F4 1190 JNZ RET +08FD FE CD 1191 DEC CH +08FF 75 F1 1192 JNZ CPSLP +0901 C3 1193 RET +0902 1194 +0902 1195 GETLAB: +0902 BB 00 00 1196 MOV BX,0 +0905 89 1E CE 20 1197 MOV [LABPT],BX +0909 C6 06 D0 20 FF 1198 MOV B,[FLAG],-1 +090E B6 00 1199 MOV DH,0 +0910 A0 2F 21 1200 MOV AL,[CHR] +0913 3C 21 1201 CMP AL,' '+1 +0915 72 03 1202 JC NOT1 +0917 80 CE 01 1203 OR DH,001H +091A 1204 NOT1: +091A E8 9C FD 1205 CALL GETLET +091D 72 E2 1206 JC RET +091F 3C 3A 1207 CMP AL,':' +0921 75 05 1208 JNZ LABCHK +0923 E8 90 F9 1209 CALL NEXTCHR +0926 EB 07 1210 JP LABEL +0928 1211 LABCHK: +0928 0A C0 1212 OR AL,AL +092A F6 C6 01 1213 TEST DH,001H +092D 74 D2 1214 JZ RET +092F 1215 LABEL: +092F A0 4B 21 1216 MOV AL,[CHKLAB] +0932 0A C0 1217 OR AL,AL +0934 74 03 1218 JZ $+5 +0936 E9 80 FD 1219 JMP GETLET +0939 E8 3C FF 1220 CALL LOOKUP +093C B1 0B 1221 MOV CL,11 +093E 75 11 1222 JNZ ERR5 +0940 8B 16 CA 20 1223 MOV DX,[PC] +0944 C6 07 01 1224 MOV B,[BX],1 +0947 43 1225 INC BX +0948 89 17 1226 MOV [BX],DX +094A 89 1E CE 20 1227 MOV [LABPT],BX +094E E9 68 FD 1228 JMP GETLET +0951 1229 +0951 E9 5D F9 1230 ERR5: JMP ERROR +0954 1231 +0954 1232 ASMLIN: +0954 C6 06 D1 20 01 1233 MOV B,[MAXFLG],1 ;Allow only B and W flags normally +0959 8B 1E CA 20 1234 MOV BX,[PC] +095D 89 1E CC 20 1235 MOV [OLDPC],BX +0961 E8 9E FF 1236 CALL GETLAB +0964 73 03 1237 JNC $+5 +0966 E9 E8 F8 1238 JMP ENDLN +0969 BB DE 20 1239 MOV BX,LENID +096C 8A 07 1240 MOV AL,[BX] +096E B1 0C 1241 MOV CL,12 +0970 2C 02 1242 SUB AL,2 +0972 8A E8 1243 MOV CH,AL +0974 72 DB 1244 JC ERR5 +0976 43 1245 INC BX +0977 82 3F 66 1246 CMP B,[BX],"f" ;See if an 8087 mnemonic +097A 74 4C 1247 JZ NDPOP +097C 3C 05 1248 CMP AL,5 +097E 73 D1 1249 JNC ERR5 +0980 8A 07 1250 MOV AL,[BX] +0982 2C 61 1251 SUB AL,'a' +0984 8A C8 1252 MOV CL,AL +0986 02 C0 1253 ADD AL,AL +0988 02 C0 1254 ADD AL,AL +098A 02 C1 1255 ADD AL,CL +098C 02 C5 1256 ADD AL,CH +098E 02 C0 1257 ADD AL,AL +0990 BB D0 1A 1258 MOV BX,OPTAB +0993 8A D0 1259 MOV DL,AL +0995 B6 00 1260 MOV DH,0 +0997 03 DA 1261 ADD BX,DX +0999 8B 1F 1262 MOV BX,[BX] +099B FE C5 1263 INC CH +099D 8A CD 1264 MOV CL,CH +099F 8A 27 1265 MOV AH,[BX] +09A1 43 1266 INC BX +09A2 0A E4 1267 OR AH,AH +09A4 74 18 1268 JZ OPERR +09A6 1269 FINDOP: +09A6 8A E9 1270 MOV CH,CL +09A8 BA E0 20 1271 MOV DX,ID+1 +09AB 95 1272 XCHG AX,BP ;Save count of opcodes in BP +09AC E8 43 FF 1273 CALL CPSLP +09AF 74 12 1274 JZ HAVOP +09B1 95 1275 XCHG AX,BP +09B2 B6 00 1276 MOV DH,0 +09B4 8A D5 1277 MOV DL,CH +09B6 42 1278 INC DX +09B7 42 1279 INC DX +09B8 03 DA 1280 ADD BX,DX +09BA FE CC 1281 DEC AH +09BC 75 E8 1282 JNZ FINDOP +09BE 1283 OPERR: +09BE B1 0C 1284 MOV CL,12 +09C0 E9 EE F8 1285 JMP ERROR +09C3 1286 +09C3 1287 HAVOP: +09C3 8A 47 02 1288 MOV AL,[BX+2] ;Get opcode +09C6 FF 27 1289 JMP [BX] +09C8 1290 +09C8 1291 NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") +09C8 C6 06 D1 20 04 1292 MOV B,[MAXFLG],4 ;Allow all type flags +09CD 43 1293 INC BX +09CE 82 3F 6E 1294 CMP B,[BX],"n" ;"No-wait" form? +09D1 B4 00 1295 MOV AH,0 +09D3 75 05 1296 JNZ SAVNFLG +09D5 B4 01 1297 MOV AH,1 +09D7 FE C8 1298 DEC AL +09D9 43 1299 INC BX ;Skip over the "N" +09DA 1300 SAVNFLG: +09DA 88 26 55 21 1301 MOV [NOWAIT],AH ;0 for wait, 1 for no wait +09DE 3C 01 1302 CMP AL,1 +09E0 72 DC 1303 JB OPERR ;Not enough char left for valid opcode? +09E2 3C 05 1304 CMP AL,5 +09E4 77 D8 1305 JA OPERR ;Too many? +09E6 98 1306 CBW +09E7 92 1307 XCHG AX,DX ;Save length in DX +09E8 8B F2 1308 MOV SI,DX +09EA 80 08 80 1309 OR B,[SI+BX],80H ;Set high bit of last character +09ED 8A 07 1310 MOV AL,[BX] ;Get first char of opcode +09EF 43 1311 INC BX +09F0 2C 61 1312 SUB AL,"a" +09F2 72 28 1313 JB TRY2XM1 ;Go see if opcode starts with "2" +09F4 3C 19 1314 CMP AL,"z"-"a" +09F6 77 C6 1315 JA OPERR +09F8 98 1316 CBW +09F9 D1 E0 1317 SHL AX ;Double to index into address table +09FB 96 1318 XCHG AX,SI ;Put in index register +09FC 8B BC D4 1B 1319 MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +0A00 1320 LOOKNDP: +0A00 8A 25 1321 MOV AH,[DI] ;Number of opcodes starting with this letter +0A02 0A E4 1322 OR AH,AH +0A04 74 B8 1323 JZ OPERR ;Any start with this letter? +0A06 1324 FNDNDP: +0A06 47 1325 INC DI +0A07 8B F3 1326 MOV SI,BX ;Pointer to start of opcode +0A09 8B CA 1327 MOV CX,DX ;Get length of opcode +0A0B F3 1328 REPE +0A0C A6 1329 CMPB ;Compare opcode to table entry +0A0D 74 38 1330 JZ HAVNDP +0A0F 4F 1331 DEC DI ;Back up in case that was last letter +0A10 B0 80 1332 MOV AL,80H ;Look for char with high bit set +0A12 1333 ENDOP: +0A12 AE 1334 SCASB +0A13 77 FD 1335 JA ENDOP +0A15 47 1336 INC DI ;Skip over info about opcode +0A16 FE CC 1337 DEC AH +0A18 75 EC 1338 JNZ FNDNDP +0A1A EB A2 1339 OPERRJ: JP OPERR +0A1C 1340 +0A1C 1341 TRY2XM1: +0A1C 3C D1 1342 CMP AL,"2"-"a" +0A1E 75 9E 1343 JNZ OPERR +0A20 BF 5E 19 1344 MOV DI,XM1 +0A23 EB DB 1345 JP LOOKNDP +0A25 1346 +0A25 1347 SPECIALOP: +0A25 24 07 1348 AND AL,7 ;Mask to special op number +0A27 74 16 1349 JZ FWAIT ;If zero, go handle FWAIT +0A29 1350 ;Handle FNOP +0A29 82 3E 55 21 00 1351 CMP B,[NOWAIT],0 ;Was "N" present (If not opcode was "FOP") +0A2E 74 8E 1352 JZ OPERR +0A30 B0 9B 1353 MOV AL,9BH ;Need Wait opcode after all +0A32 E8 67 01 1354 CALL PUT +0A35 B0 D9 1355 MOV AL,0D9H +0A37 E8 62 01 1356 CALL PUT +0A3A B0 D0 1357 MOV AL,0D0H +0A3C E9 5D 01 1358 JMP PUT +0A3F 1359 +0A3F 1360 FWAIT: +0A3F 82 3E 55 21 00 1361 CMP B,[NOWAIT],0 ;"FNWAIT" not legal +0A44 75 D4 1362 JNZ OPERRJ +0A46 C3 1363 RET ;Nothing to do - "WAIT" already sent +0A47 1364 +0A47 1365 HAVNDP: +0A47 8B F7 1366 MOV SI,DI +0A49 82 3E 55 21 00 1367 CMP B,[NOWAIT],0 +0A4E 75 05 1368 JNZ NWAIT +0A50 B0 9B 1369 MOV AL,9BH ;Wait opcode +0A52 E8 47 01 1370 CALL PUT +0A55 1371 NWAIT: +0A55 AD 1372 LODW ;Get opcode info +0A56 A8 F8 1373 TEST AL,0F8H ;Any operand bits set? +0A58 74 66 1374 JZ NOOPS ;If no operands, output code +0A5A A8 78 1375 TEST AL,78H ;Special case? +0A5C 74 C7 1376 JZ SPECIALOP +0A5E 50 1377 PUSH AX +0A5F E8 A0 FB 1378 CALL GETSYM ;See if any operands +0A62 59 1379 POP CX +0A63 3C 3B 1380 CMP AL,";" +0A65 74 52 1381 JZ NOOPCHK +0A67 3C 0D 1382 CMP AL,EOL +0A69 74 4E 1383 JZ NOOPCHK +0A6B 3C 06 1384 CMP AL,FREG ;Is it 8087 register? +0A6D 75 6F 1385 JNZ MEMOP +0A6F 91 1386 XCHG AX,CX +0A70 A8 40 1387 TEST AL,ONEREG ;One register OK as operand? +0A72 75 36 1388 JNZ PUTREG ;Yes - save it +0A74 A8 20 1389 TEST AL,20H ;Memory-only operation? +0A76 B1 14 1390 MOV CL,20 +0A78 75 61 1391 JNZ ERRJ4 +0A7A A8 18 1392 TEST AL,18H ;Two-register operation? +0A7C 7A 5D 1393 JPE ERRJ4 ;Must be exactly one bit set +0A7E 52 1394 PUSH DX ;Save register number +0A7F 50 1395 PUSH AX ;Save opcode +0A80 E8 7F FB 1396 CALL GETSYM +0A83 3C 2C 1397 CMP AL,"," +0A85 B1 15 1398 MOV CL,15H +0A87 75 52 1399 JNZ ERRJ4 +0A89 E8 76 FB 1400 CALL GETSYM +0A8C B1 14 1401 MOV CL,20 +0A8E 3C 06 1402 CMP AL,FREG +0A90 75 49 1403 JNZ ERRJ4 +0A92 58 1404 POP AX +0A93 5B 1405 POP BX +0A94 34 02 1406 XOR AL,2 ;Flip "POP" bit +0A96 24 FB 1407 AND AL,0FBH ;Reset direction bit to ST(0) +0A98 0A DB 1408 OR BL,BL ;Is first register ST(0)? +0A9A 74 0A 1409 JZ ST0DEST +0A9C 87 DA 1410 XCHG DX,BX +0A9E 0A DB 1411 OR BL,BL ;One of these must be ST(0) +0AA0 75 39 1412 JNZ ERRJ4 +0AA2 34 04 1413 XOR AL,4 ;Flip direction +0AA4 EB 04 1414 JMPS PUTREG +0AA6 1415 ST0DEST: +0AA6 A8 02 1416 TEST AL,2 ;Is POP bit set? +0AA8 75 31 1417 JNZ ERRJ4 ;Don't allow destination ST(0) then pop +0AAA 1418 PUTREG: +0AAA 80 E4 F8 1419 AND AH,0F8H ;Zero out register field +0AAD 0A E2 1420 OR AH,DL +0AAF 80 CC C0 1421 OR AH,0C0H +0AB2 50 1422 PUSH AX +0AB3 E8 4C FB 1423 CALL GETSYM ;Get to next symbol +0AB6 58 1424 POP AX +0AB7 EB 07 1425 JMPS NOOPS +0AB9 1426 +0AB9 1427 NOOPCHK: +0AB9 91 1428 XCHG AX,CX +0ABA A8 80 1429 TEST AL,80H ;Is no operands OK? +0ABC B1 14 1430 MOV CL,20 +0ABE 75 1B 1431 JNZ ERRJ4 +0AC0 1432 NOOPS: +0AC0 1433 ;First test for FDIV or FSUB and reverse "R" bit if "D" bit is set +0AC0 50 1434 PUSH AX +0AC1 25 05 E0 1435 AND AX,0E005H +0AC4 3D 04 E0 1436 CMP AX,0E004H +0AC7 58 1437 POP AX +0AC8 75 03 1438 JNZ NOREV +0ACA 80 F4 08 1439 XOR AH,8 ;Reverse "R" bit +0ACD 1440 NOREV: +0ACD 24 07 1441 AND AL,7 +0ACF 0C D8 1442 OR AL,0D8H ;ESC hook +0AD1 E8 C8 00 1443 CALL PUT +0AD4 8A C4 1444 MOV AL,AH +0AD6 E9 C3 00 1445 JMP PUT +0AD9 1446 +0AD9 1447 BADFLAG: +0AD9 B1 20 1448 MOV CL,20H +0ADB E9 D3 F7 1449 ERRJ4: JMP ERROR +0ADE 1450 +0ADE 1451 MEMOP: +0ADE 51 1452 PUSH CX ;Save opcode +0ADF E8 E9 F8 1453 CALL GETOP1 ;Get memory operand +0AE2 3C 00 1454 CMP AL,UNDEFID ;Is it? +0AE4 B1 14 1455 MOV CL,20 +0AE6 75 F3 1456 JNZ ERRJ4 +0AE8 58 1457 POP AX +0AE9 A8 20 1458 TEST AL,20H ;Does it have memory format field? +0AEB 75 08 1459 JNZ GETFORMAT +0AED A8 08 1460 TEST AL,8 ;Check if any memory operand legal +0AEF 74 EA 1461 JZ ERRJ4 +0AF1 A8 10 1462 TEST AL,10H ;Check for 2-op arithmetic +0AF3 75 1E 1463 JNZ PUTMEM ;If not, just use as plain memory op +0AF5 1464 GETFORMAT: +0AF5 24 F9 1465 AND AL,0F9H ;Zero memory format bits +0AF7 8A 0E D0 20 1466 MOV CL,[FLAG] +0AFB FE C9 1467 DEC CL ;Must now be in range 0-3 +0AFD 7C DA 1468 JL BADFLAG +0AFF 8A E8 1469 MOV CH,AL ;Save opcode byte +0B01 D0 E8 1470 SHR AL ;Put format bits in bits 2 & 3 +0B03 24 0C 1471 AND AL,0CH +0B05 0A C1 1472 OR AL,CL ;Combine format bits with flag +0B07 BB 23 0B 1473 MOV BX,FORMATTAB +0B0A D7 1474 XLAT +0B0B 0A C0 1475 OR AL,AL ;Valid combination? +0B0D 78 CA 1476 JS BADFLAG +0B0F 0A E0 1477 OR AH,AL ;Possibly set new bits in second byte +0B11 0A C5 1478 OR AL,CH ;Set memory format bits +0B13 1479 PUTMEM: +0B13 24 07 1480 AND AL,7 +0B15 0C D8 1481 OR AL,0D8H +0B17 E8 82 00 1482 CALL PUT +0B1A 8A C4 1483 MOV AL,AH +0B1C 24 38 1484 AND AL,38H +0B1E 0A C2 1485 OR AL,DL ;Combine addressing mode +0B20 E9 39 01 1486 JMP PUTADD +0B23 1487 +0B23 1488 FORMATTAB: +0B23 1489 ;There are 16 entries in this table. The 4-bit index is built like this: +0B23 1490 ; Bit 3 0 for normal memory ops, 1 if extended is OK +0B23 1491 ; Bit 2 0 for integer, 1 for real +0B23 1492 ; Bit 0 & 1 Flag: 00=W, 01=S, 10=L, 11=T +0B23 1493 ; +0B23 1494 ;The entries in the table are used as two 3-bit fields. Bits 0-2 are ORed +0B23 1495 ;into the first byte of the opcode for the Memory Format field. Bits 3-6 +0B23 1496 ;are ORed into the second byte to modify the opcode for extended operands. +0B23 1497 ;If bit 7 is set, then that combination is illegal. +0B23 1498 +0B23 06 02 80 80 1499 DB 6,2,80H,80H ;Normal integers +0B27 80 00 04 80 1500 DB 80H,0,4,80H ;Normal reals +0B2B 06 02 2E 80 1501 DB 6,2,2EH,80H ;Extended integers +0B2F 80 00 04 2B 1502 DB 80H,0,4,2BH ;Extended reals +0B33 1503 +0B33 1504 GRP1: +0B33 B9 09 8A 1505 MOV CX,8A09H +0B36 E8 B3 F7 1506 CALL MROPS +0B39 B9 C6 00 1507 MOV CX,0C6H +0B3C 8A C7 1508 MOV AL,BH +0B3E 3C 00 1509 CMP AL,UNDEFID +0B40 75 03 1510 JNZ L0006 +0B42 E8 3C 00 1511 CALL STIMM +0B45 1512 L0006: +0B45 24 01 1513 AND AL,1 +0B47 74 0A 1514 JZ BYTIMM +0B49 B0 B8 1515 MOV AL,0B8H +0B4B 0A C3 1516 OR AL,BL +0B4D E8 4C 00 1517 CALL PUT +0B50 E9 98 00 1518 JMP PUTWOR +0B53 1519 +0B53 1520 BYTIMM: +0B53 B0 B0 1521 MOV AL,0B0H +0B55 0A C3 1522 OR AL,BL +0B57 E8 42 00 1523 CALL PUT +0B5A E9 95 00 1524 PUTBJ: JMP PUTBYT +0B5D 1525 +0B5D 1526 IMMED: +0B5D 8A C7 1527 MOV AL,BH +0B5F 3C 00 1528 CMP AL,UNDEFID +0B61 74 1E 1529 JZ STIMM +0B63 8A C3 1530 MOV AL,BL +0B65 0A C0 1531 OR AL,AL +0B67 74 32 1532 JZ RET +0B69 8A C7 1533 MOV AL,BH +0B6B E8 1E 00 1534 CALL IMM +0B6E 0C C0 1535 OR AL,0C0H +0B70 E8 29 00 1536 CALL PUT +0B73 1537 FINIMM: +0B73 8A C1 1538 MOV AL,CL +0B75 59 1539 POP CX +0B76 A8 01 1540 TEST AL,1 +0B78 74 E0 1541 JZ PUTBJ +0B7A 3C 83 1542 CMP AL,83H +0B7C 74 DC 1543 JZ PUTBJ +0B7E E9 6A 00 1544 JMP PUTWOR +0B81 1545 +0B81 1546 STIMM: +0B81 A0 D0 20 1547 MOV AL,[FLAG] +0B84 E8 05 00 1548 CALL IMM +0B87 E8 D2 00 1549 CALL PUTADD +0B8A EB E7 1550 JP FINIMM +0B8C 1551 +0B8C 1552 IMM: +0B8C 24 01 1553 AND AL,1 +0B8E 0A C1 1554 OR AL,CL +0B90 8A C8 1555 MOV CL,AL +0B92 E8 07 00 1556 CALL PUT +0B95 8A C5 1557 MOV AL,CH +0B97 24 38 1558 AND AL,38H +0B99 0A C3 1559 OR AL,BL +0B9B C3 1560 RET +0B9C 1561 +0B9C 1562 PUT: +0B9C 1563 ;Save byte in AL as pure code, with intermediate code bits 00. AL and +0B9C 1564 ;DI destroyed, no other registers affected. +0B9C 53 1565 PUSH BX +0B9D 51 1566 PUSH CX +0B9E B5 00 1567 MOV CH,0 ;Flag as pure code +0BA0 E8 03 00 1568 CALL GEN +0BA3 59 1569 POP CX +0BA4 5B 1570 POP BX +0BA5 C3 1571 RET +0BA6 1572 +0BA6 1573 GEN: +0BA6 1574 ;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. +0BA6 E8 34 00 1575 CALL PUTINC ;Save it and bump code pointer +0BA9 1576 GEN1: +0BA9 A0 3A 21 1577 MOV AL,[RELOC] +0BAC D0 D5 1578 RCL CH +0BAE D0 D0 1579 RCL AL +0BB0 D0 D5 1580 RCL CH +0BB2 D0 D0 1581 RCL AL +0BB4 A2 3A 21 1582 MOV [RELOC],AL +0BB7 BB 3B 21 1583 MOV BX,BCOUNT +0BBA FE 0F 1584 DEC B,[BX] +0BBC 75 E7 1585 JNZ RET +0BBE C6 07 04 1586 MOV B,[BX],4 +0BC1 BB 3A 21 1587 MOV BX,RELOC +0BC4 8A 07 1588 MOV AL,[BX] +0BC6 C6 07 00 1589 MOV B,[BX],0 +0BC9 8B 3E 58 21 1590 MOV DI,[IY] +0BCD 88 05 1591 MOV [DI],AL +0BCF 8B 1E 37 21 1592 MOV BX,[CODE] +0BD3 89 1E 58 21 1593 MOV [IY],BX +0BD7 43 1594 INC BX +0BD8 89 1E 37 21 1595 MOV [CODE],BX +0BDC C3 1596 RET +0BDD 1597 +0BDD 1598 PUTINC: +0BDD FF 06 CA 20 1599 INC [PC] +0BE1 1600 PUTCD: +0BE1 8B 3E 37 21 1601 MOV DI,[CODE] +0BE5 AA 1602 STOB +0BE6 89 3E 37 21 1603 MOV [CODE],DI +0BEA C3 1604 RET +0BEB 1605 +0BEB 1606 PUTWOR: +0BEB 1607 ;Save the word value described by [DLABEL] and [DATA] as code. If defined, +0BEB 1608 ;two bytes of pure code will be produced. Otherwise, appropriate intermediate +0BEB 1609 ;code will be generated. +0BEB 51 1610 PUSH CX +0BEC B5 80 1611 MOV CH,80H +0BEE 52 1612 PUSH DX +0BEF 53 1613 PUSH BX +0BF0 EB 20 1614 JP PUTBW +0BF2 1615 +0BF2 1616 PUTBYT: +0BF2 1617 ;Same as PUTWOR, above, but for byte value. +0BF2 51 1618 PUSH CX +0BF3 B5 40 1619 MOV CH,40H +0BF5 52 1620 PUSH DX +0BF6 53 1621 PUSH BX +0BF7 8B 1E D8 20 1622 MOV BX,[DLABEL] +0BFB 8A C7 1623 MOV AL,BH +0BFD 0A C3 1624 OR AL,BL +0BFF 75 11 1625 JNZ PUTBW +0C01 8B 1E D6 20 1626 MOV BX,[DATA] +0C05 0A C7 1627 OR AL,BH +0C07 74 09 1628 JZ PUTBW +0C09 FE C7 1629 INC BH +0C0B 74 05 1630 JZ PUTBW +0C0D B1 1F 1631 MOV CL,31 +0C0F E9 9F F6 1632 JMP ERROR +0C12 1633 PUTBW: +0C12 8B 16 D8 20 1634 MOV DX,[DLABEL] +0C16 8B 1E D6 20 1635 MOV BX,[DATA] +0C1A 1636 PUTCHK: +0C1A 0B D2 1637 OR DX,DX +0C1C 74 25 1638 JZ NOUNDEF +0C1E 8A C2 1639 MOV AL,DL +0C20 E8 BE FF 1640 CALL PUTCD +0C23 8A C6 1641 MOV AL,DH +0C25 E8 B9 FF 1642 CALL PUTCD +0C28 8A C3 1643 MOV AL,BL +0C2A E8 B0 FF 1644 CALL PUTINC +0C2D 8A C7 1645 MOV AL,BH +0C2F F6 C5 80 1646 TEST CH,080H +0C32 74 05 1647 JZ SMPUT +0C34 E8 6F FF 1648 CALL GEN +0C37 EB 06 1649 JP PRET +0C39 1650 SMPUT: +0C39 E8 A5 FF 1651 CALL PUTCD +0C3C E8 6A FF 1652 CALL GEN1 +0C3F 1653 PRET: +0C3F 5B 1654 POP BX +0C40 5A 1655 POP DX +0C41 59 1656 POP CX +0C42 C3 1657 RET +0C43 1658 +0C43 1659 NOUNDEF: +0C43 8A C3 1660 MOV AL,BL +0C45 8A CF 1661 MOV CL,BH +0C47 51 1662 PUSH CX +0C48 B5 00 1663 MOV CH,0 +0C4A E8 59 FF 1664 CALL GEN +0C4D 59 1665 POP CX +0C4E 8A C1 1666 MOV AL,CL +0C50 F6 C5 80 1667 TEST CH,080H +0C53 B5 00 1668 MOV CH,0 +0C55 74 E8 1669 JZ PRET +0C57 E8 4C FF 1670 CALL GEN +0C5A EB E3 1671 JP PRET +0C5C 1672 +0C5C 1673 PUTADD: +0C5C 1674 ;Save complete addressing mode. Addressing mode is in AL; if this is a register +0C5C 1675 ;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +0C5C 1676 ;the details of the addressing mode will be investigated and the optional one- +0C5C 1677 ;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. +0C5C 51 1678 PUSH CX +0C5D 52 1679 PUSH DX +0C5E 53 1680 PUSH BX +0C5F B5 00 1681 MOV CH,0 +0C61 8A C8 1682 MOV CL,AL +0C63 E8 40 FF 1683 CALL GEN ;Save the addressing mode as pure code +0C66 8A C1 1684 MOV AL,CL +0C68 B5 80 1685 MOV CH,80H +0C6A 24 C7 1686 AND AL,0C7H +0C6C 3C 06 1687 CMP AL,6 +0C6E 74 0A 1688 JZ TWOBT ;Direct address? +0C70 24 C0 1689 AND AL,0C0H +0C72 74 CB 1690 JZ PRET ;Indirect through reg, no displacement? +0C74 3C C0 1691 CMP AL,0C0H +0C76 74 C7 1692 JZ PRET ;Register to register operation? +0C78 8A E8 1693 MOV CH,AL ;Save whether one- or two-byte displacement +0C7A 1694 TWOBT: +0C7A 8B 1E D2 20 1695 MOV BX,[ADDR] +0C7E 8B 16 D4 20 1696 MOV DX,[ALABEL] +0C82 EB 96 1697 JP PUTCHK +0C84 1698 +0C84 1699 GRP2: +0C84 E8 41 F7 1700 CALL GETOP +0C87 B9 30 FF 1701 MOV CX,0FF30H +0C8A 3C 00 1702 CMP AL,UNDEFID +0C8C 74 14 1703 JZ PMEM +0C8E B5 50 1704 MOV CH,50H +0C90 3C 03 1705 CMP AL,XREG +0C92 74 1A 1706 JZ PXREG +0C94 B5 06 1707 MOV CH,6 +0C96 3C 04 1708 CMP AL,SREG +0C98 75 03 1709 JNZ $+5 +0C9A E9 01 04 1710 JMP PACKREG +0C9D B1 14 1711 MOV CL,20 +0C9F E9 0F F6 1712 JMP ERROR +0CA2 1713 +0CA2 1714 PMEM: +0CA2 8A C5 1715 MOV AL,CH +0CA4 E8 F5 FE 1716 CALL PUT +0CA7 8A C1 1717 MOV AL,CL +0CA9 0A C2 1718 OR AL,DL +0CAB E9 AE FF 1719 JMP PUTADD +0CAE 1720 +0CAE 1721 PXREG: +0CAE 8A C5 1722 MOV AL,CH +0CB0 0A C2 1723 OR AL,DL +0CB2 E9 E7 FE 1724 JMP PUT +0CB5 1725 +0CB5 1726 GRP3: +0CB5 E8 10 F7 1727 CALL GETOP +0CB8 52 1728 PUSH DX +0CB9 E8 03 F7 1729 CALL GETOP2 +0CBC 5B 1730 POP BX +0CBD B9 14 86 1731 MOV CX,8614H +0CC0 B0 04 1732 MOV AL,SREG +0CC2 3A C7 1733 CMP AL,BH +0CC4 74 4C 1734 JZ ERR6 +0CC6 3A C6 1735 CMP AL,DH +0CC8 74 48 1736 JZ ERR6 +0CCA B0 01 1737 MOV AL,CONST +0CCC 3A C7 1738 CMP AL,BH +0CCE 74 42 1739 JZ ERR6 +0CD0 3A C6 1740 CMP AL,DH +0CD2 74 3E 1741 JZ ERR6 +0CD4 B0 00 1742 MOV AL,UNDEFID +0CD6 3A C7 1743 CMP AL,BH +0CD8 74 2D 1744 JZ EXMEM +0CDA 3A C6 1745 CMP AL,DH +0CDC 74 2B 1746 JZ EXMEM1 +0CDE 8A C7 1747 MOV AL,BH +0CE0 3A C6 1748 CMP AL,DH +0CE2 B1 16 1749 MOV CL,22 +0CE4 75 2C 1750 JNZ ERR6 +0CE6 3C 03 1751 CMP AL,XREG +0CE8 74 03 1752 JZ L0008 +0CEA E8 38 F6 1753 CALL RR1 +0CED 1754 L0008: ;RR1 never returns +0CED 8A C3 1755 MOV AL,BL +0CEF 0A C0 1756 OR AL,AL +0CF1 74 0D 1757 JZ EXACC +0CF3 87 DA 1758 XCHG DX,BX +0CF5 8A C3 1759 MOV AL,BL +0CF7 0A C0 1760 OR AL,AL +0CF9 8A C7 1761 MOV AL,BH +0CFB 74 03 1762 JZ EXACC +0CFD E8 25 F6 1763 CALL RR1 +0D00 1764 EXACC: +0D00 B0 90 1765 MOV AL,90H +0D02 0A C2 1766 OR AL,DL +0D04 E9 95 FE 1767 JMP PUT +0D07 1768 +0D07 1769 EXMEM: +0D07 87 DA 1770 XCHG DX,BX +0D09 1771 EXMEM1: +0D09 3A C7 1772 CMP AL,BH +0D0B 74 05 1773 JZ ERR6 +0D0D B1 01 1774 MOV CL,1 ;Flag word as OK +0D0F E8 8D F6 1775 CALL NOTAC ;NOTAC never returns +0D12 E9 9C F5 1776 ERR6: JMP ERROR +0D15 1777 +0D15 1778 GRP4: +0D15 50 1779 PUSH AX +0D16 E8 AF F6 1780 CALL GETOP +0D19 59 1781 POP CX +0D1A 86 CD 1782 XCHG CL,CH +0D1C 3C 01 1783 CMP AL,CONST +0D1E 74 13 1784 JZ FIXED +0D20 2C 03 1785 SUB AL,XREG +0D22 FE CA 1786 DEC DL +0D24 FE CA 1787 DEC DL +0D26 0A C2 1788 OR AL,DL +0D28 B1 14 1789 MOV CL,20 +0D2A 75 E6 1790 JNZ ERR6 +0D2C 8A C5 1791 MOV AL,CH +0D2E 0C 08 1792 OR AL,8 +0D30 E9 69 FE 1793 JMP PUT +0D33 1794 FIXED: +0D33 8A C5 1795 MOV AL,CH +0D35 E8 64 FE 1796 CALL PUT +0D38 E9 B7 FE 1797 JMP PUTBYT +0D3B 1798 +0D3B 1799 GRP5: +0D3B 50 1800 PUSH AX +0D3C E8 89 F6 1801 CALL GETOP +0D3F B1 14 1802 MOV CL,20 +0D41 3C 01 1803 CMP AL,CONST +0D43 75 CD 1804 JNZ ERR6 +0D45 8B 1E D8 20 1805 MOV BX,[DLABEL] +0D49 8A C7 1806 MOV AL,BH +0D4B 0A C3 1807 OR AL,BL +0D4D B1 1E 1808 MOV CL,30 +0D4F 75 C1 1809 JNZ ERR6 +0D51 8B 1E D6 20 1810 MOV BX,[DATA] +0D55 58 1811 POP AX +0D56 0A C0 1812 OR AL,AL +0D58 74 43 1813 JZ ORG +0D5A FE C8 1814 DEC AL +0D5C 74 19 1815 JZ DSJ +0D5E FE C8 1816 DEC AL +0D60 74 27 1817 JZ EQU +0D62 FE C8 1818 DEC AL +0D64 74 03 1819 JZ $+5 +0D66 E9 98 03 1820 JMP IF +0D69 1821 PUTOP: +0D69 B0 FD 1822 MOV AL,-3 +0D6B EB 36 1823 JP NEWLOC +0D6D 1824 ALIGN: +0D6D A0 CA 20 1825 MOV AL,[PC] +0D70 24 01 1826 AND AL,1 +0D72 74 28 1827 JZ RET +0D74 BB 01 00 1828 MOV BX,1 +0D77 1829 DSJ: +0D77 87 DA 1830 XCHG DX,BX +0D79 8B 1E CA 20 1831 MOV BX,[PC] +0D7D 03 DA 1832 ADD BX,DX +0D7F 89 1E CA 20 1833 MOV [PC],BX +0D83 87 DA 1834 XCHG DX,BX +0D85 B0 FC 1835 MOV AL,-4 +0D87 EB 1A 1836 JP NEWLOC +0D89 1837 EQU: +0D89 87 DA 1838 XCHG DX,BX +0D8B 8B 1E CE 20 1839 MOV BX,[LABPT] +0D8F 8A C7 1840 MOV AL,BH +0D91 0A C3 1841 OR AL,BL +0D93 B1 22 1842 MOV CL,34 +0D95 74 27 1843 JZ ERR7 +0D97 88 17 1844 MOV [BX],DL +0D99 43 1845 INC BX +0D9A 88 37 1846 MOV [BX],DH +0D9C C3 1847 RET +0D9D 1848 ORG: +0D9D 89 1E CA 20 1849 MOV [PC],BX +0DA1 B0 FE 1850 MOV AL,-2 +0DA3 1851 NEWLOC: +0DA3 E8 3B FE 1852 CALL PUTCD +0DA6 8A C3 1853 MOV AL,BL +0DA8 E8 36 FE 1854 CALL PUTCD +0DAB 8A C7 1855 MOV AL,BH +0DAD E8 31 FE 1856 CALL PUTCD +0DB0 B5 C0 1857 MOV CH,0C0H +0DB2 E9 F4 FD 1858 JMP GEN1 +0DB5 1859 GRP6: +0DB5 8A E8 1860 MOV CH,AL +0DB7 B1 04 1861 MOV CL,4 +0DB9 E8 30 F5 1862 CALL MROPS +0DBC B1 17 1863 MOV CL,23 +0DBE E9 F0 F4 1864 ERR7: JMP ERROR +0DC1 1865 GRP7: +0DC1 8A E8 1866 MOV CH,AL +0DC3 B1 01 1867 MOV CL,1 +0DC5 E8 24 F5 1868 CALL MROPS +0DC8 B1 80 1869 MOV CL,80H +0DCA 8B 16 D8 20 1870 MOV DX,[DLABEL] +0DCE 8A C6 1871 MOV AL,DH +0DD0 0A C2 1872 OR AL,DL +0DD2 75 12 1873 JNZ ACCJ +0DD4 87 DA 1874 XCHG DX,BX +0DD6 8B 1E D6 20 1875 MOV BX,[DATA] +0DDA 8A C3 1876 MOV AL,BL +0DDC 98 1877 CBW +0DDD 3B C3 1878 CMP AX,BX +0DDF 87 DA 1879 XCHG DX,BX +0DE1 75 03 1880 JNZ ACCJ +0DE3 80 C9 02 1881 OR CL,002H +0DE6 E9 B7 00 1882 ACCJ: JMP ACCIMM +0DE9 1883 GRP8: +0DE9 8A C8 1884 MOV CL,AL +0DEB B5 FE 1885 MOV CH,0FEH +0DED EB 04 1886 JP ONEOP +0DEF 1887 GRP9: +0DEF 8A C8 1888 MOV CL,AL +0DF1 B5 F6 1889 MOV CH,0F6H +0DF3 1890 ONEOP: +0DF3 51 1891 PUSH CX +0DF4 E8 D1 F5 1892 CALL GETOP +0DF7 1893 ONE: +0DF7 B1 1A 1894 MOV CL,26 +0DF9 3C 01 1895 CMP AL,CONST +0DFB 74 C1 1896 JZ ERR7 +0DFD 3C 04 1897 CMP AL,SREG +0DFF B1 16 1898 MOV CL,22 +0E01 74 BB 1899 JZ ERR7 +0E03 59 1900 POP CX +0E04 3C 00 1901 CMP AL,UNDEFID +0E06 74 12 1902 JZ MOP +0E08 24 01 1903 AND AL,1 +0E0A 74 21 1904 JZ ROP +0E0C F6 C1 01 1905 TEST CL,001H +0E0F 74 1C 1906 JZ ROP +0E11 8A C1 1907 MOV AL,CL +0E13 24 F8 1908 AND AL,0F8H +0E15 0A C2 1909 OR AL,DL +0E17 E9 82 FD 1910 JMP PUT +0E1A 1911 MOP: +0E1A A0 D0 20 1912 MOV AL,[FLAG] +0E1D 24 01 1913 AND AL,1 +0E1F 0A C5 1914 OR AL,CH +0E21 E8 78 FD 1915 CALL PUT +0E24 8A C1 1916 MOV AL,CL +0E26 24 38 1917 AND AL,38H +0E28 0A C2 1918 OR AL,DL +0E2A E9 2F FE 1919 JMP PUTADD +0E2D 1920 ROP: +0E2D 0A C5 1921 OR AL,CH +0E2F E8 6A FD 1922 CALL PUT +0E32 8A C1 1923 MOV AL,CL +0E34 24 38 1924 AND AL,38H +0E36 0C C0 1925 OR AL,0C0H +0E38 0A C2 1926 OR AL,DL +0E3A E9 5F FD 1927 JMP PUT +0E3D 1928 GRP10: +0E3D 8A C8 1929 MOV CL,AL +0E3F B5 F6 1930 MOV CH,0F6H +0E41 51 1931 PUSH CX +0E42 E8 83 F5 1932 CALL GETOP +0E45 B1 14 1933 MOV CL,20 +0E47 8A C2 1934 MOV AL,DL +0E49 0A C0 1935 OR AL,AL +0E4B 75 08 1936 JNZ ERRJ1 +0E4D 8A C6 1937 MOV AL,DH +0E4F 3C 03 1938 CMP AL,XREG +0E51 74 04 1939 JZ G10 +0E53 3C 02 1940 CMP AL,REG +0E55 75 67 1941 ERRJ1: JNZ ERR8 +0E57 1942 G10: +0E57 50 1943 PUSH AX +0E58 E8 6D F5 1944 CALL GETOP +0E5B 58 1945 POP AX +0E5C 24 01 1946 AND AL,1 +0E5E A2 D0 20 1947 MOV [FLAG],AL +0E61 8A C6 1948 MOV AL,DH +0E63 EB 92 1949 ONEJ: JP ONE +0E65 1950 GRP11: +0E65 E8 34 FD 1951 CALL PUT +0E68 B0 0A 1952 MOV AL,0AH +0E6A E9 2F FD 1953 JMP PUT +0E6D 1954 GRP12: +0E6D 8A C8 1955 MOV CL,AL +0E6F B5 D0 1956 MOV CH,0D0H +0E71 51 1957 PUSH CX +0E72 E8 53 F5 1958 CALL GETOP +0E75 A0 30 21 1959 MOV AL,[SYM] +0E78 3C 2C 1960 CMP AL,',' +0E7A 8A C6 1961 MOV AL,DH +0E7C 75 E5 1962 JNZ ONEJ +0E7E 52 1963 PUSH DX +0E7F E8 46 F5 1964 CALL GETOP +0E82 2C 02 1965 SUB AL,REG +0E84 B1 14 1966 MOV CL,20 +0E86 FE CA 1967 DEC DL +0E88 0A C2 1968 OR AL,DL +0E8A 75 32 1969 JNZ ERR8 +0E8C 5A 1970 POP DX +0E8D 8A C6 1971 MOV AL,DH +0E8F 59 1972 POP CX +0E90 80 CD 02 1973 OR CH,002H +0E93 51 1974 PUSH CX +0E94 E9 60 FF 1975 JMP ONE +0E97 1976 GRP13: +0E97 8A E8 1977 MOV CH,AL +0E99 B1 01 1978 MOV CL,1 +0E9B E8 4E F4 1979 CALL MROPS +0E9E B1 80 1980 MOV CL,80H +0EA0 1981 ACCIMM: +0EA0 E8 BA FC 1982 CALL IMMED +0EA3 80 CD 04 1983 OR CH,004H +0EA6 80 E5 FD 1984 AND CH,0FDH +0EA9 1985 AIMM: +0EA9 8A C7 1986 MOV AL,BH +0EAB 24 01 1987 AND AL,1 +0EAD 9F 1988 LAHF +0EAE 50 1989 PUSH AX +0EAF 0A C5 1990 OR AL,CH +0EB1 E8 E8 FC 1991 CALL PUT +0EB4 58 1992 POP AX +0EB5 9E 1993 SAHF +0EB6 75 03 1994 JNZ $+5 +0EB8 E9 37 FD 1995 JMP PUTBYT +0EBB E9 2D FD 1996 JMP PUTWOR +0EBE 1997 +0EBE E9 F0 F3 1998 ERR8: JMP ERROR +0EC1 1999 +0EC1 2000 GRP14: +0EC1 2001 ;JMP and CALL mnemonics +0EC1 9F 2002 LAHF +0EC2 86 E0 2003 XCHG AH,AL +0EC4 50 2004 PUSH AX +0EC5 86 E0 2005 XCHG AH,AL +0EC7 C6 06 D1 20 03 2006 MOV B,[MAXFLG],3 ;Allow "L" flag +0ECC E8 F9 F4 2007 CALL GETOP +0ECF 3C 01 2008 CMP AL,CONST +0ED1 74 33 2009 JZ DIRECT +0ED3 B1 14 2010 MOV CL,20 +0ED5 3C 02 2011 CMP AL,REG +0ED7 74 E5 2012 JZ ERR8 +0ED9 3C 04 2013 CMP AL,SREG +0EDB 74 E1 2014 JZ ERR8 +0EDD 3C 03 2015 CMP AL,XREG +0EDF 75 03 2016 JNZ NOTRG +0EE1 80 CA C0 2017 OR DL,0C0H +0EE4 2018 NOTRG: +0EE4 2019 ;Indirect jump. DL has addressing mode. +0EE4 B0 FF 2020 MOV AL,0FFH +0EE6 E8 B3 FC 2021 CALL PUT +0EE9 58 2022 POP AX +0EEA 86 E0 2023 XCHG AH,AL +0EEC 9E 2024 SAHF +0EED 24 38 2025 AND AL,38H +0EEF 0A C2 2026 OR AL,DL +0EF1 8A 2E D0 20 2027 MOV CH,[FLAG] +0EF5 82 FD 03 2028 CMP CH,3 ;Flag "L" present? +0EF8 74 09 2029 JZ PUTADDJ ;If so, do inter-segment +0EFA B1 27 2030 MOV CL,27H +0EFC 82 FD FF 2031 CMP CH,-1 ;Better not be a flag +0EFF 75 BD 2032 JNZ ERR8 +0F01 24 F7 2033 AND AL,0F7H ;Convert to intra-segment +0F03 2034 PUTADDJ: +0F03 E9 56 FD 2035 JMP PUTADD +0F06 2036 DIRECT: +0F06 A0 30 21 2037 MOV AL,[SYM] +0F09 3C 2C 2038 CMP AL,',' +0F0B 74 1C 2039 JZ LONGJ +0F0D 58 2040 POP AX +0F0E 86 E0 2041 XCHG AH,AL +0F10 9E 2042 SAHF +0F11 FE C8 2043 DEC AL +0F13 3C E9 2044 CMP AL,0E9H +0F15 74 02 2045 JZ GOTOP +0F17 B0 E8 2046 MOV AL,0E8H +0F19 2047 GOTOP: +0F19 E8 80 FC 2048 CALL PUT +0F1C 8B 16 CA 20 2049 MOV DX,[PC] +0F20 42 2050 INC DX +0F21 42 2051 INC DX +0F22 29 16 D6 20 2052 SUB [DATA],DX +0F26 E9 C2 FC 2053 JMP PUTWOR +0F29 2054 LONGJ: +0F29 58 2055 POP AX +0F2A 86 E0 2056 XCHG AH,AL +0F2C 9E 2057 SAHF +0F2D E8 6C FC 2058 CALL PUT +0F30 E8 B8 FC 2059 CALL PUTWOR +0F33 E8 92 F4 2060 CALL GETOP +0F36 B1 14 2061 MOV CL,20 +0F38 3C 01 2062 CMP AL,CONST +0F3A 75 82 2063 JNZ ERR8 +0F3C E9 AC FC 2064 JMP PUTWOR +0F3F 2065 +0F3F 2066 GRP16: +0F3F 2067 ;RET mnemonic +0F3F 9F 2068 LAHF +0F40 86 E0 2069 XCHG AH,AL +0F42 50 2070 PUSH AX +0F43 86 E0 2071 XCHG AH,AL +0F45 E8 BA F6 2072 CALL GETSYM +0F48 3C 05 2073 CMP AL,5 +0F4A 74 1C 2074 JZ LONGR +0F4C 3C 0D 2075 CMP AL,EOL +0F4E 74 3F 2076 JZ NODEC +0F50 3C 3B 2077 CMP AL,';' +0F52 74 3B 2078 JZ NODEC +0F54 2079 GETSP: +0F54 E8 74 F4 2080 CALL GETOP1 +0F57 59 2081 POP CX +0F58 3C 01 2082 CMP AL,CONST +0F5A B1 14 2083 MOV CL,20 +0F5C 75 63 2084 JNZ ERR9 +0F5E 8A C5 2085 MOV AL,CH +0F60 24 FE 2086 AND AL,0FEH +0F62 E8 37 FC 2087 CALL PUT +0F65 E9 83 FC 2088 JMP PUTWOR +0F68 2089 LONGR: +0F68 82 FA 03 2090 CMP DL,3 ;Is flag "L"? +0F6B B1 27 2091 MOV CL,27H +0F6D 75 7D 2092 JNZ ERR10 ;If not, bad flag +0F6F 58 2093 POP AX +0F70 86 E0 2094 XCHG AH,AL +0F72 9E 2095 SAHF +0F73 0C 08 2096 OR AL,8 +0F75 9F 2097 LAHF +0F76 86 E0 2098 XCHG AH,AL +0F78 50 2099 PUSH AX +0F79 86 E0 2100 XCHG AH,AL +0F7B 2101 NOTLON: +0F7B E8 84 F6 2102 CALL GETSYM +0F7E 3C 0D 2103 CMP AL,EOL +0F80 74 2E 2104 JZ DORET +0F82 3C 3B 2105 CMP AL,';' +0F84 74 2A 2106 JZ DORET +0F86 3C 2C 2107 CMP AL,',' +0F88 75 03 2108 JNZ L0011 +0F8A E8 75 F6 2109 CALL GETSYM +0F8D 2110 L0011: +0F8D EB C5 2111 JP GETSP +0F8F 2112 NODEC: +0F8F 2113 ;Return is intra-segment (short) without add to SP. +0F8F 2114 ;Record position for RET symbol. +0F8F 8B 1E CA 20 2115 MOV BX,[PC] +0F93 89 1E 4E 21 2116 MOV [LSTRET],BX +0F97 87 DA 2117 XCHG DX,BX +0F99 8B 1E 50 21 2118 MOV BX,[RETPT] +0F9D 8A C7 2119 MOV AL,BH +0F9F 0A C3 2120 OR AL,BL +0FA1 74 0D 2121 JZ DORET +0FA3 C6 07 01 2122 MOV B,[BX],1 +0FA6 43 2123 INC BX +0FA7 89 17 2124 MOV [BX],DX +0FA9 BB 00 00 2125 MOV BX,0 +0FAC 89 1E 50 21 2126 MOV [RETPT],BX +0FB0 2127 DORET: +0FB0 58 2128 POP AX +0FB1 86 E0 2129 XCHG AH,AL +0FB3 9E 2130 SAHF +0FB4 E9 E5 FB 2131 JMP PUT +0FB7 2132 +0FB7 2133 GRP17: +0FB7 E8 E2 FB 2134 CALL PUT +0FBA E8 0B F4 2135 CALL GETOP +0FBD 3C 01 2136 CMP AL,CONST +0FBF B1 14 2137 MOV CL,20 +0FC1 75 29 2138 ERR9: JNZ ERR10 +0FC3 8B 1E D6 20 2139 MOV BX,[DATA] +0FC7 8B 16 CA 20 2140 MOV DX,[PC] +0FCB 42 2141 INC DX +0FCC 2B DA 2142 SUB BX,DX +0FCE 89 1E D6 20 2143 MOV [DATA],BX +0FD2 E8 1D FC 2144 CALL PUTBYT +0FD5 8B 1E D8 20 2145 MOV BX,[DLABEL] +0FD9 8A C7 2146 MOV AL,BH +0FDB 0A C3 2147 OR AL,BL +0FDD 75 10 2148 JNZ RET +0FDF 8B 1E D6 20 2149 MOV BX,[DATA] +0FE3 8A C3 2150 MOV AL,BL +0FE5 98 2151 CBW +0FE6 3B C3 2152 CMP AX,BX ;Signed 8-bit number? +0FE8 74 05 2153 JZ RET +0FEA B1 1F 2154 MOV CL,31 +0FEC E9 C2 F2 2155 ERR10: JMP ERROR +0FEF C3 2156 RET +0FF0 2157 GRP18: +0FF0 E8 D5 F3 2158 CALL GETOP +0FF3 3C 01 2159 CMP AL,CONST +0FF5 B1 14 2160 MOV CL,20 +0FF7 75 F3 2161 JNZ ERR10 +0FF9 8B 1E D8 20 2162 MOV BX,[DLABEL] +0FFD 8A C7 2163 MOV AL,BH +0FFF 0A C3 2164 OR AL,BL +1001 75 10 2165 JNZ GENINT +1003 8B 1E D6 20 2166 MOV BX,[DATA] +1007 BA 03 00 2167 MOV DX,3 +100A 1B DA 2168 SBB BX,DX +100C 75 05 2169 JNZ GENINT +100E B0 CC 2170 MOV AL,0CCH +1010 E9 89 FB 2171 JMP PUT +1013 2172 GENINT: +1013 B0 CD 2173 MOV AL,0CDH +1015 E8 84 FB 2174 CALL PUT +1018 E9 D7 FB 2175 JMP PUTBYT +101B 2176 +101B 2177 GRP19: ;ESC opcode +101B E8 AA F3 2178 CALL GETOP +101E B1 14 2179 MOV CL,20 +1020 3C 01 2180 CMP AL,CONST +1022 75 39 2181 JNZ ERRJ ;First operand must be immediate +1024 B1 1E 2182 MOV CL,1EH +1026 F7 06 D8 20 FF FF 2183 TEST [DLABEL],-1 ;See if all labels have been defined +102C 75 2F 2184 JNZ ERRJ +102E A1 D6 20 2185 MOV AX,[DATA] +1031 3D 40 00 2186 CMP AX,64 ;Must only be 6 bits +1034 B1 1F 2187 MOV CL,1FH +1036 73 25 2188 JNB ERRJ +1038 8A D8 2189 MOV BL,AL ;Save for second byte +103A D0 E8 2190 SHR AL +103C D0 E8 2191 SHR AL +103E D0 E8 2192 SHR AL +1040 0C D8 2193 OR AL,0D8H ;ESC opcode +1042 E8 57 FB 2194 CALL PUT +1045 53 2195 PUSH BX +1046 E8 76 F3 2196 CALL GETOP2 +1049 5B 2197 POP BX +104A 80 E3 07 2198 AND BL,7 ;Low 3 bits of first operand +104D D0 E3 2199 SHL BL +104F D0 E3 2200 SHL BL +1051 D0 E3 2201 SHL BL +1053 3C 00 2202 CMP AL,UNDEFID ;Check for memory operand +1055 74 09 2203 JZ ESCMEM +1057 3C 01 2204 CMP AL,CONST ;Check for another immediate +1059 74 0C 2205 JZ ESCIMM +105B B1 14 2206 MOV CL,20 +105D E9 51 F2 2207 ERRJ: JMP ERROR +1060 2208 +1060 2209 ESCMEM: +1060 0A DA 2210 OR BL,DL ;Combine mode with first operand +1062 8A C3 2211 MOV AL,BL +1064 E9 F5 FB 2212 JMP PUTADD +1067 2213 +1067 2214 ESCIMM: +1067 B1 1E 2215 MOV CL,1EH +1069 F7 06 D8 20 FF FF 2216 TEST [DLABEL],-1 ;See if second operand is fully defined +106F 75 EC 2217 JNZ ERRJ +1071 A1 D6 20 2218 MOV AX,[DATA] +1074 B1 1F 2219 MOV CL,1FH +1076 3D 08 00 2220 CMP AX,8 ;Must only be 3 bit value +1079 73 E2 2221 JNB ERRJ +107B 0A C3 2222 OR AL,BL ;Combine first and second operands +107D 0C C0 2223 OR AL,0C0H ;Force "register" mode +107F E9 1A FB 2224 JMP PUT +1082 2225 +1082 2226 GRP20: +1082 8A E8 2227 MOV CH,AL +1084 B1 01 2228 MOV CL,1 +1086 E8 63 F2 2229 CALL MROPS +1089 B1 F6 2230 MOV CL,0F6H +108B E8 CF FA 2231 CALL IMMED +108E B5 A8 2232 MOV CH,0A8H +1090 E9 16 FE 2233 JMP AIMM +1093 2234 GRP21: +1093 E8 32 F3 2235 CALL GETOP +1096 3C 04 2236 CMP AL,SREG +1098 B1 1C 2237 MOV CL,28 +109A 75 C1 2238 JNZ ERRJ +109C B5 26 2239 MOV CH,26H +109E 2240 PACKREG: +109E 8A C2 2241 MOV AL,DL +10A0 02 C0 2242 ADD AL,AL +10A2 02 C0 2243 ADD AL,AL +10A4 02 C0 2244 ADD AL,AL +10A6 0A C5 2245 OR AL,CH +10A8 E9 F1 FA 2246 JMP PUT +10AB 2247 GRP22: +10AB E8 1A F3 2248 CALL GETOP +10AE B9 00 8F 2249 MOV CX,8F00H +10B1 3C 00 2250 CMP AL,UNDEFID +10B3 75 03 2251 JNZ $+5 +10B5 E9 EA FB 2252 JMP PMEM +10B8 B5 58 2253 MOV CH,58H +10BA 3C 03 2254 CMP AL,XREG +10BC 75 03 2255 JNZ $+5 +10BE E9 ED FB 2256 JMP PXREG +10C1 B5 07 2257 MOV CH,7 +10C3 3C 04 2258 CMP AL,SREG +10C5 74 D7 2259 JZ PACKREG +10C7 B1 14 2260 MOV CL,20 +10C9 E9 E5 F1 2261 ERR11: JMP ERROR +10CC 2262 GRP23: +10CC A2 39 21 2263 MOV [DATSIZ],AL +10CF 2264 GETDAT: +10CF E8 30 F5 2265 CALL GETSYM +10D2 B0 02 2266 MOV AL,2 +10D4 E8 0A F3 2267 CALL VAL1 +10D7 A0 30 21 2268 MOV AL,[SYM] +10DA 3C 2C 2269 CMP AL,',' +10DC A0 39 21 2270 MOV AL,[DATSIZ] +10DF 75 05 2271 JNZ ENDDAT +10E1 E8 13 00 2272 CALL SAVDAT +10E4 EB E9 2273 JP GETDAT +10E6 2274 ENDDAT: +10E6 3C 02 2275 CMP AL,2 +10E8 75 0D 2276 JNZ SAVDAT +10EA 8B 1E D6 20 2277 MOV BX,[DATA] +10EE 9F 2278 LAHF +10EF 80 CB 80 2279 OR BL,080H +10F2 9E 2280 SAHF +10F3 89 1E D6 20 2281 MOV [DATA],BX +10F7 2282 SAVDAT: +10F7 0A C0 2283 OR AL,AL +10F9 74 03 2284 JZ $+5 +10FB E9 F4 FA 2285 JMP PUTBYT +10FE E9 EA FA 2286 JMP PUTWOR +1101 2287 IF: +1101 0B DB 2288 OR BX,BX +1103 74 05 2289 JZ SKIPCD +1105 FE 06 4A 21 2290 INC B,[IFFLG] +1109 C3 2291 RET +110A 2292 +110A 2293 SKIPCD: +110A FE 06 4B 21 2294 INC B,[CHKLAB] +110E 2295 SKIPLP: +110E 32 C0 2296 XOR AL,AL +1110 E8 48 F1 2297 CALL NEXLIN +1113 E8 A0 F1 2298 CALL NEXTCHR +1116 3C 1A 2299 CMP AL,1AH +1118 74 40 2300 JZ END +111A E8 E5 F7 2301 CALL GETLAB +111D 72 EF 2302 JC SKIPLP +111F BF DE 20 2303 MOV DI,LENID +1122 BE 74 20 2304 MOV SI,IFEND +1125 B5 00 2305 MOV CH,0 +1127 8A 0D 2306 MOV CL,[DI] +1129 FE C1 2307 INC CL +112B F3 2308 REPE +112C A6 2309 CMPB +112D 74 14 2310 JZ ENDCOND +112F BF DE 20 2311 MOV DI,LENID +1132 BE 7A 20 2312 MOV SI,IFNEST +1135 8A 0D 2313 MOV CL,[DI] +1137 FE C1 2314 INC CL +1139 F3 2315 REPE +113A A6 2316 CMPB +113B 75 D1 2317 JNZ SKIPLP +113D FE 06 4B 21 2318 INC B,[CHKLAB] +1141 EB CB 2319 JP SKIPLP +1143 2320 +1143 2321 ENDCOND: +1143 FE 0E 4B 21 2322 DEC B,[CHKLAB] +1147 75 C5 2323 JNZ SKIPLP +1149 C3 2324 RET +114A 2325 +114A 2326 ENDIF: +114A A0 4A 21 2327 MOV AL,[IFFLG] +114D B1 24 2328 MOV CL,36 +114F FE C8 2329 DEC AL +1151 78 04 2330 JS ERRJMP +1153 A2 4A 21 2331 MOV [IFFLG],AL +1156 C3 2332 RET +1157 2333 +1157 E9 57 F1 2334 ERRJMP: JMP ERROR +115A 2335 +115A 2336 ;********************************************************************* +115A 2337 ; +115A 2338 ; PASS 2 +115A 2339 ; +115A 2340 ;********************************************************************* +115A 2341 +115A 2342 END: +115A B2 04 2343 MOV DL,4 +115C 2344 WREND: +115C B5 FF 2345 MOV CH,0FFH +115E 8A C5 2346 MOV AL,CH +1160 E8 43 FA 2347 CALL GEN +1163 FE CA 2348 DEC DL +1165 75 F5 2349 JNZ WREND +1167 C7 06 A4 25 A6 25 2350 MOV [BUFPT],SRCBUF +116D C6 06 46 21 FB 2351 MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY +1172 C7 06 5C 21 A4 21 2352 MOV [LSTPNT],LSTBUF +1178 C7 06 5A 21 5E 21 2353 MOV [HEXPNT],HEXBUF +117E 33 C0 2354 XOR AX,AX +1180 A3 4C 21 2355 MOV [ERRCNT],AX +1183 A3 CA 20 2356 MOV [PC],AX +1186 A3 3E 21 2357 MOV [LINE],AX ;Current line number +1189 C7 06 42 21 00 01 2358 MOV [HEXADD],OBJECT +118F BA 5C 00 2359 MOV DX,FCB +1192 B4 0F 2360 MOV AH,OPEN +1194 CD 21 2361 INT 33 ;Re-open source file +1196 33 C0 2362 XOR AX,AX +1198 A3 68 00 2363 MOV [FCB+12],AX ;Set CURRENT BLOCK to zero +119B A2 7C 00 2364 MOV [FCB+20H],AL ;Set NEXT RECORD field to zero +119E C7 06 6A 00 00 04 2365 MOV [FCB+14],BUFSIZ +11A4 A2 3C 21 2366 MOV [COUNT],AL +11A7 B5 01 2367 MOV CH,1 +11A9 BE A6 2A 2368 MOV SI,START +11AC 2369 FIXLINE: +11AC BF A6 2A 2370 MOV DI,START ;Store code over used up intermediate code +11AF 32 C0 2371 XOR AL,AL +11B1 A2 54 21 2372 MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) +11B4 A2 3D 21 2373 MOV [ERR],AL ;No second pass errors yet +11B7 2374 NEXBT: +11B7 D0 E1 2375 SHL CL ;Shift out last bit of previous code +11B9 FE CD 2376 DEC CH ;Still have codes left? +11BB 75 05 2377 JNZ TESTTYP +11BD AC 2378 LODB ;Get next flag byte +11BE 8A C8 2379 MOV CL,AL +11C0 B5 04 2380 MOV CH,4 +11C2 2381 TESTTYP: +11C2 D0 E1 2382 SHL CL ;Set flags based on two bits +11C4 70 06 2383 JO FIXUP +11C6 AC 2384 LODB +11C7 72 4E 2385 JC EMARK +11C9 2386 OBJBT: +11C9 AA 2387 STOB +11CA EB EB 2388 JP NEXBT +11CC 2389 +11CC 2390 FIXUP: +11CC 2391 ;Either a word or byte fixup is needed from a forward reference +11CC AD 2392 LODW ;Get pointer to symbol +11CD 93 2393 XCHG AX,BX +11CE AD 2394 LODW ;Get constant part +11CF 03 47 01 2395 ADD AX,[BX+1] ;Add symbol value to constant part +11D2 82 3F 00 2396 CMP B,[BX],0 ;See if symbol got defined +11D5 75 07 2397 JNZ HAVDEF +11D7 C6 06 3D 21 64 2398 MOV B,[ERR],100 ;Undefined - flag error +11DC 33 C0 2399 XOR AX,AX +11DE 2400 HAVDEF: +11DE 0A C9 2401 OR CL,CL ;See if word or byte fixup +11E0 78 03 2402 JS DEFBYT +11E2 AB 2403 STOW +11E3 EB D2 2404 JP NEXBT +11E5 2405 +11E5 2406 DEFBYT: +11E5 8B D0 2407 MOV DX,AX +11E7 98 2408 CBW ;Extend sign +11E8 3B C2 2409 CMP AX,DX ;See if in range +127 to -128 +11EA 74 DD 2410 JZ OBJBT ;If so, it's always OK +11EC F6 D4 2411 NOT AH ;Check for range +255 to -256 +11EE 3A E6 2412 CMP AH,DH +11F0 75 1B 2413 JNZ RNGERR ;Must always be in this range +11F2 2414 ;Check for short jump. If so, we're out of range; otherwise we're OK +11F2 81 FF A7 2A 2415 CMP DI,START+1 ;Only one other byte on line? +11F6 75 D1 2416 JNZ OBJBT ;Can't be short jump if not +11F8 A0 A6 2A 2417 MOV AL,[START] ;Get the first byte of this line +11FB 3C EB 2418 CMP AL,0EBH ;Direct short jump? +11FD 74 0E 2419 JZ RNGERR +11FF 24 FC 2420 AND AL,0FCH +1201 3C E0 2421 CMP AL,0E0H ;LOOP or JCXZ instruction? +1203 74 08 2422 JZ RNGERR +1205 24 F0 2423 AND AL,0F0H +1207 3C 70 2424 CMP AL,70H ;Conditional jump? +1209 8A C2 2425 MOV AL,DL ;Get code byte in AL +120B 75 BC 2426 JNZ OBJBT ;If not, we're OK +120D 2427 RNGERR: +120D C6 06 3D 21 65 2428 MOV B,[ERR],101 ;Value out of range +1212 EB B5 2429 JP OBJBT +1214 2430 +1214 E9 7A 01 2431 FINIJ: JMP FINI +1217 2432 +1217 2433 EMARK: +1217 3C FF 2434 CMP AL,-1 ;End of file? +1219 74 F9 2435 JZ FINIJ +121B 3C F6 2436 CMP AL,-10 ;Special item? +121D 77 5C 2437 JA SPEND +121F 51 2438 PUSH CX +1220 56 2439 PUSH SI +1221 50 2440 PUSH AX ;Save error code +1222 8A 26 52 21 2441 MOV AH,[LSTDEV] +1226 80 E4 FE 2442 AND AH,0FEH ;Reset error indicator +1229 0A 06 3D 21 2443 OR AL,[ERR] ;See if any errors on this line +122D 74 03 2444 JZ NOERR +122F 80 CC 01 2445 OR AH,1 ;Send line to console if error occured +1232 2446 NOERR: +1232 88 26 52 21 2447 MOV [LSTDEV],AH +1236 8B CF 2448 MOV CX,DI +1238 E8 EE 00 2449 CALL STRTLIN ;Print address of line +123B BE A6 2A 2450 MOV SI,START +123E 2B CE 2451 SUB CX,SI ;Get count of bytes of code +1240 74 06 2452 JZ SHOLIN +1242 2453 CODLP: +1242 AC 2454 LODB +1243 E8 59 02 2455 CALL SAVCD ;Ouput code to HEX and PRN files +1246 E2 FA 2456 LOOP CODLP +1248 2457 SHOLIN: +1248 B0 00 2458 MOV AL,0 +124A 86 06 3C 21 2459 XCHG AL,[COUNT] +124E B9 07 00 2460 MOV CX,7 ;Allow 7 bytes of code per line +1251 2A C8 2461 SUB CL,AL +1253 B0 20 2462 MOV AL,' ' +1255 74 0B 2463 JZ NOFIL +1257 2464 BLNK: ;Put in 3 blanks for each byte not present +1257 E8 E4 00 2465 CALL LIST +125A E8 E1 00 2466 CALL LIST +125D E8 DE 00 2467 CALL LIST +1260 E2 F5 2468 LOOP BLNK +1262 2469 NOFIL: +1262 E8 45 00 2470 CALL OUTLIN +1265 58 2471 POP AX ;Restore error code +1266 E8 6C 02 2472 CALL REPERR +1269 A0 3D 21 2473 MOV AL,[ERR] +126C E8 66 02 2474 CALL REPERR +126F 5E 2475 POP SI +1270 59 2476 POP CX +1271 A0 54 21 2477 MOV AL,[SPC] ;Any special funtion? +1274 0A C0 2478 OR AL,AL +1276 75 0D 2479 JNZ SPCFUN +1278 E9 31 FF 2480 JMP FIXLINE +127B 2481 +127B 2482 SPEND: +127B A2 54 21 2483 MOV [SPC],AL ;Record special function +127E AD 2484 LODW ;Get it's data +127F A3 D6 20 2485 MOV [DATA],AX +1282 E9 32 FF 2486 JMP NEXBT +1285 2487 +1285 2488 SPCFUN: +1285 8B 16 D6 20 2489 MOV DX,[DATA] +1289 3C FE 2490 CMP AL,-2 +128B 74 0F 2491 JZ DORG +128D 3C FD 2492 CMP AL,-3 +128F 74 12 2493 JZ DPUT +1291 2494 DDS: +1291 2495 ;Handle DS pseudo-op +1291 01 16 CA 20 2496 ADD [PC],DX +1295 01 16 42 21 2497 ADD [HEXADD],DX +1299 E9 10 FF 2498 JMP FIXLINE +129C 2499 +129C 2500 DORG: +129C 2501 ;Handle ORG pseudo-op +129C 89 16 CA 20 2502 MOV [PC],DX +12A0 E9 09 FF 2503 JMP FIXLINE +12A3 2504 +12A3 2505 DPUT: +12A3 2506 ;Handle PUT pseudo-op +12A3 89 16 42 21 2507 MOV [HEXADD],DX +12A7 E9 02 FF 2508 JMP FIXLINE +12AA 2509 +12AA 2510 OUTLIN: +12AA 2511 ;Copy the source line to the ouput device. Line will be preceded by +12AA 2512 ;assembler-generated line number. This routine may be called several times +12AA 2513 ;on one line (once for each line of object code bytes), so it sets a flag +12AA 2514 ;so the line will only be output on the first call. +12AA B0 FF 2515 MOV AL,-1 +12AC 86 06 48 21 2516 XCHG AL,[LINFLG] +12B0 0A C0 2517 OR AL,AL +12B2 75 33 2518 JNZ CRLF ;Output line only if first time +12B4 A1 3E 21 2519 MOV AX,[LINE] +12B7 40 2520 INC AX +12B8 A3 3E 21 2521 MOV [LINE],AX +12BB B7 00 2522 MOV BH,0 ;No leading zero suppression +12BD E8 30 00 2523 CALL OUT10 +12C0 B0 20 2524 MOV AL," " +12C2 E8 79 00 2525 CALL LIST +12C5 A0 A5 20 2526 MOV AL,[LSTFCB] +12C8 3C 5A 2527 CMP AL,'Z' +12CA 74 1B 2528 JZ CRLF ;Don't call NEXTCHR if listing suppressed +12CC 56 2529 PUSH SI ;Save the only register destroyed by NEXTCHR +12CD 2530 OUTLN: +12CD E8 E6 EF 2531 CALL NEXTCHR +12D0 E8 6B 00 2532 CALL LIST +12D3 3C 0A 2533 CMP AL,10 ;Output until linefeed found +12D5 75 F6 2534 JNZ OUTLN +12D7 5E 2535 POP SI +12D8 C3 2536 RET +12D9 2537 +12D9 2538 PRTCNT: +12D9 BB 4C 20 2539 MOV BX,ERCNTM +12DC E8 25 02 2540 CALL PRINT +12DF A1 4C 21 2541 MOV AX,[ERRCNT] +12E2 B7 10 2542 MOV BH,"0"-" " ;Enable leading zero suppression +12E4 E8 09 00 2543 CALL OUT10 +12E7 2544 CRLF: +12E7 B0 0D 2545 MOV AL,13 +12E9 E8 52 00 2546 CALL LIST +12EC B0 0A 2547 MOV AL,10 +12EE EB 4E 2548 JP LIST +12F0 2549 +12F0 2550 OUT10: +12F0 33 D2 2551 XOR DX,DX +12F2 BF 10 27 2552 MOV DI,10000 +12F5 F7 F7 2553 DIV AX,DI +12F7 0A C0 2554 OR AL,AL ;>10,000? +12F9 75 02 2555 JNZ LEAD +12FB 2C 10 2556 SUB AL,"0"-" " ;Convert leading zero to blank +12FD 2557 LEAD: +12FD 04 30 2558 ADD AL,"0" +12FF E8 3C 00 2559 CALL LIST +1302 92 2560 XCHG AX,DX +1303 B3 64 2561 MOV BL,100 +1305 F6 F3 2562 DIV AL,BL +1307 8A DC 2563 MOV BL,AH +1309 E8 0C 00 2564 CALL HIDIG ;Convert to decimal and print 1000s digit +130C E8 0E 00 2565 CALL DIGIT ;Print 100s digit +130F 8A C3 2566 MOV AL,BL +1311 E8 04 00 2567 CALL HIDIG ;Convert to decimal and print 10s digit +1314 B7 00 2568 MOV BH,0 ;Ensure leading zero suppression is off +1316 EB 05 2569 JP DIGIT +1318 2570 +1318 2571 HIDIG: +1318 D4 0A 2572 AAM ;Convert binary to unpacked BCD +131A 0D 30 30 2573 OR AX,3030H ;Add "0" bias +131D 2574 DIGIT: +131D 86 C4 2575 XCHG AL,AH +131F 3C 30 2576 CMP AL,"0" +1321 74 02 2577 JZ SUPZ +1323 B7 00 2578 MOV BH,0 ;Turn off zero suppression if not zero +1325 2579 SUPZ: +1325 2A C7 2580 SUB AL,BH ;Convert leading zeros to blanks +1327 EB 15 2581 JP LIST +1329 2582 +1329 2583 STRTLIN: +1329 C6 06 48 21 00 2584 MOV B,[LINFLG],0 +132E 8B 1E CA 20 2585 MOV BX,[PC] +1332 8A C7 2586 MOV AL,BH +1334 E8 4D 00 2587 CALL PHEX +1337 8A C3 2588 MOV AL,BL +1339 2589 PHEXB: +1339 E8 48 00 2590 CALL PHEX +133C B0 20 2591 MOV AL,' ' +133E 2592 LIST: +133E 50 2593 PUSH AX +133F 52 2594 PUSH DX +1340 24 7F 2595 AND AL,7FH +1342 8A D0 2596 MOV DL,AL +1344 F6 06 52 21 03 2597 TEST B,[LSTDEV],3 ;See if output goes to console +1349 74 04 2598 JZ PRNCHK +134B B4 02 2599 MOV AH,2 +134D CD 21 2600 INT 33 ;Output to console +134F 2601 PRNCHK: +134F F6 06 52 21 04 2602 TEST B,[LSTDEV],4 ;See if output goes to printer +1354 74 04 2603 JZ FILCHK +1356 B4 05 2604 MOV AH,5 +1358 CD 21 2605 INT 33 ;Output to printer +135A 2606 FILCHK: +135A 8A C2 2607 MOV AL,DL +135C 5A 2608 POP DX +135D F6 06 52 21 80 2609 TEST B,[LSTDEV],80H ;See if output goes to a file +1362 74 03 2610 JZ LISTRET +1364 E8 02 00 2611 CALL WRTBUF +1367 2612 LISTRET: +1367 58 2613 POP AX +1368 C3 2614 RET +1369 2615 +1369 2616 WRTBUF: +1369 57 2617 PUSH DI +136A 8B 3E 5C 21 2618 MOV DI,[LSTPNT] +136E AA 2619 STOB +136F 81 FF A4 25 2620 CMP DI,LSTBUF+LSTBUFSIZ +1373 75 09 2621 JNZ SAVPT +1375 50 2622 PUSH AX +1376 51 2623 PUSH CX +1377 52 2624 PUSH DX +1378 E8 61 02 2625 CALL FLUSHBUF +137B 5A 2626 POP DX +137C 59 2627 POP CX +137D 58 2628 POP AX +137E 2629 SAVPT: +137E 89 3E 5C 21 2630 MOV [LSTPNT],DI +1382 5F 2631 POP DI +1383 C3 2632 RET +1384 2633 +1384 2634 PHEX: +1384 50 2635 PUSH AX +1385 E8 74 02 2636 CALL UHALF +1388 E8 B3 FF 2637 CALL LIST +138B 58 2638 POP AX +138C E8 75 02 2639 CALL LHALF +138F EB AD 2640 JP LIST +1391 2641 +1391 2642 FINI: +1391 80 0E 52 21 01 2643 OR B,[LSTDEV],1 +1396 E8 40 FF 2644 CALL PRTCNT +1399 80 26 52 21 FE 2645 AND B,[LSTDEV],0FEH +139E A0 80 20 2646 MOV AL,[HEXFCB] +13A1 3C 5A 2647 CMP AL,'Z' +13A3 74 35 2648 JZ SYMDMP +13A5 A0 46 21 2649 MOV AL,[HEXCNT] +13A8 3C FB 2650 CMP AL,-5 +13AA 74 03 2651 JZ L0012 +13AC E8 DF 01 2652 CALL ENHEXL +13AF 2653 L0012: +13AF B0 3A 2654 MOV AL,':' +13B1 E8 1E 02 2655 CALL PUTCHR +13B4 B5 0A 2656 MOV CH,10 +13B6 2657 HEXEND: +13B6 51 2658 PUSH CX +13B7 B0 30 2659 MOV AL,'0' +13B9 E8 16 02 2660 CALL PUTCHR +13BC 59 2661 POP CX +13BD FE CD 2662 DEC CH +13BF 75 F5 2663 JNZ HEXEND +13C1 B0 0D 2664 MOV AL,13 +13C3 E8 0C 02 2665 CALL PUTCHR +13C6 B0 0A 2666 MOV AL,10 +13C8 E8 07 02 2667 CALL PUTCHR +13CB B0 1A 2668 MOV AL,1AH +13CD E8 02 02 2669 CALL PUTCHR +13D0 E8 E4 01 2670 CALL WRTHEX ;Flush HEX file buffer +13D3 BA 80 20 2671 MOV DX,HEXFCB +13D6 B4 10 2672 MOV AH,CLOSE +13D8 CD 21 2673 INT 33 +13DA 2674 SYMDMP: +13DA A0 35 21 2675 MOV AL,[SYMFLG] +13DD 3C 53 2676 CMP AL,'S' +13DF 75 2A 2677 JNZ ENDSYM +13E1 A0 52 21 2678 MOV AL,[LSTDEV] +13E4 0A C0 2679 OR AL,AL ;Any output device for symbol table dump? +13E6 75 05 2680 JNZ DOSYMTAB +13E8 0C 01 2681 OR AL,1 ;If not, send it to console +13EA A2 52 21 2682 MOV [LSTDEV],AL +13ED 2683 DOSYMTAB: +13ED BB 5D 20 2684 MOV BX,SYMMES +13F0 E8 11 01 2685 CALL PRINT +13F3 8B 16 31 21 2686 MOV DX,[BASE] +13F7 8A C6 2687 MOV AL,DH +13F9 0A C2 2688 OR AL,DL +13FB 74 0E 2689 JZ ENDSYM +13FD C6 06 36 21 05 2690 MOV B,[SYMLIN],SYMWID ;No symbols on this line yet +1402 8B 1E 33 21 2691 MOV BX,[HEAP] +1406 8B E3 2692 MOV SP,BX ;Need maximum stack for recursive tree walk +1408 E8 1A 00 2693 CALL NODE +140B 2694 ENDSYM: +140B F6 06 52 21 80 2695 TEST B,[LSTDEV],80H ;Print listing to file? +1410 74 10 2696 JZ EXIT +1412 B0 1A 2697 MOV AL,1AH +1414 E8 52 FF 2698 CALL WRTBUF ;Write end-of-file mark +1417 8B 3E 5C 21 2699 MOV DI,[LSTPNT] +141B E8 BE 01 2700 CALL FLUSHBUF +141E B4 10 2701 MOV AH,CLOSE +1420 CD 21 2702 INT 33 +1422 E9 DB EB 2703 EXIT: JMP 0 +1425 2704 +1425 2705 NODE: +1425 87 DA 2706 XCHG DX,BX +1427 53 2707 PUSH BX +1428 8A 17 2708 MOV DL,[BX] +142A B6 00 2709 MOV DH,0 +142C 43 2710 INC BX +142D 03 DA 2711 ADD BX,DX +142F 8B 17 2712 MOV DX,[BX] +1431 0B D2 2713 OR DX,DX +1433 74 03 2714 JZ L0014 +1435 E8 ED FF 2715 CALL NODE +1438 2716 L0014: +1438 5B 2717 POP BX +1439 8A 07 2718 MOV AL,[BX] +143B 43 2719 INC BX +143C 8A E8 2720 MOV CH,AL +143E 04 18 2721 ADD AL,24 +1440 D0 E8 2722 SHR AL +1442 D0 E8 2723 SHR AL +1444 D0 E8 2724 SHR AL +1446 8A C8 2725 MOV CL,AL +1448 FE C1 2726 INC CL ;Invert last bit +144A 80 E1 01 2727 AND CL,1 ;Number of extra tabs needed (0 or 1) +144D D0 E8 2728 SHR AL ;Number of positions wide this symbol needs +144F 28 06 36 21 2729 SUB [SYMLIN],AL +1453 73 0A 2730 JNC WRTSYM ;Will it fit? +1455 2C 05 2731 SUB AL,SYMWID +1457 F6 D8 2732 NEG AL +1459 A2 36 21 2733 MOV [SYMLIN],AL +145C E8 88 FE 2734 CALL CRLF ;Start new line if not +145F 2735 WRTSYM: +145F 8A 07 2736 MOV AL,[BX] +1461 43 2737 INC BX +1462 E8 D9 FE 2738 CALL LIST +1465 FE CD 2739 DEC CH +1467 75 F6 2740 JNZ WRTSYM +1469 FE C1 2741 INC CL +146B 2742 TABVAL: +146B B0 09 2743 MOV AL,9 +146D E8 CE FE 2744 CALL LIST +1470 E2 F9 2745 LOOP TABVAL +1472 43 2746 INC BX +1473 43 2747 INC BX +1474 53 2748 PUSH BX +1475 8A 47 04 2749 MOV AL,[BX+4] +1478 E8 09 FF 2750 CALL PHEX +147B 8A 47 03 2751 MOV AL,[BX+3] +147E E8 03 FF 2752 CALL PHEX +1481 82 3E 36 21 00 2753 CMP B,[SYMLIN],0 ;Will any more fit on line? +1486 74 07 2754 JZ NEXSYMLIN +1488 B0 09 2755 MOV AL,9 +148A E8 B1 FE 2756 CALL LIST +148D EB 08 2757 JP RIGHTSON +148F 2758 NEXSYMLIN: +148F E8 55 FE 2759 CALL CRLF +1492 C6 06 36 21 05 2760 MOV B,[SYMLIN],SYMWID +1497 2761 RIGHTSON: +1497 5B 2762 POP BX +1498 8B 17 2763 MOV DX,[BX] +149A 0B D2 2764 OR DX,DX +149C 75 87 2765 JNZ NODE +149E C3 2766 RET +149F 2767 +149F 2768 SAVCD: +149F A2 49 21 2769 MOV [PREV],AL +14A2 53 2770 PUSH BX +14A3 51 2771 PUSH CX +14A4 50 2772 PUSH AX +14A5 52 2773 PUSH DX +14A6 E8 72 00 2774 CALL CODBYT +14A9 5A 2775 POP DX +14AA BB 3C 21 2776 MOV BX,COUNT +14AD FE 07 2777 INC B,[BX] +14AF 8A 07 2778 MOV AL,[BX] +14B1 3C 08 2779 CMP AL,8 +14B3 75 11 2780 JNZ NOEXT +14B5 C6 07 01 2781 MOV B,[BX],1 +14B8 E8 EF FD 2782 CALL OUTLIN +14BB B0 20 2783 MOV AL,' ' +14BD B5 05 2784 MOV CH,5 +14BF 2785 TAB: +14BF E8 7C FE 2786 CALL LIST +14C2 FE CD 2787 DEC CH +14C4 75 F9 2788 JNZ TAB +14C6 2789 NOEXT: +14C6 58 2790 POP AX +14C7 E8 6F FE 2791 CALL PHEXB +14CA 59 2792 POP CX +14CB FF 06 CA 20 2793 INC [PC] +14CF FF 06 42 21 2794 INC [HEXADD] +14D3 5B 2795 POP BX +14D4 C3 2796 RET +14D5 2797 +14D5 2798 REPERR: +14D5 0A C0 2799 OR AL,AL ;Did an error occur? +14D7 74 FB 2800 JZ RET +14D9 FF 06 4C 21 2801 INC [ERRCNT] +14DD 50 2802 PUSH AX +14DE BB D6 1F 2803 MOV BX,ERRMES ;Print "ERROR" +14E1 E8 20 00 2804 CALL PRINT +14E4 58 2805 POP AX +14E5 2806 ;We have error number in AL. See if there's an error message for it +14E5 BF 08 1C 2807 MOV DI,ERRTAB +14E8 B3 80 2808 MOV BL,80H +14EA 2809 ERRLOOK: +14EA AE 2810 SCASB ;Do we have the error message +14EB 76 07 2811 JBE HAVMES ;Quit looking if we have it or passed it +14ED 93 2812 XCHG AX,BX ;Put 80H in AL to look for end of this message +14EE 2813 NEXTMES: +14EE AE 2814 SCASB ;Look for high bit set in message +14EF 77 FD 2815 JA NEXTMES ; which means we've reached the end +14F1 93 2816 XCHG AX,BX ;Restore error number to AL +14F2 EB F6 2817 JMPS ERRLOOK ;Keep looking +14F4 2818 +14F4 2819 HAVMES: +14F4 8B DF 2820 MOV BX,DI ;Put address of message in BX +14F6 74 06 2821 JZ PRNERR ;Do we have a message for this error? +14F8 E8 89 FE 2822 CALL PHEX ;If not, just print error number +14FB E9 E9 FD 2823 JMP CRLF +14FE 2824 +14FE 2825 PRNERR: +14FE E8 03 00 2826 CALL PRINT +1501 E9 E3 FD 2827 JMP CRLF +1504 2828 +1504 2829 PRINT: +1504 8A 07 2830 MOV AL,[BX] +1506 E8 35 FE 2831 CALL LIST +1509 0A C0 2832 OR AL,AL +150B 78 C7 2833 JS RET +150D 43 2834 INC BX +150E EB F4 2835 JP PRINT +1510 2836 +1510 2837 OUTA: +1510 8A D0 2838 MOV DL,AL +1512 2839 OUT: +1512 80 E2 7F 2840 AND DL,7FH +1515 B1 02 2841 MOV CL,2 +1517 2842 SYSTEM: +1517 E8 EB EA 2843 CALL 5 +151A C3 2844 RET +151B 2845 +151B 2846 CODBYT: +151B 82 3E 80 20 5A 2847 CMP B,[HEXFCB],"Z" +1520 74 F8 2848 JZ RET +1522 50 2849 PUSH AX +1523 8B 16 44 21 2850 MOV DX,[LASTAD] +1527 8B 1E 42 21 2851 MOV BX,[HEXADD] +152B 89 1E 44 21 2852 MOV [LASTAD],BX +152F 42 2853 INC DX +1530 A0 46 21 2854 MOV AL,[HEXCNT] +1533 3C FB 2855 CMP AL,-5 +1535 74 07 2856 JZ NEWLIN +1537 3B DA 2857 CMP BX,DX +1539 74 2E 2858 JZ AFHEX +153B E8 50 00 2859 CALL ENHEXL +153E 2860 NEWLIN: +153E B0 3A 2861 MOV AL,':' +1540 E8 8F 00 2862 CALL PUTCHR +1543 B0 FC 2863 MOV AL,-4 +1545 A2 46 21 2864 MOV [HEXCNT],AL +1548 32 C0 2865 XOR AL,AL +154A A2 47 21 2866 MOV [CHKSUM],AL +154D 8B 1E 5A 21 2867 MOV BX,[HEXPNT] +1551 89 1E 40 21 2868 MOV [HEXLEN],BX +1555 E8 12 00 2869 CALL HEXBYT +1558 A0 43 21 2870 MOV AL,[HEXADD+1] +155B E8 0C 00 2871 CALL HEXBYT +155E A0 42 21 2872 MOV AL,[HEXADD] +1561 E8 06 00 2873 CALL HEXBYT +1564 32 C0 2874 XOR AL,AL +1566 E8 01 00 2875 CALL HEXBYT +1569 2876 AFHEX: +1569 58 2877 POP AX +156A 2878 HEXBYT: +156A 8A E8 2879 MOV CH,AL +156C BB 47 21 2880 MOV BX,CHKSUM +156F 02 07 2881 ADD AL,[BX] +1571 88 07 2882 MOV [BX],AL +1573 8A C5 2883 MOV AL,CH +1575 E8 84 00 2884 CALL UHALF +1578 E8 57 00 2885 CALL PUTCHR +157B 8A C5 2886 MOV AL,CH +157D E8 84 00 2887 CALL LHALF +1580 E8 4F 00 2888 CALL PUTCHR +1583 BB 46 21 2889 MOV BX,HEXCNT +1586 FE 07 2890 INC B,[BX] +1588 8A 07 2891 MOV AL,[BX] +158A 3C 1A 2892 CMP AL,26 +158C 75 8C 2893 JNZ RET +158E 2894 ENHEXL: +158E 8B 3E 40 21 2895 MOV DI,[HEXLEN] +1592 8A E8 2896 MOV CH,AL +1594 E8 65 00 2897 CALL UHALF +1597 AA 2898 STOB +1598 8A C5 2899 MOV AL,CH +159A E8 67 00 2900 CALL LHALF +159D AA 2901 STOB +159E B0 FA 2902 MOV AL,-6 +15A0 A2 46 21 2903 MOV [HEXCNT],AL +15A3 A0 47 21 2904 MOV AL,[CHKSUM] +15A6 02 C5 2905 ADD AL,CH +15A8 F6 D8 2906 NEG AL +15AA E8 BD FF 2907 CALL HEXBYT +15AD B0 0D 2908 MOV AL,13 +15AF E8 20 00 2909 CALL PUTCHR +15B2 B0 0A 2910 MOV AL,10 +15B4 E8 1B 00 2911 CALL PUTCHR +15B7 2912 WRTHEX: +15B7 2913 ;Write out the line +15B7 BA 5E 21 2914 MOV DX,HEXBUF +15BA 89 16 5A 21 2915 MOV [HEXPNT],DX +15BE B4 1A 2916 MOV AH,SETDMA +15C0 CD 21 2917 INT 33 +15C2 2B FA 2918 SUB DI,DX ;Length of buffer +15C4 8B CF 2919 MOV CX,DI +15C6 BA 80 20 2920 MOV DX,HEXFCB +15C9 B4 28 2921 MOV AH,BLKWRT +15CB CD 21 2922 INT 33 +15CD 0A C0 2923 OR AL,AL +15CF 75 25 2924 JNZ DSKFUL +15D1 C3 2925 RET +15D2 2926 +15D2 2927 PUTCHR: +15D2 8B 3E 5A 21 2928 MOV DI,[HEXPNT] +15D6 AA 2929 STOB +15D7 89 3E 5A 21 2930 MOV [HEXPNT],DI +15DB C3 2931 RET +15DC 2932 +15DC 2933 FLUSHBUF: +15DC 8B CF 2934 MOV CX,DI +15DE BA A4 21 2935 MOV DX,LSTBUF +15E1 8B FA 2936 MOV DI,DX +15E3 2B CA 2937 SUB CX,DX +15E5 74 F4 2938 JZ RET ;Buffer empty? +15E7 B4 1A 2939 MOV AH,SETDMA +15E9 CD 21 2940 INT 33 +15EB BA A5 20 2941 MOV DX,LSTFCB +15EE B4 28 2942 MOV AH,BLKWRT +15F0 CD 21 2943 INT 33 +15F2 0A C0 2944 OR AL,AL +15F4 74 E5 2945 JZ RET +15F6 2946 DSKFUL: +15F6 BB 27 20 2947 MOV BX,WRTERR +15F9 E9 7A EC 2948 JMP PRERR +15FC 2949 +15FC 2950 UHALF: +15FC D0 D8 2951 RCR AL +15FE D0 D8 2952 RCR AL +1600 D0 D8 2953 RCR AL +1602 D0 D8 2954 RCR AL +1604 2955 LHALF: +1604 24 0F 2956 AND AL,0FH +1606 0C 30 2957 OR AL,30H +1608 3C 3A 2958 CMP AL,'9'+1 +160A 72 CF 2959 JC RET +160C 04 07 2960 ADD AL,7 +160E C3 2961 RET +160F 2962 +160F 00 2963 NONE: DB 0 +1610 2964 +1610 2965 ; 8086 MNEMONIC TABLE +1610 2966 +1610 2967 ; This table is actually a sequence of subtables, each starting with a label. +1610 2968 ; The label signifies which mnemonics the subtable applies to--A3, for example, +1610 2969 ; means all 3-letter mnemonics beginning with A. +1610 2970 +1610 2971 A3: +1610 07 2972 DB 7 +1611 64 64 2973 DB 'dd' +1613 C1 0D 2974 DW GRP7 +1615 02 2975 DB 2 +1616 6E 64 2976 DB 'nd' +1618 97 0E 2977 DW GRP13 +161A 22 2978 DB 22H +161B 64 63 2979 DB 'dc' +161D C1 0D 2980 DW GRP7 +161F 12 2981 DB 12H +1620 61 61 2982 DB 'aa' +1622 9C 0B 2983 DW PUT +1624 37 2984 DB 37H +1625 61 73 2985 DB 'as' +1627 9C 0B 2986 DW PUT +1629 3F 2987 DB 3FH +162A 61 6D 2988 DB 'am' +162C 65 0E 2989 DW GRP11 +162E D4 2990 DB 0D4H +162F 61 64 2991 DB 'ad' +1631 65 0E 2992 DW GRP11 +1633 D5 2993 DB 0D5H +1634 2994 A5: +1634 01 2995 DB 1 +1635 6C 69 67 6E 2996 DB 'lign' +1639 6D 0D 2997 DW ALIGN +163B 00 2998 DB 0 +163C 2999 C3: +163C 07 3000 DB 7 +163D 6D 70 3001 DB 'mp' +163F C1 0D 3002 DW GRP7 +1641 3A 3003 DB 3AH +1642 6C 63 3004 DB 'lc' +1644 9C 0B 3005 DW PUT +1646 F8 3006 DB 0F8H +1647 6C 64 3007 DB 'ld' +1649 9C 0B 3008 DW PUT +164B FC 3009 DB 0FCH +164C 6C 69 3010 DB 'li' +164E 9C 0B 3011 DW PUT +1650 FA 3012 DB 0FAH +1651 6D 63 3013 DB 'mc' +1653 9C 0B 3014 DW PUT +1655 F5 3015 DB 0F5H +1656 62 77 3016 DB 'bw' +1658 9C 0B 3017 DW PUT +165A 98 3018 DB 98H +165B 77 64 3019 DB 'wd' +165D 9C 0B 3020 DW PUT +165F 99 3021 DB 99H +1660 3022 C4: +1660 03 3023 DB 3 +1661 61 6C 6C 3024 DB 'all' +1664 C1 0E 3025 DW GRP14 +1666 9A 3026 DB 9AH +1667 6D 70 62 3027 DB 'mpb' +166A 9C 0B 3028 DW PUT +166C A6 3029 DB 0A6H +166D 6D 70 77 3030 DB 'mpw' +1670 9C 0B 3031 DW PUT +1672 A7 3032 DB 0A7H +1673 3033 C5: +1673 02 3034 DB 2 +1674 6D 70 73 62 3035 DB 'mpsb' +1678 9C 0B 3036 DW PUT +167A A6 3037 DB 0A6H +167B 6D 70 73 77 3038 DB 'mpsw' +167F 9C 0B 3039 DW PUT +1681 A7 3040 DB 0A7H +1682 3041 D2: +1682 05 3042 DB 5 +1683 62 3043 DB 'b' +1684 CC 10 3044 DW GRP23 +1686 01 3045 DB 1 +1687 77 3046 DB 'w' +1688 CC 10 3047 DW GRP23 +168A 00 3048 DB 0 +168B 6D 3049 DB 'm' +168C CC 10 3050 DW GRP23 +168E 02 3051 DB 2 +168F 73 3052 DB 's' +1690 3B 0D 3053 DW GRP5 +1692 01 3054 DB 1 +1693 69 3055 DB 'i' +1694 9C 0B 3056 DW PUT +1696 FA 3057 DB 0FAH +1697 3058 D3: +1697 04 3059 DB 4 +1698 65 63 3060 DB 'ec' +169A E9 0D 3061 DW GRP8 +169C 49 3062 DB 49H +169D 69 76 3063 DB 'iv' +169F 3D 0E 3064 DW GRP10 +16A1 30 3065 DB 30H +16A2 61 61 3066 DB 'aa' +16A4 9C 0B 3067 DW PUT +16A6 27 3068 DB 27H +16A7 61 73 3069 DB 'as' +16A9 9C 0B 3070 DW PUT +16AB 2F 3071 DB 2FH +16AC 3072 D4: +16AC 01 3073 DB 1 +16AD 6F 77 6E 3074 DB 'own' +16B0 9C 0B 3075 DW PUT +16B2 FD 3076 DB 0FDH +16B3 3077 E2: +16B3 01 3078 DB 1 +16B4 69 3079 DB 'i' +16B5 9C 0B 3080 DW PUT +16B7 FB 3081 DB 0FBH +16B8 3082 E3: +16B8 03 3083 DB 3 +16B9 71 75 3084 DB 'qu' +16BB 3B 0D 3085 DW GRP5 +16BD 02 3086 DB 2 +16BE 73 63 3087 DB 'sc' +16C0 1B 10 3088 DW GRP19 +16C2 D8 3089 DB 0D8H +16C3 6E 64 3090 DB 'nd' +16C5 5A 11 3091 DW END +16C7 00 3092 DB 0 +16C8 3093 E5: +16C8 01 3094 DB 1 +16C9 6E 64 69 66 3095 DB 'ndif' +16CD 4A 11 3096 DW ENDIF +16CF 00 3097 DB 0 +16D0 3098 H3: +16D0 01 3099 DB 1 +16D1 6C 74 3100 DB 'lt' +16D3 9C 0B 3101 DW PUT +16D5 F4 3102 DB 0F4H +16D6 3103 H4: +16D6 01 3104 DB 1 +16D7 61 6C 74 3105 DB 'alt' +16DA 9C 0B 3106 DW PUT +16DC F4 3107 DB 0F4H +16DD 3108 I2: +16DD 02 3109 DB 2 +16DE 6E 3110 DB 'n' +16DF 15 0D 3111 DW GRP4 +16E1 E4 3112 DB 0E4H +16E2 66 3113 DB 'f' +16E3 3B 0D 3114 DW GRP5 +16E5 04 3115 DB 4 +16E6 3116 I3: +16E6 04 3117 DB 4 +16E7 6E 63 3118 DB 'nc' +16E9 E9 0D 3119 DW GRP8 +16EB 41 3120 DB 41H +16EC 6E 62 3121 DB 'nb' +16EE 15 0D 3122 DW GRP4 +16F0 E4 3123 DB 0E4H +16F1 6E 77 3124 DB 'nw' +16F3 15 0D 3125 DW GRP4 +16F5 E5 3126 DB 0E5H +16F6 6E 74 3127 DB 'nt' +16F8 F0 0F 3128 DW GRP18 +16FA CC 3129 DB 0CCH +16FB 3130 I4: +16FB 04 3131 DB 4 +16FC 6D 75 6C 3132 DB 'mul' +16FF 3D 0E 3133 DW GRP10 +1701 28 3134 DB 28H +1702 64 69 76 3135 DB 'div' +1705 3D 0E 3136 DW GRP10 +1707 38 3137 DB 38H +1708 72 65 74 3138 DB 'ret' +170B 9C 0B 3139 DW PUT +170D CF 3140 DB 0CFH +170E 6E 74 6F 3141 DB 'nto' +1711 9C 0B 3142 DW PUT +1713 CE 3143 DB 0CEH +1714 3144 J2: +1714 0A 3145 DB 10 +1715 70 3146 DB 'p' +1716 B7 0F 3147 DW GRP17 +1718 EB 3148 DB 0EBH +1719 7A 3149 DB 'z' +171A B7 0F 3150 DW GRP17 +171C 74 3151 DB 74H +171D 65 3152 DB 'e' +171E B7 0F 3153 DW GRP17 +1720 74 3154 DB 74H +1721 6C 3155 DB 'l' +1722 B7 0F 3156 DW GRP17 +1724 7C 3157 DB 7CH +1725 62 3158 DB 'b' +1726 B7 0F 3159 DW GRP17 +1728 72 3160 DB 72H +1729 61 3161 DB 'a' +172A B7 0F 3162 DW GRP17 +172C 77 3163 DB 77H +172D 67 3164 DB 'g' +172E B7 0F 3165 DW GRP17 +1730 7F 3166 DB 7FH +1731 6F 3167 DB 'o' +1732 B7 0F 3168 DW GRP17 +1734 70 3169 DB 70H +1735 73 3170 DB 's' +1736 B7 0F 3171 DW GRP17 +1738 78 3172 DB 78H +1739 63 3173 DB 'c' +173A B7 0F 3174 DW GRP17 +173C 72 3175 DB 72H +173D 3176 J3: +173D 11 3177 DB 17 +173E 6D 70 3178 DB 'mp' +1740 C1 0E 3179 DW GRP14 +1742 EA 3180 DB 0EAH +1743 6E 7A 3181 DB 'nz' +1745 B7 0F 3182 DW GRP17 +1747 75 3183 DB 75H +1748 6E 65 3184 DB 'ne' +174A B7 0F 3185 DW GRP17 +174C 75 3186 DB 75H +174D 6E 6C 3187 DB 'nl' +174F B7 0F 3188 DW GRP17 +1751 7D 3189 DB 7DH +1752 67 65 3190 DB 'ge' +1754 B7 0F 3191 DW GRP17 +1756 7D 3192 DB 7DH +1757 6E 62 3193 DB 'nb' +1759 B7 0F 3194 DW GRP17 +175B 73 3195 DB 73H +175C 61 65 3196 DB 'ae' +175E B7 0F 3197 DW GRP17 +1760 73 3198 DB 73H +1761 6E 63 3199 DB 'nc' +1763 B7 0F 3200 DW GRP17 +1765 73 3201 DB 73H +1766 6E 67 3202 DB 'ng' +1768 B7 0F 3203 DW GRP17 +176A 7E 3204 DB 7EH +176B 6C 65 3205 DB 'le' +176D B7 0F 3206 DW GRP17 +176F 7E 3207 DB 7EH +1770 6E 61 3208 DB 'na' +1772 B7 0F 3209 DW GRP17 +1774 76 3210 DB 76H +1775 62 65 3211 DB 'be' +1777 B7 0F 3212 DW GRP17 +1779 76 3213 DB 76H +177A 70 65 3214 DB 'pe' +177C B7 0F 3215 DW GRP17 +177E 7A 3216 DB 7AH +177F 6E 70 3217 DB 'np' +1781 B7 0F 3218 DW GRP17 +1783 7B 3219 DB 7BH +1784 70 6F 3220 DB 'po' +1786 B7 0F 3221 DW GRP17 +1788 7B 3222 DB 7BH +1789 6E 6F 3223 DB 'no' +178B B7 0F 3224 DW GRP17 +178D 71 3225 DB 71H +178E 6E 73 3226 DB 'ns' +1790 B7 0F 3227 DW GRP17 +1792 79 3228 DB 79H +1793 3229 J4: +1793 06 3230 DB 6 +1794 6D 70 73 3231 DB 'mps' +1797 B7 0F 3232 DW GRP17 +1799 EB 3233 DB 0EBH +179A 63 78 7A 3234 DB 'cxz' +179D B7 0F 3235 DW GRP17 +179F E3 3236 DB 0E3H +17A0 6E 67 65 3237 DB 'nge' +17A3 B7 0F 3238 DW GRP17 +17A5 7C 3239 DB 7CH +17A6 6E 61 65 3240 DB 'nae' +17A9 B7 0F 3241 DW GRP17 +17AB 72 3242 DB 72H +17AC 6E 62 65 3243 DB 'nbe' +17AF B7 0F 3244 DW GRP17 +17B1 77 3245 DB 77H +17B2 6E 6C 65 3246 DB 'nle' +17B5 B7 0F 3247 DW GRP17 +17B7 7F 3248 DB 7FH +17B8 3249 L3: +17B8 03 3250 DB 3 +17B9 65 61 3251 DB 'ea' +17BB B5 0D 3252 DW GRP6 +17BD 8D 3253 DB 8DH +17BE 64 73 3254 DB 'ds' +17C0 B5 0D 3255 DW GRP6 +17C2 C5 3256 DB 0C5H +17C3 65 73 3257 DB 'es' +17C5 B5 0D 3258 DW GRP6 +17C7 C4 3259 DB 0C4H +17C8 3260 L4: +17C8 05 3261 DB 5 +17C9 6F 6F 70 3262 DB 'oop' +17CC B7 0F 3263 DW GRP17 +17CE E2 3264 DB 0E2H +17CF 6F 64 62 3265 DB 'odb' +17D2 9C 0B 3266 DW PUT +17D4 AC 3267 DB 0ACH +17D5 6F 64 77 3268 DB 'odw' +17D8 9C 0B 3269 DW PUT +17DA AD 3270 DB 0ADH +17DB 61 68 66 3271 DB 'ahf' +17DE 9C 0B 3272 DW PUT +17E0 9F 3273 DB 9FH +17E1 6F 63 6B 3274 DB 'ock' +17E4 9C 0B 3275 DW PUT +17E6 F0 3276 DB 0F0H +17E7 3277 L5: +17E7 04 3278 DB 4 +17E8 6F 6F 70 65 3279 DB 'oope' +17EC B7 0F 3280 DW GRP17 +17EE E1 3281 DB 0E1H +17EF 6F 6F 70 7A 3282 DB 'oopz' +17F3 B7 0F 3283 DW GRP17 +17F5 E1 3284 DB 0E1H +17F6 6F 64 73 62 3285 DB 'odsb' +17FA 9C 0B 3286 DW PUT +17FC AC 3287 DB 0ACH +17FD 6F 64 73 77 3288 DB 'odsw' +1801 9C 0B 3289 DW PUT +1803 AD 3290 DB 0ADH +1804 3291 L6: +1804 02 3292 DB 2 +1805 6F 6F 70 6E 65 3293 DB 'oopne' +180A B7 0F 3294 DW GRP17 +180C E0 3295 DB 0E0H +180D 6F 6F 70 6E 7A 3296 DB 'oopnz' +1812 B7 0F 3297 DW GRP17 +1814 E0 3298 DB 0E0H +1815 3299 M3: +1815 02 3300 DB 2 +1816 6F 76 3301 DB 'ov' +1818 33 0B 3302 DW GRP1 +181A 88 3303 DB 88H +181B 75 6C 3304 DB 'ul' +181D 3D 0E 3305 DW GRP10 +181F 20 3306 DB 20H +1820 3307 M4: +1820 02 3308 DB 2 +1821 6F 76 62 3309 DB 'ovb' +1824 9C 0B 3310 DW PUT +1826 A4 3311 DB 0A4H +1827 6F 76 77 3312 DB 'ovw' +182A 9C 0B 3313 DW PUT +182C A5 3314 DB 0A5H +182D 3315 M5: +182D 02 3316 DB 2 +182E 6F 76 73 62 3317 DB 'ovsb' +1832 9C 0B 3318 DW PUT +1834 A4 3319 DB 0A4H +1835 6F 76 73 77 3320 DB 'ovsw' +1839 9C 0B 3321 DW PUT +183B A5 3322 DB 0A5H +183C 3323 N3: +183C 03 3324 DB 3 +183D 6F 74 3325 DB 'ot' +183F EF 0D 3326 DW GRP9 +1841 10 3327 DB 10H +1842 65 67 3328 DB 'eg' +1844 EF 0D 3329 DW GRP9 +1846 18 3330 DB 18H +1847 6F 70 3331 DB 'op' +1849 9C 0B 3332 DW PUT +184B 90 3333 DB 90H +184C 3334 O2: +184C 01 3335 DB 1 +184D 72 3336 DB 'r' +184E 97 0E 3337 DW GRP13 +1850 0A 3338 DB 0AH +1851 3339 O3: +1851 02 3340 DB 2 +1852 75 74 3341 DB 'ut' +1854 15 0D 3342 DW GRP4 +1856 E6 3343 DB 0E6H +1857 72 67 3344 DB 'rg' +1859 3B 0D 3345 DW GRP5 +185B 00 3346 DB 0 +185C 3347 O4: +185C 02 3348 DB 2 +185D 75 74 62 3349 DB 'utb' +1860 15 0D 3350 DW GRP4 +1862 E6 3351 DB 0E6H +1863 75 74 77 3352 DB 'utw' +1866 15 0D 3353 DW GRP4 +1868 E7 3354 DB 0E7H +1869 3355 P3: +1869 02 3356 DB 2 +186A 6F 70 3357 DB 'op' +186C AB 10 3358 DW GRP22 +186E 8F 3359 DB 8FH +186F 75 74 3360 DB 'ut' +1871 3B 0D 3361 DW GRP5 +1873 03 3362 DB 3 +1874 3363 P4: +1874 02 3364 DB 2 +1875 75 73 68 3365 DB 'ush' +1878 84 0C 3366 DW GRP2 +187A FF 3367 DB 0FFH +187B 6F 70 66 3368 DB 'opf' +187E 9C 0B 3369 DW PUT +1880 9D 3370 DB 9DH +1881 3371 P5: +1881 01 3372 DB 1 +1882 75 73 68 66 3373 DB 'ushf' +1886 9C 0B 3374 DW PUT +1888 9C 3375 DB 9CH +1889 3376 R3: +1889 06 3377 DB 6 +188A 65 74 3378 DB 'et' +188C 3F 0F 3379 DW GRP16 +188E C3 3380 DB 0C3H +188F 65 70 3381 DB 'ep' +1891 9C 0B 3382 DW PUT +1893 F3 3383 DB 0F3H +1894 6F 6C 3384 DB 'ol' +1896 6D 0E 3385 DW GRP12 +1898 00 3386 DB 0 +1899 6F 72 3387 DB 'or' +189B 6D 0E 3388 DW GRP12 +189D 08 3389 DB 8 +189E 63 6C 3390 DB 'cl' +18A0 6D 0E 3391 DW GRP12 +18A2 10 3392 DB 10H +18A3 63 72 3393 DB 'cr' +18A5 6D 0E 3394 DW GRP12 +18A7 18 3395 DB 18H +18A8 3396 R4: +18A8 02 3397 DB 2 +18A9 65 70 7A 3398 DB 'epz' +18AC 9C 0B 3399 DW PUT +18AE F3 3400 DB 0F3H +18AF 65 70 65 3401 DB 'epe' +18B2 9C 0B 3402 DW PUT +18B4 F3 3403 DB 0F3H +18B5 3404 R5: +18B5 02 3405 DB 2 +18B6 65 70 6E 7A 3406 DB 'epnz' +18BA 9C 0B 3407 DW PUT +18BC F2 3408 DB 0F2H +18BD 65 70 6E 65 3409 DB 'epne' +18C1 9C 0B 3410 DW PUT +18C3 F2 3411 DB 0F2H +18C4 3412 S3: +18C4 0B 3413 DB 11 +18C5 75 62 3414 DB 'ub' +18C7 C1 0D 3415 DW GRP7 +18C9 2A 3416 DB 2AH +18CA 62 62 3417 DB 'bb' +18CC C1 0D 3418 DW GRP7 +18CE 1A 3419 DB 1AH +18CF 62 63 3420 DB 'bc' +18D1 C1 0D 3421 DW GRP7 +18D3 1A 3422 DB 1AH +18D4 74 63 3423 DB 'tc' +18D6 9C 0B 3424 DW PUT +18D8 F9 3425 DB 0F9H +18D9 74 64 3426 DB 'td' +18DB 9C 0B 3427 DW PUT +18DD FD 3428 DB 0FDH +18DE 74 69 3429 DB 'ti' +18E0 9C 0B 3430 DW PUT +18E2 FB 3431 DB 0FBH +18E3 68 6C 3432 DB 'hl' +18E5 6D 0E 3433 DW GRP12 +18E7 20 3434 DB 20H +18E8 68 72 3435 DB 'hr' +18EA 6D 0E 3436 DW GRP12 +18EC 28 3437 DB 28H +18ED 61 6C 3438 DB 'al' +18EF 6D 0E 3439 DW GRP12 +18F1 20 3440 DB 20H +18F2 61 72 3441 DB 'ar' +18F4 6D 0E 3442 DW GRP12 +18F6 38 3443 DB 38H +18F7 65 67 3444 DB 'eg' +18F9 93 10 3445 DW GRP21 +18FB 26 3446 DB 26H +18FC 3447 S4: +18FC 05 3448 DB 5 +18FD 63 61 62 3449 DB 'cab' +1900 9C 0B 3450 DW PUT +1902 AE 3451 DB 0AEH +1903 63 61 77 3452 DB 'caw' +1906 9C 0B 3453 DW PUT +1908 AF 3454 DB 0AFH +1909 74 6F 62 3455 DB 'tob' +190C 9C 0B 3456 DW PUT +190E AA 3457 DB 0AAH +190F 74 6F 77 3458 DB 'tow' +1912 9C 0B 3459 DW PUT +1914 AB 3460 DB 0ABH +1915 61 68 66 3461 DB 'ahf' +1918 9C 0B 3462 DW PUT +191A 9E 3463 DB 9EH +191B 3464 S5: +191B 04 3465 DB 4 +191C 63 61 73 62 3466 DB 'casb' +1920 9C 0B 3467 DW PUT +1922 AE 3468 DB 0AEH +1923 63 61 73 77 3469 DB 'casw' +1927 9C 0B 3470 DW PUT +1929 AF 3471 DB 0AFH +192A 74 6F 73 62 3472 DB 'tosb' +192E 9C 0B 3473 DW PUT +1930 AA 3474 DB 0AAH +1931 74 6F 73 77 3475 DB 'tosw' +1935 9C 0B 3476 DW PUT +1937 AB 3477 DB 0ABH +1938 3478 T4: +1938 01 3479 DB 1 +1939 65 73 74 3480 DB 'est' +193C 82 10 3481 DW GRP20 +193E 84 3482 DB 84H +193F 3483 U2: +193F 01 3484 DB 1 +1940 70 3485 DB 'p' +1941 9C 0B 3486 DW PUT +1943 FC 3487 DB 0FCH +1944 3488 W4: +1944 01 3489 DB 1 +1945 61 69 74 3490 DB 'ait' +1948 9C 0B 3491 DW PUT +194A 9B 3492 DB 9BH +194B 3493 X3: +194B 01 3494 DB 1 +194C 6F 72 3495 DB 'or' +194E 97 0E 3496 DW GRP13 +1950 32 3497 DB 32H +1951 3498 X4: +1951 02 3499 DB 2 +1952 63 68 67 3500 DB 'chg' +1955 B5 0C 3501 DW GRP3 +1957 86 3502 DB 86H +1958 6C 61 74 3503 DB 'lat' +195B 9C 0B 3504 DW PUT +195D D7 3505 DB 0D7H +195E 3506 +195E 3507 +195E 3508 ; 8087 MNEMONIC TABLE +195E 3509 ; Similar to 8086 table above, except NOT distinguished by opcode length +195E 3510 +195E 3511 XM1: ;F2XM1 +195E 01 3512 DB 1 ;One opcode +195F 78 6D B1 3513 DM "xm1" +1962 01 F0 3514 DB 1,0F0H +1964 3515 +1964 3516 NDPA: +1964 03 3517 DB 3 +1965 64 E4 3518 DM "dd" +1967 0E C1 3519 DB 6+ARITH,0C1H +1969 64 64 F0 3520 DM "ddp" +196C 90 00 3521 DB NEEDOP+STACKOP,0 +196E 62 F3 3522 DM "bs" +1970 01 E1 3523 DB 1,0E1H +1972 3524 +1972 3525 NDPB: +1972 02 3526 DB 2 +1973 6C E4 3527 DM "ld" +1975 9F 20 3528 DB 7+NEEDOP+MEMORY,20H +1977 73 74 F0 3529 DM "stp" +197A 9F 30 3530 DB 7+NEEDOP+MEMORY,30H +197C 3531 +197C 3532 NDPC: +197C 05 3533 DB 5 +197D 6F ED 3534 DM "om" +197F 68 D1 3535 DB 0+ONEREG+REAL,0D1H +1981 6F 6D F0 3536 DM "omp" +1984 68 D9 3537 DB 0+ONEREG+REAL,0D9H +1986 68 F3 3538 DM "hs" +1988 01 E0 3539 DB 1,0E0H +198A 6F 6D 70 F0 3540 DM "ompp" +198E 06 D9 3541 DB 6,0D9H +1990 6C 65 F8 3542 DM "lex" +1993 03 E2 3543 DB 3,0E2H +1995 3544 +1995 3545 NDPD: +1995 06 3546 DB 6 +1996 69 F6 3547 DM "iv" +1998 0E F1 3548 DB 6+ARITH,0F1H +199A 69 76 F0 3549 DM "ivp" +199D 90 30 3550 DB NEEDOP+STACKOP,30H +199F 69 76 F2 3551 DM "ivr" +19A2 0E F9 3552 DB 6+ARITH,0F9H +19A4 69 76 72 F0 3553 DM "ivrp" +19A8 90 38 3554 DB NEEDOP+STACKOP,38H +19AA 65 63 73 74 F0 3555 DM "ecstp" +19AF 01 F6 3556 DB 1,0F6H +19B1 69 73 E9 3557 DM "isi" +19B4 03 E1 3558 DB 3,0E1H +19B6 3559 +19B6 3560 NDPE: +19B6 01 3561 DB 1 +19B7 6E E9 3562 DM "ni" +19B9 03 E0 3563 DB 3,0E0H +19BB 3564 +19BB 3565 NDPF: +19BB 01 3566 DB 1 +19BC 72 65 E5 3567 DM "ree" +19BF C5 00 3568 DB 5+NEEDOP+ONEREG,0 +19C1 3569 +19C1 3570 NDPI: +19C1 0D 3571 DB 13 +19C2 61 64 E4 3572 DM "add" +19C5 A2 00 3573 DB 2+NEEDOP+INTEGER,0 +19C7 6C E4 3574 DM "ld" +19C9 B3 00 3575 DB 3+NEEDOP+INTEGER+EXTENDED,0 +19CB 73 75 E2 3576 DM "sub" +19CE A2 20 3577 DB 2+NEEDOP+INTEGER,20H +19D0 73 74 F0 3578 DM "stp" +19D3 B3 18 3579 DB 3+NEEDOP+INTEGER+EXTENDED,18H +19D5 73 F4 3580 DM "st" +19D7 A3 10 3581 DB 3+NEEDOP+INTEGER,10H +19D9 6D 75 EC 3582 DM "mul" +19DC A2 08 3583 DB 2+NEEDOP+INTEGER,8 +19DE 64 69 F6 3584 DM "div" +19E1 A2 30 3585 DB 2+NEEDOP+INTEGER,30H +19E3 73 75 62 F2 3586 DM "subr" +19E7 A2 28 3587 DB 2+NEEDOP+INTEGER,28H +19E9 64 69 76 F2 3588 DM "divr" +19ED A2 38 3589 DB 2+NEEDOP+INTEGER,38H +19EF 63 6F ED 3590 DM "com" +19F2 A2 10 3591 DB 2+NEEDOP+INTEGER,10H +19F4 63 6F 6D F0 3592 DM "comp" +19F8 A2 18 3593 DB 2+NEEDOP+INTEGER,18H +19FA 6E 63 73 74 F0 3594 DM "ncstp" +19FF 01 F7 3595 DB 1,0F7H +1A01 6E 69 F4 3596 DM "nit" +1A04 03 E3 3597 DB 3,0E3H +1A06 3598 +1A06 3599 NDPL: +1A06 0A 3600 DB 10 +1A07 E4 3601 DM "d" +1A08 F9 00 3602 DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0 +1A0A 64 FA 3603 DM "dz" +1A0C 01 EE 3604 DB 1,0EEH +1A0E 64 B1 3605 DM "d1" +1A10 01 E8 3606 DB 1,0E8H +1A12 64 70 E9 3607 DM "dpi" +1A15 01 EB 3608 DB 1,0EBH +1A17 64 6C 32 F4 3609 DM "dl2t" +1A1B 01 E9 3610 DB 1,0E9H +1A1D 64 6C 32 E5 3611 DM "dl2e" +1A21 01 EA 3612 DB 1,0EAH +1A23 64 6C 67 B2 3613 DM "dlg2" +1A27 01 EC 3614 DB 1,0ECH +1A29 64 6C 6E B2 3615 DM "dln2" +1A2D 01 ED 3616 DB 1,0EDH +1A2F 64 63 F7 3617 DM "dcw" +1A32 99 28 3618 DB 1+NEEDOP+MEMORY,28H +1A34 64 65 6E F6 3619 DM "denv" +1A38 99 20 3620 DB 1+NEEDOP+MEMORY,20H +1A3A 3621 +1A3A 3622 NDPM: +1A3A 02 3623 DB 2 +1A3B 75 EC 3624 DM "ul" +1A3D 0E C9 3625 DB 6+ARITH,0C9H +1A3F 75 6C F0 3626 DM "ulp" +1A42 90 08 3627 DB NEEDOP+STACKOP,8 +1A44 3628 +1A44 3629 NDPO: +1A44 01 3630 DB 1 +1A45 F0 3631 DM "p" +1A46 81 00 3632 DB NEEDOP+1,0 ;Flag special handling +1A48 3633 +1A48 3634 NDPN: +1A48 01 3635 DB 1 +1A49 6F F0 3636 DM "op" +1A4B 01 D0 3637 DB 1,0D0H +1A4D 3638 +1A4D 3639 NDPP: +1A4D 03 3640 DB 3 +1A4E 72 65 ED 3641 DM "rem" +1A51 01 F8 3642 DB 1,0F8H +1A53 74 61 EE 3643 DM "tan" +1A56 01 F2 3644 DB 1,0F2H +1A58 61 74 61 EE 3645 DM "atan" +1A5C 01 F3 3646 DB 1,0F3H +1A5E 3647 +1A5E 3648 NDPR: +1A5E 02 3649 DB 2 +1A5F 6E 64 69 6E F4 3650 DM "ndint" +1A64 01 FC 3651 DB 1,0FCH +1A66 73 74 6F F2 3652 DM "stor" +1A6A 9D 20 3653 DB 5+NEEDOP+MEMORY,20H +1A6C 3654 +1A6C 3655 NDPS: +1A6C 0C 3656 DB 12 +1A6D F4 3657 DM "t" +1A6E ED D0 3658 DB 5+NEEDOP+ONEREG+REAL,0D0H +1A70 74 F0 3659 DM "tp" +1A72 FF D8 3660 DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H +1A74 75 E2 3661 DM "ub" +1A76 0E E1 3662 DB 6+ARITH,0E1H +1A78 75 62 F0 3663 DM "ubp" +1A7B 90 E0 3664 DB NEEDOP+STACKOP,0E0H +1A7D 75 62 F2 3665 DM "ubr" +1A80 0E E9 3666 DB 6+ARITH,0E9H +1A82 75 62 72 F0 3667 DM "ubrp" +1A86 90 E8 3668 DB NEEDOP+STACKOP,0E8H +1A88 71 72 F4 3669 DM "qrt" +1A8B 01 FA 3670 DB 1,0FAH +1A8D 63 61 6C E5 3671 DM "cale" +1A91 01 FD 3672 DB 1,0FDH +1A93 61 76 E5 3673 DM "ave" +1A96 9D 30 3674 DB 5+NEEDOP+MEMORY,30H +1A98 74 63 F7 3675 DM "tcw" +1A9B 99 38 3676 DB 1+NEEDOP+MEMORY,38H +1A9D 74 65 6E F6 3677 DM "tenv" +1AA1 99 30 3678 DB 1+NEEDOP+MEMORY,30H +1AA3 74 73 F7 3679 DM "tsw" +1AA6 9D 38 3680 DB 5+NEEDOP+MEMORY,38H +1AA8 3681 +1AA8 3682 NDPT: +1AA8 01 3683 DB 1 +1AA9 73 F4 3684 DM "st" +1AAB 01 E4 3685 DB 1,0E4H +1AAD 3686 +1AAD 3687 NDPW: +1AAD 01 3688 DB 1 +1AAE 61 69 F4 3689 DM "ait" +1AB1 80 00 3690 DB NEEDOP,0 ;Flag special handling +1AB3 3691 +1AB3 3692 NDPX: +1AB3 03 3693 DB 3 +1AB4 63 E8 3694 DM "ch" +1AB6 41 C9 3695 DB 1+ONEREG,0C9H +1AB8 61 ED 3696 DM "am" +1ABA 01 E5 3697 DB 1,0E5H +1ABC 74 72 61 63 F4 3698 DM "tract" +1AC1 01 F4 3699 DB 1,0F4H +1AC3 3700 +1AC3 3701 NDPY: +1AC3 02 3702 DB 2 +1AC4 6C 32 F8 3703 DM "l2x" +1AC7 01 F1 3704 DB 1,0F1H +1AC9 6C 32 78 70 B1 3705 DM "l2xp1" +1ACE 01 F9 3706 DB 1,0F9H +1AD0 3707 +1AD0 3708 +1AD0 3709 OPTAB: +1AD0 3710 ; Table of pointers to mnemonics. For each letter of the alphabet (the +1AD0 3711 ; starting letter of the mnemonic), there are 5 entries. Each entry +1AD0 3712 ; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +1AD0 3713 ; long, respectively. If there are no mnemonics for a given combination +1AD0 3714 ; of first letter and length (such as A-2), then the corresponding entry +1AD0 3715 ; points to NONE. Otherwise, it points to a place in the mnemonic table +1AD0 3716 ; for that type. +1AD0 3717 +1AD0 3718 ; This table only needs to be modified if a mnemonic is added to a group +1AD0 3719 ; previously marked NONE. Change the NONE to a label made up of the first +1AD0 3720 ; letter of the mnemonic and its length, then add a new subsection to +1AD0 3721 ; the mnemonic table in alphabetical order. +1AD0 3722 +1AD0 0F 16 3723 DW NONE +1AD2 10 16 3724 DW A3 +1AD4 0F 16 3725 DW NONE +1AD6 34 16 3726 DW A5 +1AD8 0F 16 3727 DW NONE +1ADA 0F 16 3728 DW NONE ;B +1ADC 0F 16 3729 DW NONE +1ADE 0F 16 3730 DW NONE +1AE0 0F 16 3731 DW NONE +1AE2 0F 16 3732 DW NONE +1AE4 0F 16 3733 DW NONE ;C +1AE6 3C 16 3734 DW C3 +1AE8 60 16 3735 DW C4 +1AEA 73 16 3736 DW C5 +1AEC 0F 16 3737 DW NONE +1AEE 82 16 3738 DW D2 ;D +1AF0 97 16 3739 DW D3 +1AF2 AC 16 3740 DW D4 +1AF4 0F 16 3741 DW NONE +1AF6 0F 16 3742 DW NONE +1AF8 B3 16 3743 DW E2 ;E +1AFA B8 16 3744 DW E3 +1AFC 0F 16 3745 DW NONE +1AFE C8 16 3746 DW E5 +1B00 0F 16 3747 DW NONE +1B02 0F 16 3748 DW NONE ;F +1B04 0F 16 3749 DW NONE +1B06 0F 16 3750 DW NONE +1B08 0F 16 3751 DW NONE +1B0A 0F 16 3752 DW NONE +1B0C 0F 16 3753 DW NONE ;G +1B0E 0F 16 3754 DW NONE +1B10 0F 16 3755 DW NONE +1B12 0F 16 3756 DW NONE +1B14 0F 16 3757 DW NONE +1B16 0F 16 3758 DW NONE ;H +1B18 D0 16 3759 DW H3 +1B1A D6 16 3760 DW H4 +1B1C 0F 16 3761 DW NONE +1B1E 0F 16 3762 DW NONE +1B20 DD 16 3763 DW I2 ;I +1B22 E6 16 3764 DW I3 +1B24 FB 16 3765 DW I4 +1B26 0F 16 3766 DW NONE +1B28 0F 16 3767 DW NONE +1B2A 14 17 3768 DW J2 ;J +1B2C 3D 17 3769 DW J3 +1B2E 93 17 3770 DW J4 +1B30 0F 16 3771 DW NONE +1B32 0F 16 3772 DW NONE +1B34 0F 16 3773 DW NONE ;K +1B36 0F 16 3774 DW NONE +1B38 0F 16 3775 DW NONE +1B3A 0F 16 3776 DW NONE +1B3C 0F 16 3777 DW NONE +1B3E 0F 16 3778 DW NONE ;L +1B40 B8 17 3779 DW L3 +1B42 C8 17 3780 DW L4 +1B44 E7 17 3781 DW L5 +1B46 04 18 3782 DW L6 +1B48 0F 16 3783 DW NONE ;M +1B4A 15 18 3784 DW M3 +1B4C 20 18 3785 DW M4 +1B4E 2D 18 3786 DW M5 +1B50 0F 16 3787 DW NONE +1B52 0F 16 3788 DW NONE ;N +1B54 3C 18 3789 DW N3 +1B56 0F 16 3790 DW NONE +1B58 0F 16 3791 DW NONE +1B5A 0F 16 3792 DW NONE +1B5C 4C 18 3793 DW O2 ;O +1B5E 51 18 3794 DW O3 +1B60 5C 18 3795 DW O4 +1B62 0F 16 3796 DW NONE +1B64 0F 16 3797 DW NONE +1B66 0F 16 3798 DW NONE ;P +1B68 69 18 3799 DW P3 +1B6A 74 18 3800 DW P4 +1B6C 81 18 3801 DW P5 +1B6E 0F 16 3802 DW NONE +1B70 0F 16 3803 DW NONE ;Q +1B72 0F 16 3804 DW NONE +1B74 0F 16 3805 DW NONE +1B76 0F 16 3806 DW NONE +1B78 0F 16 3807 DW NONE +1B7A 0F 16 3808 DW NONE ;R +1B7C 89 18 3809 DW R3 +1B7E A8 18 3810 DW R4 +1B80 B5 18 3811 DW R5 +1B82 0F 16 3812 DW NONE +1B84 0F 16 3813 DW NONE ;S +1B86 C4 18 3814 DW S3 +1B88 FC 18 3815 DW S4 +1B8A 1B 19 3816 DW S5 +1B8C 0F 16 3817 DW NONE +1B8E 0F 16 3818 DW NONE ;T +1B90 0F 16 3819 DW NONE +1B92 38 19 3820 DW T4 +1B94 0F 16 3821 DW NONE +1B96 0F 16 3822 DW NONE +1B98 3F 19 3823 DW U2 ;U +1B9A 0F 16 3824 DW NONE +1B9C 0F 16 3825 DW NONE +1B9E 0F 16 3826 DW NONE +1BA0 0F 16 3827 DW NONE +1BA2 0F 16 3828 DW NONE ;V +1BA4 0F 16 3829 DW NONE +1BA6 0F 16 3830 DW NONE +1BA8 0F 16 3831 DW NONE +1BAA 0F 16 3832 DW NONE +1BAC 0F 16 3833 DW NONE ;W +1BAE 0F 16 3834 DW NONE +1BB0 44 19 3835 DW W4 +1BB2 0F 16 3836 DW NONE +1BB4 0F 16 3837 DW NONE +1BB6 0F 16 3838 DW NONE ;X +1BB8 4B 19 3839 DW X3 +1BBA 51 19 3840 DW X4 +1BBC 0F 16 3841 DW NONE +1BBE 0F 16 3842 DW NONE +1BC0 0F 16 3843 DW NONE ;Y +1BC2 0F 16 3844 DW NONE +1BC4 0F 16 3845 DW NONE +1BC6 0F 16 3846 DW NONE +1BC8 0F 16 3847 DW NONE +1BCA 0F 16 3848 DW NONE ;Z +1BCC 0F 16 3849 DW NONE +1BCE 0F 16 3850 DW NONE +1BD0 0F 16 3851 DW NONE +1BD2 0F 16 3852 DW NONE +1BD4 3853 +1BD4 3854 NDPTAB: +1BD4 3855 ;Lookup table for 8087 mnemonics. There is one entry for each letter of the +1BD4 3856 ;alphabet +1BD4 64 19 3857 DW NDPA +1BD6 72 19 3858 DW NDPB +1BD8 7C 19 3859 DW NDPC +1BDA 95 19 3860 DW NDPD +1BDC B6 19 3861 DW NDPE +1BDE BB 19 3862 DW NDPF +1BE0 0F 16 3863 DW NONE ;G +1BE2 0F 16 3864 DW NONE ;H +1BE4 C1 19 3865 DW NDPI +1BE6 0F 16 3866 DW NONE ;J +1BE8 0F 16 3867 DW NONE ;K +1BEA 06 1A 3868 DW NDPL +1BEC 3A 1A 3869 DW NDPM +1BEE 48 1A 3870 DW NDPN +1BF0 44 1A 3871 DW NDPO +1BF2 4D 1A 3872 DW NDPP +1BF4 0F 16 3873 DW NONE ;Q +1BF6 5E 1A 3874 DW NDPR +1BF8 6C 1A 3875 DW NDPS +1BFA A8 1A 3876 DW NDPT +1BFC 0F 16 3877 DW NONE ;U +1BFE 0F 16 3878 DW NONE ;V +1C00 AD 1A 3879 DW NDPW +1C02 B3 1A 3880 DW NDPX +1C04 C3 1A 3881 DW NDPY +1C06 0F 16 3882 DW NONE ;Z +1C08 3883 +1C08 3884 ;Error message table +1C08 3885 +1C08 3886 ERRTAB: +1C08 01 52 65 67 69 73 74 3887 DM 1,"Register not allowed in immediate value" + 65 72 20 6E 6F 74 20 + 61 6C 6C 6F 77 65 64 + 20 69 6E 20 69 6D 6D + 65 64 69 61 74 65 20 + 76 61 6C 75 E5 +1C30 02 49 6E 64 65 78 20 3888 DM 2,"Index or base register must be BP, BX, SI, or DI" + 6F 72 20 62 61 73 65 + 20 72 65 67 69 73 74 + 65 72 20 6D 75 73 74 + 20 62 65 20 42 50 2C + 20 42 58 2C 20 53 49 + 2C 20 6F 72 20 44 C9 +1C61 03 4F 6E 6C 79 20 6F 3889 DM 3,"Only one base register (BX, BP) allowed" + 6E 65 20 62 61 73 65 + 20 72 65 67 69 73 74 + 65 72 20 28 42 58 2C + 20 42 50 29 20 61 6C + 6C 6F 77 65 E4 +1C89 04 4F 6E 6C 79 20 6F 3890 DM 4,"Only one index register (SI or DI) allowed" + 6E 65 20 69 6E 64 65 + 78 20 72 65 67 69 73 + 74 65 72 20 28 53 49 + 20 6F 72 20 44 49 29 + 20 61 6C 6C 6F 77 65 + E4 +1CB4 05 4F 6E 6C 79 20 61 3891 DM 5,"Only addition allowed on register or undefined label" + 64 64 69 74 69 6F 6E + 20 61 6C 6C 6F 77 65 + 64 20 6F 6E 20 72 65 + 67 69 73 74 65 72 20 + 6F 72 20 75 6E 64 65 + 66 69 6E 65 64 20 6C + 61 62 65 EC +1CE9 06 4F 6E 6C 79 20 6F 3892 DM 6,"Only one undefined label per expression allowed" + 6E 65 20 75 6E 64 65 + 66 69 6E 65 64 20 6C + 61 62 65 6C 20 70 65 + 72 20 65 78 70 72 65 + 73 73 69 6F 6E 20 61 + 6C 6C 6F 77 65 E4 +1D19 07 49 6C 6C 65 67 61 3893 DM 7,"Illegal digit in hexadecimal number" + 6C 20 64 69 67 69 74 + 20 69 6E 20 68 65 78 + 61 64 65 63 69 6D 61 + 6C 20 6E 75 6D 62 65 + F2 +1D3D 08 49 6C 6C 65 67 61 3894 DM 8,"Illegal digit in decimal number" + 6C 20 64 69 67 69 74 + 20 69 6E 20 64 65 63 + 69 6D 61 6C 20 6E 75 + 6D 62 65 F2 +1D5D 0A 49 6C 6C 65 67 61 3895 DM 10,"Illegal character in label or opcode" + 6C 20 63 68 61 72 61 + 63 74 65 72 20 69 6E + 20 6C 61 62 65 6C 20 + 6F 72 20 6F 70 63 6F + 64 E5 +1D82 0B 4C 61 62 65 6C 20 3896 DM 11,"Label defined twice" + 64 65 66 69 6E 65 64 + 20 74 77 69 63 E5 +1D96 0C 4F 70 63 6F 64 65 3897 DM 12,"Opcode not recognized" + 20 6E 6F 74 20 72 65 + 63 6F 67 6E 69 7A 65 + E4 +1DAC 14 49 6E 76 61 6C 69 3898 DM 20,"Invalid operand" + 64 20 6F 70 65 72 61 + 6E E4 +1DBC 15 22 2C 22 20 61 6E 3899 DM 21,'"," and second operand expected' + 64 20 73 65 63 6F 6E + 64 20 6F 70 65 72 61 + 6E 64 20 65 78 70 65 + 63 74 65 E4 +1DDC 16 52 65 67 69 73 74 3900 DM 22,"Register mismatch" + 65 72 20 6D 69 73 6D + 61 74 63 E8 +1DEE 17 49 6D 6D 65 64 69 3901 DM 23,"Immediate operand not allowed" + 61 74 65 20 6F 70 65 + 72 61 6E 64 20 6E 6F + 74 20 61 6C 6C 6F 77 + 65 E4 +1E0C 18 22 5D 22 20 65 78 3902 DM 24,'"]" expected' + 70 65 63 74 65 E4 +1E19 19 54 77 6F 20 6D 65 3903 DM 25,"Two memory operands not allowed" + 6D 6F 72 79 20 6F 70 + 65 72 61 6E 64 73 20 + 6E 6F 74 20 61 6C 6C + 6F 77 65 E4 +1E39 1A 44 65 73 74 69 6E 3904 DM 26,"Destination must not be immediate value" + 61 74 69 6F 6E 20 6D + 75 73 74 20 6E 6F 74 + 20 62 65 20 69 6D 6D + 65 64 69 61 74 65 20 + 76 61 6C 75 E5 +1E61 1B 42 6F 74 68 20 6F 3905 DM 27,"Both operands must not be registers" + 70 65 72 61 6E 64 73 + 20 6D 75 73 74 20 6E + 6F 74 20 62 65 20 72 + 65 67 69 73 74 65 72 + F3 +1E85 1C 4F 70 65 72 61 6E 3906 DM 28,"Operand must be segment register" + 64 20 6D 75 73 74 20 + 62 65 20 73 65 67 6D + 65 6E 74 20 72 65 67 + 69 73 74 65 F2 +1EA6 1D 46 69 72 73 74 20 3907 DM 29,"First operand must be register" + 6F 70 65 72 61 6E 64 + 20 6D 75 73 74 20 62 + 65 20 72 65 67 69 73 + 74 65 F2 +1EC5 1E 55 6E 64 65 66 69 3908 DM 30,"Undefined label not allowed" + 6E 65 64 20 6C 61 62 + 65 6C 20 6E 6F 74 20 + 61 6C 6C 6F 77 65 E4 +1EE1 1F 56 61 6C 75 65 20 3909 DM 31,"Value out of range" + 6F 75 74 20 6F 66 20 + 72 61 6E 67 E5 +1EF4 20 4D 69 73 73 69 6E 3910 DM 32,"Missing or illegal operand size flag" + 67 20 6F 72 20 69 6C + 6C 65 67 61 6C 20 6F + 70 65 72 61 6E 64 20 + 73 69 7A 65 20 66 6C + 61 E7 +1F19 21 4D 75 73 74 20 68 3911 DM 33,"Must have label on same line" + 61 76 65 20 6C 61 62 + 65 6C 20 6F 6E 20 73 + 61 6D 65 20 6C 69 6E + E5 +1F36 23 5A 65 72 6F 2D 6C 3912 DM 35,"Zero-length string illegal" + 65 6E 67 74 68 20 73 + 74 72 69 6E 67 20 69 + 6C 6C 65 67 61 EC +1F51 24 45 4E 44 49 46 20 3913 DM 36,"ENDIF without IF" + 77 69 74 68 6F 75 74 + 20 49 C6 +1F62 25 4F 6E 65 2D 63 68 3914 DM 37,"One-character strings only" + 61 72 61 63 74 65 72 + 20 73 74 72 69 6E 67 + 73 20 6F 6E 6C F9 +1F7D 26 49 6C 6C 65 67 61 3915 DM 38,"Illegal expression" + 6C 20 65 78 70 72 65 + 73 73 69 6F EE +1F90 27 45 6E 64 20 6F 66 3916 DM 39,"End of string not found" + 20 73 74 72 69 6E 67 + 20 6E 6F 74 20 66 6F + 75 6E E4 +1FA8 64 55 6E 64 65 66 69 3917 DM 100,"Undefined label" + 6E 65 64 20 6C 61 62 + 65 EC +1FB8 65 56 61 6C 75 65 20 3918 DM 101,"Value out of range (forward)" + 6F 75 74 20 6F 66 20 + 72 61 6E 67 65 20 28 + 66 6F 72 77 61 72 64 + A9 +1FD5 FF 3919 DB 255 +1FD6 3920 +1FD6 2A 2A 2A 2A 2A 20 45 3921 ERRMES: DM '***** ERROR: ' + 52 52 4F 52 3A 20 A0 +1FE4 0D 0A 46 69 6C 65 20 3922 NOSPAC: DB 13,10,'File creation error',13,10,"$" + 63 72 65 61 74 69 6F + 6E 20 65 72 72 6F 72 + 0D 0A 24 +1FFC 0D 0A 49 6E 73 75 66 3923 NOMEM: DB 13,10,'Insufficient memory',13,10,'$' + 66 69 63 69 65 6E 74 + 20 6D 65 6D 6F 72 79 + 0D 0A 24 +2014 0D 0A 46 69 6C 65 20 3924 NOFILE: DB 13,10,'File not found',13,10,'$' + 6E 6F 74 20 66 6F 75 + 6E 64 0D 0A 24 +2027 0D 0A 44 69 73 6B 20 3925 WRTERR: DB 13,10,'Disk full',13,10,'$' + 66 75 6C 6C 0D 0A 24 +2035 0D 0A 42 61 64 20 64 3926 BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' + 69 73 6B 20 73 70 65 + 63 69 66 69 65 72 0D + 0A 24 +204C 0D 0A 0D 0A 45 72 72 3927 ERCNTM: DM 13,10,13,10,'Error Count =' + 6F 72 20 43 6F 75 6E + 74 20 BD +205D 0D 0A 53 79 6D 62 6F 3928 SYMMES: DM 13,10,'Symbol Table',13,10,13,10 + 6C 20 54 61 62 6C 65 + 0D 0A 0D 8A +206F 41 53 4D 00 00 3929 EXTEND: DB 'ASM',0,0 +2074 05 65 6E 64 69 66 3930 IFEND: DB 5,'endif' +207A 02 69 66 3931 IFNEST: DB 2,'if' +207D 72 65 F4 3932 RETSTR: DM 'ret' +2080 00 20 20 20 20 20 20 3933 HEXFCB: DB 0,' HEX',0,0,0,0 + 20 20 48 45 58 00 00 + 00 00 +2090 3934 DS 16 +20A0 00 00 00 00 00 3935 DB 0,0,0,0,0 +20A5 00 20 20 20 20 20 20 3936 LSTFCB: DB 0,' PRN',0,0,0,0 + 20 20 50 52 4E 00 00 + 00 00 +20B5 3937 DS 16 +20C5 00 00 00 00 00 3938 DB 0,0,0,0,0 +20CA 3939 PC: DS 2 +20CC 3940 OLDPC: DS 2 +20CE 3941 LABPT: DS 2 +20D0 3942 FLAG: DS 1 +20D1 3943 MAXFLG: DS 1 +20D2 3944 ADDR: DS 2 +20D4 3945 ALABEL: DS 2 +20D6 3946 DATA: DS 2 +20D8 3947 DLABEL: DS 2 +20DA 3948 CON: DS 2 +20DC 3949 UNDEF: DS 2 +20DE 3950 LENID: DS 1 +20DF 3951 ID: DS 80 +212F 3952 CHR: DS 1 +2130 3953 SYM: DS 1 +2131 3954 BASE: DS 2 +2133 3955 HEAP: DS 2 +2135 3956 SYMFLG: DS 1 +2136 3957 SYMLIN: DS 1 +2137 3958 CODE: DS 2 +2139 3959 DATSIZ: DS 1 +213A 3960 RELOC: DS 1 +213B 3961 BCOUNT: DS 1 +213C 3962 COUNT: DS 1 +213D 3963 ERR: DS 1 +213E 3964 LINE: DS 2 +2140 3965 HEXLEN: DS 2 +2142 3966 HEXADD: DS 2 +2144 3967 LASTAD: DS 2 +2146 3968 HEXCNT: DS 1 +2147 3969 CHKSUM: DS 1 +2148 3970 LINFLG: DS 1 +2149 3971 PREV: DS 1 +214A 3972 IFFLG: DS 1 +214B 3973 CHKLAB: DS 1 +214C 3974 ERRCNT: DS 2 +214E 3975 LSTRET: DS 2 +2150 3976 RETPT: DS 2 +2152 3977 LSTDEV: DS 2 +2154 3978 SPC: DS 1 +2155 3979 NOWAIT: DS 1 +2156 3980 IX: DS 2 +2158 3981 IY: DS 2 +215A 3982 HEXPNT: DS 2 +215C 3983 LSTPNT: DS 2 +215E 3984 HEXBUF: DS HEXBUFSIZ +21A4 3985 LSTBUF: DS LSTBUFSIZ +25A4 3986 BUFPT: DS 2 +25A6 3987 SRCBUF: DS BUFSIZ +29A6 3988 DS 100H +2AA6 3989 ALIGN +2AA6 3990 STACK: EQU $ +2AA6 3991 START: EQU $ + + +Error Count = 0 + +Symbol Table + +a3 1610 a5 1634 abort 0273 accimm 0EA0 accj 0DE6 +add 04CE addr 20D2 afhex 1569 aimm 0EA9 alabel 20D4 +align 0D6D allret 0858 arith 0008 asmlin 0954 baddsk 2035 +badflag 0AD9 badop 04E3 base 2131 bcount 213B begin 0176 +blkwrt 0028 blnk 1257 bpj 0576 bufpt 25A4 bufsiz 0400 +bxj 0579 bytimm 0B53 bytsiz 05DE c3 163C c4 1660 +c5 1673 chkdsk 02A0 chklab 214B chkret 0830 chksum 2147 +chr 212F close 0010 codbyt 151B code 2137 codlp 1242 +con 20DA const 0001 count 213C cpslp 08F2 create 08AC +crlf 12E7 d2 1682 d3 1697 d4 16AC data 20D6 +datsiz 2139 dds 1291 dec 0666 default 0194 defbyt 11E5 +digit 131D dij 056A direct 0F06 dlabel 20D8 dollar 061B +domul 051E doret 0FB0 dorg 129C dosymtab 13ED +dput 12A3 dsj 0D77 dskerr 02AC dskful 15F6 e2 16B3 +e3 16B8 e5 16C8 emark 1217 empty 08A4 end 115A +endcond 1143 enddat 10E6 endif 114A endj 024E endlin 0253 +endln 0251 endop 0A12 endsym 140B endterm 0527 enhexl 158E +enter 089B eol 000D equ 0D89 ercntm 204C err 213D +err1 03BC err10 0FEC err11 10C9 err2 0567 err30 05A1 +err4 06B6 err5 0951 err6 0D12 err7 0DBE err8 0EBE +err9 0FC1 errcnt 214C errj 105D errj1 0E55 errj3 073D +errj4 0ADB errjmp 1157 errlook 14EA errmes 1FD6 error 02B1 +errtab 1C08 escimm 1067 escmem 1060 exacc 0D00 exit 1422 +exmem 0D07 exmem1 0D09 expression 049A extend 206F +extended 0010 factor 052B fcb 005C filchk 135A +findop 09A6 fini 1391 finij 1214 finimm 0B73 fixed 0D33 +fixline 11AC fixup 11CC flag 20D0 flg 042A flgtab 0740 +flushbuf 15DC fndndp 0A06 formattab 0B23 +fpreg 0745 freg 0006 fwait 0A3F g10 0E57 gen 0BA6 +gen1 0BA9 genint 1013 getch 02DA getchr 05F0 getdat 10CF +geteol 0266 getfact 04F9 getformat 0AF5 getlab 0902 +getlet 06B9 getop 03C8 getop1 03CB getop2 03BF getsp 0F54 +getsy 0627 getsym 0602 getval 043B gotit 06A5 gotop 0F19 +grp1 0B33 grp10 0E3D grp11 0E65 grp12 0E6D grp13 0E97 +grp14 0EC1 grp16 0F3F grp17 0FB7 grp18 0FF0 grp19 101B +grp2 0C84 grp20 1082 grp21 1093 grp22 10AB grp23 10CC +grp3 0CB5 grp4 0D15 grp5 0D3B grp6 0DB5 grp7 0DC1 +grp8 0DE9 grp9 0DEF h3 16D0 h4 16D6 havdef 11DE +havmes 14F4 havndp 0A47 havop 09C3 havreg 0777 header 0102 +heap 2133 hex 0690 hex1 0695 hexadd 2142 hexbuf 215E +hexbufsiz 0046 hexbyt 156A hexcnt 2146 hexend 13B6 +hexfcb 2080 hexlen 2140 hexpnt 215A hidig 1318 i2 16DD +i3 16E6 i4 16FB id 20DF if 1101 ifend 2074 +ifflg 214A ifnest 207A imm 0B8C immed 0B5D integer 0020 +ix 2156 iy 2158 j2 1714 j3 173D j4 1793 +l0000 019C l0002 0242 l0003 05B6 l0004 0722 l0006 0B45 +l0008 0CED l0011 0F8D l0012 13AF l0014 1438 l3 17B8 +l4 17C8 l5 17E7 l6 1804 labchk 0928 label 092F +labpt 20CE lastad 2144 lead 12FD lenid 20DE letter 06FD +lhalf 1604 line 213E linflg 2148 list 133E listret 1367 +load 036B longj 0F29 longr 0F68 look 07EF lookit 087C +lookndp 0A00 lookret 0823 lookup 0878 loop 0229 lstbuf 21A4 +lstbufsiz 0400 lstdev 2152 lstfcb 20A5 lstpnt 215C +lstret 214E m3 1815 m4 1820 m5 182D make 0016 +makfil 027E maxflg 20D1 mem 03FF memop 0ADE memory 0018 +mode 0462 mop 0E1A moreid 06D7 mrerr 03BA mrops 02EC +mulop 04EB n3 183C ndpa 1964 ndpb 1972 ndpc 197C +ndpd 1995 ndpe 19B6 ndpf 19BB ndpi 19C1 ndpl 1A06 +ndpm 1A3A ndpn 1A48 ndpo 1A44 ndpop 09C8 ndpp 1A4D +ndpr 1A5E ndps 1A6C ndpt 1AA8 ndptab 1BD4 ndpw 1AAD +ndpx 1AB3 ndpy 1AC3 needop 0080 newlin 153E newloc 0DA3 +nexb 0616 nexbt 11B7 nexfact 0520 nexlin 025B +nexsymlin 148F nextchj 0624 nextchr 02B6 nexterm 04D0 +nextmes 14EE nilify 08E5 nocon 04DE node 1425 nodec 0F8F +noerr 1232 noext 14C6 nofil 1262 nofile 2014 noflg 071A +noind 048E nomem 1FFC nomod 02E4 nomore 06F1 none 160F +noopchk 0AB9 noops 0AC0 noprn 01BB norev 0ACD nospac 1FE4 +not1 091A notac 039F notlon 0F7B notrg 0EE4 noundef 0C43 +nowait 2155 nreg 03F7 nwait 0A55 o2 184C o3 1851 +o4 185C objbt 11C9 object 0100 oldpc 20CC one 0DF7 +onej 0E63 oneop 0DF3 onereg 0040 open 000F operate 04BA +operr 09BE operrj 0A1A optab 1AD0 org 0D9D out 1512 +out10 12F0 outa 1510 outlin 12AA outln 12CD p3 1869 +p4 1874 p5 1881 packreg 109E paren 0582 pc 20CA +phex 1384 phexb 1339 plsmns 04B0 pmem 0CA2 preg 07C3 +prerr 0276 pret 0C3F prev 2149 print 1504 +printmes 0009 prnchk 134F prnerr 14FE prtcnt 12D9 +put 0B9C putadd 0C5C putaddj 0F03 putbj 0B5A putbw 0C12 +putbyt 0BF2 putcd 0BE1 putchk 0C1A putchr 15D2 putinc 0BDD +putmem 0B13 putop 0D69 putreg 0AAA putwor 0BEB pxreg 0CAE +r3 1889 r4 18A8 r5 18B5 read 0014 readid 06D2 +real 0028 reg 0002 regchk 077C regtab 07E7 reloc 213A +reperr 14D5 retpt 2150 retstr 207D rightson 1497 +rngerr 120D rop 0E2D rr 0321 rr1 0325 s3 18C4 +s4 18FC s5 191B savcd 149F savdat 10F7 savflg 072E +savnflg 09DA savpt 137E scanb 060B scanreg 07D0 scant 060E +segchk 033C segtab 07EB setdma 001A sholin 1248 sij 056D +skipcd 110A skiplp 110E small 080F smput 0C39 spc 2154 +spcfun 1285 specialop 0A25 spend 127B srcbuf 25A6 +sreg 0004 st0dest 0AA6 stack 2AA6 stackop 0010 start 2AA6 +sterr 03B8 stimm 0B81 store 0361 strgdat 05C7 string 05A4 +strtlin 1329 supz 1325 sym 2130 symdmp 13DA symflg 2135 +symlin 2136 symmes 205D symsav 072A symwid 0005 system 1517 +t4 1938 tab 14BF tabval 146B term 04E8 testtyp 11C2 +try2xm1 0A1C twobt 0C7A u2 193F uhalf 15FC undef 20DC +undefid 0000 uval 0592 val 03DF val1 03E1 w4 1944 +wrend 115C wrtbuf 1369 wrterr 2027 wrthex 15B7 wrtsym 145F +x3 194B x4 1951 xm1 195E xreg 0003 xrg 037E +zerlen 05E8  \ No newline at end of file diff --git a/2_printed_files/bundle_07/CHKDSK.A86 b/2_printed_files/bundle_07/CHKDSK.A86 new file mode 100644 index 0000000..32ea2ac --- /dev/null +++ b/2_printed_files/bundle_07/CHKDSK.A86 @@ -0,0 +1,560 @@ +00100 +00200 ; CHKDSK Version 1.0 03/10/81 +00300 +00400 ; Verifies and repairs 86-DOS disk directory. +00500 +00600 SETDRV: EQU 14 +00700 GETDRV: EQU 25 +00800 GETMAP: EQU 27 +00900 OPEN: EQU 15 +01000 CLOSE: EQU 16 +01100 DELETE: EQU 19 +01200 SETDMA: EQU 26 +01300 SRCHFST:EQU 17 +01400 SRCHNXT:EQU 18 +01500 OUTCH: EQU 2 +01600 BLKWRT: EQU 40 +01700 PRINTBUF:EQU 9 +01800 +01900 ORG 100H +02000 PUT 100H +02100 +02200 CHKDSK: +02205 MOV SP,STACK +02300 MOV AH,GETDRV +02400 INT 21H +02500 MOV [CURDRV],AL +02600 MOV DL,[5CH] +02700 OR DL,DL +02800 JZ DRVSET +02900 MOV AH,SETDRV +03000 DEC DL +03100 INT 21H +03110 CMP AL,DL +03120 JA DRVSET +03130 MOV DX,BADDRV +03135 ERROR: +03140 MOV AH,PRINTBUF +03150 INT 33 +03160 INT 32 +03170 +03175 BADDSK: +03177 MOV AX,CS +03178 MOV DS,AX +03180 MOV AH,SETDRV +03185 MOV DL,[CURDRV] +03190 INT 33 +03195 MOV DX,DIRBAD +03197 JP ERROR +03200 DRVSET: +03202 MOV B,[WRKDRV],DL ;Save drive indicator +03300 MOV AH,GETMAP +03400 INT 21H +03410 CMP B,[BX],0FEH ;Check for initialized disk +03420 JNE BADDSK +03500 PUSH DS +03600 PUSH ES +03700 POP DS +03800 MOV [DSKSIZ],DX ;Number of allocation units +03900 MOV [SECSIZ],CX ;Size of physical sector +04000 MOV AH,0 +04100 MOV [CLUSSIZ],AX ;Sectors per cluster +04200 MOV CX,DX +04300 MOV DI,MAP +04400 XOR AX,AX +04500 REP +04600 STOW ;Zero out allocation map +04700 MOV CX,AX +04800 MOV [ALLOC],AX ;Count of allocation units used +04900 MOV [FILECNT],AX ;Number of files found +05000 MOV [DELCNT],AX ;Number of files deleted due to error +05100 MOV BP,DI +05200 MOV [NAMTAB],BP ;First address of file list +05300 MOV DX,DI +05400 MOV AH,SETDMA +05500 INT 21H +05600 MOV AH,SRCHFST +05700 MOV DX,ALLFILE +05800 INT 21H +05900 INC AL +06000 POP ES ;ES:BX point to FAT +06100 JNZ GETFILES +06200 JMP COMPMAP +06300 GETFILES: +06400 INC CX ;Count number of files +06500 ADD DI,44 ;Separate in file in list by 44 bytes +06600 MOV DX,DI +06700 MOV AH,SETDMA +06800 INT 21H +06900 MOV AH,SRCHNXT +07000 MOV DX,ALLFILE +07100 INT 21H +07200 INC AL +07300 JNZ GETFILES ;Loop until all files are in list +07400 MOV [FILECNT],CX +07500 MOV CX,1 ;File number (position in list) +07600 MOV DX,[DSKSIZ] +07700 INC DX ;Maximum cluster number +07800 MOV [MAXCLUS],DX +07900 ADD BP,34 ;Point to "first cluster" entry +08000 EACHFIL: +08100 XOR AX,AX ;No. of clusters in file +08200 MOV SI,[BP] ;First cluster of file +08300 CMP SI,[MAXCLUS] ;Make sure it's legal +08400 MOV DI,BADDIR +08500 JA BADFIRST +08600 OR SI,SI ;Check for zero-length file +08700 JZ HAVENDJ +08800 SCANFAT: +08900 MOV DI,CX +09000 SHL SI +09100 XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. +09200 SHR SI +09300 OR DI,DI ;Should be zero for unallocated cluster +09400 JNZ CROSSLINK +09500 INC AX ;Count cluster as part of this file +09600 CALL UNPACK +09700 JZ FORCEND ;Make sure cluster knows it's allocated +09800 CMP DI,0FF8H ;Bigger than this means End of File +09900 HAVENDJ:JAE HAVEND +10000 CMP DI,[MAXCLUS] ;Make sure it's a legal value +10100 JA FORCEND +10200 MOV SI,DI +10300 JP SCANFAT ;Visit each cluster allocated to file +10400 +10500 BADFIRST: +10600 PUSH AX ;Because FILERR will pop it later +10700 MOV AX,CX +10800 MOV DX,44 +10900 DEC AX +11000 MUL AX,DX ;Get position in file name table +11100 MOV DX,AX +11200 ADD DX,[NAMTAB] +11300 MOV AH,DELETE +11400 INT 21H +11405 OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY +11450 JZ DISKOK +11452 JMP BADDSK +11454 DISKOK: +11500 INC [DELCNT] ;Count one deleted file +11600 MOV DX,BADDIR +11700 JP FILERR +11800 +11900 CROSSLINK: +12000 MOV DX,LINKED +12100 PUSH AX +12200 MOV AH,PRINTBUF +12300 INT 21H +12400 MOV AX,DI +12500 CALL PRINTNAM +12600 MOV DX,FILE2 +12700 MOV AH,PRINTBUF +12800 INT 33 +12900 MOV AX,CX +13000 CALL PRINTNAM +13100 MOV DX,CRLF +13200 MOV AH,PRINTBUF +13300 INT 33 +13400 POP AX +13500 ADD [ALLOC],AX +13600 JMP SIZSET1 +13700 +13800 FORCEND: +13900 ; Come here if a cluster allocated to a file contained an illegal +14000 ; link--either a zero (meaning unallocated), or a value larger than +14100 ; the maximum cluster number, but not End of File. Put an End of File +14200 ; mark there so the FAT will at least be well-formed. +14300 MOV DX,0FFFH +14400 CALL PACK +14500 MOV DX,BADCLUS +14600 PUSH AX +14700 +14800 FILERR: +14900 MOV AH,PRINTBUF +15000 INT 21H +15100 MOV AX,CX +15200 CALL PRINTNAM +15300 MOV DX,CRLF +15400 MOV AH,PRINTBUF +15500 INT 21H +15600 POP AX +15700 +15800 HAVEND: +15900 ADD [ALLOC],AX ;Total up allocated clusters +16000 MOV SI,AX +16100 MOV AX,[BP+2] +16200 MOV DX,[BP+4] ;AX:DX now have file length +16300 PUSH CX +16400 MOV CX,[CLUSSIZ] +16500 DEC CX +16600 ADD AX,CX +16700 ADC DX,0 +16800 INC CX +16900 SCALE: +17000 SHR CX +17100 JC SCALED +17200 SHR DX +17300 RCR AX +17400 JP SCALE +17500 SCALED: +17600 DIV AX,[SECSIZ] +17700 OR DX,DX +17800 JZ HAVSIZ +17900 INC AX +18000 HAVSIZ: +18100 CMP AX,SI ;See if file size corresponds with allocation +18200 JZ SIZSET +18300 XOR DI,DI +18400 MOV CX,[CLUSSIZ] +18500 CALL UNSCALE +18600 MOV [BP+6],SI +18700 MOV [BP+8],DI +18800 MOV DX,BP +18900 SUB DX,34 +19000 MOV AH,OPEN +19100 INT 21H +19110 OR AL,AL +19120 JZ DISKOK2 +19130 JMP BADDSK +19140 DISKOK2: +19200 MOV AX,[SECSIZ] +19300 MOV [BP-27+14],AX ;Make record size=sector size +19400 MOV CX,0 +19500 MOV AH,BLKWRT +19600 INT 21H +19700 MOV AH,CLOSE ;Write back corrected directory entry +19800 INT 21H +19900 MOV AH,GETMAP +20000 PUSH DS +20100 INT 33 ;Make sure FAT dirty bit is still set +20200 POP DS +20300 MOV DX,BADSIZ +20400 MOV AH,PRINTBUF +20500 INT 21H +20600 POP AX +20700 PUSH AX +20800 CALL PRINTNAM +20900 MOV DX,CRLF +21000 MOV AH,PRINTBUF +21100 INT 21H +21200 SIZSET: +21300 POP CX +21400 SIZSET1: +21500 ADD BP,44 ;Scan next file +21600 INC CX +21700 CMP CX,[FILECNT] +21800 JA COMPMAP +21900 JMP EACHFIL +22000 ; Now compare the allocation map we have made with the FAT. Any +22100 ; clusters not allocated in the map will be released. +22200 COMPMAP: +22300 XOR AX,AX ;Keep count of clusters released +22400 MOV BP,MAP +22500 MOV SI,2 ;First usable cluster number +22600 MOV CX,[DSKSIZ] +22700 RELCLUS: +22800 TEST [BP],-1 ;Allocated in our map? +22900 JNZ NXTCLUS ;If so, skip to next +23000 CALL UNPACK +23100 JZ NXTCLUS ;If not allocated, skip to next +23200 XOR DX,DX +23300 CALL PACK ;Change to "Free" status +23400 INC AX ;Count clusters released +23500 NXTCLUS: +23600 INC BP +23700 INC BP +23800 INC SI +23900 LOOP RELCLUS +24000 OR AX,AX ;Any clusters released? +24100 JZ REPORT ;If not, do final report +24200 MOV BX,FREED +24300 CALL DISPCLUS +24400 REPORT: +24500 ; Make status report. Include no. of files, total disk space, +24600 ; free space on disk, total memory, and free memory. +24610 SEG CS +24620 MOV DL,[CURDRV] +24630 MOV AH,SETDRV +24640 INT 21H +24700 MOV SI,[FILECNT] +24800 SUB SI,[DELCNT] +24900 XOR DI,DI +25000 MOV BX,NUMFIL +25100 CALL DISP32BITS +25200 MOV AX,[DSKSIZ] +25300 MOV BX,DSKSPC +25400 CALL DISPCLUS +25500 MOV AX,[DSKSIZ] +25600 SUB AX,[ALLOC] +25700 MOV BX,FRESPC +25800 CALL DISPCLUS +25900 MOV AX,[2] +26000 MOV DX,16 +26100 MUL AX,DX +26200 MOV SI,AX +26300 MOV DI,DX +26400 MOV BX,TOTMEM +26500 CALL DISP32BITS +26600 MOV AX,[2] +26700 MOV DX,CS +26800 SUB AX,DX +26900 MOV DX,16 +27000 MUL AX,DX +27100 MOV SI,AX +27200 MOV DI,DX +27300 MOV BX,FREMEM +27400 CALL DISP32BITS +27405 CALL WRTFRC ;Force all writes and handle write +27410 ;protect violation +27900 INT 20H ;All done +27902 +27904 WRTFRC: ;******************************************************** +27906 ; This code forces all writes by performing a disk +27908 ; reset (function 13). When the attempt to write +27910 ; the allocation table fails in the case of a write- +27912 ; protected diskette, this logic determines if the +27914 ; allocation table had changed and if no changes were +27916 ; made a normal termination will be forced +27918 ;********************************************************* +27919 MOV AX,DS +27920 PUSH DS ;Must first intercept INT 24H +27921 MOV ES,AX +27922 XOR AX,AX +27924 MOV DS,AX +27926 MOV SI,90H +27928 MOV DI,INT24 ;will move vector to local address +27930 MOV CX,2 +27931 CLD ;So move will increment +27932 REP +27934 MOVW ;Vector now locally stored +27936 MOV AL,24H ; +27938 MOV AH,37 +27940 MOV DX,WRTPRT ; +27942 POP DS ;Get local segment +27944 INT 21H ;Interrupt vector now set +27946 MOV AH,13 +27948 INT 21H +27953 PUSH ES ;Will now reset INT 24H vector +27955 XOR AX,AX +27957 MOV ES,AX +27959 CLD +27961 MOV DI,90H +27963 MOV SI,INT24 +27965 MOV CX,2 +27967 REP +27969 MOVW +27971 POP ES +27973 RET +27974 +27976 WRTPRT: ;********************************************************* +27978 ; This logic is designed to handle the case where +27980 ; CHKDSK found no problems and upon rewriting the +27982 ; allocation table (by the DOS) the disk was write- +27984 ; protected and an error thus occured. With no problems +27986 ; this code will cause normal termination, otherwise +27987 ; normal error handling will occur. +27988 ;********************************************************* +27990 EI ;Run with interrupts live +27992 AND DI,0FFH ;See if write-protect +27994 JNZ WRT100 ;Do normal error handling +27996 CMP AH,3 ;File allocation write? +27998 JNZ WRT100 ;If not do normal handling +27999 SEG CS +28000 CMP [WRKDRV],AL ;Correct drive? +28002 JNZ WRT100 ; +28003 SEG CS +28004 CMP B,[CHGCLS],1 ;Legitimate change? +28006 JZ WRT100 ;If so do normal handling +28007 XOR AL,AL ;Ignore the error +28008 IRET +28009 WRT100: SEG CS +28010 JMP L,[INT24] ;Normal error handling +28012 +28014 +28015 +28100 UNPACK: +28200 MOV DI,SI +28300 SHR DI +28400 ADD DI,SI +28500 SEG ES +28600 MOV DI,[DI+BX] +28700 TEST SI,1 +28800 JZ HAVCLUS +28900 SHR DI +29000 SHR DI +29100 SHR DI +29200 SHR DI +29300 HAVCLUS: +29400 AND DI,0FFFH +29500 RET +29600 +29700 PACK: +29705 ;************************************************************* +29710 ; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +29715 ; SI CLUSTER NUMBER TO BE PACKED +29720 ; DX POINTER TO BE PLACED IN CLUSTER (SI) +29725 ;************************************************************* +29730 MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED +29800 PUSH SI +29900 MOV DI,SI +30000 SHR SI +30100 ADD SI,BX +30200 ADD SI,DI +30300 SHR DI +30400 SEG ES +30500 MOV DI,[SI] +30600 JNC ALIGNED +30700 SHL DX +30800 SHL DX +30900 SHL DX +31000 SHL DX +31100 AND DI,0FH +31200 JP PACKIN +31300 ALIGNED: +31400 AND DI,0F000H +31500 PACKIN: +31600 OR DI,DX +31700 SEG ES +31800 MOV [SI],DI +31900 POP SI +32000 RET +32100 +32200 UNSCALE: +32300 SHR CX +32400 JC RET +32500 SHL SI +32600 RCL DI +32700 JP UNSCALE +32800 +32900 DISPCLUS: +33000 MUL AX,[SECSIZ] +33100 MOV CX,[CLUSSIZ] +33200 MOV SI,AX +33300 MOV DI,DX +33400 CALL UNSCALE +33500 DISP32BITS: +33600 PUSH BX +33700 XOR AX,AX +33800 MOV BX,AX +33900 MOV BP,AX +34000 MOV CX,32 +34100 CONVLP: +34200 SHL SI +34300 RCL DI +34400 XCHG AX,BP +34500 CALL CONVWRD +34600 XCHG AX,BP +34700 XCHG AX,BX +34800 CALL CONVWRD +34900 XCHG AX,BX +35000 ADC AL,0 +35100 LOOP CONVLP +35200 ; Conversion complete. Print 10-digit number with 2 leading blanks. +35300 MOV CX,1B10H +35400 CALL OUTWORD +35500 MOV AX,BX +35600 CALL OUTWORD +35700 MOV AX,BP +35800 CALL OUTWORD +35900 POP DX +36000 MOV AH,PRINTBUF +36100 INT 21H +36200 RET +36300 +36400 OUTWORD: +36500 PUSH AX +36600 MOV DL,AH +36700 CALL OUTBYTE +36800 POP DX +36900 OUTBYTE: +37000 MOV DH,DL +37100 SHR DL +37200 SHR DL +37300 SHR DL +37400 SHR DL +37500 CALL DIGIT +37600 MOV DL,DH +37700 DIGIT: +37800 AND DL,0FH +37900 JZ BLANKZER +38000 MOV CL,0 +38100 BLANKZER: +38200 DEC CH +38300 AND CL,CH +38400 OR DL,30H +38500 SUB DL,CL +38600 MOV AH,OUTCH +38700 INT 21H +38800 RET +38900 +39000 CONVWRD: +39100 ADC AL,AL +39200 DAA +39300 XCHG AL,AH +39400 ADC AL,AL +39500 DAA +39600 XCHG AL,AH +39700 RET +39800 +39900 PRINTNAM: +39910 PUSH CX +40000 DEC AX +40100 MOV CX,44 +40200 MUL AX,CX +40300 MOV SI,AX +40400 ADD SI,[NAMTAB] +40500 ADD SI,8 +40600 MOV CX,8 +40700 MOV AH,OUTCH +40800 CALL PRINTCNT +40900 MOV DL," " +41000 INT 21H +41100 MOV CL,3 +41110 CALL PRINTCNT +41120 POP CX +41130 RET +41140 +41200 PRINTCNT: +41300 LODB +41400 MOV DL,AL +41500 INT 21H +41700 LOOP PRINTCNT +41800 RET +41900 +41950 ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB +42000 DB 0,"???????????" +42100 DS 25 +42200 +42300 FILE2: DB " and $" +42305 BADDRV: DB "Invalid drive specification$" +42400 BADCLUS:DB "Allocation error for file $" +42500 BADDIR: DB "Directory error-file : $" +42600 LINKED: DB "Files cross-linked: " +42605 DB 13,10 +42610 DB " $" +42700 BADSIZ: DB "File size error for file $" +42705 DIRBAD: DB "Diskette not initialized $" +42800 FREED: DB " bytes disk space freed",13,10,13,10,"$" +42900 NUMFIL: DB " disk files",13,10,"$" +43000 DSKSPC: DB " bytes total disk space",13,10,"$" +43100 FRESPC: DB " bytes remain available",13,10,13,10,"$" +43200 TOTMEM: DB " bytes total memory",13,10,"$" +43300 FREMEM: DB " bytes free" +43400 CRLF: DB 13,10,"$" +43500 +43600 DSKSIZ: DS 2 +43700 SECSIZ: DS 2 +43800 CLUSSIZ:DS 2 +43805 CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +43810 WRKDRV: DB 0 +43815 INT24: DS 4 +43900 FILECNT:DS 2 +44000 NAMTAB: DS 2 +44100 ALLOC: DS 2 +44200 MAXCLUS:DS 2 +44300 DELCNT: DS 2 +44400 CURDRV: DS 1 +44405 DS 100H +44410 STACK: +44500 +44600 MAP: diff --git a/2_printed_files/bundle_08/86DOS.DIF b/2_printed_files/bundle_08/86DOS.DIF new file mode 100644 index 0000000..bc003ee --- /dev/null +++ b/2_printed_files/bundle_08/86DOS.DIF @@ -0,0 +1,1810 @@ +File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1)1 00230 SMALLDIR: EQU 1 ;1 to enable, 0 to disable +1) 00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +**** +2)1 00230 SMALLDIR: EQU 0 ;1 to enable, 0 to disable +2) 00260 ; Turn on switch below to allow testing disk code with DEBUG. It sets +************** +1)1 00300 DSKTEST: EQU 0 ;1 to enable, 0 to disable +1) 00330 ; Interrupt Entry Points: +**** +2)1 00300 DSKTEST: EQU 1 ;1 to enable, 0 to disable +2) 00330 ; Interrupt Entry Points: +************** +1)1 00460 MAXCOM: EQU 41 +1) 00470 ESCCH: EQU 1BH +1) 00480 INTBASE:EQU 80H +**** +2)1 00460 MAXCOM: EQU 45 +2) 00470 ESCCH: EQU 0 +2) 00480 INTBASE:EQU 80H +************** +1)1 00590 ; Field definition for FCBs +**** +2)1 00580 ;Date format +2) 00590 ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 +2) 00600 ; y y y y y y y m m m m d d d d d +2) 00610 ; +2) 00620 ;where y=year,m=month,d=day +2) 00640 ; Field definition for FCBs +************** +1)1 00790 ; +1) 00800 ; Location bytes Description +1) 00810 ; +1) 00820 ; 0 11 File name and extension ( 0E5H if empty) +1) 00830 ; 11 13 Zero field (for expansion) +1) 00840 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +**** +2)1 00850 ; Location bytes Description +2) 00870 ; 0 11 File name and extension ( 0E5H if empty) +2) 00880 ; 11 1 Attributes. Bits 1 or 2 make file hidden +2) 00890 ; 12 12 Zero field (for expansion) +2) 00900 ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +************** +1)1 00870 ; +1) 00880 ; The File Allocation Table uses a 12-bit entry for each allocation unit on +1) 00890 ; the disk. These entries are packed, two for every three bytes. The contents +1) 00900 ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +1) 00910 ; to the base address of the Allocation Table; 3) fetching the 16-bit word at +1) 00920 ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +1) 00930 ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +1) 00940 ; zero is used as an end-of-file trap in the OS and as a flag for directory +1) 00950 ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The +1) 00960 ; first available allocation unit is assigned entry number two, and for Drive Parameter Block +1) 00980 ORG 0 +**** +2)1 00950 ; Field definition for Drive Parameter Block +2) 00970 ORG 0 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 01270 BIOSSEG: EQU 40H +1) 01280 ORG 0 +**** +2)1 01260 BIOSSEG: EQU 60H +2) 01270 ORG 0 +************** +1)1 01650 ESCTAB: +1) 01660 DB "SC" ;Copy one char +1) 01670 DB "VN" ;Skip one char +1) 01680 DB "TA" ;Copy to char +1) 01690 DB "WB" ;Skip to char +1) 01700 DB "UH" ;Copy line +1) 01710 DB "HH" ;Kill line (no change in template) +1) 01720 DB "RM" ;Reedit line (new template) +1) 01730 DB "DD" ;Backspace +1) 01740 DB "P@" ;Enter insert mode +1) 01750 DB "QL" ;Exit insert mode +1) 01760 DB ESCCH,ESCCH ;Escape character +1) 01770 DB ESCCH,ESCCH ;End of table +1) 01790 ESCTABLEN:EQU $-ESCTAB +1) 01810 HEADER: DB 13,10,"86-DOS version 1.00" +1) 01830 IF DSKTEST +1) 01840 DB "D" +1) 01850 ENDIF +1) 01870 DB 13,10 +1) 01880 DB "Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$" +1) 01900 QUIT: +**** +2)1 01630 ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +2) 01640 ESCTAB: +2) 01650 DB 77 ;Copy one char--RIGHT ARROW +2) 01660 DB 59 ;Copy one char--F1 +2) 01670 DB 83 ;Skip one char--DELETE +2) 01680 DB 60 ;Copy to char--F2 +2) 01690 DB 62 ;Skip to char--F4 +2) 01700 DB 61 ;Copy line--F3 +2) 01710 DB 64 ;Ctrl-Z--F6 +2) 01720 DB 63 ;Reedit line (new template)--F5 +2) 01730 DB 75 ;Backspace--LEFT ARROW +2) 01740 DB 82 ;Toggle insert mode--INSERT +2) 01750 DB 65 ;Escape character--F7 +2) 01760 DB 65 ;End of table +2) 01780 ESCTABLEN:EQU $-ESCTAB +2) 01810 QUIT: +************** +1)1 02420 MOV BP,SP +1) 02430 MOV BX,[BP+CSSAVE] +1) 02440 SEG CS +1) 02450 MOV [CSLOC],BX +1) 02460 MOV SP,CS +1) 02470 MOV SS,SP +1) 02480 MOV SP,STACK +1) 02490 EI ;Stack OK now +**** +2)1 02330 MOV SP,CS + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 02340 MOV SS,SP +2) 02350 REDISP: +2) 02360 MOV SP,IOSTACK +2) 02370 EI ;Stack OK now +************** +1)1 02570 IF DSKTEST +1) 02580 CMP AH,12 +1) 02590 JL SAMSTK +1) 02600 MOV SP,TESTSTK +1) 02610 SAMSTK: +1) 02620 ENDIF +1) 02640 SEG CS +**** +2)1 02440 CMP AH,12 +2) 02450 JLE SAMSTK +2) 02460 MOV SP,DSKSTACK +2) 02470 SAMSTK: +2) 02480 SEG CS +************** +1)1 02790 MOV [SPSA ENDIF +1) 02810 PBX +1) 02820 POP CX +**** +2)1 02630 MOV [SPSAVE],AX +2) 02640 SEG CS +2) 02650 MOV AX,[NSS] +2) 02660 SEG CS +2) 02670 MOV [SSSAVE],AX +2) 02680 ENDIF +2) 02700 POP AX +2) 02710 POP BX +2) 02720 POP CX +************** +1)1 02930 DW ABORT ;0 +1) 02940 DW CONIN +**** +2)1 02830 DW ABORT +2) 02840 DW CONIN +************** +1)1 02980 DW LIST ;5 +1) 02990 DW RAWIO +**** +2)1 02880 DW LIST +2) 02890 DW RAWIO +************** +1)1 03030 DW BUFIN ;10 +1) 03040 DW CONSTAT +1) 03050 DW VERSION +1) 03060 DW DSKRESET +1) 03070 DW SELDSK +1) 03080 DW OPEN ;15 +1) 03090 DW CLOSE +**** +2)1 02930 DW BUFIN +2) 02940 DW CONSTAT +2) 02950 DW FLUSHKB + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 02960 DW DSKRESET +2) 02970 DW SELDSK +2) 02980 DW OPEN +2) 02990 DW CLOSE +************** +1)1 03130 DW SEQRD ;20 +1) 03140 DW SEQWRT +**** +2)1 03030 DW SEQRD +2) 03040 DW SEQWRT +************** +1)1 03180 DW CURDRV ;25 +1) 03190 DW SETDMA +**** +2)1 03080 DW CURDRV +2) 03090 DW SETDMA +************** +1)1 03230 DW SETATTRIB ;30 +1) 03240 DW GETDSKPT +**** +2)1 03130 DW SETATTRIB +2) 03140 DW GETDSKPT +************** +1)1 03280 DW FILESIZE ;35 +1) 03290 DW SETRNDREC +**** +2)1 03180 DW FILESIZE +2) 03190 DW SETRNDREC +************** +1)1 03370 VERSION: +1) 03380 GETIO: +**** +2)1 03260 DW GETDATE +2) 03270 DW SETDATE +2) 03280 DW GETTIME +2) 03290 DW SETTIME ;45 +2) 03310 GETIO: +************** +1)1 03440 MOV AL,0 +1) 03450 RET +1) 03480 READER: +1) 03490 CALL BIOSAUXIN,BIOSSEG +**** +2)1 03370 INUSE: +2) 03380 GETDSKPT: +2) 03390 MOV AL,0 +2) 03400 RET +2) 03420 FLUSHKB: +2) 03430 XOR BX,BX +2) 03440 MOV ES,BX ;Select segment 0 +2) 03450 SEG ES +2) 03460 MOV B,[41AH],1EH ;Reset KB queue head pointer +2) 03470 SEG ES +2) 03480 MOV B,[41CH],1EH ;Reset tail pointer +2) 03490 MOV AH,AL +2) 03500 CMP AL,1 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 03510 JZ REDISPJ +2) 03520 CMP AL,7 +2) 03530 JZ REDISPJ +2) 03540 CMP AL,8 +2) 03550 JZ REDISPJ +2) 03560 CMP AL,10 +2) 03570 JZ REDISPJ +2) 03575 MOV AL,0 +2) 03580 RET +2) 03600 REDISPJ:JMP REDISP +2) 03620 READER: +2) 03630 AUXIN: +2) 03640 CALL STATCHK +2) 03650 CALL BIOSAUXIN,BIOSSEG +************** +1)1 03540 CALL BIOSAUXOUT,BIOSSEG +**** +2)1 03700 AUXOUT: +2) 03710 PUSH AX +2) 03720 CALL STATCHK +2) 03730 POP AX +2) 03740 CALL BIOSAUXOUT,BIOSSEG +************** +1)1 03860 MOV SI,BADMES +1) 03870 CALL OUTMES +1) 03880 JMP ERROR +1) 03910 PACK: +**** +2)1 04070 PUSH AX +2) 04080 MOV AH,80H +2) 04090 MOV DI,0FFFH +2) 04100 CALL FATAL +2) 04110 POP AX +2) 04120 RET +2) 04150 PACK: +************** +1)1 04230 IOCHK: +1) 04240 MOV CX,5 ;Check rest of name but not extension +1) 04250 CMP B,[DI],":" +1) 04260 JNZ NOCOL +1) 04270 INC DI ;Skip over colon +1) 04280 DEC CX +1) 04290 NOCOL: +1) 04300 MOV AL," " +**** +2)1 04454 DEVNAME: +2) 04455 MOV SI,IONAME ;List of I/O devices with file names +2) 04456 MOV BL,6 ;BL = number of device names +2) 04457 LOOKIO: +2) 04458 MOV DI,NAME1 +2) 04459 MOV CX,4 ;All device names are 4 letters +2) 04460 REPE +2) 04461 CMPB ;Check for name in list +2) 04462 JZ IOCHK ;If first 4 letters OK, check the rest +2) 04463 ADD SI,CX ;Point to next device name +2) 04464 DEC BL + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 04465 JNZ LOOKIO +2) 04466 CRET: +2) 04467 STC +2) 04468 RET +2) 04470 IOCHK: +2) 04480 MOV CX,4 ;Check rest of name but not extension +2) 04490 MOV AL," " +************** +1)1 04330 JNZ FILSRCH +1) 04340 DEC BL +1) 04350 RET +1) 04370 GETFILE: +1) 04390 ; Inputs: +**** +2)1 04520 JNZ CRET +2) 04530 MOV AL,BL +2) 04540 MOV BX,IONUM-1 +2) 04550 XLAT ;Translate to internal device number +2) 04560 MOV BL,AL +2) 04570 MOV BH,-1 +2) 04580 RET +2) 04600 GETFILE: +2) 04610 ; Same as GETNAME except ES:DI points to FCB on successful return +2) 04620 CALL MOVNAME +2) 04630 JC RET +2) 04640 PUSH DX +2) 04650 PUSH DS +2) 04660 CALL FINDNAME +2) 04670 POP ES +2) 04680 POP DI +2) 04690 RET +2) 04710 GETNAME: +2) 04730 ; Inputs: +************** +1)1 04480 ; BP = Base of drive parameters +**** +2)1 04820 ; Zero set if attributes match (always except when creating) +2) 04830 ; BP = Base of drive parameters +************** +1)1 04620 MOV SI,IONAME ;List of I/O devices with file names +1) 04630 MOV BX,0FF04H ;BL = number of devices +1) 04640 LOOKIO: +1) 04650 MOV DI,NAME1 +1) 04660 MOV CX,3 ;All device names are 3 letters +1) 04670 REPE +1) 04680 CMPB ;Check for name in list +1) 04690 JZ IOCHK ;If first 3 letters OK, check the rest +1) 04700 ADD SI,CX ;Point to next device name +1) 04710 DEC BL +1) 04720 JNZ LOOKIO +1) 04730 FILSRCH: ;Not a device name +1) 04740 CALL STARTSRCH +**** +2)1 04961 CALL DEVNAME +2) 04962 JNC RET +2) 05090 CALL STARTSRCH + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 05010 ADD SI,15 +1) 05020 RET +**** +2)1 05370 ;Check if attributes allow finding it +2) 05380 MOV AH,[ATTRIB] ;Attributes of search +2) 05390 NOT AH +2) 05400 AND AH,[SI] ;Compare with attributes of file +2) 05410 ADD SI,15 +2) 05420 AND AH,6 ;Only look at bits 1 and 2 +2) 05430 JZ RET +2) 05440 TEST B,[CREATING],-1 +2) 05450 JZ NEXTENT +2) 05460 RET +************** +1)1 05230 MOV [LASTENT],AX +**** +2)1 05670 GETENT: +2) 05680 MOV [LASTENT],AX +************** +1)1 05920 CALL GETFILE +1) 05930 JC ERRET +1) 05940 CMP BH,-1 ;Check if device name +1) 05950 JZ ERRET ;Can't delete I/O devices +1) 05960 DELFILE: +**** +2)1 06370 CALL GETNAME +2) 06375 MOV AL,-1 +2) 06380 JC RET +2) 06390 CMP BH,AL ;Check if device name +2) 06400 JZ RET ;Can't delete I/O devices +2) 06410 DELFILE: +************** +1)1 06180 CMP BH,-1 ;Check if I/O device name +1) 06190 JZ ERRET ;If so, can't rename it +1) 06200 ADD SI,5 +**** +2)1 06650 ADD SI,5 +************** +1)1 06250 RENFIL: +1) 06260 MOV B,[DIRTYDIR],-1 +1) 06270 MOV DI,BX +1) 06280 MOV SI,NAME2 +**** +2)1 06692 CMP BH,-1 ;Check if I/O device name +2) 06694 JZ ERRET ;If so, can't rename it +2) 06700 MOV SI,NAME1 +2) 06710 MOV DI,NAME3 +2) 06720 MOV CX,6 ;Include attribute byte +2) 06730 REP +2) 06740 MOVW ;Copy name to search for +2) 06750 RENFIL: +2) 06760 MOV DI,NAME1 +2) 06770 MOV SI,NAME2 +************** +1)1 06330 JZ NOCHG + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 06340 MOV [DI],AL +1) 06350 NOCHG: +1) 06360 INC DI +1) 06370 LOOP NEWNAM +1) 06380 CALL CONTSRCH +**** +2)1 06820 JNZ NOCHG +2) 06830 MOV AL,[BX] +2) 06840 NOCHG: +2) 06850 STOB +2) 06860 INC BX +2) 06870 LOOP NEWNAM +2) 06871 MOV B,[DI],6 ;Stop duplicates with any attributes +2) 06872 CALL DEVNAME ;Check if giving it a device name +2) 06874 JNC RENERR +2) 06890 PUSH [LASTENT] ;Save position of match +2) 06895 MOV [LASTENT],-1 ;Search entire dirctory for duplicate +2) 06900 CALL CONTSRCH ;See if new name already exists +2) 06910 POP AX +2) 06920 JNC RENERR ;Error if found +2) 06930 CALL GETENT ;Re-read matching entry +2) 06940 MOV DI,BX +2) 06950 MOV SI,NAME1 +2) 06960 MOV CX,11 +2) 06970 REP +2) 06980 MOVB ;Replace old name with new +2) 06990 MOV B,[DIRTYDIR],-1 ;Flag change in directory +2) 07000 MOV SI,NAME3 +2) 07010 MOV DI,NAME1 +2) 07020 MOV CX,6 ;Include attribute byte +2) 07030 REP +2) 07040 MOVW ;Copy name back into search buffer +2) 07050 CALL CONTSRCH +************** +1)1 06440 ERRET: +**** +2)1 07102 RENERR: +2) 07104 CALL CHKDIRWRITE +2) 07110 ERRET: +************** +1)1 06520 ; DS, DX point to FCB +1) 06530 ; Outputs: +1) 06540 ; ES = CS +**** +2)1 07190 ; DS, DX point to FCB or extended FCB +2) 07200 ; Outputs: +2) 07210 ; DS:DX point to normal FCB +2) 07220 ; ES = CS +************** +1)1 06610 MOV AX,CS +**** +2)1 07290 SEG CS +2) 07300 MOV B,[CREATING],0 +2) 07310 MOV AX,CS +************** +1)1 06660 CALL GETBP + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +**** +2)1 07360 SEG CS +2) 07370 MOV [EXTFCB],AL +2) 07380 MOV AH,0 +2) 07390 CMP AL,-1 +2) 07400 JNZ HAVATTRB +2) 07410 ADD DX,7 +2) 07420 ADD SI,6 +2) 07430 MOV AH,[SI-1] +2) 07440 LODB +2) 07450 HAVATTRB: +2) 07460 SEG CS +2) 07470 MOV [ATTRIB],AH +2) 07480 CALL GETBP +************** +1)1 06730 LODB +1) 06740 AND AL,7FH +1) 06750 CMP AL,60H +1) 06760 JLE CASEOK +1) 06770 AND AL,5FH +1) 06780 CASEOK: +1) 06790 CMP AL,20H +**** +2)1 07550 CALL GETLET +2) 07560 JNZ CTRLCHK ;Is it a delimiter? +2) 07570 CMP AL," " ;This is the only delimiter allowed +2) 07580 STC ;In case of error +2) 07590 JNZ RET +2) 07600 CTRLCHK: +2) 07610 CMP AL,20H +************** +1)1 06970 PUSH DX +1) 06980 PUSH DS +1) 06990 CALL GETFILE +**** +2)1 07790 CALL GETFILE +************** +1)1 07020 ; in directory. DS=ES=CS, BX points to directory +1) 07030 ; entry in DIRBUF, SI points to First Cluster field, and +1) 07040 ; the top of the stack has the address and segment +1) 07050 ; of the FCB to be opened. This entry point is used +1) 07060 ; by CREATE. +1) 07070 POP ES +1) 07080 POP DI +1) 07090 JC ERRET +**** +2)1 07820 ; in directory. DS=CS, BX points to directory +2) 07830 ; entry in DIRBUF, SI points to First Cluster field, and +2) 07840 ; ES:DI point to the FCB to be opened. This entry point +2) 07850 ; is used by CREATE. +2) 07860 JC ERRET +************** +1)1 07870 PUSH DX +1) 07880 PUSH CX +1) 07890 PUSH BX +1) 07900 PUSH AX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 07910 CALL DREAD +1) 07920 OR AL,AL +1) 07930 POP AX +1) 07940 POP BX +1) 07950 POP CX +1) 07960 POP DX +1) 07970 JNZ BADFAT +1) 07990 IF SMALLDIR +**** +2)1 08640 PUSH AX +2) 08650 CALL DSKREAD +2) 08660 POP AX +2) 08670 JC BADFAT +2) 08690 IF SMALLDIR +************** +1)1 08220 ADD DX,CX +**** +2)1 08920 MOV CX,DI +2) 08930 ADD DX,CX +************** +1)1 08250 POP BP +1) 08260 ;{Insert error code here. All FATs on drive are bad.} +1) 08270 MOV SI,BADFATMES +1) 08280 CALL HARDERR +1) 08290 JP FATREAD +1) 08310 OKRET1: +**** +2)1 08960 CALL FIGFAT ;Reset registers +2) 08970 JMP DREAD ;Try first FAT once more +2) 08990 OKRET1: +************** +1)1 08370 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +**** +2)1 09050 CMP B,[DI],-1 +2) 09060 JNZ NORMFCB3 +2) 09070 ADD DI,7 +2) 09080 NORMFCB3: +2) 09090 CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device +************** +1)1 08620 PUSH DX +1) 08630 PUSH DS +1) 08640 CALL GETFILE +1) 08650 POP ES +1) 08660 POP DI +1) 08670 BADCLOSEJ: +**** +2)1 09340 CALL GETFILE +2) 09350 BADCLOSEJ: +************** +1)1 09710 PUSH DX +**** +2)1 10390 SEG CS +2) 10400 MOV B,[CREATING],1 +2) 10410 PUSH DX +************** +1)1 09820 POP DS + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +**** +2)1 10520 ERRPOP: +2) 10530 POP DS +************** +1)1 09890 CMP BH,-1 ;Check if file is I/O device +1) 09900 JZ OPENJMP ;If so, no action +1) 09910 XOR CX,CX +1) 09920 MOV [SI+2],CX +1) 09930 MOV AX,[DATE] +1) 09950 IF SMALLDIR +1) 09960 MOV [SI+4],CL +1) 09970 CMP B,[BP+DIRSIZ],-1 +1) 09980 JZ SMLENT +1) 09990 MOV [SI+5],CL +1) 10000 MOV [SI-2],AX +1) 10010 SMLENT: +1) 10020 ENDIF +1) 10040 IF 1-SMALLDIR +1) 10050 MOV [SI+4],CX +1) 10060 MOV [SI-2],AX +1) 10070 ENDIF +1) 10090 XCHG CX,[SI] +1) 10100 PUSH SI +1) 10110 PUSH BX +1) 10120 JCXZ WRTBACK +1) 10130 CMP CX,[BP+MAXCLUS] +1) 10140 JA WRTBACK +1) 10150 MOV BX,CX +1) 10160 LEA SI,[BP+FAT] +1) 10170 CALL RELEASE +1) 10180 CALL FATWRT +1) 10190 JP WRTBACK +1) 10210 FREESPOT: +**** +2)1 10600 JNZ ERRPOP ;Error if attributes don't match +2) 10610 CMP BH,-1 ;Check if file is I/O device +2) 10620 JZ OPENJMP ;If so, no action +2) 10630 MOV CX,[SI] ;Get pointer to clusters +2) 10640 JCXZ FREESPOT +2) 10650 CMP CX,[BP+MAXCLUS] +2) 10660 JA FREESPOT +2) 10670 PUSH BX +2) 10680 MOV BX,CX +2) 10690 LEA SI,[BP+FAT] +2) 10700 CALL RELEASE ;Free any data already allocated +2) 10710 CALL FATWRT +2) 10720 POP BX +2) 10730 FREESPOT: +************** +1)1 10280 XOR AX,AX +1) 10300 IF SMALLDIR +**** +2)1 10810 IF SMALLDIR +************** +1)1 10350 JP SMALLENT +**** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2)1 10860 XOR AX,AX +2) 10870 JP SMALLENT +************** +1)1 10390 MOV CL,13 +1) 10400 REP +1) 10410 STOB +1) 10420 MOV AX,[DATE] +1) 10430 STOW +**** +2)1 10910 MOV AL,[ATTRIB] +2) 10920 STOB +2) 10930 XOR AX,AX +2) 10940 MOV CL,6 +2) 10950 REP +2) 10960 STOW +2) 10970 CALL DATE16 +2) 10980 STOW +************** +1)1 10510 WRTBACK: +1) 10520 CALL DIRWRITE +**** +2)1 11060 CALL DIRWRITE +************** +1)1 10570 JMP DOOPEN +**** +2)1 11110 POP ES +2) 11120 POP DI +2) 11130 JMP DOOPEN +************** +1)1 10940 ; Outputs: +1) 10950 ; AL = 0 if no error, otherwise non-zero +1) 10960 ; BP preserved. All other registers destroyed. +1) 10980 MOV AL,[BP+DRVNUM] +**** +2)1 11500 ; BP preserved. All other registers destroyed. +2) 11520 CALL DSKREAD +2) 11530 JNC RET +2) 11540 SEG CS +2) 11550 MOV B,[READOP],0 +2) 11560 CALL HARDERR +2) 11570 CMP AL,1 ;Check for retry +2) 11580 JZ DREAD +2) 11590 RET ;Ignore otherwise +2) 11610 HARDERR: +2) 11620 ;Hard disk error handler. Entry conditions: +2) 11630 ; DS:BX = Original disk transfer address +2) 11640 ; DX = Original logical sector number +2) 11650 ; CX = Number of sectors to go (first one gave the error) +2) 11660 ; AX = Hardware error code +2) 11670 ; DI = Original sector transfer count +2) 11680 ; BP = Base of drive parameters +2) 11690 ; [READOP] = 0 for read, 1 for write +2) 11710 XCHG AX,DI ;Error code in DI, count in AX +2) 11720 SUB AX,CX ;Number of sectors successfully transferred +2) 11730 ADD DX,AX ;First sector number to retry +2) 11740 PUSH DX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 11750 MUL AX,[BP+SECSIZ] ;Number of bytes transferred +2) 11760 POP DX +2) 11770 ADD BX,AX ;First address for retry +2) 11780 MOV AH,0 ;Flag disk section in error +2) 11790 CMP DX,[BP+FIRFAT] ;In reserved area? +2) 11800 JB ERRINT +2) 11810 INC AH ;Flag for FAT +2) 11820 CMP DX,[FIRDIR] ;In FAT? +2) 11830 JB ERRINT +2) 11840 INC AH +2) 11850 CMP DX,[FIRREC] ;In directory? +2) 11860 JB ERRINT +2) 11870 INC AH ;Must be in data area +2) 11880 ERRINT: +2) 11890 SHL AH ;Make room for read/write bit +2) 11900 SEG CS +2) 11910 OR AH,[READOP] +2) 11920 FATAL: +2) 11930 MOV AL,[BP+DRVNUM] ;Get drive number +2) 11940 PUSH BP ;The only thing we preserve +2) 11950 SEG CS +2) 11960 MOV [CONTSTK],SP +2) 11970 DI ;Prepare to play with stack +2) 11980 SEG CS +2) 11990 MOV SS,[SSSAVE] +2) 12000 SEG CS +2) 12010 MOV SP,[SPSAVE] ;User stack pointer restored +2) 12020 INT 24H ;Fatal error interrupt vector +2) 12030 SEG CS +2) 12040 MOV [SPSAVE],SP +2) 12050 SEG CS +2) 12060 MOV [SSSAVE],SS +2) 12070 MOV SP,CS +2) 12080 MOV SS,SP +2) 12090 SEG CS +2) 12100 MOV SP,[CONTSTK] +2) 12110 EI +2) 12120 POP BP +2) 12130 CMP AL,2 +2) 12140 JZ ERROR +2) 12150 RET +2) 12170 DSKREAD: +2) 12180 MOV AL,[BP+DRVNUM] +************** +1)1 11080 JC HARDREAD +1) 11090 XOR AL,AL +1) 11100 RET +1) 11120 HARDREAD: +1) 11130 MOV SI,RDERRMES +1) 11140 CALL HARDERR +1) 11150 JP DREAD +1) 11180 CHKDIRWRITE: +**** +2)1 12280 RET +2) 12310 CHKDIRWRITE: +************** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1)1 11490 ; Outputs: +1) 11500 ; AL = 0 if no error, otherwise non-zero +1) 11510 ; BP preserved. All other registers destroyed. +1) 11530 MOV AL,[BP+DRVNUM] +1) 11540 WRTDRV: +1) 11550 PUSH AX +1) 11560 PUSH BP +**** +2)1 12620 ; BP preserved. All other registers destroyed. +2) 12640 MOV AL,[BP+DRVNUM] +2) 12650 PUSH BP +************** +1)1 11650 POP AX +1) 11660 JC HARDWRITE +1) 11670 XOR AL,AL +1) 11680 RET +1) 11690 HARDWRITE: +1) 11700 MOV SI,WRTERRMES +1) 11710 CALL HARDERR +1) 11720 JP WRTDRV +1) 11750 HARDERR: +1) 11760 SUB DI,CX +1) 11770 ADD DX,DI +1) 11780 CALL SHFTDI7 +1) 11790 ADD BX,DI +1) 11800 MOV AH,AL ;Save drive number +1) 11810 CALL OUTMES +1) 11820 GETINSTR: +1) 11830 CALL IN +1) 11840 OR AL,20H +1) 11850 CMP AL,"a" +1) 11860 JZ ERROR +1) 11870 CMP AL,"r" +1) 11880 JZ RETRY +1) 11890 CMP AL,"i" +1) 11900 JZ IGNORE +1) 11910 CMP AL,"c" +1) 11920 JNZ GETINSTR +1) 11930 CONTINUE: +1) 11940 POP AX +1) 11950 MOV AL,1 +1) 11960 RET +1) 11970 IGNORE: +1) 11980 POP AX +1) 11990 MOV AL,0 +1) 12000 RET +1) 12010 RETRY: +1) 12020 MOV AL,AH ;Restore drive number +1) 12030 RET +**** +2)1 12740 JNC RET +2) 12750 SEG CS +2) 12760 MOV B,[READOP],1 +2) 12770 CALL HARDERR +2) 12780 CMP AL,1 ;Check for retry +2) 12790 JZ DWRITE + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 12800 RET +************** +1)1 12080 MOV DS,[CSLOC] +1) 12090 XOR AX,AX +**** +2)1 12840 LDS SI,[SPSAVE] +2) 12850 MOV DS,[SI+CSSAVE] +2) 12860 XOR AX,AX +************** +1)1 13120 MOV AX,[DI+RR] +**** +2)1 13890 CMP B,[DI],-1 +2) 13900 JNZ NORMFCB1 +2) 13910 ADD DI,7 +2) 13920 NORMFCB1: +2) 13930 MOV AX,[DI+RR] +************** +1)1 13180 MOV B,[DSKERR],-2 +1) 13190 POP BX +**** +2)1 13990 MOV B,[DSKERR],4 +2) 14000 POP BX +************** +1)1 13880 DIV AX,[BP+SECSIZ] +1) 13890 MOV [SECPOS],AX +**** +2)1 14690 MOV BX,[BP+SECSIZ] +2) 14700 CMP DX,BX ;See if divide will overflow +2) 14710 JNC EOFERR +2) 14720 DIV AX,BX +2) 14730 MOV [SECPOS],AX +************** +1)1 14020 JZ OK ;Must stay within 64K +1) 14030 MOV AX,[DMAADD] +1) 14040 NEG AX ;Amount of room left in segment +1) 14050 XOR DX,DX +1) 14060 DIV AX,SI ;How many records will fit? +1) 14070 MUL AX,SI ;Translate that back into bytes +**** +2)1 14860 JZ OK ;Must be less than 64K +2) 14870 MOV AX,[DMAADD] +2) 14880 NEG AX ;Amount of room left in segment +2) 14890 JNZ PARTSEG ;All 64K available? +2) 14900 DEC AX ;If so, reduce it by one +2) 14910 PARTSEG: +2) 14920 XOR DX,DX +2) 14930 DIV AX,SI ;How many records will fit? +2) 14940 MOV [RECCNT],AX +2) 14950 MUL AX,SI ;Translate that back into bytes +************** +1)1 15170 OR AL,AL +1) 15180 JNZ SETBUF +1) 15190 CMP DX,[BUFSECNO] +**** +2)1 16050 MOV [PREREAD],AL +2) 16060 CMP DX,[BUFSECNO] + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +************** +1)1 15280 MOV AL,[BUFDRVNO] +1) 15290 MOV BX,[BUFFER] +**** +2)1 16150 PUSH BP +2) 16160 MOV BP,[BUFDRVBP] +2) 16170 MOV BX,[BUFFER] +************** +1)1 15320 CALL WRTDRV +1) 15330 POP DX +1) 15340 RDSEC: +1) 15350 MOV BX,[BUFFER] +**** +2)1 16200 CALL DWRITE +2) 16210 POP BP +2) 16220 POP DX +2) 16230 RDSEC: +2) 16240 TEST B,[PREREAD],-1 +2) 16250 JNZ SETBUF +2) 16260 MOV BX,[BUFFER] +************** +1)1 15450 FINBUF: +**** +2)1 16360 MOV [BUFDRVBP],BP +2) 16370 FINBUF: +************** +1)1 16560 CALL BIOSAUXIN,BIOSSEG +1) 16570 STOB +**** +2)1 17480 CALL AUXIN +2) 17490 STOB +************** +1)1 18310 WRTLST: +**** +2)1 19230 DEC BL +2) 19240 JNZ ENDWRDEV ;Done if device is NUL +2) 19250 WRTLST: +************** +1)1 18350 CALL BIOSPRINT,BIOSSEG +1) 18360 LOOP WRTLST +**** +2)1 19290 CALL LISTOUT +2) 19300 LOOP WRTLST +************** +1)1 18410 CALL BIOSAUXOUT,BIOSSEG +1) 18420 CMP AL,1AH +**** +2)1 19350 CALL AUXOUT +2) 19360 CMP AL,1AH +************** +1)1 18900 SEG CS +1) 18910 MOV BX,[DATE] +1) 18920 MOV [DI+FDATE],BX +1) 18930 CALL SETUP +1) 18940 SEG ES +**** + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2)1 19840 CALL SETUP +2) 19850 CALL DATE16 +2) 19860 SEG ES +2) 19870 MOV [DI+FDATE],AX +2) 19880 SEG ES +************** +1)1 19120 MOV DX,[DI+FILSIZ] +1) 19130 DIV AX,[BP+SECSIZ] +**** +2)1 20060 MOV DX,[DI+FILSIZ+2] +2) 20070 DIV AX,[BP+SECSIZ] +************** +1)1 19260 JCXZ HAVSTART +1) 19270 PUSH CX ;No. of clusters short of first +**** +2)1 20200 JCXZ HAVSTART ;See if no more data +2) 20210 PUSH CX ;No. of clusters short of first +************** +1)1 21460 MOV CX,1 +**** +2)1 22400 CMP B,[DI],-1 +2) 22410 JNZ NORMFCB2 +2) 22420 ADD DI,7 +2) 22430 NORMFCB2: +2) 22440 MOV CX,1 +************** +1)1 22920 PUSH DX +1) 22930 PUSH DS +1) 22940 CALL GETFILE +**** +2)1 23900 CALL GETFILE +************** +1)1 22980 POP ES +1) 22990 POP DI +1) 23000 JC KILLSRCH +**** +2)1 23940 JC KILLSRCH +************** +1)1 23100 MOV AL,[BP+DRVNUM] +**** +2)1 24040 MOV AX,00FFH +2) 24050 CMP AL,[EXTFCB] +2) 24060 JNZ NORMFCB +2) 24070 STOW +2) 24080 INC AL +2) 24090 STOW +2) 24100 STOW +2) 24110 MOV AL,[ATTRIB] +2) 24120 STOB +2) 24130 NORMFCB: +2) 24140 MOV AL,[BP+DRVNUM] +************** +1)1 23530 SUB SI,3 ;Point to device name +1) 23540 MOVW +1) 23550 MOVB +1) 23560 MOV AX,2020H + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 23570 MOV CX,4 +1) 23580 REP +1) 23590 STOW ;Fill with 8 blanks +1) 23600 XOR AX,AX +**** +2)1 24570 SUB SI,4 ;Point to device name +2) 24580 MOVW +2) 24590 MOVW +2) 24600 MOV AX,2020H +2) 24610 MOV CX,3 +2) 24620 REP +2) 24630 STOW ;Fill with 6 blanks +2) 24640 STOB ;And a 7th +2) 24650 XOR AX,AX +************** +1)1 23780 JMP SAVPLCE +1) 23810 FILESIZE: ;System call 35 +1) 23820 PUSH DS +1) 23830 PUSH DX +1) 23840 CALL GETFILE +1) 23850 POP DI +1) 23860 POP ES +1) 23870 MOV AL,-1 +**** +2)1 24830 POP ES +2) 24840 POP DI +2) 24850 JMP SAVPLCE +2) 24880 FILESIZE: ;System call 35 +2) 24890 CALL GETFILE +2) 24900 MOV AL,-1 +************** +1)1 24610 GETDSKPT: ;System call 31 +1) 24620 SEG CS +1) 24630 MOV BX,[CURDRVPT] +1) 24640 SEG CS +1) 24650 LDS SI,[SPSAVE] +1) 24660 MOV [SI+BXSAVE],BX +1) 24670 MOV [SI+DSSAVE],CS +1) 24680 RET +1) 24710 DSKRESET: ;System call 13 +**** +2)1 25640 DSKRESET: ;System call 13 +************** +1)1 24810 MOV CL,[NUMDRV] +**** +2)1 25740 MOV AX,[BUFDRVNO] +2) 25750 OR AH,AH +2) 25760 JZ NOBUF +2) 25770 CBW +2) 25780 MOV BX,AX +2) 25790 SHL BX +2) 25800 MOV BP,[BX+DRVTAB] +2) 25810 MOV B,[DIRTYBUF],0 +2) 25820 MOV DX,[BUFSECNO] +2) 25830 MOV BX,BUFFER +2) 25840 MOV CX,1 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 25850 CALL DWRITE +2) 25860 NOBUF: +2) 25870 MOV CL,[NUMDRV] +************** +1)1 24930 MOV AX,[BUFDRVNO] +1) 24940 OR AH,AH +1) 24950 JZ RET +1) 24960 CBW +1) 24970 MOV BX,AX +1) 24980 SHL BX +1) 24990 MOV BP,[BX+DRVTAB] +1) 25000 MOV B,[DIRTYBUF],0 +1) 25010 MOV DX,[BUFSECNO] +1) 25020 MOV BX,BUFFER +1) 25030 MOV CX,1 +1) 25040 JMP DWRITE +1) 25070 CURDRV: ;System call 25 +**** +2)1 25990 RET +2) 26020 CURDRV: ;System call 25 +************** +1)1 25140 INUSE: ;System call 24 +1) 25150 MOV AX,CS +1) 25160 MOV DS,AX +1) 25170 MOV CL,[NUMDRV] +1) 25180 MOV CH,0 +1) 25190 MOV SI,CX +1) 25200 SHL SI +1) 25210 ADD SI,CURDRVPT +1) 25220 MOV BX,0 +1) 25230 DOWN +1) 25240 CHKUSE: +1) 25250 LODW +1) 25260 MOV BP,AX +1) 25270 CMP B,[BP+DIRTYFAT],-1 ;Carry set if not equal +1) 25280 RCL BX +1) 25290 LOOP CHKUSE +1) 25300 MOV AL,BL +1) 25310 RET +1) 25340 SETRNDREC: ;System call 36 +**** +2)1 26090 SETRNDREC: ;System call 36 +************** +1)1 25380 RET +**** +2)1 26130 CMP [DI+RECSIZ],64 +2) 26140 JAE RET +2) 26150 MOV [DI+36],DH ;Set 4th byte only if record size < 64 +2) 26160 RET +************** +1)1 25870 JZ BACKSP +1) 25880 CMP AL,8 +1) 25890 JZ BACKSP +1) 25900 CMP AL,13 +**** +2)1 26650 JZ BACKSPJ + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 26660 CMP AL,8 +2) 26670 JZ BACKSPJ +2) 26680 CMP AL,13 +************** +1)1 25960 CMP AL,ESCCH +**** +2)1 26740 CMP AL,1BH +2) 26750 JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X +2) 26760 CMP AL,ESCCH +************** +1)1 26000 JAE GETCH +1) 26010 STOB +**** +2)1 26800 JAE BELL +2) 26810 STOB +************** +1)1 26120 ESC: +1) 26130 CALL IN +1) 26140 MOV CL,ESCTABLEN +1) 26150 PUSH DI +1) 26160 MOV DI,ESCTAB +**** +2)1 26920 BELL: +2) 26930 MOV AL,7 +2) 26940 CALL OUTCH +2) 26950 JP GETCH +2) 26970 BACKSPJ:JP BACKSP +2) 26990 ESC: +2) 27000 CALL IN +2) 27010 PUSH DI +2) 27020 MOV CL,ESCTABLEN +2) 27030 MOV DI,ESCTAB +************** +1)1 26200 AND CL,0FEH +1) 26210 MOV BP,CX +1) 26220 SEG CS ;To work in init +**** +2)1 27070 MOV BP,CX +2) 27080 SHL BP +2) 27090 SEG CS ;To work in init +************** +1)1 27420 CMP DH,DL +**** +2)1 28290 MOV AH,0 ;Turn off insert mode when copying +2) 28300 CMP DH,DL +************** +1)1 28080 ENTERINS: +1) 28090 MOV AH,-1 +1) 28100 JMP GETCH +1) 28120 EXITINS: +1) 28130 MOV AH,0 +1) 28140 JMP GETCH +1) 28160 ESCFUNC: +**** +2)1 28960 TOGGLINS: +2) 28970 NOT AH + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 28980 JMP GETCH +2) 29000 CTRLZ: +2) 29010 MOV AL,1AH +2) 29020 JMP SAVCH +2) 29040 ESCFUNC: +************** +1)1 28190 DW EXITINS +1) 28200 DW ENTERINS +1) 28210 DW BACKSP +1) 28220 DW REEDIT +1) 28230 DW KILNEW +1) 28240 DW COPYLIN +**** +2)1 29070 DW TOGGLINS +2) 29080 DW BACKSP +2) 29090 DW REEDIT +2) 29100 DW CTRLZ +2) 29110 DW COPYLIN +************** +1)1 28300 BUFOUT: +**** +2)1 29160 DW COPYONE +2) 29180 BUFOUT: +************** +1)1 28520 CALL BIOSOUT,BIOSSEG +**** +2)1 29400 PUSH AX +2) 29410 CALL STATCHK +2) 29420 POP AX +2) 29430 CALL BIOSOUT,BIOSSEG +************** +1)1 28550 JZ STATCHK +1) 28560 CALL BIOSPRINT,BIOSSEG +1) 28570 STATCHK: +**** +2)1 29460 JZ RET +2) 29470 CALL BIOSPRINT,BIOSSEG +2) 29480 RET +2) 29500 NOSTOP: +2) 29510 CMP AL,"P"-"@" +2) 29520 JZ INCHK +2) 29530 CMP AL,"C"-"@" +2) 29540 JZ INCHK +2) 29550 RET +2) 29570 STATCHK: +************** +1)1 28600 INCHK: +1) 28610 CALL BIOSIN,BIOSSEG +1) 28620 CMP AL,'S'-'@' +1) 28630 JNZ NOSTOP +1) 28640 CALL BIOSIN,BIOSSEG +1) 28650 NOSTOP: +1) 28660 CMP AL,'P'-'@' +1) 28670 JZ PRINTON +1) 28680 CMP AL,'N'-'@' +1) 28690 JZ PRINTOFF + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 28700 CMP AL,'C'-'@' +**** +2)1 29600 CMP AL,'S'-'@' +2) 29610 JNZ NOSTOP +2) 29620 CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +2) 29630 INCHK: +2) 29640 CALL BIOSIN,BIOSSEG +2) 29650 CMP AL,'P'-'@' +2) 29660 JZ PRINTOGL +2) 29670 CMP AL,'C'-'@' +************** +1)1 28810 ; repeated, except for console output (function 2), which has already output +1) 28820 ; its character before the interrupt. +1) 28830 SEG CS +**** +2)1 29780 ; repeated. +2) 29790 SEG CS +************** +1)1 29090 CMP AH,2 ;Check if function was console output +1) 29100 JZ SETAL +1) 29110 JMP COMMAND ;Repeat command otherwise +1) 29120 SETAL: +1) 29130 MOV AL,DL +1) 29140 IRET ;Return to user program +1) 29160 PRINTON: +1) 29170 SEG CS +1) 29180 MOV B,[PFLAG],1 +1) 29190 RET +1) 29200 PRINTOFF: +1) 29210 SEG CS +1) 29220 MOV B,[PFLAG],0 +1) 29230 RET +**** +2)1 30050 JMP COMMAND ;Repeat command otherwise +2) 30070 PRINTOGL: +2) 30080 SEG CS +2) 30090 XOR B,[PFLAG],1 +2) 30100 XOR AL,AL ;Set zero flag--character not received +2) 30110 RET +************** +1)1 29590 JZ RET +**** +2)1 30470 MOV AL,0 +2) 30480 JZ RET +************** +1)1 29820 JZ RET +**** +2)1 30710 MOV AL,0 +2) 30720 JZ RET +************** +1)1 29920 CALL BIOSPRINT,BIOSSEG +**** +2)1 30820 LISTOUT: +2) 30830 PUSH AX +2) 30840 CALL STATCHK +2) 30850 POP AX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 30860 CALL BIOSPRINT,BIOSSEG +************** +1)1 30220 CMP B,[SI+1],":" ;Check for potential drive specifier +1) 30230 JNZ DEFAULT +1) 30240 CALL GETLET +1) 30250 SUB AL,"@" ;Convert drive letter to binary drive number +1) 30260 JZ NODRV ;Valid drive numbers are 1-15 +1) 30270 INCcifier--back up pointer +1) 30280 DEFAULT: +1) 30290 XOR AL,AL +1) 30300 HAVDRV: +**** +2)1 31160 MOV AL,0 +2) 31170 CMP B,[SI],20H ;Check for termination character +2) 31180 JB HAVDRV +2) 31190 CMP B,[SI+1],":" ;Check for potential drive specifier +2) 31200 JNZ HAVDRV +2) 31210 CALL GETLET +2) 31220 SUB AL,"@" ;Convert drive letter to binary drive number +2) 31230 JBE BADDRV ;Valid drive numbers are 1-15 +2) 31240 SEG CS +2) 31250 CMP AL,[NUMDRV] +2) 31260 JA BADDRV +2) 31270 INC SI ;Skip over colon +2) 31280 HAVDRV: +************** +1)1 30490 GETWORD: +**** +2)1 31470 BADDRV: +2) 31480 MOV AL,-1 +2) 31490 RET +2) 31510 GETWORD: +************** +1)1 30780 CMP AL,"a" +**** +2)1 31800 AND AL,7FH +2) 31810 CMP AL,"a" +************** +1)1 30960 CMP AL,9 ;Filter out TABs too +**** +2)1 31990 CMP AL,'"' +2) 32000 JZ RET +2) 32010 CMP AL,"+" +2) 32020 JZ RET +2) 32030 CMP AL,"/" +2) 32040 JZ RET +2) 32050 CMP AL,"[" +2) 32060 JZ RET +2) 32070 CMP AL,"]" +2) 32080 JZ RET +2) 32090 CMP AL,9 ;Filter out TABs too +************** +1)1 31160 MOV DS,[CSLOC] +1) 31170 XOR SI,SI +**** +2)1 32290 LDS SI,[SPSAVE] + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 32300 MOV DS,[SI+CSSAVE] +2) 32310 XOR SI,SI +************** +1)1 31830 ; Default handler for division overflow trap +1) 31840 DIVOV: +1) 31850 XOR DX,DX ;Say no remainder +1) 31860 MOV AX,-1 ;But large quotient +1) 31870 IRET +1) 31900 ;***** DATA AREA ***** +1) 31920 BADMES: DB 13,10,"Bad FAT",13,10,"$" +1) 31930 BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$" +1) 31940 RDERRMES:DB 13,10,"Disk read error",13,10,"$" +1) 31950 WRTERRMES:DB 13,10,"Disk write error",13,10,"$" +1) 31960 IONAME: DB "PRN","LST","AUX","CON" +1) 31980 CARPOS: DB 0 +1) 31990 STARTPOS:DB 0 +1) 32000 PFLAG: DB 0 +1) 32010 DIRTYDIR:DB 0 ;Dirty buffer flag +**** +2)1 32960 DATE16: +2) 32970 PUSH CX +2) 32980 PUSH DX +2) 32990 PUSH BX +2) 33000 CALL READTIME +2) 33010 POP BX +2) 33020 POP DX +2) 33030 POP CX +2) 33040 MOV AX,[MONTH] ;Fetch month and year +2) 33050 SHL AL ;Push month to left to make room for day +2) 33060 SHL AL +2) 33070 SHL AL +2) 33080 SHL AL +2) 33090 SHL AX +2) 33100 OR AL,[DAY] +2) 33110 RET +2) 33130 READTIME: +2) 33140 ;Gets tick count in CX:DX. Causes date rollover if new day has started +2) 33150 ;since last call. Destroys AX, BX. +2) 33160 MOV AH,0 ;Request get time +2) 33170 INT 1AH ;Time-of-day interrupt +2) 33180 OR AL,AL ;See if day has changed +2) 33190 JZ RET +2) 33200 ADD AL,[DAY] +2) 33210 MOV [DAY],AL +2) 33220 MOV AH,AL +2) 33230 MOV AL,[MONTH] +2) 33240 MOV BX,DAYTAB-1 ;Table of days in each month +2) 33250 XLAT ;Get number of days in current month +2) 33260 SUB AH,AL ;Have we rolled into next month? +2) 33270 JBE RET +2) 33280 MOV [DAY],AH ;Yes-store day of new month +2) 33290 MOV AL,[MONTH] +2) 33300 INC AL +2) 33310 MOV [MONTH],AL +2) 33320 CMP AL,12 ;Have we rolled into next year? +2) 33330 JBE RET + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 33340 MOV B,[MONTH],1 ;Set first month to January +2) 33350 MOV AL,[YEAR] +2) 33360 INC AL +2) 33370 SETYEAR: +2) 33380 ;Set year with value in AL. Adjust length of February for this year. +2) 33390 MOV [YEAR],AL +2) 33400 AND AL,3 ;Check for leap year +2) 33410 MOV AL,28 +2) 33420 JNZ SAVFEB ;28 days if no leap year +2) 33430 INC AL ;Add leap day +2) 33440 SAVFEB: +2) 33450 MOV [DAYTAB+1],AL ;Store for February +2) 33460 RET +2) 33480 DAYTAB: ;Days of each month +2) 33490 DB 31 ;January +2) 33500 DB 28 ;February--reset each time year changes +2) 33510 DB 31 ;March +2) 33520 DB 30 ;April +2) 33530 DB 31 ;May +2) 33540 DB 30 ;June +2) 33550 DB 31 ;July +2) 33560 DB 31 ;August +2) 33570 DB 30 ;September +2) 33580 DB 31 ;October +2) 33590 DB 30 ;November +2) 33600 DB 31 ;December +2) 33620 GETDATE: ;Function call 42 +2) 33630 PUSH CS +2) 33640 POP DS +2) 33650 CALL READTIME ;Check for rollover to next day +2) 33660 MOV AX,[YEAR] +2) 33670 MOV BX,[DAY] +2) 33680 LDS SI,[SPSAVE] ;Get pointer to user registers +2) 33690 MOV [SI+DXSAVE],BX ;DH=month, DL=day +2) 33700 ADD AX,1980 ;Put bias back +2) 33710 MOV [SI+CXSAVE],AX ;CX=year +2) 33720 XOR AL,AL +2) 33730 RET +2) 33750 SETDATE: ;Function call 43 +2) 33760 MOV AL,-1 ;Be ready to flag an error +2) 33770 SUB CX,1980 ;Fix bias in year +2) 33780 JC RET ;Error if not big enough +2) 33790 CMP CX,119 ;Year must be less than 2100 +2) 33800 JA RET +2) 33810 OR DH,DH +2) 33820 JZ RET +2) 33830 OR DL,DL +2) 33840 JZ RET ;Error if either month or day is 0 +2) 33850 CMP DH,12 ;Check against max. month +2) 33860 JA RET +2) 33870 PUSH CS +2) 33880 POP DS +2) 33890 CMP DH,2 ;Check for Feb.--needs special handling +2) 33900 JNE DAYCHK +2) 33910 CMP DL,29 +2) 33920 JA RET ;Max 29 days in Feb. + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 33930 JB DAYOK ;If 28 or less, definitely OK +2) 33940 TEST CL,3 ;Check for leap year +2) 33950 JZ DAYOK ;If it is, 29 days OK +2) 33960 RET ;Error if it's not +2) 33970 DAYCHK: +2) 33980 MOV AL,DH +2) 33990 MOV BX,DAYTAB-1 +2) 34000 XLAT ;Look up days in month +2) 34010 CMP AL,DL +2) 34020 MOV AL,-1 ;Restore error flag, just in case +2) 34030 JB RET ;Error if too many days +2) 34040 DAYOK: +2) 34050 PUSH DX +2) 34060 PUSH CX +2) 34070 MOV AH,0 +2) 34080 INT 1AH ;Read time to clear day overflow +2) 34090 POP AX ;Year +2) 34100 CALL SETYEAR +2) 34110 POP [DAY] ;Set both day and month +2) 34120 XOR AL,AL ;Flag OK +2) 34130 RET +2) 34150 ;*************************************** +2) 34160 ; Time Functions +2) 34170 ; +2) 34180 ; Uses clock with 1,193,180/65536 ticks per second. User sees only +2) 34190 ; time in hours, minutes, seconds, and 1/100 second, in registers +2) 34200 ; CH, CL, DH, DL respectively. (Each is a binary number.) To +2) 34210 ; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +2) 34220 ; reciprocal of the tick rate. To convert the other way, 1/100 secs +2) 34230 ; is multiplied by 59659/(5 * 2**16). +2) 34250 GETTIME: ;Function call 44 +2) 34260 PUSH CS +2) 34270 POP DS +2) 34280 CALL READTIME ;Get tick count in CX:DX +2) 34290 ;First multiply by 5 +2) 34300 MOV AX,CX +2) 34310 MOV BX,DX +2) 34320 SHL DX +2) 34330 RCL CX ;Times 2 +2) 34340 SHL DX +2) 34350 RCL CX ;Times 4 +2) 34360 ADD DX,BX +2) 34370 ADC AX,CX ;Times 5 +2) 34380 XCHG AX,DX +2) 34390 MOV CX,59659 +2) 34400 DIV AX,CX +2) 34410 MOV BX,AX ;Save quotient +2) 34420 XOR AX,AX ;Extend precision +2) 34430 DIV AX,CX +2) 34440 ;Rounding based on the remainder may be added here +2) 34450 ;The result in BX:AX is time in 1/100 second. +2) 34460 MOV DX,BX +2) 34470 MOV CX,200 ;Extract 1/100's +2) 34480 ;Division by 200 is necessary to ensure no overflow--max result +2) 34490 ;is number of seconds in a day/2 = 43200. +2) 34500 DIV AX,CX + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 34510 CMP DL,100 ;Remainder over 100? +2) 34520 JB NOADJ +2) 34530 SUB DL,100 ;Keep 1/100's less than 100 +2) 34540 NOADJ: +2) 34550 CMC ;If we subtracted 100, carry is now set +2) 34560 MOV BL,DL ;Save 1/100's +2) 34570 ;To compensate for dividing by 200 instead of 100, we now multiply +2) 34580 ;by two, shifting a one in if the remainder had exceeded 100. +2) 34590 RCL AX +2) 34600 MOV DL,0 +2) 34610 RCL DX +2) 34620 MOV CX,60 ;Divide out seconds +2) 34630 DIV AX,CX +2) 34640 MOV BH,DL ;Save the seconds +2) 34650 DIV AL,CL ;Break into hours and minutes +2) 34660 XCHG AL,AH +2) 34670 ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) +2) 34680 LDS SI,[SPSAVE] ;Get pointer to user registers +2) 34690 MOV [SI+DXSAVE],BX +2) 34700 MOV [SI+CXSAVE],AX +2) 34710 XOR AL,AL +2) 34720 RET +2) 34740 SETTIME: ;Function call 45 +2) 34750 ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec +2) 34760 MOV AL,-1 ;Flag in case of error +2) 34770 CMP CH,24 ;Check hours +2) 34780 JAE RET +2) 34790 CMP CL,60 ;Check minutes +2) 34800 JAE RET +2) 34810 CMP DH,60 ;Check seconds +2) 34820 JAE RET +2) 34830 CMP DL,100 ;Check 1/100's +2) 34840 JAE RET +2) 34850 MOV AL,60 +2) 34860 MUL AL,CH ;Hours to minutes +2) 34870 MOV CH,0 +2) 34880 ADD AX,CX ;Total minutes +2) 34890 MOV CX,6000 ;60*100 +2) 34900 MOV BX,DX ;Get out of the way of the multiply +2) 34910 MUL AX,CX ;Convert to 1/100 sec +2) 34920 MOV CX,AX +2) 34930 MOV AL,100 +2) 34940 MUL AL,BH ;Convert seconds to 1/100 sec +2) 34950 ADD CX,AX ;Combine seconds with hours and min. +2) 34960 ADC DX,0 ;Ripple carry +2) 34970 MOV BH,0 +2) 34980 ADD CX,BX ;Combine 1/100 sec +2) 34990 ADC DX,0 +2) 35000 ;DX:CX is time in 1/100 sec +2) 35010 XCHG AX,DX +2) 35020 XCHG AX,CX ;Now time is in CX:AX +2) 35030 MOV BX,59659 +2) 35040 MUL AX,BX ;Multiply low half +2) 35050 XCHG DX,CX +2) 35060 XCHG AX,DX ;CX->AX, AX->DX, DX->CX +2) 35070 MUL AX,BX ;Multiply high half + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 35080 ADD AX,CX ;Combine overlapping products +2) 35090 ADC DX,0 +2) 35100 XCHG AX,DX ;AX:DX=time*59659 +2) 35110 MOV BX,5 +2) 35120 DIV AL,BL ;Divide high half by 5 +2) 35130 MOV CL,AL +2) 35140 MOV CH,0 +2) 35150 MOV AL,AH ;Remainder of divide-by-5 +2) 35160 CBW +2) 35170 XCHG AX,DX ;Use it to extend low half +2) 35180 DIV AX,BX ;Divde low half by 5 +2) 35190 MOV DX,AX +2) 35200 ;CX:DX now has time in ticks +2) 35210 MOV AH,1 +2) 35220 INT 1AH ;Set clock +2) 35230 XOR AL,AL ;Return no error +2) 35240 RET +2) 35260 ;***** DATA AREA ***** +2) 35280 ;Device number mapping +2) 35290 ;0,1 = CON, AUX (Bidirectional devices) +2) 35300 ;2,3 = Printer, bit bucket (output only) +2) 35320 IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +2) 35330 IONUM: DB 3,0,1,1,2,2 +2) 35350 CARPOS: DB 0 +2) 35360 INSFLG: DB 0 +2) 35370 STARTPOS:DB 0 +2) 35380 PFLAG: DB 0 +2) 35390 DAY: DB 0 +2) 35400 MONTH: DB 0 +2) 35410 YEAR: DW 0 +2) 35420 DIRTYDIR:DB 0 ;Dirty buffer flag +************** +1)1 32120 DIRBUFID:DW -1 +1) 32130 DATE: DS 2 +1) 32140 CURDRVPT:DS 2 +**** +2)1 35530 BUFDRVBP:DS 2 +2) 35540 DIRBUFID:DW -1 +2) 35550 CURDRVPT:DS 2 +************** +1)1 32290 NAME2: DS 11 +1) 32300 TEMP: +1) 32310 CSLOC: DS 2 +1) 32320 SPSAVE: DS 2 +1) 32330 SSSAVE: DS 2 +1) 32340 SECCLUSPOS:DS 1 ;Position of first sector within cluster +**** +2)1 35700 ATTRIB: DS 1 ;Search attributes +2) 35710 NAME2: DS 11 +2) 35715 NAME3: DS 12 +2) 35720 EXTFCB: DS 1 +2) 35730 CREATING:DS 1 +2) 35740 TEMP: +2) 35750 SPSAVE: DS 2 +2) 35760 SSSAVE: DS 2 +2) 35770 CONTSTK:DS 2 + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +2) 35780 SECCLUSPOS:DS 1 ;Position of first sector within cluster +************** +1)1 32380 ALIGN +**** +2)1 35810 PREREAD:DS 1 ;0 means must preread; 1 means optional +2) 35820 READOP: DS 1 +2) 35840 ALIGN +************** +1)1 32490 BYTCNT1:DS 2 ;No. of bytes in first sector +1) 32500 BYTCNT2:DS 2 ;No. of bytes in last sector +1) 32510 SECCNT: DS 2 ;No. of whole sectors +1) 32530 DS 60 ;Stack space +1) 32540 STACK: +1) 32560 IF DSKTEST +**** +2)1 35950 BYTCNT1:DS 2 ;No. of bytes in first sector +2) 35960 BYTCNT2:DS 2 ;No. of bytes in last sector +2) 35970 SECCNT: DS 2 ;No. of whole sectors +2) 35990 DS 100H ;Stack space +2) 36000 IOSTACK: +2) 36010 DS 100H +2) 36020 DSKSTACK: +2) 36040 IF DSKTEST +************** +1)1 32590 DS 60 +1) 32600 TESTSTK: +1) 32610 ENDIF +**** +2)1 36070 ENDIF +************** +1)1 33840 ADD AX,[BP+DIRSEC] ;Add number of dir. sectores for 32-byte entry +1) 33850 STOW ;FIRREC2 +**** +2)1 37300 ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry +2) 37310 STOW ;FIRREC2 +************** +1)1 34330 MOV [0],DIVOV ;Set default divide trap address +1) 34340 MOV [2],AX +1) 34350 MOV CX,9 +**** +2)1 37790 MOV CX,9 +************** +1)1 34550 MOV CX,DX +1) 34560 MOV BX,0FH +1) 34570 MEMSCAN: +1) 34580 INC CX +1) 34590 JZ HAVMEM +1) 34600 MOV DS,CX +1) 34610 MOV AL,[BX] +1) 34620 NOT AL +1) 34630 MOV [BX],AL +1) 34640 CMP AL,[BX] +1) 34650 NOT AL +1) 34660 MOV [BX],AL +1) 34670 JZ MEMSCAN +1) 34680 HAVMEM: + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 34690 SEG CS +1) 34700 MOV [ENDMEM],CX +1) 34710 XOR CX,CX +**** +2)1 37990 INT 12H ;Get memory size--1K blocks in AX +2) 38000 MOV CL,6 +2) 38010 SHL AX,CL ;Convert to 16-byte blocks (segment no.) +2) 38020 SEG CS +2) 38030 MOV [ENDMEM],AX +2) 38040 XOR CX,CX +************** +1)1 34750 MOV SI,HEADER +1) 34760 CALL OUTMES +1) 34770 PUSH CS +**** +2)1 38080 PUSH CS +************** +1)1 34810 PUSH DX +1) 34820 GETDAT: +1) 34830 MOV SI,DATMES +1) 34840 CALL OUTMES +1) 34850 MOV DX,DATBUF +1) 34860 CALL BUFIN +1) 34870 CALL CRLF +1) 34880 MOV SI,DATBUF+2 +1) 34890 MOV DX,12 +1) 34900 CALL MYD +1) 34910 JC GETDAT +1) 34920 MOV CL,5 +1) 34930 SHL AX,CL +1) 34940 MOV [DATE],AX +1) 34950 MOV DX,31 +1) 34960 CALL MYD +1) 34970 JC GETDAT +1) 34980 OR [DATE],AL +1) 34990 MOV DX,2100 +1) 35000 CALL MYD +1) 35010 JC GETDAT +1) 35020 SUB AX,80 +1) 35030 JC GETDAT +1) 35040 CMP AX,19 +1) 35050 JBE SAVYR +1) 35060 SUB AX,1900 +1) 35070 JC GETDAT +1) 35080 SAVYR: +1) 35090 SHL AL +1) 35100 OR [DATE+1],AL +1) 35110 ;Move the FATs into position and adjust the drive pointer table +1) 35120 POP DX +1) 35130 POP SI +**** +2)1 38120 MOV [ENDDOS],DX +2) 38130 ;Move FATs into position. Segment of COMMAND still in DX. +2) 38140 POP SI +************** +1)1 35700 MYD: + File 1) DSKC:86DOS.ASM[500,500] created: 1056 05-MAY-1981 +File 2) DSKC:86DOS.A86[500,500] created: 1425 16-JUNE-1981 + +1) 35710 ;SI points to input buffer. Get decimal number < DX and return it +1) 35720 ;in AX. Carry set on error. +1) 35730 XOR BX,BX +1) 35740 MOV AH,0 +1) 35750 GETDIG: +1) 35760 LODB +1) 35770 SUB AL,"0" +1) 35780 JC CHKRET +1) 35790 CMP AL,10 +1) 35800 JNC CHKRET +1) 35810 SHL BX +1) 35820 MOV CX,BX +1) 35830 SHL BX +1) 35840 SHL BX +1) 35850 ADD BX,CX +1) 35860 ADD BX,AX +1) 35870 JP GETDIG +1) 35880 CHKRET: +1) 35890 MOV AX,BX +1) 35900 OR AX,AX +1) 35910 STC +1) 35920 JZ RET +1) 35930 CMP DX,AX +1) 35940 RET +1) 35960 DRVCNT: DB 0 +1) 35980 DATMES: DB "Enter today's date (m-d-y): $" +1) 35990 DATBUF: DB 12,8,"04-28-81",13 +1) 36000 DS 5 +1) 36020 SDIRSEC:DS 2 +1) 36040 MEMSTRT: +1) 36050 ADJFAC: EQU DIRBUF-MEMSTRT +**** +2)1 38710 DRVCNT: DB 0 +2) 38720 SDIRSEC:DS 1 +2) 38740 MEMSTRT: +2) 38750 ADJFAC: EQU DIRBUF-MEMSTRT +************** diff --git a/3_source_code/86-DOS_1.00/86DOS.ASM b/3_source_code/86-DOS_1.00/86DOS.ASM new file mode 100644 index 0000000..34123aa --- /dev/null +++ b/3_source_code/86-DOS_1.00/86DOS.ASM @@ -0,0 +1,3622 @@ +; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +; by Tim Paterson + +; ****************** Revision History ************************* +; >> EVERY change must noted below!! << +; +; 0.34 12/29/80 General release, updating all past customers +; 0.42 02/25/81 32-byte directory entries added +; 0.56 03/23/81 Variable record and sector sizes +; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +; 0.74 04/15/81 Recognize I/O devices with file names +; 0.75 04/17/81 Improve and correct buffer handling +; 0.76 04/23/81 Correct directory size when not 2^N entries +; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +; 1.00 04/28/81 Renumber for general release +; +; ************************************************************* + +; Use the switch below to generate code to accept the old 16-byte +; directory entry as well as the new 32-byte entry. + +SMALLDIR: EQU 1 ;1 to enable, 0 to disable + + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + +DSKTEST: EQU 0 ;1 to enable, 0 to disable + + +; 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 + + +MAXCALL:EQU 36 +MAXCOM: EQU 41 +ESCCH: EQU 1BH +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 +MAXDIF: EQU 0FFFH +SAVEXIT:EQU 10 + +; Field definition for FCBs + + ORG 0 + DS 12 ;Drive code and name +EXTENT: DS 2 +RECSIZ: DS 2 ;Size of record (user settable) +FILSIZ: DS 4 ;Size of file in bytes +FDATE: DS 2 ;Date of last writing +FILDIRBLK:DS 2 ;Location in directory +FIRCLUS:DS 2 ;First cluster of file +LSTCLUS:DS 2 ;Last cluster accessed +CLUSPOS:DS 2 ;Position of last cluster accessed +DIRTYFIL:DS 1 ;File has been written to if <>0 + ORG 32 +NR: DS 1 ;Next record +RR: DS 3 ;Random record + + +; Description of 32-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 13 Zero field (for expansion) +; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +; 26 2 First allocation unit ( < 4080 ) +; 28 4 File size, in bytes (LSB first, 30 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 and as a flag for directory +; entry size (if SMALLDIR selected). 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 greater than 0FF8H 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 + + ORG 0 +DRVNUM: DS 1 ;Drive number +SECSIZ: DS 2 ;Size of physical sector in bytes +CLUSMSK:DS 1 ;Sectors/cluster - 1 +CLUSSHFT:DS 1 ;Log2 of sectors/cluster +FIRFAT: DS 2 ;Starting record of FATs +FATCNT: DS 1 ;Number of FATs for this drive +MAXENT: DS 2 ;Number of directory entries +DIRSEC: ;Number of dir. sectors (init temporary) +FIRREC: DS 2 ;First sector of first cluster +DSKSIZ: ;Size of disk (temp used during init only) +MAXCLUS:DS 2 ;Number of clusters on drive + 1 +FATSIZ: DS 1 ;Number of records occupied by FAT +FIRDIR: DS 2 ;Starting record of directory + + IF SMALLDIR +FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries + ENDIF + +DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +FAT: ;Start of FAT +DIRSIZ: ;-1=small dir. entry, else large + + +; BIOS entry point defintions + +BIOSSEG: EQU 40H + ORG 0 + DS 3 +BIOSSTAT: DS 3 +BIOSIN: DS 3 +BIOSOUT: DS 3 +BIOSPRINT: DS 3 +BIOSAUXIN: DS 3 +BIOSAUXOUT: DS 3 +BIOSREAD: DS 3 +BIOSWRITE: DS 3 +BIOSDSKCHG: DS 3 + + +; Location of user registers relative user stack pointer + + ORG 0 +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 +IPSAVE: DS 2 +CSSAVE: DS 2 +FSAVE: DS 2 + + +; Start of code + + ORG 0 + PUT 100H + + JMP DOSINIT + +ESCTAB: + DB "SC" ;Copy one char + DB "VN" ;Skip one char + DB "TA" ;Copy to char + DB "WB" ;Skip to char + DB "UH" ;Copy line + DB "HH" ;Kill line (no change in template) + DB "RM" ;Reedit line (new template) + DB "DD" ;Backspace + DB "P@" ;Enter insert mode + DB "QL" ;Exit insert mode + DB ESCCH,ESCCH ;Escape character + DB ESCCH,ESCCH ;End of table + +ESCTABLEN:EQU $-ESCTAB + +HEADER: DB 13,10,"86-DOS version 1.00" + + IF DSKTEST + DB "D" + ENDIF + + DB 13,10 + DB "Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$" + +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 + DI + 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: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + IF DSKTEST + SEG CS + MOV AX,[SPSAVE] + SEG CS + MOV [NSP],AX + SEG CS + MOV AX,[SSSAVE] + SEG CS + MOV [NSS],AX + POP AX + PUSH AX + ENDIF + + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + MOV BP,SP + MOV BX,[BP+CSSAVE] + SEG CS + MOV [CSLOC],BX + MOV SP,CS + MOV SS,SP + MOV SP,STACK + EI ;Stack OK now + SEG CS + MOV [FUNC],AH + MOV BL,AH + MOV BH,0 + SHL BX + UP + + IF DSKTEST + CMP AH,12 + JL SAMSTK + MOV SP,TESTSTK +SAMSTK: + ENDIF + + SEG CS + CALL [BX+DISPATCH] +LEAVE: + DI + SEG CS + MOV SP,[SPSAVE] + SEG CS + MOV SS,[SSSAVE] + MOV BP,SP + MOV [BP+AXSAVE],AL + + IF DSKTEST + SEG CS + MOV AX,[NSP] + SEG CS + MOV [SPSAVE],AX + SEG CS + MOV AX,[NSS] + SEG CS + MOV [SSSAVE],AX + ENDIF + + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + IRET + +DISPATCH: +; Standard Functions + DW ABORT ;0 + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST ;5 + DW RAWIO + DW RAWINP + DW IN + DW PRTBUF + DW BUFIN ;10 + DW CONSTAT + DW VERSION + 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 CURDRV ;25 + DW SETDMA + DW GETFATPT + DW WRTPROT + 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 + DW MAKEFCB + +VERSION: +GETIO: +SETIO: +WRTPROT: +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,BADMES + 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 + +IOCHK: + MOV CX,5 ;Check rest of name but not extension + CMP B,[DI],":" + JNZ NOCOL + INC DI ;Skip over colon + DEC CX +NOCOL: + MOV AL," " + REPE + SCAB ;Make sure rest of name is blanks + JNZ FILSRCH + DEC BL + RET + +GETFILE: + +; 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 +; BX = Pointer into directory buffer +; SI = Pointer to First Cluster field in directory entry +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + CALL MOVNAME + JC RET ;Bad file name? +FINDNAME: + MOV AX,CS + MOV DS,AX + MOV SI,IONAME ;List of I/O devices with file names + MOV BX,0FF04H ;BL = number of devices +LOOKIO: + MOV DI,NAME1 + MOV CX,3 ;All device names are 3 letters + REPE + CMPB ;Check for name in list + JZ IOCHK ;If first 3 letters OK, check the rest + ADD SI,CX ;Point to next device name + DEC BL + JNZ LOOKIO +FILSRCH: ;Not a device name + CALL STARTSRCH +CONTSRCH: + CALL GETENTRY + JC RET +SRCH: + CMP B,[BX],0E5H + JZ NEXTENT + MOV SI,BX + MOV DI,NAME1 + MOV CX,11 +WILDCRD: + REPE + CMPB + JZ FOUND + CMP B,[DI-1],"?" + JZ WILDCRD +NEXTENT: + CALL NEXTENTRY + JNC SRCH + RET + +FOUND: + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ RET + ENDIF + + ADD SI,15 + RET + + +GETENTRY: + +; Inputs: +; [LASTENT] has previously searched directory entry +; Function: +; Locates next sequential directory entry in preparation for search +; Outputs: +; Carry set if none +; ELSE +; AL = Current directory block +; BX = Pointer to next directory entry in [DIRBUF] +; DX = Pointer to first byte after end of DIRBUF +; [LASTENT] = New directory entry number + + MOV AX,[LASTENT] + INC AX ;Start with next entry + CMP AX,[BP+MAXENT] + JAE NONE + MOV [LASTENT],AX + MOV CL,4 + SHL AX,CL + XOR DX,DX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ SMALENT1 + ENDIF + + SHL AX + RCL DX ;Account for overflow in last shift +SMALENT1: + MOV BX,[BP+SECSIZ] + AND BL,255-31 ;Must be multiple of 32 + DIV AX,BX + MOV BX,DX ;Position within sector + MOV AH,[BP+DRVNUM] ;AL=Directory sector no. + CMP AX,[DIRBUFID] + JZ HAVDIRBUF + PUSH BX + CALL DIRREAD + POP BX +HAVDIRBUF: + MOV DX,DIRBUF + ADD BX,DX + ADD DX,[BP+SECSIZ] + RET + +NEXTENTRY: + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update AL, BX, and [LASTENT] for next directory entry. +; Carry set if no more. + + MOV DI,[LASTENT] + INC DI + CMP DI,[BP+MAXENT] + JAE NONE + MOV [LASTENT],DI + ADD BX,32 + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT3 + SUB BX,16 +BIGENT3: + ENDIF + + CMP BX,DX + JB HAVIT + INC AL ;Next directory sector + PUSH DX ;Save limit + CALL DIRREAD + POP DX + MOV BX,DIRBUF +HAVIT: + CLC + RET + +NONE: + CALL CHKDIRWRITE + STC + RET + + +DELETE: ; System call 19 + CALL GETFILE + JC ERRET + CMP BH,-1 ;Check if device name + JZ ERRET ;Can't delete I/O devices +DELFILE: + MOV B,[DIRTYDIR],-1 + MOV B,[BX],0E5H + MOV BX,[SI] + LEA SI,[BP+FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP+MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + CALL CONTSRCH + JNC DELFILE + CALL FATWRT + CALL CHKDIRWRITE + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + CMP BH,-1 ;Check if I/O device name + JZ ERRET ;If so, can't rename it + ADD SI,5 + MOV DI,NAME2 + CALL LODNAME + CALL FINDNAME + JC ERRET +RENFIL: + MOV B,[DIRTYDIR],-1 + MOV DI,BX + MOV SI,NAME2 + MOV CX,11 +NEWNAM: + LODB + CMP AL,"?" + JZ NOCHG + MOV [DI],AL +NOCHG: + INC DI + LOOP NEWNAM + CALL CONTSRCH + JNC RENFIL + CALL CHKDIRWRITE + 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 + CALL GETBP + JB RET +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,60H + JLE CASEOK + AND AL,5FH +CASEOK: + CMP AL,20H + JC RET + STOB + LOOP MOVCHK + RET + +GETBP: + SEG CS + CMP [NUMDRV],AL + JC RET + CBW + XCHG BP,AX + SHL BP + MOV BP,[BP+CURDRVPT] + RET + + +OPEN: ;System call 15 + PUSH DX + PUSH DS + CALL GETFILE +DOOPEN: +; Enter here to perform OPEN on file already found +; in directory. DS=ES=CS, BX points to directory +; entry in DIRBUF, SI points to First Cluster field, and +; the top of the stack has the address and segment +; of the FCB to be opened. This entry point is used +; by CREATE. + POP ES + POP DI + JC ERRET + CMP BH,-1 ;Check if file is I/O device + JZ OPENDEV ;Special handler if so + MOV AL,[BP+DRVNUM] + INC AL + STOB + ADD DI,11 ;Point to extent field + XOR AX,AX + STOW ;Set extent field to 0 + MOV AX,128 ;Default record size + STOW ;Set record size + LODW ;Get starting cluster + MOV DX,AX ;Save it for the moment + MOVW ;Transfer size to FCB + MOVW + MOV AX,[SI-8] ;Get date + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT10 + SEG ES + MOV [DI-1],0 + XOR AX,AX ;Date not available in small entry +BIGENT10: + ENDIF + + STOW ;Save date in FCB + MOV AX,[LASTENT] + STOW ;directory location + MOV AX,DX ;Restore starting cluster + STOW ; first cluster + STOW ; last cluster accessed + XOR AX,AX + STOW ; position of last cluster + STOB ; dirty flag + RET + +OPENDEV: + SEG ES + MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag + XOR AL,AL + RET + + +STARTSRCH: + MOV [LASTENT],-1 +FATREAD: + +; Inputs: +; DS = CS +; BP = Base of drive parameters +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV AL,[BP+DRVNUM] + CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say + MOV AL,[BP+DRVNUM] + OR AH,[BP+DIRTYFAT] + JS NEWDSK ;If either say new disk, then it's so + DEC AH ;Check for AH=1 (disk not changed) + JZ RET + MOV AH,1 + CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? + JZ RET ;If so, disk has not been changed +NEWDSK: + CMP AL,[BUFDRVNO] ;See if buffer is for this drive + JNZ BUFOK ;If not, don't touch it + MOV [BUFSECNO],0 ;Flag buffers invalid + MOV [BUFDRVNO],00FFH +BUFOK: + MOV [DIRBUFID],-1 + CALL FIGFAT +NEXTFAT: + PUSH DX + PUSH CX + PUSH BX + PUSH AX + CALL DREAD + OR AL,AL + POP AX + POP BX + POP CX + POP DX + JNZ BADFAT + + IF SMALLDIR + MOV DL,AL + LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries + CMP B,[BP+DIRSIZ],-1 + JZ SETSIZ + ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +SETSIZ: + LODW + MOV [BP+FIRREC],AX + LODW + MOV [BP+MAXCLUS],AX + MOV AL,DL + ENDIF + + SUB AL,[BP+FATCNT] + JZ RET + NEG AL +;{Insert error code here. AL=number of bad fats. +;Since one good FAT was read, should include option +;to rewrite all FATs.} + JMP FATWRT + +BADFAT: + ADD DX,CX + DEC AL + JNZ NEXTFAT + POP BP +;{Insert error code here. All FATs on drive are bad.} + MOV SI,BADFATMES + CALL HARDERR + JP FATREAD + +OKRET1: + MOV AL,0 + RET + +CLOSE: ;System call 16 + MOV DI,DX + CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device + JZ OKRET1 ;Can't close I/O device + TEST B,[DI+DIRTYFIL],-1 + JZ OKRET1 ;If not written to, do nothing + MOV AL,[DI] ;Get drive number + CALL GETBP ;Get base of drive parameters + JC BADCLOSEJ + MOV AL,[BP+DRVNUM] + MOV AH,1 ;Look for dirty buffer + SEG CS + CMP AX,[BUFDRVNO] + JNZ FNDDIR +;Write back dirty buffer if on same drive + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV B,[DIRTYBUF],0 + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP DS + POP DX +FNDDIR: + PUSH DX + PUSH DS + CALL GETFILE + POP ES + POP DI +BADCLOSEJ: + JC BADCLOSE + MOV AX,[LASTENT] + SEG ES + CMP AX,[DI+FILDIRBLK] + JNZ BADCLOSE + SEG ES + MOV CX,[DI+FIRCLUS] + MOV [SI],CX + SEG ES + MOV DX,[DI+FILSIZ] + MOV [SI+2],DX + SEG ES + MOV DX,[DI+FILSIZ+2] + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT11 + MOV [SI+4],DL + JP SMALLENT2 +BIGENT11: + ENDIF + + MOV [SI+4],DX + SEG ES + MOV DX,[DI+FDATE] + MOV [SI-2],DX +SMALLENT2: + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty + + CMP B,[BP+DIRTYFAT],1 + JNZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty bit. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV B,[BP+DIRTYFAT],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+DIRTYFAT],0 + MOV AL,-1 + RET + + +FIGFAT: +; Loads registers with values needed to read or +; write a FAT. + MOV AL,[BP+FATCNT] + LEA 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 + CALL FINDNAME + JNC EXISTENT + CALL STARTSRCH + CALL GETENTRY +LOOKFRE: + CMP B,[BX],0E5H + JZ FREESPOT + CALL NEXTENTRY + JNC LOOKFRE + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET + +EXISTENT: + CMP BH,-1 ;Check if file is I/O device + JZ OPENJMP ;If so, no action + XOR CX,CX + MOV [SI+2],CX + MOV AX,[DATE] + + IF SMALLDIR + MOV [SI+4],CL + CMP B,[BP+DIRSIZ],-1 + JZ SMLENT + MOV [SI+5],CL + MOV [SI-2],AX +SMLENT: + ENDIF + + IF 1-SMALLDIR + MOV [SI+4],CX + MOV [SI-2],AX + ENDIF + + XCHG CX,[SI] + PUSH SI + PUSH BX + JCXZ WRTBACK + CMP CX,[BP+MAXCLUS] + JA WRTBACK + MOV BX,CX + LEA SI,[BP+FAT] + CALL RELEASE + CALL FATWRT + JP WRTBACK + +FREESPOT: + MOV DI,BX + MOV SI,NAME1 + MOV CX,5 + MOVB + REP + MOVW + XOR AX,AX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT4 + PUSH DI + MOV CL,5 + JP SMALLENT +BIGENT4: + ENDIF + + MOV CL,13 + REP + STOB + MOV AX,[DATE] + STOW + XOR AX,AX + PUSH DI + MOV CL,6 +SMALLENT: + REP + STOB + PUSH BX +WRTBACK: + CALL DIRWRITE + POP BX + POP SI +OPENJMP: + CLC ;Clear carry so OPEN won't fail + JMP DOOPEN + + +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. + + PUSH AX + CALL CHKDIRWRITE + POP AX + PUSH AX + MOV AH,[BP+DRVNUM] + MOV [DIRBUFID],AX + CALL DIRCOMP + CALL DREAD + POP AX + RET + + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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. +; Outputs: +; AL = 0 if no error, otherwise non-zero +; BP preserved. All other registers destroyed. + + MOV AL,[BP+DRVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSREAD,BIOSSEG + POP DX + POP DI + POP BX + POP BP + JC HARDREAD + XOR AL,AL + RET + +HARDREAD: + MOV SI,RDERRMES + CALL HARDERR + JP DREAD + + +CHKDIRWRITE: + TEST B,[DIRTYDIR],-1 + JZ RET + +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. + + MOV B,[DIRTYDIR],0 + MOV AL,[DIRBUFID] + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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. +; Outputs: +; AL = 0 if no error, otherwise non-zero +; BP preserved. All other registers destroyed. + + MOV AL,[BP+DRVNUM] +WRTDRV: + PUSH AX + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSWRITE,BIOSSEG + POP DX + POP DI + POP BX + POP BP + POP AX + JC HARDWRITE + XOR AL,AL + RET +HARDWRITE: + MOV SI,WRTERRMES + CALL HARDERR + JP WRTDRV + + +HARDERR: + SUB DI,CX + ADD DX,DI + CALL SHFTDI7 + ADD BX,DI + MOV AH,AL ;Save drive number + CALL OUTMES +GETINSTR: + CALL IN + OR AL,20H + CMP AL,"a" + JZ ERROR + CMP AL,"r" + JZ RETRY + CMP AL,"i" + JZ IGNORE + CMP AL,"c" + JNZ GETINSTR +CONTINUE: + POP AX + MOV AL,1 + RET +IGNORE: + POP AX + MOV AL,0 + RET +RETRY: + MOV AL,AH ;Restore drive number + RET + + +ABORT: + SEG CS + MOV DS,[CSLOC] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVW + MOVW + MOVW + MOVW +ERROR: + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL WRTFATS + XOR AX,AX + DI + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + MOV DS,AX + MOV SI,EXIT + MOV DI,EXITHOLD + MOVW + MOVW + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + EI ;Stack OK now + SEG CS + JMP L,[EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + CALL LOAD + JP FINSEQ + +SEQWRT: ;System call 21 + CALL GETREC + CALL STORE +FINSEQ: + JCXZ SETNREX + ADD AX,1 + ADC DX,0 + JP SETNREX + +RNDRD: ;System call 33 + CALL GETRRPOS1 + CALL LOAD + JP FINRND + +RNDWRT: ;System call 34 + CALL GETRRPOS1 + CALL STORE + JP FINRND + +BLKRD: ;System call 39 + CALL GETRRPOS + CALL LOAD + JP FINBLK + +BLKWRT: ;System call 40 + CALL GETRRPOS + CALL STORE +FINBLK: + LDS SI,[SPSAVE] + MOV [SI+CXSAVE],CX + JCXZ FINRND + ADD AX,1 + ADC DX,0 +FINRND: + SEG ES + MOV [DI+RR],AX + SEG ES + MOV [DI+RR+2],DL + OR DH,DH + JZ SETNREX + SEG ES + MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +SETNREX: + MOV CX,AX + AND AL,7FH + SEG ES + MOV [DI+NR],AL + AND CL,80H + SHL CX + RCL DX + MOV AL,CH + MOV AH,DL + SEG ES + MOV [DI+EXTENT],AX + SEG CS + MOV AL,[DSKERR] + RET + +GETRRPOS1: + MOV CX,1 +GETRRPOS: + MOV DI,DX + MOV AX,[DI+RR] + MOV DX,[DI+RR+2] + RET + +NOFILERR: + XOR CX,CX + MOV B,[DSKERR],-2 + POP BX + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; CX = No. of bytes to transfer +; BP = Base of drive parameters +; SI = FAT pointer +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DI +; [NEXTADD] = Displacement of disk transfer within segment +; [SECPOS] = Position of first sector +; [BYTPOS] = Byte position in file +; [BYTSECPOS] = Byte position in first sector +; [CLUSNUM] = First cluster +; [SECCLUSPOS] = Sector within first cluster +; [DSKERR] = 0 (no errors yet) +; [TRANS] = 0 (No transfers yet) +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + PUSH AX + MOV AL,[DI] + MOV SI,[DI+RECSIZ] + OR SI,SI + JNZ HAVRECSIZ + MOV SI,128 + MOV [DI+RECSIZ],SI +HAVRECSIZ: + MOV BX,DS + MOV ES,BX + MOV BX,CS + MOV DS,BX + CALL GETBP + POP AX + JC NOFILERR + CMP SI,64 ;Check if highest byte of RECPOS is significant + JB SMALREC + MOV DH,0 ;Ignore MSB if record >= 64 bytes +SMALREC: + MOV [RECCNT],CX + MOV [RECPOS],AX + MOV [RECPOS+2],DX + MOV [FCB],DI + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV B,[DSKERR],0 + MOV B,[TRANS],0 + MOV BX,DX + MUL AX,SI + MOV [BYTPOS],AX + PUSH DX + MOV AX,BX + MUL AX,SI + POP BX + ADD AX,BX + ADC DX,0 ;Ripple carry + JNZ EOFERR + MOV [BYTPOS+2],AX + MOV DX,AX + MOV AX,[BYTPOS] + DIV AX,[BP+SECSIZ] + MOV [SECPOS],AX + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,[BP+CLUSMSK] + MOV [SECCLUSPOS],AL + MOV AX,CX ;Record count + MOV CL,[BP+CLUSSHFT] + SHR DX,CL + MOV [CLUSNUM],DX + MUL AX,SI ;Multiply by bytes per record + MOV CX,AX + ADD AX,[DMAADD] ;See if it will fit in one segment + ADC DX,0 + JZ OK ;Must stay within 64K + MOV AX,[DMAADD] + NEG AX ;Amount of room left in segment + XOR DX,DX + DIV AX,SI ;How many records will fit? + MUL AX,SI ;Translate that back into bytes + MOV B,[DSKERR],2 ;Flag that trimming took place + MOV CX,AX + JCXZ NOROOM +OK: + LEA SI,[BP+FAT] + RET + +EOFERR: + MOV B,[DSKERR],1 + XOR CX,CX +NOROOM: + POP BX ;Kill return address + RET + +BREAKDOWN: + +;Inputs: +; DS = CS +; CX = Length of disk transfer in bytes +; BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +;Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +;AX, BX, DX destroyed. No other registers affected. + + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ;Partial first sector? + SUB AX,[BP+SECSIZ] + NEG AX ;Max number of bytes left in first sector + SUB BX,AX ;Subtract from total length + JAE SAVFIR + ADD AX,BX ;Don't use all of the rest of the sector + XOR BX,BX ;And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV AX,[BP+SECSIZ] ;How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ;Bytes remaining for last sector + 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,0FF8H + JAE RET + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +BUFSEC: +; Inputs: +; AL = 0 if buffer must be read, 1 if no pre-read needed +; 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: +; SI = Pointer to buffer +; DI = 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 + OR AL,AL + JNZ SETBUF + CMP DX,[BUFSECNO] + JNZ GETSEC + MOV AL,[BUFDRVNO] + CMP AL,[BP+DRVNUM] + JZ FINBUF ;Already have it? +GETSEC: + TEST B,[DIRTYBUF],-1 + JZ RDSEC + PUSH DX + MOV AL,[BUFDRVNO] + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL WRTDRV + POP DX +RDSEC: + MOV BX,[BUFFER] + MOV CX,1 + PUSH DX + CALL DREAD + POP DX +SETBUF: + MOV [BUFSECNO],DX + MOV AL,[BP+DRVNUM] + MOV AH,0 + MOV [BUFDRVNO],AX +FINBUF: + MOV B,[TRANS],1 ;A transfer is taking place + MOV DI,[NEXTADD] + MOV SI,DI + MOV CX,[BYTCNT1] + ADD SI,CX + MOV [NEXTADD],SI + MOV SI,[BUFFER] + ADD SI,[BYTSECPOS] + RET + +BUFRD: + XOR AL,AL ;Pre-read necessary + CALL BUFSEC + PUSH ES + MOV ES,[DMAADD+2] + SHR CX + JNC EVENRD + MOVB +EVENRD: + REP + MOVW + POP ES + RET + +BUFWRT: + 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 + MOV AL,0 +NOREAD: + CALL BUFSEC + XCHG DI,SI + PUSH DS + PUSH ES + PUSH CS + POP ES + MOV DS,[DMAADD+2] + SHR CX + JNC EVENWRT + MOVB +EVENWRT: + REP + MOVW + POP ES + POP DS + MOV B,[DIRTYBUF],1 + RET + +NEXTSEC: + TEST B,[TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,[BP+CLUSMSK] + JBE SAVPOS + MOV BX,[CLUSNUM] + CMP BX,0FF8H + JAE NONEXT + LEA SI,[BP+FAT] + CALL UNPACK + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + RET +NONEXT: + STC + RET + +TRANBUF: + LODB + STOB + CMP AL,13 ;Check for carriage return + JNZ NORMCH + MOV [SI],10 +NORMCH: + CMP AL,10 + LOOPNZ TRANBUF + JNZ ENDRDCON + CALL OUT ;Transmit linefeed + XOR SI,SI + OR CX,CX + JNZ GETBUF + OR AL,1 ;Clear zero flag--not end of file +ENDRDCON: + MOV [CONTPOS],SI +ENDRDDEV: + MOV [NEXTADD],DI + POP ES + JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + MOV DI,[FCB] + SEG ES + OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +SETFCBJ: + JMP SETFCB + +READDEV: + PUSH ES + LES DI,[DMAADD] + OR BL,BL + JZ READCON + DEC BL + JNZ ENDRDDEV +READAUX: + CALL BIOSAUXIN,BIOSSEG + STOB + CMP AL,1AH + LOOPNZ READAUX + JP ENDRDDEV + +READCON: + PUSH CS + POP DS + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP B,[CONBUF],128 + JZ GETBUF + MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,CONBUF + CALL BUFIN ;Get input buffer + POP DI + POP ES + POP CX + MOV SI,CONBUF+2 + CMP B,[SI],1AH ;Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOB + MOV AL,10 + CALL OUT ;Send linefeed + XOR SI,SI + JP ENDRDCON + +RDERR: + XOR CX,CX + JMP WRTERR + +RDLASTJ:JMP RDLAST + +LOAD: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file to read +; CX = No. of records to read +; Outputs: +; DX:AX = Position of last record read +; CX = No. of bytes read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 ;Check for named device I/O + JZ READDEV + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV BX,[DI+FILSIZ+2] + SUB AX,[BYTPOS] + SBC BX,[BYTPOS+2] + JB RDERR + JNZ ENUF + OR AX,AX + JZ RDERR + CMP AX,CX + JAE ENUF + MOV CX,AX +ENUF: + CALL BREAKDOWN + MOV CX,[CLUSNUM] + CALL FNDCLUS + OR CX,CX + JNZ RDERR + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + CALL BUFRD +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + CALL NEXTSEC + JC SETFCB + MOV B,[TRANS],1 ;A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DREAD + POP DS + POP CX + POP BX + JCXZ RDLAST + CMP BX,0FF8H + JAE SETFCB + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP RDLP + +SETFCB: + MOV SI,[FCB] + MOV AX,[NEXTADD] + MOV DI,AX + SUB AX,[DMAADD] ;Number of bytes transfered + XOR DX,DX + SEG ES + MOV CX,[SI+RECSIZ] + DIV AX,CX ;Number of records + CMP AX,[RECCNT] ;Check if all records transferred + JZ FULLREC + MOV B,[DSKERR],1 + OR DX,DX + JZ FULLREC ;If remainder 0, then full record transfered + MOV B,[DSKERR],3 ;Flag partial last record + SUB CX,DX ;Bytes left in last record + PUSH ES + MOV ES,[DMAADD+2] + XCHG AX,BX ;Save the record count temporarily + XOR AX,AX ;Fill with zeros + SHR CX + JNC EVENFIL + STOB +EVENFIL: + REP + STOW + XCHG AX,BX ;Restore record count to AX + POP ES + INC AX ;Add last (partial) record to total +FULLREC: + MOV CX,AX + MOV DI,SI ;ES:DI point to FCB +SETCLUS: + MOV AX,[CLUSNUM] + SEG ES + MOV [DI+LSTCLUS],AX + MOV AX,[LASTPOS] + SEG ES + MOV [DI+CLUSPOS],AX +ADDREC: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + DEC CX + ADD AX,CX ;Update current record position + ADC DX,0 + INC CX + RET + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETFCB + MOV [BYTCNT1],AX + CALL NEXTSEC + JC SETFCB + MOV [BYTSECPOS],0 + CALL BUFRD + JP SETFCB + +WRTDEV: + PUSH DS + LDS SI,[DMAADD] + AND BL,7FH + OR BL,BL + JZ WRTCON + DEC BL + JZ WRTAUX +WRTLST: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL BIOSPRINT,BIOSSEG + LOOP WRTLST + JP ENDWRDEV + +WRTAUX: + LODB + CALL BIOSAUXOUT,BIOSSEG + CMP AL,1AH + LOOPNZ WRTAUX + JP ENDWRDEV + +WRTCON: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL OUT + LOOP WRTCON +ENDWRDEV: + POP DS + MOV CX,[RECCNT] + MOV DI,[FCB] + JP ADDREC + +HAVSTART: + MOV CX,AX + CALL SKPCLP + JCXZ DOWRTJ + CALL ALLOCATE + JNC DOWRTJ +WRTERR: + MOV B,[DSKERR],1 +LVDSK: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + MOV DI,[FCB] + RET + +DOWRTJ: JMP DOWRT + +WRTEOFJ: + JMP WRTEOF + +STORE: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; DX:AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + MOV B,[DI+DIRTYFIL],1 + SEG CS + MOV BX,[DATE] + MOV [DI+FDATE],BX + CALL SETUP + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 + JZ WRTDEV + CALL BREAKDOWN + MOV AX,[BYTPOS] + MOV DX,[BYTPOS+2] + JCXZ WRTEOFJ + DEC CX + ADD AX,CX + ADC DX,0 ;AX:DX=last byte accessed + DIV AX,[BP+SECSIZ] ;AX=last sector accessed + MOV CL,[BP+CLUSSHFT] + SHR AX,CL ;Last cluster to be accessed + PUSH AX + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV DX,[DI+FILSIZ] + DIV AX,[BP+SECSIZ] + OR DX,DX + JZ NORNDUP + INC AX ;Round up if any remainder +NORNDUP: + MOV [VALSEC],AX ;Number of sectors that have been written + POP AX + MOV CX,[CLUSNUM] ;First cluster accessed + CALL FNDCLUS + MOV [CLUSNUM],BX + MOV [LASTPOS],DX + SUB AX,DX ;Last cluster minus current cluster + JZ DOWRT ;If we have last clus, we must have first + JCXZ HAVSTART + PUSH CX ;No. of clusters short of first + MOV CX,AX + CALL ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP + CALL SKPCLP +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + CALL BUFWRT +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JZ WRTLAST + ADD [SECPOS],AX + CALL NEXTSEC + MOV B,[TRANS],1 ;A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP WRTLP +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + CALL NEXTSEC + MOV [BYTSECPOS],0 + CALL BUFWRT +FINWRT: + MOV AX,[NEXTADD] + SUB AX,[DMAADD] + ADD AX,[BYTPOS] + MOV DX,[BYTPOS+2] + ADC DX,0 + MOV CX,DX + MOV DI,[FCB] + SEG ES + CMP AX,[DI+FILSIZ] + SEG ES + SBB CX,[DI+FILSIZ+2] + JB SAMSIZ + SEG ES + MOV [DI+FILSIZ],AX + SEG ES + MOV [DI+FILSIZ+2],DX +SAMSIZ: + MOV CX,[RECCNT] + JMP SETCLUS + + +WRTERRJ:JMP WRTERR + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBC DX,0 + DIV AX,[BP+SECSIZ] + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + JCXZ RELFILE + CALL ALLOCATE + JC WRTERRJ +UPDATE: + MOV DI,[FCB] + MOV AX,[BYTPOS] + SEG ES + MOV [DI+FILSIZ],AX + MOV AX,[BYTPOS+2] + SEG ES + MOV [DI+FILSIZ+2],AX + XOR CX,CX + RET + +RELFILE: + MOV DX,0FFFH + CALL RELBLKS +SETDIRT: + MOV B,[BP+DIRTYFAT],1 + JP UPDATE + +KILLFIL: + XOR BX,BX + SEG ES + XCHG BX,[DI+FIRCLUS] + OR BX,BX + JZ UPDATE + CALL RELEASE + JP SETDIRT + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = sector 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 sector 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 sectors per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of sectors left in first cluster + MOV DX,CX + LEA SI,[BP+FAT] + 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 +;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 sectors still needed + PUSH DX + MOV AX,CX + MUL AX,[BP+SECSIZ] ;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 + CALL FIGREC + MOV BX,SI + RET +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 + JP FINCLUS + + +FIGREC: + +;Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; BP = Base of drive parameters +;Outputs: +; DX = physical sector number +;No other registers affected. + + PUSH CX + MOV CL,[BP+CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP+FIRREC] + POP CX + RET + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; CX = 1 +; DX:AX = Record number determined by EXTENT and NR fields +; DS:DI point to FCB +; No other registers affected. + + MOV DI,DX + MOV CX,1 + MOV AL,[DI+NR] + MOV DX,[DI+EXTENT] + SHL AL + SHR DX + RCR AL + MOV AH,DL + MOV DL,DH + MOV DH,0 + 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 bit +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH [SI] + PUSH DX + PUSH CX + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP+MAXCLUS] + JLE TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + POP AX ;No. of clusters requested + SUB AX,CX ;AX=No. of clusters allocated + POP DX + POP [SI] + INC DX ;Position of first cluster allocated + ADD AX,DX ;AX=max no. of cluster in file + MOV DL,[BP+CLUSMSK] + MOV DH,0 + INC DX ;DX=records/cluster + MUL AX,DX ;AX=max no. of records in file + MOV CX,AX + SUB CX,[RECPOS] ;CX=max no. of records that could be written + JA MAXREC + XOR CX,CX ;If CX was negative, zero it +MAXREC: + 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+DIRTYFAT],1 + POP BX + POP CX ;Don't need this stuff since we're successful + POP DX + CALL UNPACK + POP [SI] + XCHG BX,DI + OR DI,DI + JNZ RET + MOV DI,[FCB] + SEG ES + MOV [DI+FIRCLUS],BX + 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,0FF8H + MOV BX,AX + JB 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,0FF8H + JAE RET + MOV BX,DI + JP GETEOF + + +SRCHFRST: ;System call 17 + PUSH DX + PUSH DS + CALL GETFILE +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + POP ES + POP DI + JC KILLSRCH + CMP BH,-1 + JZ SRCHDEV + MOV AX,[LASTENT] + SEG ES + MOV [DI+FILDIRBLK],AX +;Information in directory entry must be copied into the first +; 33 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,[DMAADD] + MOV AL,[BP+DRVNUM] + INC AL + STOB ;Set drive number + MOVB ;Copy first character of name + MOV CX,5 + REP + MOVW ;Copy remaining 10 characters of name + XOR AX,AX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT5 + STOB ;Zero out unused portion + MOV CX,7 + REP + STOW ;Zero a total of 15 bytes + MOVW ;Copy first cluster pointer + MOVW ;Copy low word of length + MOVB ;Copy 3rd byte of length + STOB ;4th byte of length must be zero + RET +BIGENT5: + ENDIF + + MOV CX,10 + REP + MOVW + MOVB + RET + +KILLSRCH: + SEG ES +KILLSRCH1: + MOV [DI+FILDIRBLK],-2 + MOV AL,-1 + RET + +SRCHDEV: + SEG ES + MOV [DI+FILDIRBLK],BX + LES DI,[DMAADD] + XOR AX,AX + STOB ;Zero drive byte + SUB SI,3 ;Point to device name + MOVW + MOVB + MOV AX,2020H + MOV CX,4 + REP + STOW ;Fill with 8 blanks + XOR AX,AX + MOV CX,10 + REP + STOW + STOB + RET + +SRCHNXT: ;System call 18 + CALL MOVNAME + MOV DI,DX + JC KILLSRCH1 + PUSH DX + PUSH DS + MOV AX,[DI+FILDIRBLK] + PUSH CS + POP DS + MOV [LASTENT],AX + CALL CONTSRCH + JMP SAVPLCE + + +FILESIZE: ;System call 35 + PUSH DS + PUSH DX + CALL GETFILE + POP DI + POP ES + MOV AL,-1 + JC RET + ADD DI,33 ;Write size in RR field + SEG ES + MOV CX,[DI-33+RECSIZ] + OR CX,CX + JNZ RECOK + MOV CX,128 +RECOK: + XOR AX,AX + XOR DX,DX ;Intialize size to zero + CMP BH,-1 ;Check for named I/O device + JZ DEVSIZ + INC SI + INC SI ;Point to length field + MOV AX,[SI+2] ;Get high word of size + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGSIZ + MOV AH,0 +BIGSIZ: + ENDIF + + DIV AX,CX + PUSH AX ;Save high part of result + LODW ;Get low word of size + DIV AX,CX + OR DX,DX ;Check for zero remainder + POP DX + JZ DEVSIZ + INC AX ;Round up for partial record + JNZ DEVSIZ ;Propagate carry? + INC DX +DEVSIZ: + STOW + MOV AX,DX + STOB + MOV AL,0 + CMP CX,64 + JAE RET ;Only 3-byte field if RECSIZ >= 64 + SEG ES + MOV [DI],AH + 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 BP,[CURDRVPT] + CALL FATREAD + LEA BX,[BP+FAT] + MOV AL,[BP+CLUSMSK] + INC AL + MOV DX,[BP+MAXCLUS] + DEC DX + MOV B,[BP+DIRTYFAT],1 + MOV CX,[BP+SECSIZ] + LDS SI,[SPSAVE] + MOV [SI+BXSAVE],BX + MOV [SI+DXSAVE],DX + MOV [SI+CXSAVE],CX + MOV [SI+DSSAVE],CS + RET + + +GETDSKPT: ;System call 31 + SEG CS + MOV BX,[CURDRVPT] + SEG CS + LDS SI,[SPSAVE] + MOV [SI+BXSAVE],BX + MOV [SI+DSSAVE],CS + RET + + +DSKRESET: ;System call 13 + SEG CS + MOV [DMAADD+2],DS + MOV AX,CS + MOV DS,AX + MOV [DMAADD],80H + MOV AX,[CURDRVPT+2] + MOV [CURDRVPT],AX +WRTFATS: +; DS=CS. Writes back all dirty FATs. All registers destroyed. + MOV CL,[NUMDRV] + MOV CH,0 + MOV SI,CURDRVPT+2 +WRTFAT: + LODW + PUSH CX + PUSH SI + MOV BP,AX + CALL CHKFATWRT + POP SI + POP CX + LOOP WRTFAT + MOV AX,[BUFDRVNO] + OR AH,AH + JZ RET + CBW + MOV BX,AX + SHL BX + MOV BP,[BX+DRVTAB] + MOV B,[DIRTYBUF],0 + MOV DX,[BUFSECNO] + MOV BX,BUFFER + MOV CX,1 + JMP DWRITE + + +CURDRV: ;System call 25 + SEG CS + MOV BP,[CURDRVPT] + MOV AL,[BP+DRVNUM] + RET + + +INUSE: ;System call 24 + MOV AX,CS + MOV DS,AX + MOV CL,[NUMDRV] + MOV CH,0 + MOV SI,CX + SHL SI + ADD SI,CURDRVPT + MOV BX,0 + DOWN +CHKUSE: + LODW + MOV BP,AX + CMP B,[BP+DIRTYFAT],-1 ;Carry set if not equal + RCL BX + LOOP CHKUSE + MOV AL,BL + RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+33],AX + MOV [DI+35],DL + RET + + +SELDSK: ;System call 14 + MOV DH,0 + MOV BX,DX + PUSH CS + POP DS + MOV AL,[NUMDRV] + CMP BL,AL + JNB RET + SHL BX + MOV DX,[BX+CURDRVPT+2] + MOV [CURDRVPT],DX + 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,"X"-"@" + JZ KILNEW + CMP AL,ESCCH + JZ ESC +SAVCH: + CMP DH,DL + JAE GETCH + STOB + INC DH + CALL BUFOUT + 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 + SEG CS ;To work in init + 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 + SEG CS + MOV AL,[STARTPOS] + CALL TAB + 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 + DOWN + 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 + UP + 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 OUT + MOV AL,8 + JMP OUT + +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 BUFOUT + 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 + +BUFOUT: + CMP AL," " + JAE OUT + CMP AL,9 + JZ OUT + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JP OUT + +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 +NOSTOP: + CMP AL,'P'-'@' + JZ PRINTON + CMP AL,'N'-'@' + JZ PRINTOFF + CMP AL,'C'-'@' + JNZ RET +; Ctrl-C handler. +; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +; to show line is canceled. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has +; 1) the interrupt return address should the user CTRL-C handler wish to +; allow processing to continue; 2) the original interrupt return address +; to the code that performed the function call in the first place. If the +; user CTRL-C handler wishes to continue, it must leave all registers +; unchanged and IRET. The function that was interrupted will simply be +; repeated, except for console output (function 2), which has already output +; its character before the interrupt. + SEG CS + MOV AL,[FUNC] ;Get currently executing function + CMP AL,10 ;Check if buffered line input + JZ CANLIN + CMP AL,9 ;Check if buffered line output + JNZ RESTREG +CANLIN: + MOV AL,"\" ;Display cancel line symbol + CALL OUT + CALL CRLF +RESTREG: + DI ;Prepare to play with stack + SEG CS + MOV SS,[SSSAVE] + SEG CS + MOV SP,[SPSAVE] ;User stack now restored + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES ;User registers now restored + INT CONTC ;Execute user Ctrl-C handler + CMP AH,2 ;Check if function was console output + JZ SETAL + JMP COMMAND ;Repeat command otherwise +SETAL: + MOV AL,DL + IRET ;Return to user program + +PRINTON: + SEG CS + MOV B,[PFLAG],1 + RET +PRINTOFF: + SEG CS + MOV B,[PFLAG],0 + RET +CTRLOUT: + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JNZ OUTCHJ + SEG CS + MOV AL,[CARPOS] + OR AL,0F8H + NEG AL +TAB: + PUSH CX + MOV CL,AL + MOV CH,0 +TABLP: + MOV AL," " + CALL OUT + LOOP TABLP + POP CX + RET + +ZERPOS: + SEG CS + MOV B,[CARPOS],0 +OUTCHJ: JMP OUTCH + +BACKPOS: + SEG CS + DEC B,[CARPOS] + JMP OUTCH + + +CONSTAT: ;System call 11 + CALL BIOSSTAT,BIOSSEG + JZ RET + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL IN + PUSH AX + CALL OUT + POP AX + RET + + +IN: ;Internal input routine + CALL INCHK + JZ IN + RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + CALL BIOSSTAT,BIOSSEG + JZ RET +RAWINP: ;System call 7 + 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 + + +MAKEFCB: ;Interrupt call 41 + MOV DL,0 ;Flag--not ambiguous file name + OR AL,AL ;Scan off separators if not zero + JZ NOSCAN +SCAN: + CALL GETLET + JZ SCAN ;Get rid of leading separators (e.g., blanks) + DEC SI ;Point back to first non-separator +NOSCAN: + CMP B,[SI+1],":" ;Check for potential drive specifier + JNZ DEFAULT + CALL GETLET + SUB AL,"@" ;Convert drive letter to binary drive number + JZ NODRV ;Valid drive numbers are 1-15 + INC SI + CMP AL,15 + JBE HAVDRV + DEC SI +NODRV: + DEC SI ;Invalid drive specifier--back up pointer +DEFAULT: + XOR AL,AL +HAVDRV: + STOB ;Put drive specifier in first byte + MOV CX,8 + CALL GETWORD ;Get 8-letter file name + CMP B,[SI],"." + JNZ NODOT + INC SI ;Skip over dot if present +NODOT: + MOV CX,3 ;Get 3-letter extension + CALL GETWORD + SEG CS + LDS BX,[SPSAVE] + MOV [BX+SISAVE],SI + XOR AX,AX + STOW + STOW + MOV AL,DL + RET + +GETWORD: + CALL GETLET + JZ FILLNAM ;Exit if invalid character + CMP AL," " + JBE FILLNAM + CMP AL,"*" ;Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + DEC CX + REP + STOB ;Fill rest of word with "?" + INC CX +NOSTAR: + STOB + CMP AL,"?" + JNZ NOTQ + MOV DL,1 ;Flag ambiguous file name +NOTQ: + LOOP GETWORD + INC SI ;Point to "termination" character +FILLNAM: + MOV AL," " + REP + STOB + DEC SI + RET + +GETLET: + LODB + CMP AL,"a" + JB CHK + CMP AL,"z" + JA CHK + SUB AL,20H ;Convert to upper case +CHK: + CMP AL," " + JZ RET + CMP AL,"=" + JZ RET + CMP AL,"," + JZ RET + CMP AL,";" + JZ RET + CMP AL,"." + JZ RET + CMP AL,":" + JZ RET + CMP AL,9 ;Filter out TABs too + RET + + +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,[CSLOC] + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP + MOVW + +SETMEM: + +; Inputs: +; 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) +; AX,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,MAXDIF + JBE HAVDIF + MOV CX,MAXDIF +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 + + +SHFTDI7: + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + RET + + +; Default handler for division overflow trap +DIVOV: + XOR DX,DX ;Say no remainder + MOV AX,-1 ;But large quotient + IRET + + +;***** DATA AREA ***** + +BADMES: DB 13,10,"Bad FAT",13,10,"$" +BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$" +RDERRMES:DB 13,10,"Disk read error",13,10,"$" +WRTERRMES:DB 13,10,"Disk write error",13,10,"$" +IONAME: DB "PRN","LST","AUX","CON" + +CARPOS: DB 0 +STARTPOS:DB 0 +PFLAG: DB 0 +DIRTYDIR:DB 0 ;Dirty buffer flag +NUMDRV: DS 1 ;Number of drives +CONTPOS:DW 0 +DMAADD: DW 80H ;User's disk transfer address (disp/seg) + DS 2 +ENDMEM: DS 2 +MAXSEC: DW 0 +BUFFER: DS 2 +BUFSECNO:DW 0 +BUFDRVNO:DB -1 +DIRTYBUF:DB 0 +DIRBUFID:DW -1 +DATE: DS 2 +CURDRVPT:DS 2 +DRVTAB: DS 30 ;Enough for 15 drives +INBUF: DS 15 ;Only the first part + +; Init code overlaps with data area below + +INITCODE: + + DS 128-15 ;More of INBUF +CONBUF: DS 130 ;The rest of INBUF and console buffer +FUNC: DS 1 ;Currently executing function code +LASTENT:DS 2 +EXITHOLD:DS 4 +FATBASE:DS 2 +NAME1: DS 11 ;File name buffer +NAME2: DS 11 +TEMP: +CSLOC: DS 2 +SPSAVE: DS 2 +SSSAVE: DS 2 +SECCLUSPOS:DS 1 ;Position of first sector within cluster +DSKERR: DS 1 +TRANS: DS 1 + + ALIGN +FCB: DS 2 ;Address of user FCB +NEXTADD:DS 2 +RECPOS: DS 4 +RECCNT: DS 2 +LASTPOS:DS 2 +CLUSNUM:DS 2 +SECPOS: DS 2 ;Position of first sector accessed +VALSEC: DS 2 ;Number of valid (previously written) sectors +BYTSECPOS:DS 2 ;Position of first byte within sector +BYTPOS: DS 4 ;Byte position in file of access +BYTCNT1:DS 2 ;No. of bytes in first sector +BYTCNT2:DS 2 ;No. of bytes in last sector +SECCNT: DS 2 ;No. of whole sectors + + DS 60 ;Stack space +STACK: + + IF DSKTEST +NSS: DS 2 +NSP: DS 2 + DS 60 +TESTSTK: + ENDIF + +DIRBUF: + +;Init code below overlaps with data area above + + ORG INITCODE + PUT $+100H + +MOVFAT: +;This section of code is safe from being overwritten by block move + SEG ES + REP + MOVB + UP +FININIT: + CALL SETMEM ;Set up segment + RET L + +DOSINIT: + DI + UP + PUSH CS + POP ES + LODB + SEG ES + MOV [NUMDRV],AL + MOV BX,DRVTAB + MOV DI,MEMSTRT +PERDRV: + SEG ES + MOV [BX],DI + MOV BP,DI + INC BX + INC BX + SEG ES + MOV AL,[DRVCNT] + STOB ;DRVNUM + LODW ;Pointer to DPT + PUSH SI + MOV SI,AX + LODW + STOW ;SECSIZ + MOV DX,AX + SEG ES + CMP AX,[MAXSEC] + JBE NOTMAX + SEG ES + MOV [MAXSEC],AX +NOTMAX: + LODB + DEC AL + STOB ;CLUSMSK + JZ HAVSHFT + CBW +FIGSHFT: + INC AH + SAR AL + JNZ FIGSHFT + MOV AL,AH +HAVSHFT: + STOB ;CLUSSHFT + MOVW ;FIRFAT (= number of reserved sectors) + MOVB ;FATCNT + MOVW ;MAXENT + MOV AX,DX ;SECSIZ again + MOV CL,5 + SHR AX,CL + MOV CX,AX ;Directory entries per sector + DEC AX + SEG ES + ADD AX,[BP+MAXENT] + XOR DX,DX + DIV AX,CX + STOW ;DIRSEC (temporarily) + SHR AX ;Divide by two + ADC AX,0 ;Round up + SEG ES + MOV [SDIRSEC],AX ;Number of directory records for small entries + MOVW ;DSKSIZ (temporarily) +FNDFATSIZ: + MOV AL,1 + MOV DX,1 +GETFATSIZ: + PUSH DX + CALL FIGFATSIZ + POP DX + CMP AL,DL ;Compare newly computed FAT size with trial + JZ HAVFATSIZ ;Has sequence converged? + CMP AL,DH ;Compare with previous trial + MOV DH,DL + MOV DL,AL ;Shuffle trials + JNZ GETFATSIZ ;Continue iterations if not oscillating + SEG ES + DEC [BP+DSKSIZ] ;Damp those oscillations + JP FNDFATSIZ ;Try again +HAVFATSIZ: + STOB ;FATSIZ + SEG ES + MUL AL,[BP+FATCNT] ;Space occupied by all FATs + SEG ES + ADD AX,[BP+FIRFAT] + STOW ;FIRDIR + + IF SMALLDIR-1 + SEG ES + ADD AX,[BP+DIRSEC] + SEG ES + MOV [BP+FIRREC],AX ;Destroys DIRSEC + CALL FIGMAX + SEG ES + MOV [BP+MAXCLUS],CX + ENDIF + + IF SMALLDIR + MOV DX,AX ;Save FIRDIR momentarily + SEG ES + ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry + STOW ;FIRREC1 + XCHG AX,CX ;Previously computed MAXCLUS + STOW ;MAXCLUS1 + XCHG DX,AX + SEG ES + ADD AX,[BP+DIRSEC] ;Add number of dir. sectores for 32-byte entry + STOW ;FIRREC2 + CALL FIGMAX + XCHG AX,CX + STOW ;MAXCLUS2 + ENDIF + + MOV AX,0FFH + STOB ;DIRTYFAT + SEG ES + MOV AL,[BP+FATSIZ] + SEG ES + MUL AX,[BP+SECSIZ] + ADD DI,AX ;Allocate FAT + POP SI ;Restore pointer to init. table + SEG ES + MOV AL,[DRVCNT] + INC AL + SEG ES + MOV [DRVCNT],AL + SEG ES + CMP AL,[NUMDRV] + JAE CONTINIT + JMP PERDRV +CONTINIT: + LODW ;Max. buffer size + SEG ES + MOV BX,[MAXSEC] + MOV AX,DIRBUF + ADD AX,BX + SEG ES + MOV [BUFFER],AX ;Start of buffer + PUSH DI ;Save ending location + ADD DI,BX ;Allocate directory buffer + ADD DI,BX ;Allocate buffer space + ADD DI,ADJFAC+15 ;True start of free space + MOV CL,4 + SHR DI,CL ;First free segment + MOV BP,DI + 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 [ENTRYPOINT+1],ENTRY + MOV [ENTRYPOINT+3],AX + MOV [0],DIVOV ;Set default divide trap address + MOV [2],AX + MOV CX,9 + REP + STOW ;Set 5 segments (skip 2 between each) + MOV [INTBASE+4],COMMAND + MOV [INTBASE+12],IRET ;CTRL-C exit + MOV [INTBASE+16],IRET ;Fatal error exit + MOV AX,BIOSREAD + STOW + MOV AX,BIOSSEG + STOW + STOW ;Add 2 to DI + STOW + MOV [INTBASE+18H],BIOSWRITE + MOV DX,CS + MOV DS,DX + ADD DX,BP + MOV [DMAADD],80H + MOV [DMAADD+2],DX + MOV AX,[DRVTAB] + MOV [CURDRVPT],AX + MOV CX,DX + MOV BX,0FH +MEMSCAN: + INC CX + JZ HAVMEM + MOV DS,CX + MOV AL,[BX] + NOT AL + MOV [BX],AL + CMP AL,[BX] + NOT AL + MOV [BX],AL + JZ MEMSCAN +HAVMEM: + SEG CS + MOV [ENDMEM],CX + XOR CX,CX + MOV DS,CX + MOV [EXIT],100H + MOV [EXIT+2],DX + MOV SI,HEADER + CALL OUTMES + PUSH CS + POP DS + PUSH CS + POP ES + PUSH DX +GETDAT: + MOV SI,DATMES + CALL OUTMES + MOV DX,DATBUF + CALL BUFIN + CALL CRLF + MOV SI,DATBUF+2 + MOV DX,12 + CALL MYD + JC GETDAT + MOV CL,5 + SHL AX,CL + MOV [DATE],AX + MOV DX,31 + CALL MYD + JC GETDAT + OR [DATE],AL + MOV DX,2100 + CALL MYD + JC GETDAT + SUB AX,80 + JC GETDAT + CMP AX,19 + JBE SAVYR + SUB AX,1900 + JC GETDAT +SAVYR: + SHL AL + OR [DATE+1],AL +;Move the FATs into position and adjust the drive pointer table + POP DX + POP SI + MOV AX,[MAXSEC] + SHL AX ;Allocate two buffers + ADD AX,ADJFAC + JZ FINJMP + MOV DI,DRVTAB + MOV CX,15 +ADJLP: + ADD [DI],AX + INC DI + INC DI + LOOP ADJLP + MOV CX,SI + MOV SI,MEMSTRT ;Place to move FATs from + SUB CX,SI ;Total length of FATs + MOV DI,AX + ADD DI,SI ;Place to move FATs to + OR AX,AX + JS MOVJMP + DEC CX + ADD DI,CX + ADD SI,CX + INC CX + DOWN +MOVJMP: + JMP MOVFAT +FINJMP: JMP FININIT + +FIGFATSIZ: + SEG ES + MUL AL,[BP+FATCNT] + SEG ES + ADD AX,[BP+FIRFAT] + SEG ES + ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +FIGMAX: +;AX has equivalent of FIRREC + SEG ES + SUB AX,[BP+DSKSIZ] + NEG AX + SEG ES + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + INC AX + MOV CX,AX ;MAXCLUS + INC AX + MOV DX,AX + SHR DX + ADC AX,DX ;Size of FAT in bytes + SEG ES + MOV SI,[BP+SECSIZ] + ADD AX,SI + DEC AX + XOR DX,DX + DIV AX,SI + RET + +MYD: +;SI points to input buffer. Get decimal number < DX and return it +;in AX. Carry set on error. + XOR BX,BX + MOV AH,0 +GETDIG: + LODB + SUB AL,"0" + JC CHKRET + CMP AL,10 + JNC CHKRET + SHL BX + MOV CX,BX + SHL BX + SHL BX + ADD BX,CX + ADD BX,AX + JP GETDIG +CHKRET: + MOV AX,BX + OR AX,AX + STC + JZ RET + CMP DX,AX + RET + +DRVCNT: DB 0 + +DATMES: DB "Enter today's date (m-d-y): $" +DATBUF: DB 12,8,"04-28-81",13 + DS 5 + +SDIRSEC:DS 2 + +MEMSTRT: +ADJFAC: EQU DIRBUF-MEMSTRT + \ No newline at end of file diff --git a/3_source_code/MS-DOS_1.25/MSDOS.ASM b/3_source_code/MS-DOS_1.25/MSDOS.ASM new file mode 100644 index 0000000..40a80c0 --- /dev/null +++ b/3_source_code/MS-DOS_1.25/MSDOS.ASM @@ -0,0 +1,4031 @@ +; 86-DOS High-performance operating system for the 8086 version 1.25 +; by Tim Paterson + + +; ****************** Revision History ************************* +; >> EVERY change must noted below!! << +; +; 0.34 12/29/80 General release, updating all past customers +; 0.42 02/25/81 32-byte directory entries added +; 0.56 03/23/81 Variable record and sector sizes +; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +; 0.74 04/15/81 Recognize I/O devices with file names +; 0.75 04/17/81 Improve and correct buffer handling +; 0.76 04/23/81 Correct directory size when not 2^N entries +; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +; 1.00 04/28/81 Renumber for general release +; 1.01 05/12/81 Fix bug in `STORE' +; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time, +; RENAME fix, general cleanup +; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE +; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't) +; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling +; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; +; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; +; Lots of smaller improvements +; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory +; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write +; 1.23 02/11/82 Add defaulting to parser; use variable escape character +; Don't zero extent field in IBM version (back to 1.01!) +; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28 +; 1.25 03/03/82 Put marker (00) at end of directory to speed searches +; +; ************************************************************* + + +; 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 + + IF IBM +ESCCH EQU 0 +CANCEL EQU 1BH ;Cancel with ESC +TOGLINS EQU TRUE ;One key toggles insert mode +TOGLPRN EQU TRUE ;One key toggles printer echo +NUMDEV EQU 6 ;Include "COM1" as I/O device name +ZEROEXT EQU TRUE + ELSE +ESCCH EQU 1BH +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLINS EQU FALSE ;Separate keys for insert mode on and off +TOGLPRN EQU FALSE ;Separate keys for printer echo on and off +NUMDEV EQU 5 ;Number of I/O device names +ZEROEXT EQU FALSE + ENDIF + +MAXCALL EQU 36 +MAXCOM EQU 46 +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 +MAXDIF EQU 0FFFH +SAVEXIT EQU 10 + +; Field definition for FCBs + +FCBLOCK STRUC + DB 12 DUP (?) ;Drive code and name +EXTENT DW ? +RECSIZ DW ? ;Size of record (user settable) +FILSIZ DW ? ;Size of file in bytes +DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT +FDATE DW ? ;Date of last writing +FTIME DW ? ;Time of last writing +DEVID DB ? ;Device ID number, bits 0-5 + ;bit 7=0 for file, bit 7=1 for I/O device + ;If file, bit 6=0 if dirty + ;If I/O device, bit 6=0 if EOF (input) +FIRCLUS DW ? ;First cluster of file +LSTCLUS DW ? ;Last cluster accessed +CLUSPOS DW ? ;Position of last cluster accessed + DB ? ;Forces NR to offset 32 +NR DB ? ;Next record +RR DB 3 DUP (?) ;Random record +FCBLOCK ENDS +FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT + +; Description of 32-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 1 Attributes. Bits 1 or 2 make file hidden +; 12 10 Zero field (for expansion) +; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour +; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +; 26 2 First allocation unit ( < 4080 ) +; 28 4 File size, in bytes (LSB first, 30 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 and as a flag for directory +; entry size (if SMALLDIR selected). 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 greater than 0FF8H 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 + +DPBLOCK STRUC +DEVNUM DB ? ;I/O driver number +DRVNUM DB ? ;Physical Unit number +SECSIZ DW ? ;Size of physical sector in bytes +CLUSMSK DB ? ;Sectors/cluster - 1 +CLUSSHFT DB ? ;Log2 of sectors/cluster +FIRFAT DW ? ;Starting record of FATs +FATCNT DB ? ;Number of FATs for this drive +MAXENT DW ? ;Number of directory entries +FIRREC DW ? ;First sector of first cluster +MAXCLUS DW ? ;Number of clusters on drive + 1 +FATSIZ DB ? ;Number of records occupied by FAT +FIRDIR DW ? ;Starting record of directory +FAT DW ? ;Pointer to start of FAT +DPBLOCK ENDS + +DPBSIZ EQU 20 ;Size of the structure in bytes +DIRSEC = FIRREC ;Number of dir. sectors (init temporary) +DSKSIZ = MAXCLUS ;Size of disk (temp used during init only) + +;The following are all of the segments used +;They are declared in the order that they should be placed in the executable + +CODE SEGMENT +CODE ENDS + +CONSTANTS SEGMENT BYTE +CONSTANTS ENDS + +DATA SEGMENT WORD +DATA ENDS + +DOSGROUP GROUP CODE,CONSTANTS,DATA + +SEGBIOS SEGMENT +SEGBIOS ENDS + + +; BOIS entry point definitions + + IF IBM +BIOSSEG EQU 60H + ENDIF + IF NOT IBM +BIOSSEG EQU 40H + ENDIF + +SEGBIOS SEGMENT AT BIOSSEG + ORG 0 + DB 3 DUP (?) ;Reserve room for jump to init code +BIOSSTAT DB 3 DUP (?) ;Console input status check +BIOSIN DB 3 DUP (?) ;Get console character +BIOSOUT DB 3 DUP (?) ;Output console character +BIOSPRINT DB 3 DUP (?) ;Output to printer +BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary +BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary +BIOSREAD DB 3 DUP (?) ;Disk read +BIOSWRITE DB 3 DUP (?) ;Disk write +BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status +BIOSSETDATE DB 3 DUP (?) ;Set date +BIOSSETTIME DB 3 DUP (?) ;Set time +BIOSGETTIME DB 3 DUP (?) ;Get time and date +BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer +BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper + +SEGBIOS ENDS +; Location of user registers relative user stack pointer + +STKPTRS STRUC +AXSAVE DW ? +BXSAVE DW ? +CXSAVE DW ? +DXSAVE DW ? +SISAVE DW ? +DISAVE DW ? +BPSAVE DW ? +DSSAVE DW ? +ESSAVE DW ? +IPSAVE DW ? +CSSAVE DW ? +FSAVE DW ? +STKPTRS ENDS + +; Start of code + +CODE SEGMENT +ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP + + ORG 0 +CODSTRT EQU $ + JMP DOSINIT + +ESCCHAR DB ESCCH ;Lead-in character for escape sequences +ESCTAB: + IF NOT IBM + DB "S" ;Copy one char + DB "V" ;Skip one char + DB "T" ;Copy to char + DB "W" ;Skip to char + DB "U" ;Copy line + DB "E" ;Kill line (no change in template) + DB "J" ;Reedit line (new template) + DB "D" ;Backspace + DB "P" ;Enter insert mode + DB "Q" ;Exit insert mode + DB "R" ;Escape character + DB "R" ;End of table + ENDIF + IF IBM + DB 64 ;Crtl-Z - F6 + DB 77 ;Copy one char - --> + DB 59 ;Copy one char - F1 + DB 83 ;Skip one char - DEL + DB 60 ;Copy to char - F2 + DB 62 ;Skip to char - F4 + DB 61 ;Copy line - F3 + DB 61 ;Kill line (no change to template ) - Not used + DB 63 ;Reedit line (new template) - F5 + DB 75 ;Backspace - <-- + DB 82 ;Enter insert mode - INS (toggle) + DB 65 ;Escape character - F7 + DB 65 ;End of table + ENDIF + +ESCTABLEN EQU $-ESCTAB + IF NOT IBM +HEADER DB 13,10,"MS-DOS version 1.25" + IF HIGHMEM + DB "H" + ENDIF + IF DSKTEST + DB "D" + ENDIF + + DB 13,10 + DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$" + ENDIF + +QUIT: + MOV AH,0 + JMP SHORT 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 + POP CS:[TEMP] ;IP from the CALL 5 + PUSHF ;Start re-ordering the stack + CLI + PUSH AX ;Save segment + PUSH CS:[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: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + IF DSKTEST + MOV AX,CS:[SPSAVE] + MOV CS:[NSP],AX + MOV AX,CS:[SSSAVE] + MOV CS:[NSS],AX + POP AX + PUSH AX + ENDIF + + MOV CS:[SPSAVE],SP + MOV CS:[SSSAVE],SS + MOV SP,CS + MOV SS,SP +REDISP: + MOV SP,OFFSET DOSGROUP:IOSTACK + STI ;Stack OK now + MOV BL,AH + MOV BH,0 + SHL BX,1 + CLD + CMP AH,12 + JLE SAMSTK + MOV SP,OFFSET DOSGROUP:DSKSTACK +SAMSTK: + CALL CS:[BX+DISPATCH] +LEAVE: + CLI + MOV SP,CS:[SPSAVE] + MOV SS,CS:[SSSAVE] + MOV BP,SP + MOV BYTE PTR [BP.AXSAVE],AL + + IF DSKTEST + MOV AX,CS:[NSP] + MOV CS:[SPSAVE],AX + MOV AX,CS:[NSS] + MOV CS:[SSSAVE],AX + ENDIF + + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + IRET +; Standard Functions +DISPATCH DW ABORT ;0 + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST ;5 + DW RAWIO + DW RAWINP + DW IN + DW PRTBUF + DW BUFIN ;10 + DW CONSTAT + DW FLUSHKB + 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 + DW MAKEFCB + DW GETDATE + DW SETDATE + DW GETTIME + DW SETTIME ;45 + DW VERIFY + +INUSE: +GETIO: +SETIO: +GETRDONLY: +SETATTRIB: +USERCODE: + MOV AL,0 + RET + +VERIFY: + AND AL,1 + MOV CS:VERFLG,AL + RET + +FLUSHKB: + PUSH AX + CALL FAR PTR BIOSFLUSH + POP AX + MOV AH,AL + CMP AL,1 + JZ REDISPJ + CMP AL,6 + JZ REDISPJ + CMP AL,7 + JZ REDISPJ + CMP AL,8 + JZ REDISPJ + CMP AL,10 + JZ REDISPJ + MOV AL,0 + RET + +REDISPJ:JMP REDISP + +READER: +AUXIN: + CALL STATCHK + CALL FAR PTR BIOSAUXIN + RET + +PUNCH: + MOV AL,DL +AUXOUT: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSAUXOUT + 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,1 + MOV DI,[DI+BX] + JNC HAVCLUS + SHR DI,1 + SHR DI,1 + SHR DI,1 + SHR DI,1 + STC +HAVCLUS: + RCL BX,1 + AND DI,0FFFH + RET +HURTFAT: + PUSH AX + MOV AH,80H ;Signal Bad FAT to INT 24H handler + MOV DI,0FFFH ;In case INT 24H returns (it shouldn't) + CALL FATAL + POP AX ;Try to ignore bad FAT + RET + + +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,1 + ADD BX,SI + ADD BX,DI + SHR DI,1 + MOV DI,[BX] + JNC ALIGNED + SHL DX,1 + SHL DX,1 + SHL DX,1 + SHL DX,1 + AND DI,0FH + JMP SHORT PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + MOV [BX],DI + RET + +DEVNAME: + MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names + MOV BH,NUMDEV ;BH = number of device names +LOOKIO: + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,4 ;All devices are 4 letters + REPE CMPSB ;Check for name in list + JZ IOCHK ;If first 3 letters OK, check for the rest + ADD SI,CX ;Point to next device name + DEC BH + JNZ LOOKIO +CRET: + STC ;Not found + RET + +IOCHK: + IF IBM + CMP BH,NUMDEV ;Is it the first device? + JNZ NOTCOM1 + MOV BH,2 ;Make it the same as AUX +NOTCOM1: + ENDIF + NEG BH + MOV CX,2 ;Check rest of name but not extension + MOV AX,2020H + REPE SCASW ;Make sure rest of name is blanks + JNZ CRET +RET1: RET ;Zero set so CREATE works + +GETFILE: +; Same as GETNAME except ES:DI points to FCB on successful return + CALL MOVNAME + JC RET1 + PUSH DX + PUSH DS + CALL FINDNAME + POP ES + POP DI +RET2: 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 +; Zero set if attributes match (always except when creating) +; BP = Base of drive parameters +; DS = CS +; ES = CS +; BX = Pointer into directory buffer +; SI = Pointer to First Cluster field in directory entry +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + CALL MOVNAME + JC RET2 ;Bad file name? +FINDNAME: + MOV AX,CS + MOV DS,AX + CALL DEVNAME + JNC RET2 + CALL STARTSRCH +CONTSRCH: + CALL GETENTRY + JC RET2 +SRCH: + MOV AH,BYTE PTR [BX] + OR AH,AH ;End of directory? + JZ FREE + CMP AH,[DELALL] ;Free entry? + JZ FREE + MOV SI,BX + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,11 +WILDCRD: + REPE CMPSB + JZ FOUND + CMP BYTE PTR [DI-1],"?" + JZ WILDCRD +NEXTENT: + CALL NEXTENTRY + JNC SRCH +RET3: RET + +FREE: + CMP [ENTFREE],-1 ;Found a free entry before? + JNZ TSTALL ;If so, ignore this one + MOV CX,[LASTENT] + MOV [ENTFREE],CX +TSTALL: + CMP AH,[DELALL] ;At end of directory? + JZ NEXTENT ;No - continue search + STC ;Report not found + RET + +FOUND: +;Check if attributes allow finding it + MOV AH,[ATTRIB] ;Attributes of search + NOT AH + AND AH,[SI] ;Compare with attributes of file + ADD SI,15 + AND AH,6 ;Only look at bits 1 and 2 + JZ RET3 + TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating + JZ NEXTENT ;Otherwise continue searching + RET + + +GETENTRY: + +; Inputs: +; [LASTENT] has previously searched directory entry +; Function: +; Locates next sequential directory entry in preparation for search +; Outputs: +; Carry set if none +; ELSE +; AL = Current directory block +; BX = Pointer to next directory entry in [DIRBUF] +; DX = Pointer to first byte after end of DIRBUF +; [LASTENT] = New directory entry number + + MOV AX,[LASTENT] + INC AX ;Start with next entry + CMP AX,[BP.MAXENT] + JAE NONE +GETENT: + MOV [LASTENT],AX + MOV CL,4 + SHL AX,CL + XOR DX,DX + SHL AX,1 + RCL DX,1 ;Account for overflow in last shift + MOV BX,[BP.SECSIZ] + AND BL,255-31 ;Must be multiple of 32 + DIV BX + MOV BX,DX ;Position within sector + MOV AH,[BP.DEVNUM] ;AL=Directory sector no. + CMP AX,[DIRBUFID] + JZ HAVDIRBUF + PUSH BX + CALL DIRREAD + POP BX +HAVDIRBUF: + MOV DX,OFFSET DOSGROUP:DIRBUF + ADD BX,DX + ADD DX,[BP.SECSIZ] + RET + +NEXTENTRY: + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update AL, BX, and [LASTENT] for next directory entry. +; Carry set if no more. + + MOV DI,[LASTENT] + INC DI + CMP DI,[BP.MAXENT] + JAE NONE + MOV [LASTENT],DI + ADD BX,32 + CMP BX,DX + JB HAVIT + INC AL ;Next directory sector + PUSH DX ;Save limit + CALL DIRREAD + POP DX + MOV BX,OFFSET DOSGROUP:DIRBUF +HAVIT: + CLC + RET + +NONE: + CALL CHKDIRWRITE + STC +RET4: RET + + +DELETE: ; System call 19 + CALL MOVNAME + MOV AL,-1 + JC RET4 + MOV AL,CS:[ATTRIB] + AND AL,6 ;Look only at hidden bits + CMP AL,6 ;Both must be set + JNZ NOTALL + MOV CX,11 + MOV AL,"?" + MOV DI,OFFSET DOSGROUP:NAME1 + REPE SCASB ;See if name is *.* + JNZ NOTALL + MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all +NOTALL: + CALL FINDNAME + MOV AL,-1 + JC RET4 + OR BH,BH ;Check if device name + JS RET4 ;Can't delete I/O devices +DELFILE: + MOV BYTE PTR [DIRTYDIR],-1 + MOV AH,[DELALL] + MOV BYTE PTR [BX],AH + MOV BX,[SI] + MOV SI,[BP.FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP.MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + CALL CONTSRCH + JNC DELFILE + CALL FATWRT + CALL CHKDIRWRITE + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + ADD SI,5 + MOV DI,OFFSET DOSGROUP:NAME2 + CALL LODNAME + JC ERRET ;Report error if second name invalid + CALL FINDNAME + JC ERRET + OR BH,BH ;Check if I/O device name + JS ERRET ;If so, can't rename it + MOV SI,OFFSET DOSGROUP:NAME1 + MOV DI,OFFSET DOSGROUP:NAME3 + MOV CX,6 ;6 words (12 bytes)--include attribute byte + REP MOVSW ;Copy name to search for +RENFIL: + MOV DI,OFFSET DOSGROUP:NAME1 + MOV SI,OFFSET DOSGROUP:NAME2 + MOV CX,11 +NEWNAM: + LODSB + CMP AL,"?" + JNZ NOCHG + MOV AL,[BX] +NOCHG: + STOSB + INC BX + LOOP NEWNAM + MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes + CALL DEVNAME ;Check if giving it a device name + JNC RENERR + PUSH [LASTENT] ;Save position of match + MOV [LASTENT],-1 ;Search entire directory for duplicate + CALL CONTSRCH ;See if new name already exists + POP AX + JNC RENERR ;Error if found + CALL GETENT ;Re-read matching entry + MOV DI,BX + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,5 + MOVSB + REP MOVSW ;Replace old name with new one + MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory + MOV SI,OFFSET DOSGROUP:NAME3 + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,6 ;Include attribute byte + REP MOVSW ;Copy name back into search buffer + CALL CONTSRCH + JNC RENFIL + CALL CHKDIRWRITE + XOR AL,AL + RET + +RENERR: + CALL CHKDIRWRITE +ERRET: + MOV AL,-1 +RET5: RET + + +MOVNAME: + +; Inputs: +; DS, DX point to FCB or extended FCB +; Outputs: +; DS:DX point to normal FCB +; 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 CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.* + MOV AX,CS + MOV ES,AX + MOV DI,OFFSET DOSGROUP:NAME1 + MOV SI,DX + LODSB + MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use + MOV AH,0 ;Set default attributes + CMP AL,-1 ;Is it an extended FCB? + JNZ HAVATTRB + ADD DX,7 ;Adjust to point to normal FCB + ADD SI,6 ;Point to drive select byte + MOV AH,[SI-1] ;Get attribute byte + LODSB ;Get drive select byte +HAVATTRB: + MOV CS:[ATTRIB],AH ;Save attributes + CALL GETTHISDRV +LODNAME: +; This entry point copies a file name from DS,SI +; to ES,DI converting to upper case. + CMP BYTE PTR [SI]," " ;Don't allow blank as first letter + STC ;In case of error + JZ RET5 + MOV CX,11 +MOVCHK: + CALL GETLET + JB RET5 + JNZ STOLET ;Is it a delimiter? + CMP AL," " ;This is the only delimiter allowed + STC ;In case of error + JNZ RET5 +STOLET: + STOSB + LOOP MOVCHK + CLC ;Got through whole name - no error +RET6: RET + +GETTHISDRV: + CMP CS:[NUMDRV],AL + JC RET6 + DEC AL + JNS PHYDRV + MOV AL,CS:[CURDRV] +PHYDRV: + MOV CS:[THISDRV],AL + RET + + +OPEN: ;System call 15 + CALL GETFILE +DOOPEN: +; Enter here to perform OPEN on file already found +; in directory. DS=CS, BX points to directory +; entry in DIRBUF, SI points to First Cluster field, and +; ES:DI point to the FCB to be opened. This entry point +; is used by CREATE. + JC ERRET + OR BH,BH ;Check if file is I/O device + JS OPENDEV ;Special handler if so + MOV AL,[THISDRV] + INC AX + STOSB + XOR AX,AX + IF ZEROEXT + ADD DI,11 + STOSW ;Zero low byte of extent field if IBM only + ENDIF + IF NOT ZEROEXT + ADD DI,12 ;Point to high half of CURRENT BLOCK field + STOSB ;Set it to zero (CP/M programs set low byte) + ENDIF + MOV AL,128 ;Default record size + STOSW ;Set record size + LODSW ;Get starting cluster + MOV DX,AX ;Save it for the moment + MOVSW ;Transfer size to FCB + MOVSW + MOV AX,[SI-8] ;Get date + STOSW ;Save date in FCB + MOV AX,[SI-10] ;Get time + STOSW ;Save it in FCB + MOV AL,[BP.DEVNUM] + OR AL,40H + STOSB + MOV AX,DX ;Restore starting cluster + STOSW ; first cluster + STOSW ; last cluster accessed + XOR AX,AX + STOSW ; position of last cluster + RET + + +OPENDEV: + ADD DI,13 ;point to 2nd half of extent field + XOR AX,AX + STOSB ;Set it to zero + MOV AL,128 + STOSW ;Set record size to 128 + XOR AX,AX + STOSW + STOSW ;Set current size to zero + CALL DATE16 + STOSW ;Date is todays + XCHG AX,DX + STOSW ;Use current time + MOV AL,BH ;Get device number + STOSB + XOR AL,AL ;No error + RET +FATERR: + XCHG AX,DI ;Put error code in DI + MOV AH,2 ;While trying to read FAT + MOV AL,[THISDRV] ;Tell which drive + CALL FATAL1 + JMP SHORT FATREAD +STARTSRCH: + MOV AX,-1 + MOV [LASTENT],AX + MOV [ENTFREE],AX +FATREAD: + +; Inputs: +; DS = CS +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; BP = Base of drive parameters +; Carry set if invalid drive returned by MAPDEV +; All other registers destroyed + + MOV AL,[THISDRV] + XOR AH,AH ;Set default response to zero & clear carry + CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say + JC FATERR + CALL GETBP + MOV AL,[THISDRV] ;Use physical unit number + MOV SI,[BP.FAT] + OR AH,[SI-1] ;Dirty byte for FAT + JS NEWDSK ;If either say new disk, then it's so + JNZ MAPDRV + MOV AH,1 + CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive? + JZ MAPDRV +NEWDSK: + CMP AL,[BUFDRVNO] ;See if buffer is for this drive + JNZ BUFOK ;If not, don't touch it + MOV [BUFSECNO],0 ;Flag buffers invalid + MOV WORD PTR [BUFDRVNO],00FFH +BUFOK: + MOV [DIRBUFID],-1 + CALL FIGFAT +NEXTFAT: + PUSH AX + CALL DSKREAD + POP AX + JC BADFAT + SUB AL,[BP.FATCNT] + JZ NEWFAT + CALL FATWRT +NEWFAT: + MOV SI,[BP.FAT] + MOV AL,[BP.DEVNUM] + MOV AH,[SI] ;Get first byte of FAT + OR AH,0F8H ;Put in range + CALL FAR PTR BIOSMAPDEV + MOV AH,0 + MOV [SI-2],AX ;Set device no. and reset dirty bit +MAPDRV: + MOV AL,[SI-2] ;Get device number +GETBP: + MOV BP,[DRVTAB] ;Just in case drive isn't valid + AND AL,3FH ;Mask out dirty bit + CMP AL,[NUMIO] + CMC + JC RET7 + PUSH AX + MOV AH,DPBSIZ + MUL AH + ADD BP,AX + POP AX +RET7: RET + +BADFAT: + MOV CX,DI + ADD DX,CX + DEC AL + JNZ NEXTFAT + CALL FIGFAT ;Reset registers + CALL DREAD ;Try first FAT once more + JMP SHORT NEWFAT + +OKRET1: + MOV AL,0 + RET + +CLOSE: ;System call 16 + MOV DI,DX + CMP BYTE PTR [DI],-1 ;Check for extended FCB + JNZ NORMFCB3 + ADD DI,7 +NORMFCB3: + TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files + JNZ OKRET1 ;can't close if I/O device, or not writen + MOV AL,[DI] ;Get physical unit number + DEC AL ;Make zero = drive A + MOV AH,1 ;Look for dirty buffer + CMP AX,CS:WORD PTR [BUFDRVNO] + JNZ FNDDIR +;Write back dirty buffer if on same drive + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV BYTE PTR [DIRTYBUF],0 + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + MOV BP,[BUFDRVBP] + CALL DWRITE + POP DS + POP DX +FNDDIR: + CALL GETFILE +BADCLOSEJ: + JC BADCLOSE + MOV CX,ES:[DI.FIRCLUS] + MOV [SI],CX + MOV DX,ES:WORD PTR [DI.FILSIZ] + MOV [SI+2],DX + MOV DX,ES:WORD PTR [DI.FILSIZ+2] + MOV [SI+4],DX + MOV DX,ES:[DI.FDATE] + MOV [SI-2],DX + MOV DX,ES:[DI.FTIME] + MOV [SI-4],DX + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty and uses same I/O driver + MOV SI,[BP.FAT] + MOV AL,[BP.DEVNUM] + MOV AH,1 + CMP [SI-2],AX ;See if FAT dirty and uses same driver + JNZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty bit. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + CALL FIGFAT + MOV BYTE PTR [BX-1],0 +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 SI,[BP.FAT] + MOV BYTE PTR [SI-1],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,OFFSET DOSGROUP:DIRBUF + MOV CX,1 + RET + + +CREATE: ;System call 22 + CALL MOVNAME + JC ERRET3 + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,11 + MOV AL,"?" + REPNE SCASB + JZ ERRET3 + MOV CS:BYTE PTR [CREATING],-1 + PUSH DX + PUSH DS + CALL FINDNAME + JNC EXISTENT + MOV AX,[ENTFREE] ;First free entry found in FINDNAME + CMP AX,-1 + JZ ERRPOP + CALL GETENT ;Point at that free entry + JMP SHORT FREESPOT +ERRPOP: + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET + +EXISTENT: + JNZ ERRPOP ;Error if attributes don't match + OR BH,BH ;Check if file is I/O device + JS OPENJMP ;If so, no action + MOV CX,[SI] ;Get pointer to clusters + JCXZ FREESPOT + CMP CX,[BP.MAXCLUS] + JA FREESPOT + PUSH BX + MOV BX,CX + MOV SI,[BP.FAT] + CALL RELEASE ;Free any data already allocated + CALL FATWRT + POP BX +FREESPOT: + MOV DI,BX + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,5 + MOVSB + REP MOVSW + MOV AL,[ATTRIB] + STOSB + XOR AX,AX + MOV CL,5 + REP STOSW + CALL DATE16 + XCHG AX,DX + STOSW + XCHG AX,DX + STOSW + XOR AX,AX + PUSH DI + MOV CL,6 +SMALLENT: + REP STOSB + PUSH BX + CALL DIRWRITE + POP BX + POP SI +OPENJMP: + CLC ;Clear carry so OPEN won't fail + POP ES + POP DI + JMP DOOPEN + + +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. + + PUSH AX + CALL CHKDIRWRITE + POP AX + PUSH AX + MOV AH,[BP.DEVNUM] + MOV [DIRBUFID],AX + CALL DIRCOMP + CALL DREAD + POP AX +RET8: RET + + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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. + + CALL DSKREAD + JNC RET8 + MOV CS:BYTE PTR [READOP],0 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DREAD + RET ;Ignore otherwise + + +HARDERR: + +;Hard disk error handler. Entry conditions: +; DS:BX = Original disk transfer address +; DX = Original logical sector number +; CX = Number of sectors to go (first one gave the error) +; AX = Hardware error code +; DI = Original sector transfer count +; BP = Base of drive parameters +; [READOP] = 0 for read, 1 for write + + XCHG AX,DI ;Error code in DI, count in AX + SUB AX,CX ;Number of sectors successfully transferred + ADD DX,AX ;First sector number to retry + PUSH DX + MUL [BP.SECSIZ] ;Number of bytes transferred + POP DX + ADD BX,AX ;First address for retry + MOV AH,0 ;Flag disk section in error + CMP DX,[BP.FIRFAT] ;In reserved area? + JB ERRINT + INC AH ;Flag for FAT + CMP DX,[BP.FIRDIR] ;In FAT? + JB ERRINT + INC AH + CMP DX,[BP.FIRREC] ;In directory? + JB ERRINT + INC AH ;Must be in data area +ERRINT: + SHL AH,1 ;Make room for read/write bit + OR AH,CS:[READOP] +FATAL: + MOV AL,[BP.DRVNUM] ;Get drive number +FATAL1: + PUSH BP ;The only thing we preserve + MOV CS:[CONTSTK],SP + CLI ;Prepare to play with stack + MOV SS,CS:[SSSAVE] + MOV SP,CS:[SPSAVE] ;User stack pointer restored + INT 24H ;Fatal error interrupt vector + MOV CS:[SPSAVE],SP + MOV CS:[SSSAVE],SS + MOV SP,CS + MOV SS,SP + MOV SP,CS:[CONTSTK] + STI + POP BP + CMP AL,2 + JZ ERROR + RET + +DSKREAD: + MOV AL,[BP.DEVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL FAR PTR BIOSREAD + POP DX + POP DI + POP BX + POP BP +RET9: RET + + +CHKDIRWRITE: + TEST BYTE PTR [DIRTYDIR],-1 + JZ RET9 + +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. + + MOV BYTE PTR [DIRTYDIR],0 + MOV AL,BYTE PTR [DIRBUFID] + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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,CS:VERFLG + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL FAR PTR BIOSWRITE + POP DX + POP DI + POP BX + POP BP + JNC RET9 + MOV CS:BYTE PTR [READOP],1 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DWRITE + RET + + +ABORT: + LDS SI,CS:DWORD PTR [SPSAVE] + MOV DS,[SI.CSSAVE] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW +ERROR: + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL WRTFATS + XOR AX,AX + CLI + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + MOV DS,AX + MOV SI,EXIT + MOV DI,OFFSET DOSGROUP:EXITHOLD + MOVSW + MOVSW + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + STI ;Stack OK now + JMP CS:DWORD PTR [EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + CALL LOAD + JMP SHORT FINSEQ + +SEQWRT: ;System call 21 + CALL GETREC + CALL STORE +FINSEQ: + JCXZ SETNREX + ADD AX,1 + ADC DX,0 + JMP SHORT SETNREX + +RNDRD: ;System call 33 + CALL GETRRPOS1 + CALL LOAD + JMP SHORT FINRND + +RNDWRT: ;System call 34 + CALL GETRRPOS1 + CALL STORE + JMP SHORT FINRND + +BLKRD: ;System call 39 + CALL GETRRPOS + CALL LOAD + JMP SHORT FINBLK + +BLKWRT: ;System call 40 + CALL GETRRPOS + CALL STORE +FINBLK: + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.CXSAVE],CX + JCXZ FINRND + ADD AX,1 + ADC DX,0 +FINRND: + MOV ES:WORD PTR [DI.RR],AX + MOV ES:[DI.RR+2],DL + OR DH,DH + JZ SETNREX + MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant +SETNREX: + MOV CX,AX + AND AL,7FH + MOV ES:[DI.NR],AL + AND CL,80H + SHL CX,1 + RCL DX,1 + MOV AL,CH + MOV AH,DL + MOV ES:[DI.EXTENT],AX + MOV AL,CS:[DSKERR] + RET + +GETRRPOS1: + MOV CX,1 +GETRRPOS: + MOV DI,DX + CMP BYTE PTR [DI],-1 + JNZ NORMFCB1 + ADD DI,7 +NORMFCB1: + MOV AX,WORD PTR [DI.RR] + MOV DX,WORD PTR [DI.RR+2] + RET + +NOFILERR: + XOR CX,CX + MOV BYTE PTR [DSKERR],4 + POP BX + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; BL = DEVID from FCB +; CX = No. of bytes to transfer +; BP = Base of drive parameters +; SI = FAT pointer +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DI +; [NEXTADD] = Displacement of disk transfer within segment +; [SECPOS] = Position of first sector +; [BYTPOS] = Byte position in file +; [BYTSECPOS] = Byte position in first sector +; [CLUSNUM] = First cluster +; [SECCLUSPOS] = Sector within first cluster +; [DSKERR] = 0 (no errors yet) +; [TRANS] = 0 (No transfers yet) +; [THISDRV] = Physical drive unit number +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + PUSH AX + MOV AL,[DI] + DEC AL + MOV CS:[THISDRV],AL + MOV AL,[DI.DEVID] + MOV SI,[DI.RECSIZ] + OR SI,SI + JNZ HAVRECSIZ + MOV SI,128 + MOV [DI.RECSIZ],SI +HAVRECSIZ: + PUSH DS + POP ES ;Set ES to DS + PUSH CS + POP DS ;Set DS to CS + OR AL,AL ;Is it a device? + JNS NOTDEVICE + MOV AL,0 ;Fake in drive 0 so we can get SP +NOTDEVICE: + CALL GETBP + POP AX + JC NOFILERR + CMP SI,64 ;Check if highest byte of RECPOS is significant + JB SMALREC + MOV DH,0 ;Ignore MSB if record >= 64 bytes +SMALREC: + MOV [RECCNT],CX + MOV WORD PTR [RECPOS],AX + MOV WORD PTR [RECPOS+2],DX + MOV [FCB],DI + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV BYTE PTR [DSKERR],0 + MOV BYTE PTR [TRANS],0 + MOV BX,DX + MUL SI + MOV WORD PTR [BYTPOS],AX + PUSH DX + MOV AX,BX + MUL SI + POP BX + ADD AX,BX + ADC DX,0 ;Ripple carry + JNZ EOFERR + MOV WORD PTR [BYTPOS+2],AX + MOV DX,AX + MOV AX,WORD PTR [BYTPOS] + MOV BX,[BP.SECSIZ] + CMP DX,BX ;See if divide will overflow + JNC EOFERR + DIV BX + MOV [SECPOS],AX + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,[BP.CLUSMSK] + MOV [SECCLUSPOS],AL + MOV AX,CX ;Record count + MOV CL,[BP.CLUSSHFT] + SHR DX,CL + MOV [CLUSNUM],DX + MUL SI ;Multiply by bytes per record + MOV CX,AX + ADD AX,[DMAADD] ;See if it will fit in one segment + ADC DX,0 + JZ OK ;Must be less than 64K + MOV AX,[DMAADD] + NEG AX ;Amount of room left in segment + JNZ PARTSEG ;All 64K available? + DEC AX ;If so, reduce by one +PARTSEG: + XOR DX,DX + DIV SI ;How many records will fit? + MOV [RECCNT],AX + MUL SI ;Translate that back into bytes + MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place + MOV CX,AX + JCXZ NOROOM +OK: + MOV BL,ES:[DI.DEVID] + MOV SI,[BP.FAT] + RET + +EOFERR: + MOV BYTE PTR [DSKERR],1 + XOR CX,CX +NOROOM: + POP BX ;Kill return address + RET + +BREAKDOWN: + +;Inputs: +; DS = CS +; CX = Length of disk transfer in bytes +; BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +;Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +;AX, BX, DX destroyed. No other registers affected. + + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ;Partial first sector? + SUB AX,[BP.SECSIZ] + NEG AX ;Max number of bytes left in first sector + SUB BX,AX ;Subtract from total length + JAE SAVFIR + ADD AX,BX ;Don't use all of the rest of the sector + XOR BX,BX ;And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV [BP.SECSIZ] ;How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ;Bytes remaining for last sector +RET10: 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. + + MOV BX,ES:[DI.LSTCLUS] + MOV DX,ES:[DI.CLUSPOS] + OR BX,BX + JZ NOCLUS + SUB CX,DX + JNB FINDIT + ADD CX,DX + XOR DX,DX + MOV BX,ES:[DI.FIRCLUS] +FINDIT: + JCXZ RET10 +SKPCLP: + CALL UNPACK + CMP DI,0FF8H + JAE RET10 + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +BUFSEC: +; Inputs: +; AL = 0 if buffer must be read, 1 if no pre-read needed +; 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: +; SI = Pointer to buffer +; DI = 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 + MOV [PREREAD],AL + CMP DX,[BUFSECNO] + JNZ GETSEC + MOV AL,[BUFDRVNO] + CMP AL,[THISDRV] + JZ FINBUF ;Already have it? +GETSEC: + XOR AL,AL + XCHG [DIRTYBUF],AL ;Read dirty flag and reset it + OR AL,AL + JZ RDSEC + PUSH DX + PUSH BP + MOV BP,[BUFDRVBP] + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP BP + POP DX +RDSEC: + TEST BYTE PTR [PREREAD],-1 + JNZ SETBUF + XOR AX,AX + MOV [BUFSECNO],AX ;Set buffer valid in case of disk error + DEC AX + MOV [BUFDRVNO],AL + MOV BX,[BUFFER] + MOV CX,1 + PUSH DX + CALL DREAD + POP DX +SETBUF: + MOV [BUFSECNO],DX + MOV AL,[THISDRV] + MOV [BUFDRVNO],AL + MOV [BUFDRVBP],BP +FINBUF: + MOV BYTE PTR [TRANS],1 ;A transfer is taking place + MOV DI,[NEXTADD] + MOV SI,DI + MOV CX,[BYTCNT1] + ADD SI,CX + MOV [NEXTADD],SI + MOV SI,[BUFFER] + ADD SI,[BYTSECPOS] + RET + +BUFRD: + XOR AL,AL ;Pre-read necessary + CALL BUFSEC + PUSH ES + MOV ES,[DMAADD+2] + SHR CX,1 + JNC EVENRD + MOVSB +EVENRD: + REP MOVSW + POP ES + RET + +BUFWRT: + 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 + MOV AL,0 +NOREAD: + CALL BUFSEC + XCHG DI,SI + PUSH DS + PUSH ES + PUSH CS + POP ES + MOV DS,[DMAADD+2] + SHR CX,1 + JNC EVENWRT + MOVSB +EVENWRT: + REP MOVSW + POP ES + POP DS + MOV BYTE PTR [DIRTYBUF],1 + RET + +NEXTSEC: + TEST BYTE PTR [TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,[BP.CLUSMSK] + JBE SAVPOS + MOV BX,[CLUSNUM] + CMP BX,0FF8H + JAE NONEXT + MOV SI,[BP.FAT] + CALL UNPACK + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + RET +NONEXT: + STC + RET + +TRANBUF: + LODSB + STOSB + CMP AL,13 ;Check for carriage return + JNZ NORMCH + MOV BYTE PTR [SI],10 +NORMCH: + CMP AL,10 + LOOPNZ TRANBUF + JNZ ENDRDCON + CALL OUT ;Transmit linefeed + XOR SI,SI + OR CX,CX + JNZ GETBUF + OR AL,1 ;Clear zero flag--not end of file +ENDRDCON: + MOV [CONTPOS],SI +ENDRDDEV: + MOV [NEXTADD],DI + POP ES + JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + MOV DI,[FCB] + AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available +SETFCBJ: + JMP SETFCB + +READDEV: + PUSH ES + LES DI,DWORD PTR [DMAADD] + INC BL + JZ READCON + INC BL + JNZ ENDRDDEV +READAUX: + CALL AUXIN + STOSB + CMP AL,1AH + LOOPNZ READAUX + JMP SHORT ENDRDDEV + +READCON: + PUSH CS + POP DS + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP BYTE PTR [CONBUF],128 + JZ GETBUF + MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,OFFSET DOSGROUP:CONBUF + CALL BUFIN ;Get input buffer + POP DI + POP ES + POP CX + MOV SI,2 + OFFSET DOSGROUP:CONBUF + CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOSB + MOV AL,10 + CALL OUT ;Send linefeed + XOR SI,SI + JMP SHORT ENDRDCON + +RDERR: + XOR CX,CX + JMP WRTERR + +RDLASTJ:JMP RDLAST + +LOAD: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file to read +; CX = No. of records to read +; Outputs: +; DX:AX = Position of last record read +; CX = No. of bytes read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + OR BL,BL ;Check for named device I/O + JS READDEV + MOV AX,ES:WORD PTR [DI.FILSIZ] + MOV BX,ES:WORD PTR [DI.FILSIZ+2] + SUB AX,WORD PTR [BYTPOS] + SBB BX,WORD PTR [BYTPOS+2] + JB RDERR + JNZ ENUF + OR AX,AX + JZ RDERR + CMP AX,CX + JAE ENUF + MOV CX,AX +ENUF: + CALL BREAKDOWN + MOV CX,[CLUSNUM] + CALL FNDCLUS + OR CX,CX + JNZ RDERR + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + CALL BUFRD +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + CALL NEXTSEC + JC SETFCB + MOV BYTE PTR [TRANS],1 ;A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + PUSH DX + PUSH BX + PUSHF ;Save carry flag + CALL DREAD + POPF ;Restore carry flag + POP DI ;Initial transfer address + POP AX ;First sector transfered + POP DS + JC NOTBUFFED ;Was one of those sectors in the buffer? + CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty? + JZ NOTBUFFED ;If not no problem +;We have transfered in a sector from disk when a dirty copy of it is in the buffer. +;We must transfer the sector from the buffer to correct memory address + SUB AX,[BUFSECNO] ;How many sectors into the transfer? + NEG AX + MOV CX,[BP.SECSIZ] + MUL CX ;How many bytes into the transfer? + ADD DI,AX + MOV SI,[BUFFER] + PUSH ES + MOV ES,[DMAADD+2] ;Get disk transfer segment + SHR CX,1 + REP MOVSW + JNC EVENMOV + MOVSB +EVENMOV: + POP ES +NOTBUFFED: + POP CX + POP BX + JCXZ RDLAST + CMP BX,0FF8H + JAE SETFCB + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JMP SHORT RDLP + +SETFCB: + MOV SI,[FCB] + MOV AX,[NEXTADD] + MOV DI,AX + SUB AX,[DMAADD] ;Number of bytes transfered + XOR DX,DX + MOV CX,ES:[SI.RECSIZ] + DIV CX ;Number of records + CMP AX,[RECCNT] ;Check if all records transferred + JZ FULLREC + MOV BYTE PTR [DSKERR],1 + OR DX,DX + JZ FULLREC ;If remainder 0, then full record transfered + MOV BYTE PTR [DSKERR],3 ;Flag partial last record + SUB CX,DX ;Bytes left in last record + PUSH ES + MOV ES,[DMAADD+2] + XCHG AX,BX ;Save the record count temporarily + XOR AX,AX ;Fill with zeros + SHR CX,1 + JNC EVENFIL + STOSB +EVENFIL: + REP STOSW + XCHG AX,BX ;Restore record count to AX + POP ES + INC AX ;Add last (partial) record to total +FULLREC: + MOV CX,AX + MOV DI,SI ;ES:DI point to FCB +SETCLUS: + MOV AX,[CLUSNUM] + MOV ES:[DI.LSTCLUS],AX + MOV AX,[LASTPOS] + MOV ES:[DI.CLUSPOS],AX +ADDREC: + MOV AX,WORD PTR [RECPOS] + MOV DX,WORD PTR [RECPOS+2] + JCXZ RET28 ;If no records read, don't change position + DEC CX + ADD AX,CX ;Update current record position + ADC DX,0 + INC CX +RET28: RET + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETFCB + MOV [BYTCNT1],AX + CALL NEXTSEC + JC SETFCB + MOV [BYTSECPOS],0 + CALL BUFRD + JMP SHORT SETFCB + +WRTDEV: + PUSH DS + LDS SI,DWORD PTR [DMAADD] + OR BL,40H + INC BL + JZ WRTCON + INC BL + JZ WRTAUX + INC BL + JZ ENDWRDEV ;Done if device is NUL +WRTLST: + LODSB + CMP AL,1AH + JZ ENDWRDEV + CALL LISTOUT + LOOP WRTLST + JMP SHORT ENDWRDEV + +WRTAUX: + LODSB + CALL AUXOUT + CMP AL,1AH + LOOPNZ WRTAUX + JMP SHORT ENDWRDEV + +WRTCON: + LODSB + CMP AL,1AH + JZ ENDWRDEV + CALL OUT + LOOP WRTCON +ENDWRDEV: + POP DS + MOV CX,[RECCNT] + MOV DI,[FCB] + JMP SHORT ADDREC + +HAVSTART: + MOV CX,AX + CALL SKPCLP + JCXZ DOWRTJ + CALL ALLOCATE + JNC DOWRTJ +WRTERR: + MOV BYTE PTR [DSKERR],1 +LVDSK: + MOV AX,WORD PTR [RECPOS] + MOV DX,WORD PTR [RECPOS+2] + MOV DI,[FCB] + RET + +DOWRTJ: JMP DOWRT + +WRTEOFJ: + JMP WRTEOF + +STORE: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; DX:AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + CALL DATE16 + MOV ES:[DI.FDATE],AX + MOV ES:[DI.FTIME],DX + OR BL,BL + JS WRTDEV + AND BL,3FH ;Mark file as dirty + MOV ES:[DI.DEVID],BL + CALL BREAKDOWN + MOV AX,WORD PTR [BYTPOS] + MOV DX,WORD PTR [BYTPOS+2] + JCXZ WRTEOFJ + DEC CX + ADD AX,CX + ADC DX,0 ;AX:DX=last byte accessed + DIV [BP.SECSIZ] ;AX=last sector accessed + MOV CL,[BP.CLUSSHFT] + SHR AX,CL ;Last cluster to be accessed + PUSH AX + MOV AX,ES:WORD PTR [DI.FILSIZ] + MOV DX,ES:WORD PTR [DI.FILSIZ+2] + DIV [BP.SECSIZ] + OR DX,DX + JZ NORNDUP + INC AX ;Round up if any remainder +NORNDUP: + MOV [VALSEC],AX ;Number of sectors that have been written + POP AX + MOV CX,[CLUSNUM] ;First cluster accessed + CALL FNDCLUS + MOV [CLUSNUM],BX + MOV [LASTPOS],DX + SUB AX,DX ;Last cluster minus current cluster + JZ DOWRT ;If we have last clus, we must have first + JCXZ HAVSTART ;See if no more data + PUSH CX ;No. of clusters short of first + MOV CX,AX + CALL ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP + CALL SKPCLP +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + CALL BUFWRT +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JZ WRTLAST + ADD [SECPOS],AX + CALL NEXTSEC + MOV BYTE PTR [TRANS],1 ;A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + CALL OPTIMIZE + JC NOTINBUF ;Is one of the sectors buffered? + MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're + MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it +NOTINBUF: + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JMP SHORT WRTLP +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + CALL NEXTSEC + MOV [BYTSECPOS],0 + CALL BUFWRT +FINWRT: + MOV AX,[NEXTADD] + SUB AX,[DMAADD] + ADD AX,WORD PTR [BYTPOS] + MOV DX,WORD PTR [BYTPOS+2] + ADC DX,0 + MOV CX,DX + MOV DI,[FCB] + CMP AX,ES:WORD PTR [DI.FILSIZ] + SBB CX,ES:WORD PTR [DI.FILSIZ+2] + JB SAMSIZ + MOV ES:WORD PTR [DI.FILSIZ],AX + MOV ES:WORD PTR [DI.FILSIZ+2],DX +SAMSIZ: + MOV CX,[RECCNT] + JMP SETCLUS + + +WRTERRJ:JMP WRTERR + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBB DX,0 + DIV [BP.SECSIZ] + MOV CL,[BP.CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + JCXZ RELFILE + CALL ALLOCATE + JC WRTERRJ +UPDATE: + MOV DI,[FCB] + MOV AX,WORD PTR [BYTPOS] + MOV ES:WORD PTR [DI.FILSIZ],AX + MOV AX,WORD PTR [BYTPOS+2] + MOV ES:WORD PTR [DI.FILSIZ+2],AX + XOR CX,CX + JMP ADDREC + +RELFILE: + MOV DX,0FFFH + CALL RELBLKS +SETDIRT: + MOV BYTE PTR [SI-1],1 + JMP SHORT UPDATE + +KILLFIL: + XOR BX,BX + XCHG BX,ES:[DI.FIRCLUS] + OR BX,BX + JZ UPDATE + CALL RELEASE + JMP SHORT SETDIRT + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = sector 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 sector address +; DI = Next cluster +; Carry clear if a sector to transfer is in the buffer +; Carry set otherwise +; [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 sectors per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of sectors left in first cluster + MOV DX,CX + MOV SI,[BP.FAT] + 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 +;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 sectors still needed + PUSH DX + MOV AX,CX + MUL [BP.SECSIZ] ;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 + CALL FIGREC + MOV BX,SI +;Now let's see if any of these sectors are already in the buffer + CMP [BUFSECNO],DX + JC RET100 ;If DX > [BUFSECNO] then not in buffer + MOV SI,DX + ADD SI,CX ;Last sector + 1 + CMP [BUFSECNO],SI + CMC + JC RET100 ;If SI <= [BUFSECNO] then not in buffer + PUSH AX + MOV AL,[BP.DEVNUM] + CMP AL,[BUFDRVNO] ;Is buffer for this drive? + POP AX + JZ RET100 ;If so, then we match + STC ;No match +RET100: RET +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 + + +FIGREC: + +;Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; BP = Base of drive parameters +;Outputs: +; DX = physical sector number +;No other registers affected. + + PUSH CX + MOV CL,[BP.CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP.FIRREC] + POP CX + RET + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; CX = 1 +; DX:AX = Record number determined by EXTENT and 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.NR] + MOV DX,[DI.EXTENT] + SHL AL,1 + SHR DX,1 + RCR AL,1 + MOV AH,DL + MOV DL,DH + MOV DH,0 + 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 bit +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH [SI] + PUSH DX + PUSH CX + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP.MAXCLUS] + JLE TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + POP AX ;No. of clusters requested + SUB AX,CX ;AX=No. of clusters allocated + POP DX + POP [SI] + INC DX ;Position of first cluster allocated + ADD AX,DX ;AX=max no. of cluster in file + MOV DL,[BP.CLUSMSK] + 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 +RET11: RET + +TRYOUT: + CALL UNPACK + JZ HAVFRE +TRYIN: + DEC AX + JLE FINDFRE + XCHG AX,BX + CALL UNPACK + JZ HAVFRE + XCHG AX,BX + JMP SHORT FINDFRE +HAVFRE: + XCHG BX,DX + MOV AX,DX + CALL PACK + MOV BX,AX + LOOP ALLOC + MOV DX,0FFFH + CALL PACK + MOV BYTE PTR [SI-1],1 + POP BX + POP CX ;Don't need this stuff since we're successful + POP DX + CALL UNPACK + POP [SI] + XCHG BX,DI + OR DI,DI + JNZ RET11 + MOV DI,[FCB] + MOV ES:[DI.FIRCLUS],BX +RET12: 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 RET12 + MOV AX,DI + CALL PACK + CMP AX,0FF8H + MOV BX,AX + JB RELEASE +RET13: 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,0FF8H + JAE RET13 + MOV BX,DI + JMP SHORT GETEOF + + +SRCHFRST: ;System call 17 + CALL GETFILE +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + JC KILLSRCH + OR BH,BH + JS SRCHDEV + MOV AX,[LASTENT] + MOV ES:[DI.FILDIRENT],AX + MOV ES:[DI.DRVBP],BP +;Information in directory entry must be copied into the first +; 33 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,DWORD PTR [DMAADD] + MOV AX,00FFH + CMP AL,[EXTFCB] + JNZ NORMFCB + STOSW + INC AL + STOSW + STOSW + MOV AL,[ATTRIB] + STOSB +NORMFCB: + MOV AL,[THISDRV] + INC AL + STOSB ;Set drive number + MOV CX,16 + REP MOVSW ;Copy remaining 10 characters of name + XOR AL,AL + RET + +KILLSRCH: +KILLSRCH1 EQU KILLSRCH+1 +;The purpose of the KILLSRCH1 label is to provide a jump label to the following +; instruction which leaves out the segment override. + MOV WORD PTR ES:[DI.FILDIRENT],-1 + MOV AL,-1 + RET + +SRCHDEV: + MOV ES:[DI.FILDIRENT],BX + LES DI,DWORD PTR [DMAADD] + XOR AX,AX + STOSB ;Zero drive byte + SUB SI,4 ;Point to device name + MOVSW + MOVSW + MOV AX,2020H + STOSB + STOSW + STOSW + STOSW ;Fill with 8 blanks + XOR AX,AX + MOV CX,10 + REP STOSW + STOSB +RET14: RET + +SRCHNXT: ;System call 18 + CALL MOVNAME + MOV DI,DX + JC NEAR PTR KILLSRCH1 + MOV BP,[DI.DRVBP] + MOV AX,[DI.FILDIRENT] + OR AX,AX + JS NEAR PTR KILLSRCH1 + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV [LASTENT],AX + CALL CONTSRCH + POP ES + POP DI + JMP SAVPLCE + + +FILESIZE: ;System call 35 + CALL GETFILE + MOV AL,-1 + JC RET14 + ADD DI,33 ;Write size in RR field + MOV CX,ES:[DI.RECSIZ-33] + OR CX,CX + JNZ RECOK + MOV CX,128 +RECOK: + XOR AX,AX + XOR DX,DX ;Intialize size to zero + OR BH,BH ;Check for named I/O device + JS DEVSIZ + INC SI + INC SI ;Point to length field + MOV AX,[SI+2] ;Get high word of size + DIV CX + PUSH AX ;Save high part of result + LODSW ;Get low word of size + DIV CX + OR DX,DX ;Check for zero remainder + POP DX + JZ DEVSIZ + INC AX ;Round up for partial record + JNZ DEVSIZ ;Propagate carry? + INC DX +DEVSIZ: + STOSW + MOV AX,DX + STOSB + MOV AL,0 + CMP CX,64 + JAE RET14 ;Only 3-byte field if RECSIZ >= 64 + MOV ES:[DI],AH + RET + + +SETDMA: ;System call 26 + MOV CS:[DMAADD],DX + MOV CS:[DMAADD+2],DS + RET + +NOSUCHDRV: + MOV AL,-1 + RET + +GETFATPT: ;System call 27 + MOV DL,0 ;Use default drive + +GETFATPTDL: ;System call 28 + PUSH CS + POP DS + MOV AL,DL + CALL GETTHISDRV + JC NOSUCHDRV + CALL FATREAD + MOV BX,[BP.FAT] + MOV AL,[BP.CLUSMSK] + INC AL + MOV DX,[BP.MAXCLUS] + DEC DX + MOV CX,[BP.SECSIZ] + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.BXSAVE],BX + MOV [SI.DXSAVE],DX + MOV [SI.CXSAVE],CX + MOV [SI.DSSAVE],CS + RET + + +GETDSKPT: ;System call 31 + PUSH CS + POP DS + MOV AL,[CURDRV] + MOV [THISDRV],AL + CALL FATREAD + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.BXSAVE],BP + MOV [SI.DSSAVE],CS + RET + + +DSKRESET: ;System call 13 + PUSH CS + POP DS +WRTFATS: +; DS=CS. Writes back all dirty FATs. All registers destroyed. + XOR AL,AL + XCHG AL,[DIRTYBUF] + OR AL,AL + JZ NOBUF + MOV BP,[BUFDRVBP] + MOV DX,[BUFSECNO] + MOV BX,[BUFFER] + MOV CX,1 + CALL DWRITE +NOBUF: + MOV CL,[NUMIO] + MOV CH,0 + MOV BP,[DRVTAB] +WRTFAT: + PUSH CX + CALL CHKFATWRT + POP CX + ADD BP,DPBSIZ + LOOP WRTFAT + RET + + +GETDRV: ;System call 25 + MOV AL,CS:[CURDRV] +RET15: RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+33],AX + MOV [DI+35],DL + CMP [DI.RECSIZ],64 + JAE RET15 + MOV [DI+36],DH ;Set 4th byte only if record size < 64 +RET16: RET + + +SELDSK: ;System call 14 + MOV AL,CS:[NUMDRV] + CMP DL,AL + JNB RET17 + MOV CS:[CURDRV],DL +RET17: RET + +BUFIN: ;System call 10 + MOV AX,CS + MOV ES,AX + MOV SI,DX + MOV CH,0 + LODSW + OR AL,AL + JZ RET17 + MOV BL,AH + MOV BH,CH + CMP AL,BL + JBE NOEDIT + CMP BYTE PTR [BX+SI],0DH + JZ EDITON +NOEDIT: + MOV BL,CH +EDITON: + MOV DL,AL + DEC DX +NEWLIN: + MOV AL,CS:[CARPOS] + MOV CS:[STARTPOS],AL + PUSH SI + MOV DI,OFFSET DOSGROUP:INBUF + MOV AH,CH + MOV BH,CH + MOV DH,CH +GETCH: + CALL IN + CMP AL,"F"-"@" ;Ignore ^F + JZ GETCH + CMP AL,CS:ESCCHAR + JZ ESC + 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 +SAVCH: + CMP DH,DL + JAE BUFFUL + STOSB + INC DH + CALL BUFOUT + OR AH,AH + JNZ GETCH + CMP BH,BL + JAE GETCH + INC SI + INC BH + JMP SHORT GETCH + +BUFFUL: + MOV AL,7 + CALL OUT + JMP SHORT GETCH + +ESC: + CALL IN + MOV CL,ESCTABLEN + PUSH DI + MOV DI,OFFSET DOSGROUP:ESCTAB + REPNE SCASB + POP DI + SHL CX,1 + MOV BP,CX + JMP [BP+OFFSET DOSGROUP:ESCFUNC] + +ENDLIN: + STOSB + 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,OFFSET DOSGROUP:INBUF + MOV CL,DH + REP MOVSB + RET +CRLF: + MOV AL,13 + CALL OUT + MOV AL,10 + JMP OUT + +PHYCRLF: + CALL CRLF + JMP SHORT GETCH + +KILNEW: + MOV AL,"\" + CALL OUT + POP SI +PUTNEW: + CALL CRLF + MOV AL,CS:[STARTPOS] + CALL TAB + JMP NEWLIN + +BACKSP: + OR DH,DH + JZ OLDBAK + CALL BACKUP + MOV AL,ES:[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: + SCASB + JNA CHKCNT + CMP ES:BYTE PTR [DI+1],9 + JZ HAVTAB + DEC BL +CHKCNT: + LOOP FNDPOS +FIGTAB: + SUB BL,CS:[STARTPOS] +HAVTAB: + SUB BL,DH + ADD CL,BL + AND CL,7 + CLD + POP BX + POP DI + JZ OLDBAK +TABBAK: + CALL BACKMES + LOOP TABBAK + JMP SHORT OLDBAK +BACKUP: + DEC DH + DEC DI +BACKMES: + MOV AL,8 + CALL OUT + MOV AL," " + CALL OUT + MOV AL,8 + JMP OUT + +TWOESC: + MOV AL,ESCCH + JMP SAVCH + +COPYLIN: + MOV CL,BL + SUB CL,BH + JMP SHORT COPYEACH + +COPYSTR: + CALL FINDOLD + JMP SHORT COPYEACH + +COPYONE: + MOV CL,1 +COPYEACH: + MOV AH,0 + CMP DH,DL + JZ GETCH2 + CMP BH,BL + JZ GETCH2 + LODSB + STOSB + CALL BUFOUT + 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 SCASB + POP DI + POP ES + JNZ NOTFND + NOT CL + ADD CL,BL + SUB CL,BH +RET30: 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: + IF TOGLINS + NOT AH + JMP GETCH + ENDIF + IF NOT TOGLINS + MOV AH,-1 + JMP GETCH + +EXITINS: + MOV AH,0 + JMP GETCH + ENDIF + +ESCFUNC DW GETCH + DW TWOESC + IF NOT TOGLINS + DW EXITINS + ENDIF + DW ENTERINS + DW BACKSP + DW REEDIT + DW KILNEW + DW COPYLIN + DW SKIPSTR + DW COPYSTR + DW SKIPONE + DW COPYONE + + IF IBM + DW COPYONE + DW CTRLZ +CTRLZ: + MOV AL,"Z"-"@" + JMP SAVCH + ENDIF +BUFOUT: + CMP AL," " + JAE OUT + CMP AL,9 + JZ OUT + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JMP SHORT OUT + +NOSTOP: + CMP AL,"P"-"@" + JZ INCHK + IF NOT TOGLPRN + CMP AL,"N"-"@" + JZ INCHK + ENDIF + CMP AL,"C"-"@" + JZ INCHK + RET + +CONOUT: ;System call 2 + MOV AL,DL +OUT: + CMP AL,20H + JB CTRLOUT + CMP AL,7FH + JZ OUTCH + INC CS:BYTE PTR [CARPOS] +OUTCH: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSOUT + TEST CS:BYTE PTR [PFLAG],-1 + JZ RET18 + CALL FAR PTR BIOSPRINT +RET18: RET + +STATCHK: + CALL FAR PTR BIOSSTAT + JZ RET18 + CMP AL,'S'-'@' + JNZ NOSTOP + CALL FAR PTR BIOSIN ;Eat Cntrl-S +INCHK: + CALL FAR PTR BIOSIN + CMP AL,'P'-'@' + JZ PRINTON + IF NOT TOGLPRN + CMP AL,'N'-'@' + JZ PRINTOFF + ENDIF + CMP AL,'C'-'@' + JNZ RET18 +; Ctrl-C handler. +; "^C" and CR/LF is printed. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has +; 1) the interrupt return address should the user CTRL-C handler wish to +; allow processing to continue; 2) the original interrupt return address +; to the code that performed the function call in the first place. If the +; user CTRL-C handler wishes to continue, it must leave all registers +; unchanged and IRET. The function that was interrupted will simply be +; repeated. + MOV AL,3 ;Display "^C" + CALL BUFOUT + CALL CRLF + CLI ;Prepare to play with stack + MOV SS,CS:[SSSAVE] + MOV SP,CS:[SPSAVE] ;User stack now restored + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES ;User registers now restored + INT CONTC ;Execute user Ctrl-C handler + JMP COMMAND ;Repeat command otherwise + +PRINTON: + IF TOGLPRN + NOT CS:BYTE PTR [PFLAG] + RET + ENDIF + IF NOT TOGLPRN + MOV CS:BYTE PTR [PFLAG],1 + RET + +PRINTOFF: + MOV CS:BYTE PTR [PFLAG],0 + RET + ENDIF + +CTRLOUT: + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JNZ OUTCHJ + MOV AL,CS:[CARPOS] + OR AL,0F8H + NEG AL +TAB: + PUSH CX + MOV CL,AL + MOV CH,0 + JCXZ POPTAB +TABLP: + MOV AL," " + CALL OUT + LOOP TABLP +POPTAB: + POP CX +RET19: RET + +ZERPOS: + MOV CS:BYTE PTR [CARPOS],0 +OUTCHJ: JMP OUTCH + +BACKPOS: + DEC CS:BYTE PTR [CARPOS] + JMP OUTCH + + +CONSTAT: ;System call 11 + CALL STATCHK + MOV AL,0 + JZ RET19 + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL IN + PUSH AX + CALL OUT + POP AX + RET + + +IN: ;System call 8 + CALL INCHK + JZ IN +RET29: RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area + CALL FAR PTR BIOSSTAT + JNZ RESFLG + OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag + XOR AL,AL + RET + +RESFLG: + AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag +RAWINP: ;System call 7 + CALL FAR PTR BIOSIN + RET +RAWOUT: + CALL FAR PTR BIOSOUT + RET + +LIST: ;System call 5 + MOV AL,DL +LISTOUT: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSPRINT +RET20: RET + +PRTBUF: ;System call 9 + MOV SI,DX +OUTSTR: + LODSB + CMP AL,"$" + JZ RET20 + CALL OUT + JMP SHORT OUTSTR + +OUTMES: ;String output for internal messages + LODS CS:BYTE PTR [SI] + CMP AL,"$" + JZ RET20 + CALL OUT + JMP SHORT OUTMES + + +MAKEFCB: ;Interrupt call 41 +DRVBIT EQU 2 +NAMBIT EQU 4 +EXTBIT EQU 8 + MOV DL,0 ;Flag--not ambiguous file name + TEST AL,DRVBIT ;Use current drive field if default? + JNZ DEFDRV + MOV BYTE PTR ES:[DI],0 ;No - use default drive +DEFDRV: + INC DI + MOV CX,8 + TEST AL,NAMBIT ;Use current name fiels as defualt? + XCHG AX,BX ;Save bits in BX + MOV AL," " + JZ FILLB ;If not, go fill with blanks + ADD DI,CX + XOR CX,CX ;Don't fill any +FILLB: + REP STOSB + MOV CL,3 + TEST BL,EXTBIT ;Use current extension as default + JZ FILLB2 + ADD DI,CX + XOR CX,CX +FILLB2: + REP STOSB + XCHG AX,CX ;Put zero in AX + STOSW + STOSW ;Initialize two words after to zero + SUB DI,16 ;Point back at start + TEST BL,1 ;Scan off separators if not zero + JZ SKPSPC + CALL SCANB ;Peel off blanks and tabs + CALL DELIM ;Is it a one-time-only delimiter? + JNZ NOSCAN + INC SI ;Skip over the delimiter +SKPSPC: + CALL SCANB ;Always kill preceding blanks and tabs +NOSCAN: + CALL GETLET + JBE NODRV ;Quit if termination character + CMP BYTE PTR[SI],":" ;Check for potential drive specifier + JNZ NODRV + INC SI ;Skip over colon + SUB AL,"@" ;Convert drive letter to binary drive number + JBE BADDRV ;Valid drive numbers are 1-15 + CMP AL,CS:[NUMDRV] + JBE HAVDRV +BADDRV: + MOV DL,-1 +HAVDRV: + STOSB ;Put drive specifier in first byte + INC SI + DEC DI ;Counteract next two instructions +NODRV: + DEC SI ;Back up + INC DI ;Skip drive byte + MOV CX,8 + CALL GETWORD ;Get 8-letter file name + CMP BYTE PTR [SI],"." + JNZ NODOT + INC SI ;Skip over dot if present + MOV CX,3 ;Get 3-letter extension + CALL MUSTGETWORD +NODOT: + LDS BX,CS:DWORD PTR [SPSAVE] + MOV [BX.SISAVE],SI + MOV AL,DL + RET + +NONAM: + ADD DI,CX + DEC SI + RET + +GETWORD: + CALL GETLET + JBE NONAM ;Exit if invalid character + DEC SI +MUSTGETWORD: + CALL GETLET + JBE FILLNAM + JCXZ MUSTGETWORD + DEC CX + CMP AL,"*" ;Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + REP STOSB +NOSTAR: + STOSB + CMP AL,"?" + JNZ MUSTGETWORD + OR DL,1 ;Flag ambiguous file name + JMP MUSTGETWORD +FILLNAM: + MOV AL," " + REP STOSB + DEC SI +RET21: RET + +SCANB: + LODSB + CALL SPCHK + JZ SCANB + DEC SI + RET + +GETLET: +;Get a byte from [SI], convert it to upper case, and compare for delimiter. +;ZF set if a delimiter, CY set if a control character (other than TAB). + LODSB + AND AL,7FH + CMP AL,"a" + JB CHK + CMP AL,"z" + JA CHK + SUB AL,20H ;Convert to upper case +CHK: + CMP AL,"." + JZ RET21 + CMP AL,'"' + JZ RET21 + CMP AL,"/" + JZ RET21 + CMP AL,"[" + JZ RET21 + CMP AL,"]" + JZ RET21 + + IF IBM +DELIM: + ENDIF + CMP AL,":" ;Allow ":" as separator in IBM version + JZ RET21 + IF NOT IBM +DELIM: + ENDIF + + CMP AL,"+" + JZ RET101 + CMP AL,"=" + JZ RET101 + CMP AL,";" + JZ RET101 + CMP AL,"," + JZ RET101 +SPCHK: + CMP AL,9 ;Filter out tabs too + JZ RET101 +;WARNING! " " MUST be the last compare + CMP AL," " +RET101: RET + +SETVECT: ; Interrupt call 37 + XOR BX,BX + MOV ES,BX + MOV BL,AL + SHL BX,1 + SHL BX,1 + MOV ES:[BX],DX + MOV ES:[BX+2],DS + RET + + +NEWBASE: ; Interrupt call 38 + MOV ES,DX + LDS SI,CS:DWORD PTR [SPSAVE] + MOV DS,[SI.CSSAVE] + XOR SI,SI + MOV DI,SI + MOV AX,DS:[2] + MOV CX,80H + REP MOVSW + +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) +; [18] to [21] have fatal error address (from INT 24H) +; DX,BP unchanged. All other registers destroyed. + + XOR CX,CX + MOV DS,CX + MOV ES,DX + MOV SI,EXIT + MOV DI,SAVEXIT + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOV ES:[2],AX + SUB AX,DX + CMP AX,MAXDIF + JBE HAVDIF + MOV AX,MAXDIF +HAVDIF: + MOV BX,ENTRYPOINTSEG + SUB BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + SHL AX,1 + MOV DS,DX + MOV DS:[6],AX + MOV DS:[8],BX + MOV DS:[0],20CDH ;"INT INTTAB" + MOV DS:(BYTE PTR [5]),LONGCALL + RET + +DATE16: + PUSH CX + CALL READTIME + SHL CL,1 ;Minutes to left part of byte + SHL CL,1 + SHL CX,1 ;Push hours and minutes to left end + SHL CX,1 + SHL CX,1 + SHR DH,1 ;Count every two seconds + OR CL,DH ;Combine seconds with hours and minutes + MOV DX,CX + POP CX + MOV AX,WORD PTR [MONTH] ;Fetch month and year + SHL AL,1 ;Push month to left to make room for day + SHL AL,1 + SHL AL,1 + SHL AL,1 + SHL AX,1 + OR AL,[DAY] +RET22: RET + +FOURYEARS EQU 3*365+366 + +READTIME: +;Gets time in CX:DX. Figures new date if it has changed. +;Uses AX, CX, DX. + CALL FAR PTR BIOSGETTIME + CMP AX,[DAYCNT] ;See if day count is the same + JZ RET22 + CMP AX,FOURYEARS*30 ;Number of days in 120 years + JAE RET22 ;Ignore if too large + MOV [DAYCNT],AX + PUSH SI + PUSH CX + PUSH DX ;Save time + XOR DX,DX + MOV CX,FOURYEARS ;Number of days in 4 years + DIV CX ;Compute number of 4-year units + SHL AX,1 + SHL AX,1 + SHL AX,1 ;Multiply by 8 (no. of half-years) + MOV CX,AX ;<240 implies AH=0 + MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year + CALL DSLIDE ;Find out which of four years we're in + SHR CX,1 ;Convert half-years to whole years + JNC SK ;Extra half-year? + ADD DX,200 +SK: + CALL SETYEAR + MOV CL,1 ;At least at first month in year + MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + CALL DSLIDE ;Find out which month we're in + MOV [MONTH],CL + INC DX ;Remainder is day of month (start with one) + MOV [DAY],DL + CALL WKDAY ;Set day of week + POP DX + POP CX + POP SI +RET23: RET + +DSLIDE: + MOV AH,0 +DSLIDE1: + LODSB ;Get count of days + CMP DX,AX ;See if it will fit + JB RET23 ;If not, done + SUB DX,AX + INC CX ;Count one more month/year + JMP SHORT DSLIDE1 + +SETYEAR: +;Set year with value in CX. Adjust length of February for this year. + MOV BYTE PTR [YEAR],CL +CHKYR: + TEST CL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [MONTAB+1],AL ;Store for February + RET + +;Days in year +YRTAB DB 200,166 ;Leap year + DB 200,165 + DB 200,165 + DB 200,165 + +;Days of each month +MONTAB DB 31 ;January + DB 28 ;February--reset each time year changes + DB 31 ;March + DB 30 ;April + DB 31 ;May + DB 30 ;June + DB 31 ;July + DB 31 ;August + DB 30 ;September + DB 31 ;October + DB 30 ;November + DB 31 ;December + +GETDATE: ;Function call 42 + PUSH CS + POP DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] + MOV BX,WORD PTR [DAY] + LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + MOV [SI.DXSAVE],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI.CXSAVE],AX ;CX=year + MOV AL,CS:[WEEKDAY] +RET24: RET + +SETDATE: ;Function call 43 + MOV AL,-1 ;Be ready to flag error + SUB CX,1980 ;Fix bias in year + JC RET24 ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET24 + OR DH,DH + JZ RET24 + OR DL,DL + JZ RET24 ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET24 + PUSH CS + POP DS + CALL CHKYR ;Set Feb. up for new year + MOV AL,DH + MOV BX,OFFSET DOSGROUP:MONTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + JB RET24 ;Error if too many days + CALL SETYEAR + MOV WORD PTR [DAY],DX ;Set both day and month + SHR CX,1 + SHR CX,1 + MOV AX,FOURYEARS + MOV BX,DX + MUL CX + MOV CL,BYTE PTR [YEAR] + AND CL,3 + MOV SI,OFFSET DOSGROUP:YRTAB + MOV DX,AX + SHL CX,1 ;Two entries per year, so double count + CALL DSUM ;Add up the days in each year + MOV CL,BH ;Month of year + MOV SI,OFFSET DOSGROUP:MONTAB + DEC CX ;Account for months starting with one + CALL DSUM ;Add up days in each month + MOV CL,BL ;Day of month + DEC CX ;Account for days starting with one + ADD DX,CX ;Add in to day total + XCHG AX,DX ;Get day count in AX + MOV [DAYCNT],AX + CALL FAR PTR BIOSSETDATE +WKDAY: + MOV AX,[DAYCNT] + XOR DX,DX + MOV CX,7 + INC AX + INC AX ;First day was Tuesday + DIV CX ;Compute day of week + MOV [WEEKDAY],DL + XOR AL,AL ;Flag OK +RET25: RET + +DSUM: + MOV AH,0 + JCXZ RET25 +DSUM1: + LODSB + ADD DX,AX + LOOP DSUM1 + RET + +GETTIME: ;Function call 44 + PUSH CS + POP DS + CALL READTIME + LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + MOV [SI.DXSAVE],DX + MOV [SI.CXSAVE],CX + XOR AL,AL +RET26: RET + +SETTIME: ;Function call 45 +;Time is in CX:DX in hours, minutes, seconds, 1/100 sec. + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET26 + CMP CL,60 ;Check minutes + JAE RET26 + CMP DH,60 ;Check seconds + JAE RET26 + CMP DL,100 ;Check 1/100's + JAE RET26 + CALL FAR PTR BIOSSETTIME + XOR AL,AL + RET + + +; Default handler for division overflow trap +DIVOV: + PUSH SI + PUSH AX + MOV SI,OFFSET DOSGROUP:DIVMES + CALL OUTMES + POP AX + POP SI + INT 23H ;Use Ctrl-C abort on divide overflow + IRET + +CODSIZ EQU $-CODSTRT ;Size of code segment +CODE ENDS + + +;***** DATA AREA ***** +CONSTANTS SEGMENT BYTE + ORG 0 +CONSTRT EQU $ ;Start of constants segment + +IONAME: + IF NOT IBM + DB "PRN ","LST ","NUL ","AUX ","CON " + ENDIF + IF IBM + DB "COM1","PRN ","LPT1","NUL ","AUX ","CON " + ENDIF +DIVMES DB 13,10,"Divide overflow",13,10,"$" +CARPOS DB 0 +STARTPOS DB 0 +PFLAG DB 0 +DIRTYDIR DB 0 ;Dirty buffer flag +NUMDRV DB 0 ;Number of drives +NUMIO DB ? ;Number of disk tables +VERFLG DB 0 ;Initialize with verify off +CONTPOS DW 0 +DMAADD DW 80H ;User's disk transfer address (disp/seg) + DW ? +ENDMEM DW ? +MAXSEC DW 0 +BUFFER DW ? +BUFSECNO DW 0 +BUFDRVNO DB -1 +DIRTYBUF DB 0 +BUFDRVBP DW ? +DIRBUFID DW -1 +DAY DB 0 +MONTH DB 0 +YEAR DW 0 +DAYCNT DW -1 +WEEKDAY DB 0 +CURDRV DB 0 ;Default to drive A +DRVTAB DW 0 ;Address of start of DPBs +DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments +CONSTANTS ENDS + +DATA SEGMENT WORD +; Init code overlaps with data area below + + ORG 0 +INBUF DB 128 DUP (?) +CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer +LASTENT DW ? +EXITHOLD DB 4 DUP (?) +FATBASE DW ? +NAME1 DB 11 DUP (?) ;File name buffer +ATTRIB DB ? +NAME2 DB 11 DUP (?) +NAME3 DB 12 DUP (?) +EXTFCB DB ? +;WARNING - the following two items are accessed as a word +CREATING DB ? +DELALL DB ? +TEMP LABEL WORD +SPSAVE DW ? +SSSAVE DW ? +CONTSTK DW ? +SECCLUSPOS DB ? ;Position of first sector within cluster +DSKERR DB ? +TRANS DB ? +PREREAD DB ? ;0 means preread; 1 means optional +READOP DB ? +THISDRV DB ? + + EVEN +FCB DW ? ;Address of user FCB +NEXTADD DW ? +RECPOS DB 4 DUP (?) +RECCNT DW ? +LASTPOS DW ? +CLUSNUM DW ? +SECPOS DW ? ;Position of first sector accessed +VALSEC DW ? ;Number of valid (previously written) sectors +BYTSECPOS DW ? ;Position of first byte within sector +BYTPOS DB 4 DUP (?) ;Byte position in file of access +BYTCNT1 DW ? ;No. of bytes in first sector +BYTCNT2 DW ? ;No. of bytes in last sector +SECCNT DW ? ;No. of whole sectors +ENTFREE DW ? + + DB 80H DUP (?) ;Stack space +IOSTACK LABEL BYTE + DB 80H DUP (?) +DSKSTACK LABEL BYTE + + IF DSKTEST +NSS DW ? +NSP DW ? + ENDIF + +DIRBUF LABEL WORD + +;Init code below overlaps with data area above + + ORG 0 + +MOVFAT: +;This section of code is safe from being overwritten by block move + REP MOVS BYTE PTR [DI],[SI] + CLD + MOV ES:[DMAADD+2],DX + MOV SI,[DRVTAB] ;Address of first DPB + MOV AL,-1 + MOV CL,[NUMIO] ;Number of DPBs +FLGFAT: + MOV DI,ES:[SI.FAT] ;get pointer to FAT + DEC DI ;Point to dirty byte + STOSB ;Flag as unused + ADD SI,DPBSIZ ;Point to next DPB + LOOP FLGFAT + MOV AX,[ENDMEM] + CALL SETMEM ;Set up segment + +XXX PROC FAR + RET +XXX ENDP + +DOSINIT: + CLI + CLD + PUSH CS + POP ES + MOV ES:[ENDMEM],DX + LODSB ;Get no. of drives & no. of I/O drivers + MOV ES:[NUMIO],AL + MOV DI,OFFSET DOSGROUP:MEMSTRT +PERDRV: + MOV BP,DI + MOV AL,ES:[DRVCNT] + STOSB ;DEVNUM + LODSB ;Physical unit no. + STOSB ;DRVNUM + CMP AL,15 + JA BADINIT + CBW ;Index into FAT size table + SHL AX,1 + ADD AX,OFFSET DOSGROUP:FATSIZTAB + XCHG BX,AX + LODSW ;Pointer to DPT + PUSH SI + MOV SI,AX + LODSW + STOSW ;SECSIZ + MOV DX,AX + CMP AX,ES:[MAXSEC] + JBE NOTMAX + MOV ES:[MAXSEC],AX +NOTMAX: + LODSB + DEC AL + STOSB ;CLUSMSK + JZ HAVSHFT + CBW +FIGSHFT: + INC AH + SAR AL,1 + JNZ FIGSHFT + MOV AL,AH +HAVSHFT: + STOSB ;CLUSSHFT + MOVSW ;FIRFAT (= number of reserved sectors) + MOVSB ;FATCNT + MOVSW ;MAXENT + MOV AX,DX ;SECSIZ again + MOV CL,5 + SHR AX,CL + MOV CX,AX ;Directory entries per sector + DEC AX + ADD AX,ES:[BP.MAXENT] + XOR DX,DX + DIV CX + STOSW ;DIRSEC (temporarily) + MOVSW ;DSKSIZ (temporarily) +FNDFATSIZ: + MOV AL,1 + MOV DX,1 +GETFATSIZ: + PUSH DX + CALL FIGFATSIZ + POP DX + CMP AL,DL ;Compare newly computed FAT size with trial + JZ HAVFATSIZ ;Has sequence converged? + CMP AL,DH ;Compare with previous trial + MOV DH,DL + MOV DL,AL ;Shuffle trials + JNZ GETFATSIZ ;Continue iterations if not oscillating + DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations + JMP SHORT FNDFATSIZ ;Try again + +BADINIT: + MOV SI,OFFSET DOSGROUP:BADMES + CALL OUTMES + STI + HLT + +HAVFATSIZ: + STOSB ;FATSIZ + MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs + ADD AX,ES:[BP.FIRFAT] + STOSW ;FIRDIR + ADD AX,ES:[BP.DIRSEC] + MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC + CALL FIGMAX + MOV ES:[BP.MAXCLUS],CX + MOV AX,BX ;Pointer into FAT size table + STOSW ;Allocate space for FAT pointer + MOV AL,ES:[BP.FATSIZ] + XOR AH,AH + MUL ES:[BP.SECSIZ] + CMP AX,ES:[BX] ;Bigger than already allocated + JBE SMFAT + MOV ES:[BX],AX +SMFAT: + POP SI ;Restore pointer to init. table + MOV AL,ES:[DRVCNT] + INC AL + MOV ES:[DRVCNT],AL + CMP AL,ES:[NUMIO] + JAE CONTINIT + JMP PERDRV + +BADINITJ: + JMP BADINIT + +CONTINIT: + PUSH CS + POP DS +;Calculate true address of buffers, FATs, free space + MOV BP,[MAXSEC] + MOV AX,OFFSET DOSGROUP:DIRBUF + ADD AX,BP + MOV [BUFFER],AX ;Start of buffer + ADD AX,BP + MOV [DRVTAB],AX ;Start of DPBs + SHL BP,1 ;Two sectors - directory and buffer + ADD BP,DI ;Allocate buffer space + ADD BP,ADJFAC ;True address of FATs + PUSH BP + MOV SI,OFFSET DOSGROUP:FATSIZTAB + MOV DI,SI + MOV CX,16 +TOTFATSIZ: + INC BP ;Add one for Dirty byte + INC BP ;Add one for I/O device number + LODSW ;Get size of this FAT + XCHG AX,BP + STOSW ;Save address of this FAT + ADD BP,AX ;Compute size of next FAT + CMP AX,BP ;If size was zero done + LOOPNZ TOTFATSIZ + MOV AL,15 + SUB AL,CL ;Compute number of FATs used + MOV [NUMDRV],AL + XOR AX,AX ;Set zero flag + REPZ SCASW ;Make sure all other entries are zero + JNZ BADINITJ + ADD BP,15 ;True start of free space + MOV CL,4 + SHR BP,CL ;First free segment + MOV DX,CS + ADD DX,BP + MOV BX,0FH + MOV CX,[ENDMEM] + CMP CX,1 ;Use memory scan? + JNZ SETEND + MOV CX,DX ;Start scanning just after DOS +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: + IF HIGHMEM + SUB CX,BP + MOV BP,CX ;Segment of DOS + MOV DX,CS ;Program segment + ENDIF + IF NOT HIGHMEM + MOV BP,CS + ENDIF +; BP has segment of DOS (whether to load high or run in place) +; DX has program segment (whether after DOS or overlaying DOS) +; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) + MOV CS:[ENDMEM],CX + IF HIGHMEM + MOV ES,BP + XOR SI,SI + MOV DI,SI + MOV CX,(DOSLEN+1)/2 + PUSH CS + POP DS + REP MOVSW ;Move DOS to high memory + ENDIF + XOR AX,AX + MOV DS,AX + MOV ES,AX + MOV DI,INTBASE + MOV AX,OFFSET DOSGROUP:QUIT + STOSW ;Set abort address--displacement + MOV AX,BP + MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP + MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY + MOV WORD PTR DS:[ENTRYPOINT+3],AX + MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address + MOV DS:[2],AX + MOV CX,9 + REP STOSW ;Set 5 segments (skip 2 between each) + MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND + MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit + MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit + MOV AX,OFFSET BIOSREAD + STOSW + MOV AX,BIOSSEG + STOSW + STOSW ;Add 2 to DI + STOSW + MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE + MOV WORD PTR DS:[EXIT],100H + MOV WORD PTR DS:[EXIT+2],DX + IF NOT IBM + MOV SI,OFFSET DOSGROUP:HEADER + CALL OUTMES + ENDIF + PUSH CS + POP DS + PUSH CS + POP ES +;Move the FATs into position + MOV AL,[NUMIO] + CBW + XCHG AX,CX + MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT +FATPOINT: + MOV SI,WORD PTR [DI] ;Get address within FAT address table + MOVSW ;Set address of this FAT + ADD DI,DPBSIZ-2 ;Point to next DPB + LOOP FATPOINT + POP CX ;True address of first FAT + MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from + MOV DI,[DRVTAB] ;Place to move DPBs to + SUB CX,DI ;Total length of DPBs + CMP DI,SI + JBE MOVJMP ;Are we moving to higher or lower memory? + DEC CX ;Move backwards to higher memory + ADD DI,CX + ADD SI,CX + INC CX + STD +MOVJMP: + MOV ES,BP + JMP MOVFAT + +FIGFATSIZ: + MUL ES:BYTE PTR[BP.FATCNT] + ADD AX,ES:[BP.FIRFAT] + ADD AX,ES:[BP.DIRSEC] +FIGMAX: +;AX has equivalent of FIRREC + SUB AX,ES:[BP.DSKSIZ] + NEG AX + MOV CL,ES:[BP.CLUSSHFT] + SHR AX,CL + INC AX + MOV CX,AX ;MAXCLUS + INC AX + MOV DX,AX + SHR DX,1 + ADC AX,DX ;Size of FAT in bytes + MOV SI,ES:[BP.SECSIZ] + ADD AX,SI + DEC AX + XOR DX,DX + DIV SI + RET + +BADMES: + DB 13,10,"INIT TABLE BAD",13,10,"$" + +FATSIZTAB: + DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +DRVCNT DB 0 + +MEMSTRT LABEL WORD +ADJFAC EQU DIRBUF-MEMSTRT +DATA ENDS + END + \ No newline at end of file diff --git a/3_source_code/MS-DOS_1.25/STDDOS.ASM b/3_source_code/MS-DOS_1.25/STDDOS.ASM new file mode 100644 index 0000000..df2fbec --- /dev/null +++ b/3_source_code/MS-DOS_1.25/STDDOS.ASM @@ -0,0 +1,23 @@ + TITLE MS-DOS version 1.25 by Tim Paterson March 3, 1982 + PAGE 60,132 +; Use the following booleans to set the switches +FALSE EQU 0 +TRUE EQU NOT FALSE + +; Use the switches below to produce the standard Microsoft version of the IBM +; version of the operating system +MSVER EQU TRUE +IBM EQU FALSE + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + +DSKTEST EQU FALSE + + INCLUDE MSDOS.ASM + + \ No newline at end of file diff --git a/3_source_code/PC-DOS_1.00_dev/86DOS_1981-06-16.ASM b/3_source_code/PC-DOS_1.00_dev/86DOS_1981-06-16.ASM new file mode 100644 index 0000000..ea183aa --- /dev/null +++ b/3_source_code/PC-DOS_1.00_dev/86DOS_1981-06-16.ASM @@ -0,0 +1,3888 @@ +; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +; by Tim Paterson + +; ****************** Revision History ************************* +; >> EVERY change must noted below!! << +; +; 0.34 12/29/80 General release, updating all past customers +; 0.42 02/25/81 32-byte directory entries added +; 0.56 03/23/81 Variable record and sector sizes +; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +; 0.74 04/15/81 Recognize I/O devices with file names +; 0.75 04/17/81 Improve and correct buffer handling +; 0.76 04/23/81 Correct directory size when not 2^N entries +; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +; 1.00 04/28/81 Renumber for general release +; +; ************************************************************* + +; Use the switch below to generate code to accept the old 16-byte +; directory entry as well as the new 32-byte entry. + +SMALLDIR: EQU 0 ;1 to enable, 0 to disable + + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + +DSKTEST: EQU 1 ;1 to enable, 0 to disable + + +; 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 + + +MAXCALL:EQU 36 +MAXCOM: EQU 45 +ESCCH: EQU 0 +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 +MAXDIF: EQU 0FFFH +SAVEXIT:EQU 10 + ;Date format + ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 + ; y y y y y y y m m m m d d d d d + ; + ;where y=year,m=month,d=day + +; Field definition for FCBs + + ORG 0 + DS 12 ;Drive code and name +EXTENT: DS 2 +RECSIZ: DS 2 ;Size of record (user settable) +FILSIZ: DS 4 ;Size of file in bytes +FDATE: DS 2 ;Date of last writing +FILDIRBLK:DS 2 ;Location in directory +FIRCLUS:DS 2 ;First cluster of file +LSTCLUS:DS 2 ;Last cluster accessed +CLUSPOS:DS 2 ;Position of last cluster accessed +DIRTYFIL:DS 1 ;File has been written to if <>0 + ORG 32 +NR: DS 1 ;Next record +RR: DS 3 ;Random record + + +; Description of 32-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 1 Attributes. Bits 1 or 2 make file hidden +; 12 12 Zero field (for expansion) +; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +; 26 2 First allocation unit ( < 4080 ) +; 28 4 File size, in bytes (LSB first, 30 bits max.) + + +; Field definition for Drive Parameter Block + + ORG 0 +DRVNUM: DS 1 ;Drive number +SECSIZ: DS 2 ;Size of physical sector in bytes +CLUSMSK:DS 1 ;Sectors/cluster - 1 +CLUSSHFT:DS 1 ;Log2 of sectors/cluster +FIRFAT: DS 2 ;Starting record of FATs +FATCNT: DS 1 ;Number of FATs for this drive +MAXENT: DS 2 ;Number of directory entries +DIRSEC: ;Number of dir. sectors (init temporary) +FIRREC: DS 2 ;First sector of first cluster +DSKSIZ: ;Size of disk (temp used during init only) +MAXCLUS:DS 2 ;Number of clusters on drive + 1 +FATSIZ: DS 1 ;Number of records occupied by FAT +FIRDIR: DS 2 ;Starting record of directory + + IF SMALLDIR +FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries + ENDIF + +DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +FAT: ;Start of FAT +DIRSIZ: ;-1=small dir. entry, else large + + +; BIOS entry point defintions + +BIOSSEG: EQU 60H + ORG 0 + DS 3 +BIOSSTAT: DS 3 +BIOSIN: DS 3 +BIOSOUT: DS 3 +BIOSPRINT: DS 3 +BIOSAUXIN: DS 3 +BIOSAUXOUT: DS 3 +BIOSREAD: DS 3 +BIOSWRITE: DS 3 +BIOSDSKCHG: DS 3 + + +; Location of user registers relative user stack pointer + + ORG 0 +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 +IPSAVE: DS 2 +CSSAVE: DS 2 +FSAVE: DS 2 + + +; Start of code + + ORG 0 + PUT 100H + + JMP DOSINIT +ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +ESCTAB: + DB 77 ;Copy one char--RIGHT ARROW + DB 59 ;Copy one char--F1 + DB 83 ;Skip one char--DELETE + DB 60 ;Copy to char--F2 + DB 62 ;Skip to char--F4 + DB 61 ;Copy line--F3 + DB 64 ;Ctrl-Z--F6 + DB 63 ;Reedit line (new template)--F5 + DB 75 ;Backspace--LEFT ARROW + DB 82 ;Toggle insert mode--INSERT + DB 65 ;Escape character--F7 + DB 65 ;End of table + +ESCTABLEN:EQU $-ESCTAB + + +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 + DI + 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: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + IF DSKTEST + SEG CS + MOV AX,[SPSAVE] + SEG CS + MOV [NSP],AX + SEG CS + MOV AX,[SSSAVE] + SEG CS + MOV [NSS],AX + POP AX + PUSH AX + ENDIF + + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + MOV SP,CS + MOV SS,SP +REDISP: + MOV SP,IOSTACK + EI ;Stack OK now + SEG CS + MOV [FUNC],AH + MOV BL,AH + MOV BH,0 + SHL BX + UP + CMP AH,12 + JLE SAMSTK + MOV SP,DSKSTACK +SAMSTK: + SEG CS + CALL [BX+DISPATCH] +LEAVE: + DI + SEG CS + MOV SP,[SPSAVE] + SEG CS + MOV SS,[SSSAVE] + MOV BP,SP + MOV [BP+AXSAVE],AL + + IF DSKTEST + SEG CS + MOV AX,[NSP] + SEG CS + MOV [SPSAVE],AX + SEG CS + MOV AX,[NSS] + SEG CS + MOV [SSSAVE],AX + ENDIF + + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + IRET + +DISPATCH: +; Standard Functions + DW ABORT + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST + DW RAWIO + DW RAWINP + DW IN + DW PRTBUF + DW BUFIN + DW CONSTAT + DW FLUSHKB + DW DSKRESET + DW SELDSK + DW OPEN + DW CLOSE + DW SRCHFRST + DW SRCHNXT + DW DELETE + DW SEQRD + DW SEQWRT + DW CREATE + DW RENAME + DW INUSE + DW CURDRV + DW SETDMA + DW GETFATPT + DW WRTPROT + DW GETRDONLY + DW SETATTRIB + DW GETDSKPT + DW USERCODE + DW RNDRD + DW RNDWRT + DW FILESIZE + DW SETRNDREC +; Extended Functions + DW SETVECT + DW NEWBASE + DW BLKRD + DW BLKWRT ;40 + DW MAKEFCB + DW GETDATE + DW SETDATE + DW GETTIME + DW SETTIME ;45 + +GETIO: +SETIO: +WRTPROT: +GETRDONLY: +SETATTRIB: +USERCODE: +INUSE: +GETDSKPT: + MOV AL,0 + RET + +FLUSHKB: + XOR BX,BX + MOV ES,BX ;Select segment 0 + SEG ES + MOV B,[41AH],1EH ;Reset KB queue head pointer + SEG ES + MOV B,[41CH],1EH ;Reset tail pointer + MOV AH,AL + CMP AL,1 + JZ REDISPJ + CMP AL,7 + JZ REDISPJ + CMP AL,8 + JZ REDISPJ + CMP AL,10 + JZ REDISPJ + MOV AL,0 + RET + +REDISPJ:JMP REDISP + +READER: +AUXIN: + CALL STATCHK + CALL BIOSAUXIN,BIOSSEG + RET + +PUNCH: + MOV AL,DL +AUXOUT: + PUSH AX + CALL STATCHK + POP AX + 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: + PUSH AX + MOV AH,80H + MOV DI,0FFFH + CALL FATAL + POP AX + RET + + +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 + +DEVNAME: + MOV SI,IONAME ;List of I/O devices with file names + MOV BL,6 ;BL = number of device names +LOOKIO: + MOV DI,NAME1 + MOV CX,4 ;All device names are 4 letters + REPE + CMPB ;Check for name in list + JZ IOCHK ;If first 4 letters OK, check the rest + ADD SI,CX ;Point to next device name + DEC BL + JNZ LOOKIO +CRET: + STC + RET +IOCHK: + MOV CX,4 ;Check rest of name but not extension + MOV AL," " + REPE + SCAB ;Make sure rest of name is blanks + JNZ CRET + MOV AL,BL + MOV BX,IONUM-1 + XLAT ;Translate to internal device number + MOV BL,AL + MOV BH,-1 + RET + +GETFILE: +; Same as GETNAME except ES:DI points to FCB on successful return + CALL MOVNAME + JC RET + PUSH DX + PUSH DS + CALL FINDNAME + POP ES + POP 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 +; Zero set if attributes match (always except when creating) +; BP = Base of drive parameters +; DS = CS +; ES = CS +; BX = Pointer into directory buffer +; SI = Pointer to First Cluster field in directory entry +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + CALL MOVNAME + JC RET ;Bad file name? +FINDNAME: + MOV AX,CS + MOV DS,AX + CALL DEVNAME + JNC RET + CALL STARTSRCH +CONTSRCH: + CALL GETENTRY + JC RET +SRCH: + CMP B,[BX],0E5H + JZ NEXTENT + MOV SI,BX + MOV DI,NAME1 + MOV CX,11 +WILDCRD: + REPE + CMPB + JZ FOUND + CMP B,[DI-1],"?" + JZ WILDCRD +NEXTENT: + CALL NEXTENTRY + JNC SRCH + RET + +FOUND: + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ RET + ENDIF + +;Check if attributes allow finding it + MOV AH,[ATTRIB] ;Attributes of search + NOT AH + AND AH,[SI] ;Compare with attributes of file + ADD SI,15 + AND AH,6 ;Only look at bits 1 and 2 + JZ RET + TEST B,[CREATING],-1 + JZ NEXTENT + RET + + +GETENTRY: + +; Inputs: +; [LASTENT] has previously searched directory entry +; Function: +; Locates next sequential directory entry in preparation for search +; Outputs: +; Carry set if none +; ELSE +; AL = Current directory block +; BX = Pointer to next directory entry in [DIRBUF] +; DX = Pointer to first byte after end of DIRBUF +; [LASTENT] = New directory entry number + + MOV AX,[LASTENT] + INC AX ;Start with next entry + CMP AX,[BP+MAXENT] + JAE NONE +GETENT: + MOV [LASTENT],AX + MOV CL,4 + SHL AX,CL + XOR DX,DX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ SMALENT1 + ENDIF + + SHL AX + RCL DX ;Account for overflow in last shift +SMALENT1: + MOV BX,[BP+SECSIZ] + AND BL,255-31 ;Must be multiple of 32 + DIV AX,BX + MOV BX,DX ;Position within sector + MOV AH,[BP+DRVNUM] ;AL=Directory sector no. + CMP AX,[DIRBUFID] + JZ HAVDIRBUF + PUSH BX + CALL DIRREAD + POP BX +HAVDIRBUF: + MOV DX,DIRBUF + ADD BX,DX + ADD DX,[BP+SECSIZ] + RET + +NEXTENTRY: + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update AL, BX, and [LASTENT] for next directory entry. +; Carry set if no more. + + MOV DI,[LASTENT] + INC DI + CMP DI,[BP+MAXENT] + JAE NONE + MOV [LASTENT],DI + ADD BX,32 + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT3 + SUB BX,16 +BIGENT3: + ENDIF + + CMP BX,DX + JB HAVIT + INC AL ;Next directory sector + PUSH DX ;Save limit + CALL DIRREAD + POP DX + MOV BX,DIRBUF +HAVIT: + CLC + RET + +NONE: + CALL CHKDIRWRITE + STC + RET + + +DELETE: ; System call 19 + CALL GETNAME + MOV AL,-1 + JC RET + CMP BH,AL ;Check if device name + JZ RET ;Can't delete I/O devices +DELFILE: + MOV B,[DIRTYDIR],-1 + MOV B,[BX],0E5H + MOV BX,[SI] + LEA SI,[BP+FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP+MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + CALL CONTSRCH + JNC DELFILE + CALL FATWRT + CALL CHKDIRWRITE + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + ADD SI,5 + MOV DI,NAME2 + CALL LODNAME + CALL FINDNAME + JC ERRET + CMP BH,-1 ;Check if I/O device name + JZ ERRET ;If so, can't rename it + MOV SI,NAME1 + MOV DI,NAME3 + MOV CX,6 ;Include attribute byte + REP + MOVW ;Copy name to search for +RENFIL: + MOV DI,NAME1 + MOV SI,NAME2 + MOV CX,11 +NEWNAM: + LODB + CMP AL,"?" + JNZ NOCHG + MOV AL,[BX] +NOCHG: + STOB + INC BX + LOOP NEWNAM + MOV B,[DI],6 ;Stop duplicates with any attributes + CALL DEVNAME ;Check if giving it a device name + JNC RENERR + PUSH [LASTENT] ;Save position of match + MOV [LASTENT],-1 ;Search entire dirctory for duplicate + CALL CONTSRCH ;See if new name already exists + POP AX + JNC RENERR ;Error if found + CALL GETENT ;Re-read matching entry + MOV DI,BX + MOV SI,NAME1 + MOV CX,11 + REP + MOVB ;Replace old name with new + MOV B,[DIRTYDIR],-1 ;Flag change in directory + MOV SI,NAME3 + MOV DI,NAME1 + MOV CX,6 ;Include attribute byte + REP + MOVW ;Copy name back into search buffer + CALL CONTSRCH + JNC RENFIL + CALL CHKDIRWRITE + XOR AL,AL + RET + +RENERR: + CALL CHKDIRWRITE +ERRET: + MOV AL,-1 + RET + + +MOVNAME: + +; Inputs: +; DS, DX point to FCB or extended FCB +; Outputs: +; DS:DX point to normal FCB +; 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 + + SEG CS + MOV B,[CREATING],0 + MOV AX,CS + MOV ES,AX + MOV DI,NAME1 + MOV SI,DX + LODB + SEG CS + MOV [EXTFCB],AL + MOV AH,0 + CMP AL,-1 + JNZ HAVATTRB + ADD DX,7 + ADD SI,6 + MOV AH,[SI-1] + LODB +HAVATTRB: + SEG CS + MOV [ATTRIB],AH + CALL GETBP + JB RET +LODNAME: +; This entry point copies a file name from DS,SI +; to ES,DI converting to upper case. + MOV CX,11 +MOVCHK: + CALL GETLET + JNZ CTRLCHK ;Is it a delimiter? + CMP AL," " ;This is the only delimiter allowed + STC ;In case of error + JNZ RET +CTRLCHK: + CMP AL,20H + JC RET + STOB + LOOP MOVCHK + RET + +GETBP: + SEG CS + CMP [NUMDRV],AL + JC RET + CBW + XCHG BP,AX + SHL BP + MOV BP,[BP+CURDRVPT] + RET + + +OPEN: ;System call 15 + CALL GETFILE +DOOPEN: +; Enter here to perform OPEN on file already found +; in directory. DS=CS, BX points to directory +; entry in DIRBUF, SI points to First Cluster field, and +; ES:DI point to the FCB to be opened. This entry point +; is used by CREATE. + JC ERRET + CMP BH,-1 ;Check if file is I/O device + JZ OPENDEV ;Special handler if so + MOV AL,[BP+DRVNUM] + INC AL + STOB + ADD DI,11 ;Point to extent field + XOR AX,AX + STOW ;Set extent field to 0 + MOV AX,128 ;Default record size + STOW ;Set record size + LODW ;Get starting cluster + MOV DX,AX ;Save it for the moment + MOVW ;Transfer size to FCB + MOVW + MOV AX,[SI-8] ;Get date + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT10 + SEG ES + MOV [DI-1],0 + XOR AX,AX ;Date not available in small entry +BIGENT10: + ENDIF + + STOW ;Save date in FCB + MOV AX,[LASTENT] + STOW ;directory location + MOV AX,DX ;Restore starting cluster + STOW ; first cluster + STOW ; last cluster accessed + XOR AX,AX + STOW ; position of last cluster + STOB ; dirty flag + RET + +OPENDEV: + SEG ES + MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag + XOR AL,AL + RET + + +STARTSRCH: + MOV [LASTENT],-1 +FATREAD: + +; Inputs: +; DS = CS +; BP = Base of drive parameters +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV AL,[BP+DRVNUM] + CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say + MOV AL,[BP+DRVNUM] + OR AH,[BP+DIRTYFAT] + JS NEWDSK ;If either say new disk, then it's so + DEC AH ;Check for AH=1 (disk not changed) + JZ RET + MOV AH,1 + CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? + JZ RET ;If so, disk has not been changed +NEWDSK: + CMP AL,[BUFDRVNO] ;See if buffer is for this drive + JNZ BUFOK ;If not, don't touch it + MOV [BUFSECNO],0 ;Flag buffers invalid + MOV [BUFDRVNO],00FFH +BUFOK: + MOV [DIRBUFID],-1 + CALL FIGFAT +NEXTFAT: + PUSH AX + CALL DSKREAD + POP AX + JC BADFAT + + IF SMALLDIR + MOV DL,AL + LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries + CMP B,[BP+DIRSIZ],-1 + JZ SETSIZ + ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +SETSIZ: + LODW + MOV [BP+FIRREC],AX + LODW + MOV [BP+MAXCLUS],AX + MOV AL,DL + ENDIF + + SUB AL,[BP+FATCNT] + JZ RET + NEG AL +;{Insert error code here. AL=number of bad fats. +;Since one good FAT was read, should include option +;to rewrite all FATs.} + JMP FATWRT + +BADFAT: + MOV CX,DI + ADD DX,CX + DEC AL + JNZ NEXTFAT + CALL FIGFAT ;Reset registers + JMP DREAD ;Try first FAT once more + +OKRET1: + MOV AL,0 + RET + +CLOSE: ;System call 16 + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB3 + ADD DI,7 +NORMFCB3: + CMP B,[DI+FILDIRBLK],-1 ;Check for I/O device + JZ OKRET1 ;Can't close I/O device + TEST B,[DI+DIRTYFIL],-1 + JZ OKRET1 ;If not written to, do nothing + MOV AL,[DI] ;Get drive number + CALL GETBP ;Get base of drive parameters + JC BADCLOSEJ + MOV AL,[BP+DRVNUM] + MOV AH,1 ;Look for dirty buffer + SEG CS + CMP AX,[BUFDRVNO] + JNZ FNDDIR +;Write back dirty buffer if on same drive + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV B,[DIRTYBUF],0 + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP DS + POP DX +FNDDIR: + CALL GETFILE +BADCLOSEJ: + JC BADCLOSE + MOV AX,[LASTENT] + SEG ES + CMP AX,[DI+FILDIRBLK] + JNZ BADCLOSE + SEG ES + MOV CX,[DI+FIRCLUS] + MOV [SI],CX + SEG ES + MOV DX,[DI+FILSIZ] + MOV [SI+2],DX + SEG ES + MOV DX,[DI+FILSIZ+2] + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT11 + MOV [SI+4],DL + JP SMALLENT2 +BIGENT11: + ENDIF + + MOV [SI+4],DX + SEG ES + MOV DX,[DI+FDATE] + MOV [SI-2],DX +SMALLENT2: + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty + + CMP B,[BP+DIRTYFAT],1 + JNZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty bit. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV B,[BP+DIRTYFAT],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+DIRTYFAT],0 + MOV AL,-1 + RET + + +FIGFAT: +; Loads registers with values needed to read or +; write a FAT. + MOV AL,[BP+FATCNT] + LEA 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 + SEG CS + MOV B,[CREATING],1 + PUSH DX + PUSH DS + CALL FINDNAME + JNC EXISTENT + CALL STARTSRCH + CALL GETENTRY +LOOKFRE: + CMP B,[BX],0E5H + JZ FREESPOT + CALL NEXTENTRY + JNC LOOKFRE +ERRPOP: + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET + +EXISTENT: + JNZ ERRPOP ;Error if attributes don't match + CMP BH,-1 ;Check if file is I/O device + JZ OPENJMP ;If so, no action + MOV CX,[SI] ;Get pointer to clusters + JCXZ FREESPOT + CMP CX,[BP+MAXCLUS] + JA FREESPOT + PUSH BX + MOV BX,CX + LEA SI,[BP+FAT] + CALL RELEASE ;Free any data already allocated + CALL FATWRT + POP BX +FREESPOT: + MOV DI,BX + MOV SI,NAME1 + MOV CX,5 + MOVB + REP + MOVW + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT4 + PUSH DI + MOV CL,5 + XOR AX,AX + JP SMALLENT +BIGENT4: + ENDIF + + MOV AL,[ATTRIB] + STOB + XOR AX,AX + MOV CL,6 + REP + STOW + CALL DATE16 + STOW + XOR AX,AX + PUSH DI + MOV CL,6 +SMALLENT: + REP + STOB + PUSH BX + CALL DIRWRITE + POP BX + POP SI +OPENJMP: + CLC ;Clear carry so OPEN won't fail + POP ES + POP DI + JMP DOOPEN + + +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. + + PUSH AX + CALL CHKDIRWRITE + POP AX + PUSH AX + MOV AH,[BP+DRVNUM] + MOV [DIRBUFID],AX + CALL DIRCOMP + CALL DREAD + POP AX + RET + + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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. + + CALL DSKREAD + JNC RET + SEG CS + MOV B,[READOP],0 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DREAD + RET ;Ignore otherwise + +HARDERR: +;Hard disk error handler. Entry conditions: +; DS:BX = Original disk transfer address +; DX = Original logical sector number +; CX = Number of sectors to go (first one gave the error) +; AX = Hardware error code +; DI = Original sector transfer count +; BP = Base of drive parameters +; [READOP] = 0 for read, 1 for write + + XCHG AX,DI ;Error code in DI, count in AX + SUB AX,CX ;Number of sectors successfully transferred + ADD DX,AX ;First sector number to retry + PUSH DX + MUL AX,[BP+SECSIZ] ;Number of bytes transferred + POP DX + ADD BX,AX ;First address for retry + MOV AH,0 ;Flag disk section in error + CMP DX,[BP+FIRFAT] ;In reserved area? + JB ERRINT + INC AH ;Flag for FAT + CMP DX,[FIRDIR] ;In FAT? + JB ERRINT + INC AH + CMP DX,[FIRREC] ;In directory? + JB ERRINT + INC AH ;Must be in data area +ERRINT: + SHL AH ;Make room for read/write bit + SEG CS + OR AH,[READOP] +FATAL: + MOV AL,[BP+DRVNUM] ;Get drive number + PUSH BP ;The only thing we preserve + SEG CS + MOV [CONTSTK],SP + DI ;Prepare to play with stack + SEG CS + MOV SS,[SSSAVE] + SEG CS + MOV SP,[SPSAVE] ;User stack pointer restored + INT 24H ;Fatal error interrupt vector + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + MOV SP,CS + MOV SS,SP + SEG CS + MOV SP,[CONTSTK] + EI + POP BP + CMP AL,2 + JZ ERROR + RET + +DSKREAD: + MOV AL,[BP+DRVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSREAD,BIOSSEG + POP DX + POP DI + POP BX + POP BP + RET + + +CHKDIRWRITE: + TEST B,[DIRTYDIR],-1 + JZ RET + +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. + + MOV B,[DIRTYDIR],0 + MOV AL,[DIRBUFID] + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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+DRVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSWRITE,BIOSSEG + POP DX + POP DI + POP BX + POP BP + JNC RET + SEG CS + MOV B,[READOP],1 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DWRITE + RET + +ABORT: + SEG CS + LDS SI,[SPSAVE] + MOV DS,[SI+CSSAVE] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVW + MOVW + MOVW + MOVW +ERROR: + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL WRTFATS + XOR AX,AX + DI + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + MOV DS,AX + MOV SI,EXIT + MOV DI,EXITHOLD + MOVW + MOVW + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + EI ;Stack OK now + SEG CS + JMP L,[EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + CALL LOAD + JP FINSEQ + +SEQWRT: ;System call 21 + CALL GETREC + CALL STORE +FINSEQ: + JCXZ SETNREX + ADD AX,1 + ADC DX,0 + JP SETNREX + +RNDRD: ;System call 33 + CALL GETRRPOS1 + CALL LOAD + JP FINRND + +RNDWRT: ;System call 34 + CALL GETRRPOS1 + CALL STORE + JP FINRND + +BLKRD: ;System call 39 + CALL GETRRPOS + CALL LOAD + JP FINBLK + +BLKWRT: ;System call 40 + CALL GETRRPOS + CALL STORE +FINBLK: + LDS SI,[SPSAVE] + MOV [SI+CXSAVE],CX + JCXZ FINRND + ADD AX,1 + ADC DX,0 +FINRND: + SEG ES + MOV [DI+RR],AX + SEG ES + MOV [DI+RR+2],DL + OR DH,DH + JZ SETNREX + SEG ES + MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +SETNREX: + MOV CX,AX + AND AL,7FH + SEG ES + MOV [DI+NR],AL + AND CL,80H + SHL CX + RCL DX + MOV AL,CH + MOV AH,DL + SEG ES + MOV [DI+EXTENT],AX + SEG CS + MOV AL,[DSKERR] + RET + +GETRRPOS1: + MOV CX,1 +GETRRPOS: + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB1 + ADD DI,7 +NORMFCB1: + MOV AX,[DI+RR] + MOV DX,[DI+RR+2] + RET + +NOFILERR: + XOR CX,CX + MOV B,[DSKERR],4 + POP BX + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; CX = No. of bytes to transfer +; BP = Base of drive parameters +; SI = FAT pointer +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DI +; [NEXTADD] = Displacement of disk transfer within segment +; [SECPOS] = Position of first sector +; [BYTPOS] = Byte position in file +; [BYTSECPOS] = Byte position in first sector +; [CLUSNUM] = First cluster +; [SECCLUSPOS] = Sector within first cluster +; [DSKERR] = 0 (no errors yet) +; [TRANS] = 0 (No transfers yet) +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + PUSH AX + MOV AL,[DI] + MOV SI,[DI+RECSIZ] + OR SI,SI + JNZ HAVRECSIZ + MOV SI,128 + MOV [DI+RECSIZ],SI +HAVRECSIZ: + MOV BX,DS + MOV ES,BX + MOV BX,CS + MOV DS,BX + CALL GETBP + POP AX + JC NOFILERR + CMP SI,64 ;Check if highest byte of RECPOS is significant + JB SMALREC + MOV DH,0 ;Ignore MSB if record >= 64 bytes +SMALREC: + MOV [RECCNT],CX + MOV [RECPOS],AX + MOV [RECPOS+2],DX + MOV [FCB],DI + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV B,[DSKERR],0 + MOV B,[TRANS],0 + MOV BX,DX + MUL AX,SI + MOV [BYTPOS],AX + PUSH DX + MOV AX,BX + MUL AX,SI + POP BX + ADD AX,BX + ADC DX,0 ;Ripple carry + JNZ EOFERR + MOV [BYTPOS+2],AX + MOV DX,AX + MOV AX,[BYTPOS] + MOV BX,[BP+SECSIZ] + CMP DX,BX ;See if divide will overflow + JNC EOFERR + DIV AX,BX + MOV [SECPOS],AX + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,[BP+CLUSMSK] + MOV [SECCLUSPOS],AL + MOV AX,CX ;Record count + MOV CL,[BP+CLUSSHFT] + SHR DX,CL + MOV [CLUSNUM],DX + MUL AX,SI ;Multiply by bytes per record + MOV CX,AX + ADD AX,[DMAADD] ;See if it will fit in one segment + ADC DX,0 + JZ OK ;Must be less than 64K + MOV AX,[DMAADD] + NEG AX ;Amount of room left in segment + JNZ PARTSEG ;All 64K available? + DEC AX ;If so, reduce it by one +PARTSEG: + XOR DX,DX + DIV AX,SI ;How many records will fit? + MOV [RECCNT],AX + MUL AX,SI ;Translate that back into bytes + MOV B,[DSKERR],2 ;Flag that trimming took place + MOV CX,AX + JCXZ NOROOM +OK: + LEA SI,[BP+FAT] + RET + +EOFERR: + MOV B,[DSKERR],1 + XOR CX,CX +NOROOM: + POP BX ;Kill return address + RET + +BREAKDOWN: + +;Inputs: +; DS = CS +; CX = Length of disk transfer in bytes +; BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +;Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +;AX, BX, DX destroyed. No other registers affected. + + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ;Partial first sector? + SUB AX,[BP+SECSIZ] + NEG AX ;Max number of bytes left in first sector + SUB BX,AX ;Subtract from total length + JAE SAVFIR + ADD AX,BX ;Don't use all of the rest of the sector + XOR BX,BX ;And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV AX,[BP+SECSIZ] ;How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ;Bytes remaining for last sector + 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,0FF8H + JAE RET + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +BUFSEC: +; Inputs: +; AL = 0 if buffer must be read, 1 if no pre-read needed +; 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: +; SI = Pointer to buffer +; DI = 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 + MOV [PREREAD],AL + CMP DX,[BUFSECNO] + JNZ GETSEC + MOV AL,[BUFDRVNO] + CMP AL,[BP+DRVNUM] + JZ FINBUF ;Already have it? +GETSEC: + TEST B,[DIRTYBUF],-1 + JZ RDSEC + PUSH DX + PUSH BP + MOV BP,[BUFDRVBP] + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP BP + POP DX +RDSEC: + TEST B,[PREREAD],-1 + JNZ SETBUF + MOV BX,[BUFFER] + MOV CX,1 + PUSH DX + CALL DREAD + POP DX +SETBUF: + MOV [BUFSECNO],DX + MOV AL,[BP+DRVNUM] + MOV AH,0 + MOV [BUFDRVNO],AX + MOV [BUFDRVBP],BP +FINBUF: + MOV B,[TRANS],1 ;A transfer is taking place + MOV DI,[NEXTADD] + MOV SI,DI + MOV CX,[BYTCNT1] + ADD SI,CX + MOV [NEXTADD],SI + MOV SI,[BUFFER] + ADD SI,[BYTSECPOS] + RET + +BUFRD: + XOR AL,AL ;Pre-read necessary + CALL BUFSEC + PUSH ES + MOV ES,[DMAADD+2] + SHR CX + JNC EVENRD + MOVB +EVENRD: + REP + MOVW + POP ES + RET + +BUFWRT: + 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 + MOV AL,0 +NOREAD: + CALL BUFSEC + XCHG DI,SI + PUSH DS + PUSH ES + PUSH CS + POP ES + MOV DS,[DMAADD+2] + SHR CX + JNC EVENWRT + MOVB +EVENWRT: + REP + MOVW + POP ES + POP DS + MOV B,[DIRTYBUF],1 + RET + +NEXTSEC: + TEST B,[TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,[BP+CLUSMSK] + JBE SAVPOS + MOV BX,[CLUSNUM] + CMP BX,0FF8H + JAE NONEXT + LEA SI,[BP+FAT] + CALL UNPACK + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + RET +NONEXT: + STC + RET + +TRANBUF: + LODB + STOB + CMP AL,13 ;Check for carriage return + JNZ NORMCH + MOV [SI],10 +NORMCH: + CMP AL,10 + LOOPNZ TRANBUF + JNZ ENDRDCON + CALL OUT ;Transmit linefeed + XOR SI,SI + OR CX,CX + JNZ GETBUF + OR AL,1 ;Clear zero flag--not end of file +ENDRDCON: + MOV [CONTPOS],SI +ENDRDDEV: + MOV [NEXTADD],DI + POP ES + JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + MOV DI,[FCB] + SEG ES + OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +SETFCBJ: + JMP SETFCB + +READDEV: + PUSH ES + LES DI,[DMAADD] + OR BL,BL + JZ READCON + DEC BL + JNZ ENDRDDEV +READAUX: + CALL AUXIN + STOB + CMP AL,1AH + LOOPNZ READAUX + JP ENDRDDEV + +READCON: + PUSH CS + POP DS + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP B,[CONBUF],128 + JZ GETBUF + MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,CONBUF + CALL BUFIN ;Get input buffer + POP DI + POP ES + POP CX + MOV SI,CONBUF+2 + CMP B,[SI],1AH ;Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOB + MOV AL,10 + CALL OUT ;Send linefeed + XOR SI,SI + JP ENDRDCON + +RDERR: + XOR CX,CX + JMP WRTERR + +RDLASTJ:JMP RDLAST + +LOAD: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file to read +; CX = No. of records to read +; Outputs: +; DX:AX = Position of last record read +; CX = No. of bytes read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 ;Check for named device I/O + JZ READDEV + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV BX,[DI+FILSIZ+2] + SUB AX,[BYTPOS] + SBC BX,[BYTPOS+2] + JB RDERR + JNZ ENUF + OR AX,AX + JZ RDERR + CMP AX,CX + JAE ENUF + MOV CX,AX +ENUF: + CALL BREAKDOWN + MOV CX,[CLUSNUM] + CALL FNDCLUS + OR CX,CX + JNZ RDERR + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + CALL BUFRD +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + CALL NEXTSEC + JC SETFCB + MOV B,[TRANS],1 ;A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DREAD + POP DS + POP CX + POP BX + JCXZ RDLAST + CMP BX,0FF8H + JAE SETFCB + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP RDLP + +SETFCB: + MOV SI,[FCB] + MOV AX,[NEXTADD] + MOV DI,AX + SUB AX,[DMAADD] ;Number of bytes transfered + XOR DX,DX + SEG ES + MOV CX,[SI+RECSIZ] + DIV AX,CX ;Number of records + CMP AX,[RECCNT] ;Check if all records transferred + JZ FULLREC + MOV B,[DSKERR],1 + OR DX,DX + JZ FULLREC ;If remainder 0, then full record transfered + MOV B,[DSKERR],3 ;Flag partial last record + SUB CX,DX ;Bytes left in last record + PUSH ES + MOV ES,[DMAADD+2] + XCHG AX,BX ;Save the record count temporarily + XOR AX,AX ;Fill with zeros + SHR CX + JNC EVENFIL + STOB +EVENFIL: + REP + STOW + XCHG AX,BX ;Restore record count to AX + POP ES + INC AX ;Add last (partial) record to total +FULLREC: + MOV CX,AX + MOV DI,SI ;ES:DI point to FCB +SETCLUS: + MOV AX,[CLUSNUM] + SEG ES + MOV [DI+LSTCLUS],AX + MOV AX,[LASTPOS] + SEG ES + MOV [DI+CLUSPOS],AX +ADDREC: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + DEC CX + ADD AX,CX ;Update current record position + ADC DX,0 + INC CX + RET + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETFCB + MOV [BYTCNT1],AX + CALL NEXTSEC + JC SETFCB + MOV [BYTSECPOS],0 + CALL BUFRD + JP SETFCB + +WRTDEV: + PUSH DS + LDS SI,[DMAADD] + AND BL,7FH + OR BL,BL + JZ WRTCON + DEC BL + JZ WRTAUX + DEC BL + JNZ ENDWRDEV ;Done if device is NUL +WRTLST: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL LISTOUT + LOOP WRTLST + JP ENDWRDEV + +WRTAUX: + LODB + CALL AUXOUT + CMP AL,1AH + LOOPNZ WRTAUX + JP ENDWRDEV + +WRTCON: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL OUT + LOOP WRTCON +ENDWRDEV: + POP DS + MOV CX,[RECCNT] + MOV DI,[FCB] + JP ADDREC + +HAVSTART: + MOV CX,AX + CALL SKPCLP + JCXZ DOWRTJ + CALL ALLOCATE + JNC DOWRTJ +WRTERR: + MOV B,[DSKERR],1 +LVDSK: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + MOV DI,[FCB] + RET + +DOWRTJ: JMP DOWRT + +WRTEOFJ: + JMP WRTEOF + +STORE: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; DX:AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + MOV B,[DI+DIRTYFIL],1 + CALL SETUP + CALL DATE16 + SEG ES + MOV [DI+FDATE],AX + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 + JZ WRTDEV + CALL BREAKDOWN + MOV AX,[BYTPOS] + MOV DX,[BYTPOS+2] + JCXZ WRTEOFJ + DEC CX + ADD AX,CX + ADC DX,0 ;AX:DX=last byte accessed + DIV AX,[BP+SECSIZ] ;AX=last sector accessed + MOV CL,[BP+CLUSSHFT] + SHR AX,CL ;Last cluster to be accessed + PUSH AX + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV DX,[DI+FILSIZ+2] + DIV AX,[BP+SECSIZ] + OR DX,DX + JZ NORNDUP + INC AX ;Round up if any remainder +NORNDUP: + MOV [VALSEC],AX ;Number of sectors that have been written + POP AX + MOV CX,[CLUSNUM] ;First cluster accessed + CALL FNDCLUS + MOV [CLUSNUM],BX + MOV [LASTPOS],DX + SUB AX,DX ;Last cluster minus current cluster + JZ DOWRT ;If we have last clus, we must have first + JCXZ HAVSTART ;See if no more data + PUSH CX ;No. of clusters short of first + MOV CX,AX + CALL ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP + CALL SKPCLP +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + CALL BUFWRT +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JZ WRTLAST + ADD [SECPOS],AX + CALL NEXTSEC + MOV B,[TRANS],1 ;A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP WRTLP +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + CALL NEXTSEC + MOV [BYTSECPOS],0 + CALL BUFWRT +FINWRT: + MOV AX,[NEXTADD] + SUB AX,[DMAADD] + ADD AX,[BYTPOS] + MOV DX,[BYTPOS+2] + ADC DX,0 + MOV CX,DX + MOV DI,[FCB] + SEG ES + CMP AX,[DI+FILSIZ] + SEG ES + SBB CX,[DI+FILSIZ+2] + JB SAMSIZ + SEG ES + MOV [DI+FILSIZ],AX + SEG ES + MOV [DI+FILSIZ+2],DX +SAMSIZ: + MOV CX,[RECCNT] + JMP SETCLUS + + +WRTERRJ:JMP WRTERR + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBC DX,0 + DIV AX,[BP+SECSIZ] + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + JCXZ RELFILE + CALL ALLOCATE + JC WRTERRJ +UPDATE: + MOV DI,[FCB] + MOV AX,[BYTPOS] + SEG ES + MOV [DI+FILSIZ],AX + MOV AX,[BYTPOS+2] + SEG ES + MOV [DI+FILSIZ+2],AX + XOR CX,CX + RET + +RELFILE: + MOV DX,0FFFH + CALL RELBLKS +SETDIRT: + MOV B,[BP+DIRTYFAT],1 + JP UPDATE + +KILLFIL: + XOR BX,BX + SEG ES + XCHG BX,[DI+FIRCLUS] + OR BX,BX + JZ UPDATE + CALL RELEASE + JP SETDIRT + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = sector 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 sector 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 sectors per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of sectors left in first cluster + MOV DX,CX + LEA SI,[BP+FAT] + 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 +;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 sectors still needed + PUSH DX + MOV AX,CX + MUL AX,[BP+SECSIZ] ;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 + CALL FIGREC + MOV BX,SI + RET +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 + JP FINCLUS + + +FIGREC: + +;Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; BP = Base of drive parameters +;Outputs: +; DX = physical sector number +;No other registers affected. + + PUSH CX + MOV CL,[BP+CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP+FIRREC] + POP CX + RET + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; CX = 1 +; DX:AX = Record number determined by EXTENT and NR fields +; DS:DI point to FCB +; No other registers affected. + + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB2 + ADD DI,7 +NORMFCB2: + MOV CX,1 + MOV AL,[DI+NR] + MOV DX,[DI+EXTENT] + SHL AL + SHR DX + RCR AL + MOV AH,DL + MOV DL,DH + MOV DH,0 + 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 bit +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH [SI] + PUSH DX + PUSH CX + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP+MAXCLUS] + JLE TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + POP AX ;No. of clusters requested + SUB AX,CX ;AX=No. of clusters allocated + POP DX + POP [SI] + INC DX ;Position of first cluster allocated + ADD AX,DX ;AX=max no. of cluster in file + MOV DL,[BP+CLUSMSK] + MOV DH,0 + INC DX ;DX=records/cluster + MUL AX,DX ;AX=max no. of records in file + MOV CX,AX + SUB CX,[RECPOS] ;CX=max no. of records that could be written + JA MAXREC + XOR CX,CX ;If CX was negative, zero it +MAXREC: + 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+DIRTYFAT],1 + POP BX + POP CX ;Don't need this stuff since we're successful + POP DX + CALL UNPACK + POP [SI] + XCHG BX,DI + OR DI,DI + JNZ RET + MOV DI,[FCB] + SEG ES + MOV [DI+FIRCLUS],BX + 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,0FF8H + MOV BX,AX + JB 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,0FF8H + JAE RET + MOV BX,DI + JP GETEOF + + +SRCHFRST: ;System call 17 + CALL GETFILE +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + JC KILLSRCH + CMP BH,-1 + JZ SRCHDEV + MOV AX,[LASTENT] + SEG ES + MOV [DI+FILDIRBLK],AX +;Information in directory entry must be copied into the first +; 33 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,[DMAADD] + MOV AX,00FFH + CMP AL,[EXTFCB] + JNZ NORMFCB + STOW + INC AL + STOW + STOW + MOV AL,[ATTRIB] + STOB +NORMFCB: + MOV AL,[BP+DRVNUM] + INC AL + STOB ;Set drive number + MOVB ;Copy first character of name + MOV CX,5 + REP + MOVW ;Copy remaining 10 characters of name + XOR AX,AX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT5 + STOB ;Zero out unused portion + MOV CX,7 + REP + STOW ;Zero a total of 15 bytes + MOVW ;Copy first cluster pointer + MOVW ;Copy low word of length + MOVB ;Copy 3rd byte of length + STOB ;4th byte of length must be zero + RET +BIGENT5: + ENDIF + + MOV CX,10 + REP + MOVW + MOVB + RET + +KILLSRCH: + SEG ES +KILLSRCH1: + MOV [DI+FILDIRBLK],-2 + MOV AL,-1 + RET + +SRCHDEV: + SEG ES + MOV [DI+FILDIRBLK],BX + LES DI,[DMAADD] + XOR AX,AX + STOB ;Zero drive byte + SUB SI,4 ;Point to device name + MOVW + MOVW + MOV AX,2020H + MOV CX,3 + REP + STOW ;Fill with 6 blanks + STOB ;And a 7th + XOR AX,AX + MOV CX,10 + REP + STOW + STOB + RET + +SRCHNXT: ;System call 18 + CALL MOVNAME + MOV DI,DX + JC KILLSRCH1 + PUSH DX + PUSH DS + MOV AX,[DI+FILDIRBLK] + PUSH CS + POP DS + MOV [LASTENT],AX + CALL CONTSRCH + POP ES + POP DI + JMP SAVPLCE + + +FILESIZE: ;System call 35 + CALL GETFILE + MOV AL,-1 + JC RET + ADD DI,33 ;Write size in RR field + SEG ES + MOV CX,[DI-33+RECSIZ] + OR CX,CX + JNZ RECOK + MOV CX,128 +RECOK: + XOR AX,AX + XOR DX,DX ;Intialize size to zero + CMP BH,-1 ;Check for named I/O device + JZ DEVSIZ + INC SI + INC SI ;Point to length field + MOV AX,[SI+2] ;Get high word of size + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGSIZ + MOV AH,0 +BIGSIZ: + ENDIF + + DIV AX,CX + PUSH AX ;Save high part of result + LODW ;Get low word of size + DIV AX,CX + OR DX,DX ;Check for zero remainder + POP DX + JZ DEVSIZ + INC AX ;Round up for partial record + JNZ DEVSIZ ;Propagate carry? + INC DX +DEVSIZ: + STOW + MOV AX,DX + STOB + MOV AL,0 + CMP CX,64 + JAE RET ;Only 3-byte field if RECSIZ >= 64 + SEG ES + MOV [DI],AH + 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 BP,[CURDRVPT] + CALL FATREAD + LEA BX,[BP+FAT] + MOV AL,[BP+CLUSMSK] + INC AL + MOV DX,[BP+MAXCLUS] + DEC DX + MOV B,[BP+DIRTYFAT],1 + MOV CX,[BP+SECSIZ] + LDS SI,[SPSAVE] + MOV [SI+BXSAVE],BX + MOV [SI+DXSAVE],DX + MOV [SI+CXSAVE],CX + MOV [SI+DSSAVE],CS + RET + + +DSKRESET: ;System call 13 + SEG CS + MOV [DMAADD+2],DS + MOV AX,CS + MOV DS,AX + MOV [DMAADD],80H + MOV AX,[CURDRVPT+2] + MOV [CURDRVPT],AX +WRTFATS: +; DS=CS. Writes back all dirty FATs. All registers destroyed. + MOV AX,[BUFDRVNO] + OR AH,AH + JZ NOBUF + CBW + MOV BX,AX + SHL BX + MOV BP,[BX+DRVTAB] + MOV B,[DIRTYBUF],0 + MOV DX,[BUFSECNO] + MOV BX,BUFFER + MOV CX,1 + CALL DWRITE +NOBUF: + MOV CL,[NUMDRV] + MOV CH,0 + MOV SI,CURDRVPT+2 +WRTFAT: + LODW + PUSH CX + PUSH SI + MOV BP,AX + CALL CHKFATWRT + POP SI + POP CX + LOOP WRTFAT + RET + + +CURDRV: ;System call 25 + SEG CS + MOV BP,[CURDRVPT] + MOV AL,[BP+DRVNUM] + RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+33],AX + MOV [DI+35],DL + CMP [DI+RECSIZ],64 + JAE RET + MOV [DI+36],DH ;Set 4th byte only if record size < 64 + RET + + +SELDSK: ;System call 14 + MOV DH,0 + MOV BX,DX + PUSH CS + POP DS + MOV AL,[NUMDRV] + CMP BL,AL + JNB RET + SHL BX + MOV DX,[BX+CURDRVPT+2] + MOV [CURDRVPT],DX + 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 BACKSPJ + CMP AL,8 + JZ BACKSPJ + CMP AL,13 + JZ ENDLIN + CMP AL,10 + JZ PHYCRLF + CMP AL,"X"-"@" + JZ KILNEW + CMP AL,1BH + JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X + CMP AL,ESCCH + JZ ESC +SAVCH: + CMP DH,DL + JAE BELL + STOB + INC DH + CALL BUFOUT + OR AH,AH + JNZ GETCH + CMP BH,BL + JAE GETCH + INC SI + INC BH + JP GETCH + +BELL: + MOV AL,7 + CALL OUTCH + JP GETCH + +BACKSPJ:JP BACKSP + +ESC: + CALL IN + PUSH DI + MOV CL,ESCTABLEN + MOV DI,ESCTAB + REPNE + SCAB + POP DI + MOV BP,CX + SHL BP + SEG CS ;To work in init + 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 + SEG CS + MOV AL,[STARTPOS] + CALL TAB + 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 + DOWN + 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 + UP + 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 OUT + MOV AL,8 + JMP OUT + +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: + MOV AH,0 ;Turn off insert mode when copying + CMP DH,DL + JZ GETCH2 + CMP BH,BL + JZ GETCH2 + LODB + STOB + CALL BUFOUT + 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 + +TOGGLINS: + NOT AH + JMP GETCH + +CTRLZ: + MOV AL,1AH + JMP SAVCH + +ESCFUNC: + DW GETCH + DW TWOESC + DW TOGGLINS + DW BACKSP + DW REEDIT + DW CTRLZ + DW COPYLIN + DW SKIPSTR + DW COPYSTR + DW SKIPONE + DW COPYONE + DW COPYONE + +BUFOUT: + CMP AL," " + JAE OUT + CMP AL,9 + JZ OUT + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JP OUT + +CONOUT: ;System call 2 + MOV AL,DL +OUT: + CMP AL,20H + JB CTRLOUT + CMP AL,7FH + JZ OUTCH + SEG CS + INC B,[CARPOS] +OUTCH: + PUSH AX + CALL STATCHK + POP AX + CALL BIOSOUT,BIOSSEG + SEG CS + TEST B,[PFLAG],-1 + JZ RET + CALL BIOSPRINT,BIOSSEG + RET + +NOSTOP: + CMP AL,"P"-"@" + JZ INCHK + CMP AL,"C"-"@" + JZ INCHK + RET + +STATCHK: + CALL BIOSSTAT,BIOSSEG + JZ RET + CMP AL,'S'-'@' + JNZ NOSTOP + CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +INCHK: + CALL BIOSIN,BIOSSEG + CMP AL,'P'-'@' + JZ PRINTOGL + CMP AL,'C'-'@' + JNZ RET +; Ctrl-C handler. +; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +; to show line is canceled. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has +; 1) the interrupt return address should the user CTRL-C handler wish to +; allow processing to continue; 2) the original interrupt return address +; to the code that performed the function call in the first place. If the +; user CTRL-C handler wishes to continue, it must leave all registers +; unchanged and IRET. The function that was interrupted will simply be +; repeated. + SEG CS + MOV AL,[FUNC] ;Get currently executing function + CMP AL,10 ;Check if buffered line input + JZ CANLIN + CMP AL,9 ;Check if buffered line output + JNZ RESTREG +CANLIN: + MOV AL,"\" ;Display cancel line symbol + CALL OUT + CALL CRLF +RESTREG: + DI ;Prepare to play with stack + SEG CS + MOV SS,[SSSAVE] + SEG CS + MOV SP,[SPSAVE] ;User stack now restored + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES ;User registers now restored + INT CONTC ;Execute user Ctrl-C handler + JMP COMMAND ;Repeat command otherwise + +PRINTOGL: + SEG CS + XOR B,[PFLAG],1 + XOR AL,AL ;Set zero flag--character not received + RET +CTRLOUT: + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JNZ OUTCHJ + SEG CS + MOV AL,[CARPOS] + OR AL,0F8H + NEG AL +TAB: + PUSH CX + MOV CL,AL + MOV CH,0 +TABLP: + MOV AL," " + CALL OUT + LOOP TABLP + POP CX + RET + +ZERPOS: + SEG CS + MOV B,[CARPOS],0 +OUTCHJ: JMP OUTCH + +BACKPOS: + SEG CS + DEC B,[CARPOS] + JMP OUTCH + + +CONSTAT: ;System call 11 + CALL BIOSSTAT,BIOSSEG + MOV AL,0 + JZ RET + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL IN + PUSH AX + CALL OUT + POP AX + RET + + +IN: ;Internal input routine + CALL INCHK + JZ IN + RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + CALL BIOSSTAT,BIOSSEG + MOV AL,0 + JZ RET +RAWINP: ;System call 7 + CALL BIOSIN,BIOSSEG + RET +RAWOUT: + CALL BIOSOUT,BIOSSEG + RET + +LIST: ;System call 5 + MOV AL,DL +LISTOUT: + PUSH AX + CALL STATCHK + POP AX + 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 + + +MAKEFCB: ;Interrupt call 41 + MOV DL,0 ;Flag--not ambiguous file name + OR AL,AL ;Scan off separators if not zero + JZ NOSCAN +SCAN: + CALL GETLET + JZ SCAN ;Get rid of leading separators (e.g., blanks) + DEC SI ;Point back to first non-separator +NOSCAN: + MOV AL,0 + CMP B,[SI],20H ;Check for termination character + JB HAVDRV + CMP B,[SI+1],":" ;Check for potential drive specifier + JNZ HAVDRV + CALL GETLET + SUB AL,"@" ;Convert drive letter to binary drive number + JBE BADDRV ;Valid drive numbers are 1-15 + SEG CS + CMP AL,[NUMDRV] + JA BADDRV + INC SI ;Skip over colon +HAVDRV: + STOB ;Put drive specifier in first byte + MOV CX,8 + CALL GETWORD ;Get 8-letter file name + CMP B,[SI],"." + JNZ NODOT + INC SI ;Skip over dot if present +NODOT: + MOV CX,3 ;Get 3-letter extension + CALL GETWORD + SEG CS + LDS BX,[SPSAVE] + MOV [BX+SISAVE],SI + XOR AX,AX + STOW + STOW + MOV AL,DL + RET + +BADDRV: + MOV AL,-1 + RET + +GETWORD: + CALL GETLET + JZ FILLNAM ;Exit if invalid character + CMP AL," " + JBE FILLNAM + CMP AL,"*" ;Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + DEC CX + REP + STOB ;Fill rest of word with "?" + INC CX +NOSTAR: + STOB + CMP AL,"?" + JNZ NOTQ + MOV DL,1 ;Flag ambiguous file name +NOTQ: + LOOP GETWORD + INC SI ;Point to "termination" character +FILLNAM: + MOV AL," " + REP + STOB + DEC SI + RET + +GETLET: + LODB + AND AL,7FH + CMP AL,"a" + JB CHK + CMP AL,"z" + JA CHK + SUB AL,20H ;Convert to upper case +CHK: + CMP AL," " + JZ RET + CMP AL,"=" + JZ RET + CMP AL,"," + JZ RET + CMP AL,";" + JZ RET + CMP AL,"." + JZ RET + CMP AL,":" + JZ RET + CMP AL,'"' + JZ RET + CMP AL,"+" + JZ RET + CMP AL,"/" + JZ RET + CMP AL,"[" + JZ RET + CMP AL,"]" + JZ RET + CMP AL,9 ;Filter out TABs too + RET + + +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 + LDS SI,[SPSAVE] + MOV DS,[SI+CSSAVE] + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP + MOVW + +SETMEM: + +; Inputs: +; 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) +; AX,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,MAXDIF + JBE HAVDIF + MOV CX,MAXDIF +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 + + +SHFTDI7: + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + RET + +DATE16: + PUSH CX + PUSH DX + PUSH BX + CALL READTIME + POP BX + POP DX + POP CX + MOV AX,[MONTH] ;Fetch month and year + SHL AL ;Push month to left to make room for day + SHL AL + SHL AL + SHL AL + SHL AX + OR AL,[DAY] + RET + +READTIME: +;Gets tick count in CX:DX. Causes date rollover if new day has started +;since last call. Destroys AX, BX. + MOV AH,0 ;Request get time + INT 1AH ;Time-of-day interrupt + OR AL,AL ;See if day has changed + JZ RET + ADD AL,[DAY] + MOV [DAY],AL + MOV AH,AL + MOV AL,[MONTH] + MOV BX,DAYTAB-1 ;Table of days in each month + XLAT ;Get number of days in current month + SUB AH,AL ;Have we rolled into next month? + JBE RET + MOV [DAY],AH ;Yes-store day of new month + MOV AL,[MONTH] + INC AL + MOV [MONTH],AL + CMP AL,12 ;Have we rolled into next year? + JBE RET + MOV B,[MONTH],1 ;Set first month to January + MOV AL,[YEAR] + INC AL +SETYEAR: +;Set year with value in AL. Adjust length of February for this year. + MOV [YEAR],AL + AND AL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [DAYTAB+1],AL ;Store for February + RET + +DAYTAB: ;Days of each month + DB 31 ;January + DB 28 ;February--reset each time year changes + DB 31 ;March + DB 30 ;April + DB 31 ;May + DB 30 ;June + DB 31 ;July + DB 31 ;August + DB 30 ;September + DB 31 ;October + DB 30 ;November + DB 31 ;December + +GETDATE: ;Function call 42 + PUSH CS + POP DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] + MOV BX,[DAY] + LDS SI,[SPSAVE] ;Get pointer to user registers + MOV [SI+DXSAVE],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI+CXSAVE],AX ;CX=year + XOR AL,AL + RET + +SETDATE: ;Function call 43 + MOV AL,-1 ;Be ready to flag an error + SUB CX,1980 ;Fix bias in year + JC RET ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET + OR DH,DH + JZ RET + OR DL,DL + JZ RET ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET + PUSH CS + POP DS + CMP DH,2 ;Check for Feb.--needs special handling + JNE DAYCHK + CMP DL,29 + JA RET ;Max 29 days in Feb. + JB DAYOK ;If 28 or less, definitely OK + TEST CL,3 ;Check for leap year + JZ DAYOK ;If it is, 29 days OK + RET ;Error if it's not +DAYCHK: + MOV AL,DH + MOV BX,DAYTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + JB RET ;Error if too many days +DAYOK: + PUSH DX + PUSH CX + MOV AH,0 + INT 1AH ;Read time to clear day overflow + POP AX ;Year + CALL SETYEAR + POP [DAY] ;Set both day and month + XOR AL,AL ;Flag OK + RET + +;*************************************** +; Time Functions +; +; Uses clock with 1,193,180/65536 ticks per second. User sees only +; time in hours, minutes, seconds, and 1/100 second, in registers +; CH, CL, DH, DL respectively. (Each is a binary number.) To +; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +; reciprocal of the tick rate. To convert the other way, 1/100 secs +; is multiplied by 59659/(5 * 2**16). + +GETTIME: ;Function call 44 + PUSH CS + POP DS + CALL READTIME ;Get tick count in CX:DX +;First multiply by 5 + MOV AX,CX + MOV BX,DX + SHL DX + RCL CX ;Times 2 + SHL DX + RCL CX ;Times 4 + ADD DX,BX + ADC AX,CX ;Times 5 + XCHG AX,DX + MOV CX,59659 + DIV AX,CX + MOV BX,AX ;Save quotient + XOR AX,AX ;Extend precision + DIV AX,CX +;Rounding based on the remainder may be added here +;The result in BX:AX is time in 1/100 second. + MOV DX,BX + MOV CX,200 ;Extract 1/100's +;Division by 200 is necessary to ensure no overflow--max result +;is number of seconds in a day/2 = 43200. + DIV AX,CX + CMP DL,100 ;Remainder over 100? + JB NOADJ + SUB DL,100 ;Keep 1/100's less than 100 +NOADJ: + CMC ;If we subtracted 100, carry is now set + MOV BL,DL ;Save 1/100's +;To compensate for dividing by 200 instead of 100, we now multiply +;by two, shifting a one in if the remainder had exceeded 100. + RCL AX + MOV DL,0 + RCL DX + MOV CX,60 ;Divide out seconds + DIV AX,CX + MOV BH,DL ;Save the seconds + DIV AL,CL ;Break into hours and minutes + XCHG AL,AH +;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) + LDS SI,[SPSAVE] ;Get pointer to user registers + MOV [SI+DXSAVE],BX + MOV [SI+CXSAVE],AX + XOR AL,AL + RET + +SETTIME: ;Function call 45 +;Time is in CX:DX in hours, minutes, seconds, 1/100 sec + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET + CMP CL,60 ;Check minutes + JAE RET + CMP DH,60 ;Check seconds + JAE RET + CMP DL,100 ;Check 1/100's + JAE RET + MOV AL,60 + MUL AL,CH ;Hours to minutes + MOV CH,0 + ADD AX,CX ;Total minutes + MOV CX,6000 ;60*100 + MOV BX,DX ;Get out of the way of the multiply + MUL AX,CX ;Convert to 1/100 sec + MOV CX,AX + MOV AL,100 + MUL AL,BH ;Convert seconds to 1/100 sec + ADD CX,AX ;Combine seconds with hours and min. + ADC DX,0 ;Ripple carry + MOV BH,0 + ADD CX,BX ;Combine 1/100 sec + ADC DX,0 +;DX:CX is time in 1/100 sec + XCHG AX,DX + XCHG AX,CX ;Now time is in CX:AX + MOV BX,59659 + MUL AX,BX ;Multiply low half + XCHG DX,CX + XCHG AX,DX ;CX->AX, AX->DX, DX->CX + MUL AX,BX ;Multiply high half + ADD AX,CX ;Combine overlapping products + ADC DX,0 + XCHG AX,DX ;AX:DX=time*59659 + MOV BX,5 + DIV AL,BL ;Divide high half by 5 + MOV CL,AL + MOV CH,0 + MOV AL,AH ;Remainder of divide-by-5 + CBW + XCHG AX,DX ;Use it to extend low half + DIV AX,BX ;Divde low half by 5 + MOV DX,AX +;CX:DX now has time in ticks + MOV AH,1 + INT 1AH ;Set clock + XOR AL,AL ;Return no error + RET + +;***** DATA AREA ***** + +;Device number mapping +;0,1 = CON, AUX (Bidirectional devices) +;2,3 = Printer, bit bucket (output only) + +IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +IONUM: DB 3,0,1,1,2,2 + +CARPOS: DB 0 +INSFLG: DB 0 +STARTPOS:DB 0 +PFLAG: DB 0 +DAY: DB 0 +MONTH: DB 0 +YEAR: DW 0 +DIRTYDIR:DB 0 ;Dirty buffer flag +NUMDRV: DS 1 ;Number of drives +CONTPOS:DW 0 +DMAADD: DW 80H ;User's disk transfer address (disp/seg) + DS 2 +ENDMEM: DS 2 +MAXSEC: DW 0 +BUFFER: DS 2 +BUFSECNO:DW 0 +BUFDRVNO:DB -1 +DIRTYBUF:DB 0 +BUFDRVBP:DS 2 +DIRBUFID:DW -1 +CURDRVPT:DS 2 +DRVTAB: DS 30 ;Enough for 15 drives +INBUF: DS 15 ;Only the first part + +; Init code overlaps with data area below + +INITCODE: + + DS 128-15 ;More of INBUF +CONBUF: DS 130 ;The rest of INBUF and console buffer +FUNC: DS 1 ;Currently executing function code +LASTENT:DS 2 +EXITHOLD:DS 4 +FATBASE:DS 2 +NAME1: DS 11 ;File name buffer +ATTRIB: DS 1 ;Search attributes +NAME2: DS 11 +NAME3: DS 12 +EXTFCB: DS 1 +CREATING:DS 1 +TEMP: +SPSAVE: DS 2 +SSSAVE: DS 2 +CONTSTK:DS 2 +SECCLUSPOS:DS 1 ;Position of first sector within cluster +DSKERR: DS 1 +TRANS: DS 1 +PREREAD:DS 1 ;0 means must preread; 1 means optional +READOP: DS 1 + + ALIGN +FCB: DS 2 ;Address of user FCB +NEXTADD:DS 2 +RECPOS: DS 4 +RECCNT: DS 2 +LASTPOS:DS 2 +CLUSNUM:DS 2 +SECPOS: DS 2 ;Position of first sector accessed +VALSEC: DS 2 ;Number of valid (previously written) sectors +BYTSECPOS:DS 2 ;Position of first byte within sector +BYTPOS: DS 4 ;Byte position in file of access +BYTCNT1:DS 2 ;No. of bytes in first sector +BYTCNT2:DS 2 ;No. of bytes in last sector +SECCNT: DS 2 ;No. of whole sectors + + DS 100H ;Stack space +IOSTACK: + DS 100H +DSKSTACK: + + IF DSKTEST +NSS: DS 2 +NSP: DS 2 + ENDIF + +DIRBUF: + +;Init code below overlaps with data area above + + ORG INITCODE + PUT $+100H + +MOVFAT: +;This section of code is safe from being overwritten by block move + SEG ES + REP + MOVB + UP +FININIT: + CALL SETMEM ;Set up segment + RET L + +DOSINIT: + DI + UP + PUSH CS + POP ES + LODB + SEG ES + MOV [NUMDRV],AL + MOV BX,DRVTAB + MOV DI,MEMSTRT +PERDRV: + SEG ES + MOV [BX],DI + MOV BP,DI + INC BX + INC BX + SEG ES + MOV AL,[DRVCNT] + STOB ;DRVNUM + LODW ;Pointer to DPT + PUSH SI + MOV SI,AX + LODW + STOW ;SECSIZ + MOV DX,AX + SEG ES + CMP AX,[MAXSEC] + JBE NOTMAX + SEG ES + MOV [MAXSEC],AX +NOTMAX: + LODB + DEC AL + STOB ;CLUSMSK + JZ HAVSHFT + CBW +FIGSHFT: + INC AH + SAR AL + JNZ FIGSHFT + MOV AL,AH +HAVSHFT: + STOB ;CLUSSHFT + MOVW ;FIRFAT (= number of reserved sectors) + MOVB ;FATCNT + MOVW ;MAXENT + MOV AX,DX ;SECSIZ again + MOV CL,5 + SHR AX,CL + MOV CX,AX ;Directory entries per sector + DEC AX + SEG ES + ADD AX,[BP+MAXENT] + XOR DX,DX + DIV AX,CX + STOW ;DIRSEC (temporarily) + SHR AX ;Divide by two + ADC AX,0 ;Round up + SEG ES + MOV [SDIRSEC],AX ;Number of directory records for small entries + MOVW ;DSKSIZ (temporarily) +FNDFATSIZ: + MOV AL,1 + MOV DX,1 +GETFATSIZ: + PUSH DX + CALL FIGFATSIZ + POP DX + CMP AL,DL ;Compare newly computed FAT size with trial + JZ HAVFATSIZ ;Has sequence converged? + CMP AL,DH ;Compare with previous trial + MOV DH,DL + MOV DL,AL ;Shuffle trials + JNZ GETFATSIZ ;Continue iterations if not oscillating + SEG ES + DEC [BP+DSKSIZ] ;Damp those oscillations + JP FNDFATSIZ ;Try again +HAVFATSIZ: + STOB ;FATSIZ + SEG ES + MUL AL,[BP+FATCNT] ;Space occupied by all FATs + SEG ES + ADD AX,[BP+FIRFAT] + STOW ;FIRDIR + + IF SMALLDIR-1 + SEG ES + ADD AX,[BP+DIRSEC] + SEG ES + MOV [BP+FIRREC],AX ;Destroys DIRSEC + CALL FIGMAX + SEG ES + MOV [BP+MAXCLUS],CX + ENDIF + + IF SMALLDIR + MOV DX,AX ;Save FIRDIR momentarily + SEG ES + ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry + STOW ;FIRREC1 + XCHG AX,CX ;Previously computed MAXCLUS + STOW ;MAXCLUS1 + XCHG DX,AX + SEG ES + ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry + STOW ;FIRREC2 + CALL FIGMAX + XCHG AX,CX + STOW ;MAXCLUS2 + ENDIF + + MOV AX,0FFH + STOB ;DIRTYFAT + SEG ES + MOV AL,[BP+FATSIZ] + SEG ES + MUL AX,[BP+SECSIZ] + ADD DI,AX ;Allocate FAT + POP SI ;Restore pointer to init. table + SEG ES + MOV AL,[DRVCNT] + INC AL + SEG ES + MOV [DRVCNT],AL + SEG ES + CMP AL,[NUMDRV] + JAE CONTINIT + JMP PERDRV +CONTINIT: + LODW ;Max. buffer size + SEG ES + MOV BX,[MAXSEC] + MOV AX,DIRBUF + ADD AX,BX + SEG ES + MOV [BUFFER],AX ;Start of buffer + PUSH DI ;Save ending location + ADD DI,BX ;Allocate directory buffer + ADD DI,BX ;Allocate buffer space + ADD DI,ADJFAC+15 ;True start of free space + MOV CL,4 + SHR DI,CL ;First free segment + MOV BP,DI + 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 [ENTRYPOINT+1],ENTRY + MOV [ENTRYPOINT+3],AX + MOV CX,9 + REP + STOW ;Set 5 segments (skip 2 between each) + MOV [INTBASE+4],COMMAND + MOV [INTBASE+12],IRET ;CTRL-C exit + MOV [INTBASE+16],IRET ;Fatal error exit + MOV AX,BIOSREAD + STOW + MOV AX,BIOSSEG + STOW + STOW ;Add 2 to DI + STOW + MOV [INTBASE+18H],BIOSWRITE + MOV DX,CS + MOV DS,DX + ADD DX,BP + MOV [DMAADD],80H + MOV [DMAADD+2],DX + MOV AX,[DRVTAB] + MOV [CURDRVPT],AX + INT 12H ;Get memory size--1K blocks in AX + MOV CL,6 + SHL AX,CL ;Convert to 16-byte blocks (segment no.) + SEG CS + MOV [ENDMEM],AX + XOR CX,CX + MOV DS,CX + MOV [EXIT],100H + MOV [EXIT+2],DX + PUSH CS + POP DS + PUSH CS + POP ES + MOV [ENDDOS],DX +;Move FATs into position. Segment of COMMAND still in DX. + POP SI + MOV AX,[MAXSEC] + SHL AX ;Allocate two buffers + ADD AX,ADJFAC + JZ FINJMP + MOV DI,DRVTAB + MOV CX,15 +ADJLP: + ADD [DI],AX + INC DI + INC DI + LOOP ADJLP + MOV CX,SI + MOV SI,MEMSTRT ;Place to move FATs from + SUB CX,SI ;Total length of FATs + MOV DI,AX + ADD DI,SI ;Place to move FATs to + OR AX,AX + JS MOVJMP + DEC CX + ADD DI,CX + ADD SI,CX + INC CX + DOWN +MOVJMP: + JMP MOVFAT +FINJMP: JMP FININIT + +FIGFATSIZ: + SEG ES + MUL AL,[BP+FATCNT] + SEG ES + ADD AX,[BP+FIRFAT] + SEG ES + ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +FIGMAX: +;AX has equivalent of FIRREC + SEG ES + SUB AX,[BP+DSKSIZ] + NEG AX + SEG ES + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + INC AX + MOV CX,AX ;MAXCLUS + INC AX + MOV DX,AX + SHR DX + ADC AX,DX ;Size of FAT in bytes + SEG ES + MOV SI,[BP+SECSIZ] + ADD AX,SI + DEC AX + XOR DX,DX + DIV AX,SI + RET + +DRVCNT: DB 0 +SDIRSEC:DS 1 + +MEMSTRT: +ADJFAC: EQU DIRBUF-MEMSTRT + \ No newline at end of file diff --git a/3_source_code/PC-DOS_1.00_dev/86DOS_1981-07-07.ASM b/3_source_code/PC-DOS_1.00_dev/86DOS_1981-07-07.ASM new file mode 100644 index 0000000..3051944 --- /dev/null +++ b/3_source_code/PC-DOS_1.00_dev/86DOS_1981-07-07.ASM @@ -0,0 +1,3901 @@ +; 86-DOS High-performance operating system for the 8086 version 1.00 04/28/81 +; by Tim Paterson + +; ****************** Revision History ************************* +; >> EVERY change must noted below!! << +; +; 0.34 12/29/80 General release, updating all past customers +; 0.42 02/25/81 32-byte directory entries added +; 0.56 03/23/81 Variable record and sector sizes +; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +; 0.74 04/15/81 Recognize I/O devices with file names +; 0.75 04/17/81 Improve and correct buffer handling +; 0.76 04/23/81 Correct directory size when not 2^N entries +; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +; 1.00 04/28/81 Renumber for general release +; +; ************************************************************* + +EXCESS: EQU 511 ;Make 86-DOS artificially larger + +; Use the switch below to generate code to accept the old 16-byte +; directory entry as well as the new 32-byte entry. + +SMALLDIR: EQU 0 ;1 to enable, 0 to disable + + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + +DSKTEST: EQU 0 ;1 to enable, 0 to disable + + +; 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 + + +MAXCALL:EQU 36 +MAXCOM: EQU 45 +ESCCH: EQU 0 +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 +MAXDIF: EQU 0FFFH +SAVEXIT:EQU 10 + ;Date format + ;16 15 14 13 11 10 9 8 7 6 5 4 3 2 1 0 + ; y y y y y y y m m m m d d d d d + ; + ;where y=year,m=month,d=day + +; Field definition for FCBs + + ORG 0 + DS 12 ;Drive code and name +EXTENT: DS 2 +RECSIZ: DS 2 ;Size of record (user settable) +FILSIZ: DS 4 ;Size of file in bytes +FDATE: DS 2 ;Date of last writing +FILDIRBLK:DS 2 ;Location in directory +FIRCLUS:DS 2 ;First cluster of file +LSTCLUS:DS 2 ;Last cluster accessed +CLUSPOS:DS 2 ;Position of last cluster accessed +DIRTYFIL:DS 1 ;File has been written to if <>0 + ORG 32 +NR: DS 1 ;Next record +RR: DS 3 ;Random record + + +; Description of 32-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 1 Attributes. Bits 1 or 2 make file hidden +; 12 12 Zero field (for expansion) +; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +; 26 2 First allocation unit ( < 4080 ) +; 28 4 File size, in bytes (LSB first, 30 bits max.) + + +; Field definition for Drive Parameter Block + + ORG 0 +DRVNUM: DS 1 ;Drive number +SECSIZ: DS 2 ;Size of physical sector in bytes +CLUSMSK:DS 1 ;Sectors/cluster - 1 +CLUSSHFT:DS 1 ;Log2 of sectors/cluster +FIRFAT: DS 2 ;Starting record of FATs +FATCNT: DS 1 ;Number of FATs for this drive +MAXENT: DS 2 ;Number of directory entries +DIRSEC: ;Number of dir. sectors (init temporary) +FIRREC: DS 2 ;First sector of first cluster +DSKSIZ: ;Size of disk (temp used during init only) +MAXCLUS:DS 2 ;Number of clusters on drive + 1 +FATSIZ: DS 1 ;Number of records occupied by FAT +FIRDIR: DS 2 ;Starting record of directory + + IF SMALLDIR +FIRREC1:DS 2 ;First data sector with 16-byte dir. entries +MAXCLUS1:DS 2 ;No. of clusters + 1 with 16-byte dir. entries +FIRREC2:DS 2 ;First data sector with 32-byte dir. entries +MAXCLUS2:DS 2 ;No. of clusters + 1 with 32-byte dir entries + ENDIF + +DIRTYFAT:DS 1 ;1=FAT has been changed, -1=never been read +FAT: ;Start of FAT +DIRSIZ: ;-1=small dir. entry, else large + + +; BIOS entry point defintions + +BIOSSEG: EQU 60H + ORG 0 + DS 3 +BIOSSTAT: DS 3 +BIOSIN: DS 3 +BIOSOUT: DS 3 +BIOSPRINT: DS 3 +BIOSAUXIN: DS 3 +BIOSAUXOUT: DS 3 +BIOSREAD: DS 3 +BIOSWRITE: DS 3 +BIOSDSKCHG: DS 3 + + +; Location of user registers relative user stack pointer + + ORG 0 +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 +IPSAVE: DS 2 +CSSAVE: DS 2 +FSAVE: DS 2 + + +; Start of code + + ORG 0 + PUT 100H + + JMP DOSINIT +ENDDOS: DW ENDDOS ;SEGMENT FOR COMMAND STORED HERE +ESCTAB: + DB 77 ;Copy one char--RIGHT ARROW + DB 59 ;Copy one char--F1 + DB 83 ;Skip one char--DELETE + DB 60 ;Copy to char--F2 + DB 62 ;Skip to char--F4 + DB 61 ;Copy line--F3 + DB 64 ;Ctrl-Z--F6 + DB 63 ;Reedit line (new template)--F5 + DB 75 ;Backspace--LEFT ARROW + DB 82 ;Toggle insert mode--INSERT + DB 65 ;Escape character--F7 + DB 65 ;End of table + +ESCTABLEN:EQU $-ESCTAB + + +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 + DI + 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: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + IF DSKTEST + SEG CS + MOV AX,[SPSAVE] + SEG CS + MOV [NSP],AX + SEG CS + MOV AX,[SSSAVE] + SEG CS + MOV [NSS],AX + POP AX + PUSH AX + ENDIF + + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + MOV SP,CS + MOV SS,SP +REDISP: + MOV SP,IOSTACK + EI ;Stack OK now + SEG CS + MOV [FUNC],AH + MOV BL,AH + MOV BH,0 + SHL BX + UP + CMP AH,12 + JLE SAMSTK + MOV SP,DSKSTACK +SAMSTK: + SEG CS + CALL [BX+DISPATCH] +LEAVE: + DI + SEG CS + MOV SP,[SPSAVE] + SEG CS + MOV SS,[SSSAVE] + MOV BP,SP + MOV [BP+AXSAVE],AL + + IF DSKTEST + SEG CS + MOV AX,[NSP] + SEG CS + MOV [SPSAVE],AX + SEG CS + MOV AX,[NSS] + SEG CS + MOV [SSSAVE],AX + ENDIF + + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + IRET + +DISPATCH: +; Standard Functions + DW ABORT + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST + DW RAWIO + DW RAWINP + DW IN + DW PRTBUF + DW BUFIN + DW CONSTAT + DW FLUSHKB + DW DSKRESET + DW SELDSK + DW OPEN + DW CLOSE + DW SRCHFRST + DW SRCHNXT + DW DELETE + DW SEQRD + DW SEQWRT + DW CREATE + DW RENAME + DW INUSE + DW CURDRV + DW SETDMA + DW GETFATPT + DW WRTPROT + DW GETRDONLY + DW SETATTRIB + DW GETDSKPT + DW USERCODE + DW RNDRD + DW RNDWRT + DW FILESIZE + DW SETRNDREC +; Extended Functions + DW SETVECT + DW NEWBASE + DW BLKRD + DW BLKWRT ;40 + DW MAKEFCB + DW GETDATE + DW SETDATE + DW GETTIME + DW SETTIME ;45 + +GETIO: +SETIO: +WRTPROT: +GETRDONLY: +SETATTRIB: +USERCODE: +INUSE: +GETDSKPT: + MOV AL,0 + RET + +FLUSHKB: + XOR BX,BX + MOV ES,BX ;Select segment 0 + SEG ES + MOV B,[41AH],1EH ;Reset KB queue head pointer + SEG ES + MOV B,[41CH],1EH ;Reset tail pointer + MOV AH,AL + CMP AL,1 + JZ REDISPJ + CMP AL,6 + JZ REDISPJ + CMP AL,7 + JZ REDISPJ + CMP AL,8 + JZ REDISPJ + CMP AL,10 + JZ REDISPJ + MOV AL,0 + RET + +REDISPJ:JMP REDISP + +READER: +AUXIN: + CALL STATCHK + CALL BIOSAUXIN,BIOSSEG + RET + +PUNCH: + MOV AL,DL +AUXOUT: + PUSH AX + CALL STATCHK + POP AX + 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: + PUSH AX + MOV AH,80H + MOV DI,0FFFH + CALL FATAL + POP AX + RET + + +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 + +DEVNAME: + MOV SI,IONAME ;List of I/O devices with file names + MOV BL,6 ;BL = number of device names +LOOKIO: + MOV DI,NAME1 + MOV CX,4 ;All device names are 4 letters + REPE + CMPB ;Check for name in list + JZ IOCHK ;If first 4 letters OK, check the rest + ADD SI,CX ;Point to next device name + DEC BL + JNZ LOOKIO +CRET: + STC + RET +IOCHK: + MOV CX,4 ;Check rest of name but not extension + MOV AL," " + REPE + SCAB ;Make sure rest of name is blanks + JNZ CRET + MOV AL,BL + MOV BX,IONUM-1 + XLAT ;Translate to internal device number + MOV BL,AL + MOV BH,-1 + RET + +GETFILE: +; Same as GETNAME except ES:DI points to FCB on successful return + CALL MOVNAME + JC RET + PUSH DX + PUSH DS + CALL FINDNAME + POP ES + POP 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 +; Zero set if attributes match (always except when creating) +; BP = Base of drive parameters +; DS = CS +; ES = CS +; BX = Pointer into directory buffer +; SI = Pointer to First Cluster field in directory entry +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + CALL MOVNAME + JC RET ;Bad file name? +FINDNAME: + MOV AX,CS + MOV DS,AX + CALL DEVNAME + JNC RET + CALL STARTSRCH +CONTSRCH: + CALL GETENTRY + JC RET +SRCH: + CMP B,[BX],0E5H + JZ NEXTENT + MOV SI,BX + MOV DI,NAME1 + MOV CX,11 +WILDCRD: + REPE + CMPB + JZ FOUND + CMP B,[DI-1],"?" + JZ WILDCRD +NEXTENT: + CALL NEXTENTRY + JNC SRCH + RET + +FOUND: + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ RET + ENDIF + +;Check if attributes allow finding it + MOV AH,[ATTRIB] ;Attributes of search + NOT AH + AND AH,[SI] ;Compare with attributes of file + ADD SI,15 + AND AH,6 ;Only look at bits 1 and 2 + JZ RET + TEST B,[CREATING],-1 + JZ NEXTENT + RET + + +GETENTRY: + +; Inputs: +; [LASTENT] has previously searched directory entry +; Function: +; Locates next sequential directory entry in preparation for search +; Outputs: +; Carry set if none +; ELSE +; AL = Current directory block +; BX = Pointer to next directory entry in [DIRBUF] +; DX = Pointer to first byte after end of DIRBUF +; [LASTENT] = New directory entry number + + MOV AX,[LASTENT] + INC AX ;Start with next entry + CMP AX,[BP+MAXENT] + JAE NONE +GETENT: + MOV [LASTENT],AX + MOV CL,4 + SHL AX,CL + XOR DX,DX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JZ SMALENT1 + ENDIF + + SHL AX + RCL DX ;Account for overflow in last shift +SMALENT1: + MOV BX,[BP+SECSIZ] + AND BL,255-31 ;Must be multiple of 32 + DIV AX,BX + MOV BX,DX ;Position within sector + MOV AH,[BP+DRVNUM] ;AL=Directory sector no. + CMP AX,[DIRBUFID] + JZ HAVDIRBUF + PUSH BX + CALL DIRREAD + POP BX +HAVDIRBUF: + MOV DX,DIRBUF + ADD BX,DX + ADD DX,[BP+SECSIZ] + RET + +NEXTENTRY: + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update AL, BX, and [LASTENT] for next directory entry. +; Carry set if no more. + + MOV DI,[LASTENT] + INC DI + CMP DI,[BP+MAXENT] + JAE NONE + MOV [LASTENT],DI + ADD BX,32 + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT3 + SUB BX,16 +BIGENT3: + ENDIF + + CMP BX,DX + JB HAVIT + INC AL ;Next directory sector + PUSH DX ;Save limit + CALL DIRREAD + POP DX + MOV BX,DIRBUF +HAVIT: + CLC + RET + +NONE: + CALL CHKDIRWRITE + STC + RET + + +DELETE: ; System call 19 + CALL GETNAME + MOV AL,-1 + JC RET + CMP BH,AL ;Check if device name + JZ RET ;Can't delete I/O devices +DELFILE: + MOV B,[DIRTYDIR],-1 + MOV B,[BX],0E5H + MOV BX,[SI] + LEA SI,[BP+FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP+MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + CALL CONTSRCH + JNC DELFILE + CALL FATWRT + CALL CHKDIRWRITE + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + ADD SI,5 + MOV DI,NAME2 + CALL LODNAME + JC ERRET + CALL FINDNAME + JC ERRET + CMP BH,-1 ;Check if I/O device name + JZ ERRET ;If so, can't rename it + MOV SI,NAME1 + MOV DI,NAME3 + MOV CX,6 ;Include attribute byte + REP + MOVW ;Copy name to search for +RENFIL: + MOV DI,NAME1 + MOV SI,NAME2 + MOV CX,11 +NEWNAM: + LODB + CMP AL,"?" + JNZ NOCHG + MOV AL,[BX] +NOCHG: + STOB + INC BX + LOOP NEWNAM + MOV B,[DI],6 ;Stop duplicates with any attributes + CALL DEVNAME ;Check if giving it a device name + JNC RENERR + PUSH [LASTENT] ;Save position of match + MOV [LASTENT],-1 ;Search entire dirctory for duplicate + CALL CONTSRCH ;See if new name already exists + POP AX + JNC RENERR ;Error if found + CALL GETENT ;Re-read matching entry + MOV DI,BX + MOV SI,NAME1 + MOV CX,11 + REP + MOVB ;Replace old name with new + MOV B,[DIRTYDIR],-1 ;Flag change in directory + MOV SI,NAME3 + MOV DI,NAME1 + MOV CX,6 ;Include attribute byte + REP + MOVW ;Copy name back into search buffer + CALL CONTSRCH + JNC RENFIL + CALL CHKDIRWRITE + XOR AL,AL + RET + +RENERR: + CALL CHKDIRWRITE +ERRET: + MOV AL,-1 + RET + + +MOVNAME: + +; Inputs: +; DS, DX point to FCB or extended FCB +; Outputs: +; DS:DX point to normal FCB +; 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 + + SEG CS + MOV B,[CREATING],0 + MOV AX,CS + MOV ES,AX + MOV DI,NAME1 + MOV SI,DX + LODB + SEG CS + MOV [EXTFCB],AL + MOV AH,0 + CMP AL,-1 + JNZ HAVATTRB + ADD DX,7 + ADD SI,6 + MOV AH,[SI-1] + LODB +HAVATTRB: + SEG CS + MOV [ATTRIB],AH + CALL GETBP + JB RET +LODNAME: +; This entry point copies a file name from DS,SI +; to ES,DI converting to upper case. + CMP B,[SI]," " ;First letter may not be blank + STC ;Ready to indicate error + JZ RET + MOV CX,11 +MOVCHK: + CALL GETLET + JNZ CTRLCHK ;Is it a delimiter? + CMP AL," " ;This is the only delimiter allowed + STC ;In case of error + JNZ RET +CTRLCHK: + CMP AL,20H + JC RET + STOB + LOOP MOVCHK + RET + +GETBP: + SEG CS + CMP [NUMDRV],AL + JC RET + CBW + XCHG BP,AX + SHL BP + MOV BP,[BP+CURDRVPT] + RET + + +OPEN: ;System call 15 + CALL GETFILE +DOOPEN: +; Enter here to perform OPEN on file already found +; in directory. DS=CS, BX points to directory +; entry in DIRBUF, SI points to First Cluster field, and +; ES:DI point to the FCB to be opened. This entry point +; is used by CREATE. + JC ERRET + CMP BH,-1 ;Check if file is I/O device + JZ OPENDEV ;Special handler if so + MOV AL,[BP+DRVNUM] + INC AL + STOB + ADD DI,11 ;Point to extent field + XOR AX,AX + STOW ;Set extent field to 0 + MOV AX,128 ;Default record size + STOW ;Set record size + LODW ;Get starting cluster + MOV DX,AX ;Save it for the moment + MOVW ;Transfer size to FCB + MOVW + MOV AX,[SI-8] ;Get date + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT10 + SEG ES + MOV [DI-1],0 + XOR AX,AX ;Date not available in small entry +BIGENT10: + ENDIF + + STOW ;Save date in FCB + MOV AX,[LASTENT] + STOW ;directory location + MOV AX,DX ;Restore starting cluster + STOW ; first cluster + STOW ; last cluster accessed + XOR AX,AX + STOW ; position of last cluster + STOB ; dirty flag + RET + +OPENDEV: + SEG ES + MOV [DI+FILDIRBLK],BX ;Use dir. entry number as flag + XOR AL,AL + RET + + +STARTSRCH: + MOV [LASTENT],-1 +FATREAD: + +; Inputs: +; DS = CS +; BP = Base of drive parameters +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV AL,[BP+DRVNUM] + CALL BIOSDSKCHG,BIOSSEG ;See what BIOS has to say + MOV AL,[BP+DRVNUM] + OR AH,[BP+DIRTYFAT] + JS NEWDSK ;If either say new disk, then it's so + DEC AH ;Check for AH=1 (disk not changed) + JZ RET + MOV AH,1 + CMP AX,[BUFDRVNO] ;Does buffer have dirty sector of this drive? + JZ RET ;If so, disk has not been changed +NEWDSK: + CMP AL,[BUFDRVNO] ;See if buffer is for this drive + JNZ BUFOK ;If not, don't touch it + MOV [BUFSECNO],0 ;Flag buffers invalid + MOV [BUFDRVNO],00FFH +BUFOK: + MOV [DIRBUFID],-1 + CALL FIGFAT +NEXTFAT: + PUSH AX + CALL DSKREAD + POP AX + JC BADFAT + + IF SMALLDIR + MOV DL,AL + LEA SI,[BP+FIRREC1] ;FIRREC and MAXCLUS for 16-byte dir entries + CMP B,[BP+DIRSIZ],-1 + JZ SETSIZ + ADD SI,4 ;FIRREC and MAXCLUS for 32-byte entries +SETSIZ: + LODW + MOV [BP+FIRREC],AX + LODW + MOV [BP+MAXCLUS],AX + MOV AL,DL + ENDIF + + SUB AL,[BP+FATCNT] + JZ RET + NEG AL +;{Insert error code here. AL=number of bad fats. +;Since one good FAT was read, should include option +;to rewrite all FATs.} + JMP FATWRT + +BADFAT: + MOV CX,DI + ADD DX,CX + DEC AL + JNZ NEXTFAT + CALL FIGFAT ;Reset registers + JMP DREAD ;Try first FAT once more + +OKRET1: + MOV AL,0 + RET + +CLOSE: ;System call 16 + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB3 + ADD DI,7 +NORMFCB3: + CMP B,[DI+FILDIRBLK+1],-1 ;Check for I/O device + JZ OKRET1 ;Can't close I/O device + TEST B,[DI+DIRTYFIL],-1 + JZ OKRET1 ;If not written to, do nothing + MOV AL,[DI] ;Get drive number + CALL GETBP ;Get base of drive parameters + JC BADCLOSEJ + MOV AL,[BP+DRVNUM] + MOV AH,1 ;Look for dirty buffer + SEG CS + CMP AX,[BUFDRVNO] + JNZ FNDDIR +;Write back dirty buffer if on same drive + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV B,[DIRTYBUF],0 + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP DS + POP DX +FNDDIR: + CALL GETFILE +BADCLOSEJ: + JC BADCLOSE + MOV AX,[LASTENT] + SEG ES + CMP AX,[DI+FILDIRBLK] + JNZ BADCLOSE + SEG ES + MOV CX,[DI+FIRCLUS] + MOV [SI],CX + SEG ES + MOV DX,[DI+FILSIZ] + MOV [SI+2],DX + SEG ES + MOV DX,[DI+FILSIZ+2] + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT11 + MOV [SI+4],DL + JP SMALLENT2 +BIGENT11: + ENDIF + + MOV [SI+4],DX + SEG ES + MOV DX,[DI+FDATE] + MOV [SI-2],DX +SMALLENT2: + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty + + CMP B,[BP+DIRTYFAT],1 + JNZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty bit. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + MOV B,[BP+DIRTYFAT],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+DIRTYFAT],0 + MOV AL,-1 + RET + + +FIGFAT: +; Loads registers with values needed to read or +; write a FAT. + MOV AL,[BP+FATCNT] + LEA 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 + SEG CS + MOV B,[CREATING],1 + PUSH DX + PUSH DS + CALL FINDNAME + JNC EXISTENT + CALL STARTSRCH + CALL GETENTRY +LOOKFRE: + CMP B,[BX],0E5H + JZ FREESPOT + CALL NEXTENTRY + JNC LOOKFRE +ERRPOP: + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET + +EXISTENT: + JNZ ERRPOP ;Error if attributes don't match + CMP BH,-1 ;Check if file is I/O device + JZ OPENJMP ;If so, no action + MOV CX,[SI] ;Get pointer to clusters + JCXZ FREESPOT + CMP CX,[BP+MAXCLUS] + JA FREESPOT + PUSH BX + MOV BX,CX + LEA SI,[BP+FAT] + CALL RELEASE ;Free any data already allocated + CALL FATWRT + POP BX +FREESPOT: + MOV DI,BX + MOV SI,NAME1 + MOV CX,5 + MOVB + REP + MOVW + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT4 + PUSH DI + MOV CL,5 + XOR AX,AX + JP SMALLENT +BIGENT4: + ENDIF + + MOV AL,[ATTRIB] + STOB + XOR AX,AX + MOV CL,6 + REP + STOW + CALL DATE16 + STOW + XOR AX,AX + PUSH DI + MOV CL,6 +SMALLENT: + REP + STOB + PUSH BX + CALL DIRWRITE + POP BX + POP SI +OPENJMP: + CLC ;Clear carry so OPEN won't fail + POP ES + POP DI + JMP DOOPEN + + +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. + + PUSH AX + CALL CHKDIRWRITE + POP AX + PUSH AX + MOV AH,[BP+DRVNUM] + MOV [DIRBUFID],AX + CALL DIRCOMP + CALL DREAD + POP AX + RET + + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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. + + CALL DSKREAD + JNC RET + SEG CS + MOV B,[READOP],0 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DREAD + RET ;Ignore otherwise + +HARDERR: +;Hard disk error handler. Entry conditions: +; DS:BX = Original disk transfer address +; DX = Original logical sector number +; CX = Number of sectors to go (first one gave the error) +; AX = Hardware error code +; DI = Original sector transfer count +; BP = Base of drive parameters +; [READOP] = 0 for read, 1 for write + + XCHG AX,DI ;Error code in DI, count in AX + SUB AX,CX ;Number of sectors successfully transferred + ADD DX,AX ;First sector number to retry + PUSH DX + MUL AX,[BP+SECSIZ] ;Number of bytes transferred + POP DX + ADD BX,AX ;First address for retry + MOV AH,0 ;Flag disk section in error + CMP DX,[BP+FIRFAT] ;In reserved area? + JB ERRINT + INC AH ;Flag for FAT + CMP DX,[FIRDIR] ;In FAT? + JB ERRINT + INC AH + CMP DX,[FIRREC] ;In directory? + JB ERRINT + INC AH ;Must be in data area +ERRINT: + SHL AH ;Make room for read/write bit + SEG CS + OR AH,[READOP] +FATAL: + MOV AL,[BP+DRVNUM] ;Get drive number + PUSH BP ;The only thing we preserve + SEG CS + MOV [CONTSTK],SP + DI ;Prepare to play with stack + SEG CS + MOV SS,[SSSAVE] + SEG CS + MOV SP,[SPSAVE] ;User stack pointer restored + INT 24H ;Fatal error interrupt vector + SEG CS + MOV [SPSAVE],SP + SEG CS + MOV [SSSAVE],SS + MOV SP,CS + MOV SS,SP + SEG CS + MOV SP,[CONTSTK] + EI + POP BP + CMP AL,2 + JZ ERROR + RET + +DSKREAD: + MOV AL,[BP+DRVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSREAD,BIOSSEG + POP DX + POP DI + POP BX + POP BP + RET + + +CHKDIRWRITE: + TEST B,[DIRTYDIR],-1 + JZ RET + +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. + + MOV B,[DIRTYDIR],0 + MOV AL,[DIRBUFID] + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; 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+DRVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL BIOSWRITE,BIOSSEG + POP DX + POP DI + POP BX + POP BP + JNC RET + SEG CS + MOV B,[READOP],1 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DWRITE + RET + +ABORT: + SEG CS + LDS SI,[SPSAVE] + MOV DS,[SI+CSSAVE] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVW + MOVW + MOVW + MOVW +ERROR: + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL WRTFATS + XOR AX,AX + DI + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + MOV DS,AX + MOV SI,EXIT + MOV DI,EXITHOLD + MOVW + MOVW + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + EI ;Stack OK now + SEG CS + JMP L,[EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + CALL LOAD + JP FINSEQ + +SEQWRT: ;System call 21 + CALL GETREC + CALL STORE +FINSEQ: + JCXZ SETNREX + ADD AX,1 + ADC DX,0 + JP SETNREX + +RNDRD: ;System call 33 + CALL GETRRPOS1 + CALL LOAD + JP FINRND + +RNDWRT: ;System call 34 + CALL GETRRPOS1 + CALL STORE + JP FINRND + +BLKRD: ;System call 39 + CALL GETRRPOS + CALL LOAD + JP FINBLK + +BLKWRT: ;System call 40 + CALL GETRRPOS + CALL STORE +FINBLK: + LDS SI,[SPSAVE] + MOV [SI+CXSAVE],CX + JCXZ FINRND + ADD AX,1 + ADC DX,0 +FINRND: + SEG ES + MOV [DI+RR],AX + SEG ES + MOV [DI+RR+2],DL + OR DH,DH + JZ SETNREX + SEG ES + MOV [DI+RR+3],DH ;Save 4 byte of RECPOS only if significant +SETNREX: + MOV CX,AX + AND AL,7FH + SEG ES + MOV [DI+NR],AL + AND CL,80H + SHL CX + RCL DX + MOV AL,CH + MOV AH,DL + SEG ES + MOV [DI+EXTENT],AX + SEG CS + MOV AL,[DSKERR] + RET + +GETRRPOS1: + MOV CX,1 +GETRRPOS: + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB1 + ADD DI,7 +NORMFCB1: + MOV AX,[DI+RR] + MOV DX,[DI+RR+2] + RET + +NOFILERR: + XOR CX,CX + MOV B,[DSKERR],4 + POP BX + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; CX = No. of bytes to transfer +; BP = Base of drive parameters +; SI = FAT pointer +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DI +; [NEXTADD] = Displacement of disk transfer within segment +; [SECPOS] = Position of first sector +; [BYTPOS] = Byte position in file +; [BYTSECPOS] = Byte position in first sector +; [CLUSNUM] = First cluster +; [SECCLUSPOS] = Sector within first cluster +; [DSKERR] = 0 (no errors yet) +; [TRANS] = 0 (No transfers yet) +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + PUSH AX + MOV AL,[DI] + MOV SI,[DI+RECSIZ] + OR SI,SI + JNZ HAVRECSIZ + MOV SI,128 + MOV [DI+RECSIZ],SI +HAVRECSIZ: + MOV BX,DS + MOV ES,BX + MOV BX,CS + MOV DS,BX + CALL GETBP + POP AX + JC NOFILERR + CMP SI,64 ;Check if highest byte of RECPOS is significant + JB SMALREC + MOV DH,0 ;Ignore MSB if record >= 64 bytes +SMALREC: + MOV [RECCNT],CX + MOV [RECPOS],AX + MOV [RECPOS+2],DX + MOV [FCB],DI + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV B,[DSKERR],0 + MOV B,[TRANS],0 + MOV BX,DX + MUL AX,SI + MOV [BYTPOS],AX + PUSH DX + MOV AX,BX + MUL AX,SI + POP BX + ADD AX,BX + ADC DX,0 ;Ripple carry + JNZ EOFERR + MOV [BYTPOS+2],AX + MOV DX,AX + MOV AX,[BYTPOS] + MOV BX,[BP+SECSIZ] + CMP DX,BX ;See if divide will overflow + JNC EOFERR + DIV AX,BX + MOV [SECPOS],AX + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,[BP+CLUSMSK] + MOV [SECCLUSPOS],AL + MOV AX,CX ;Record count + MOV CL,[BP+CLUSSHFT] + SHR DX,CL + MOV [CLUSNUM],DX + MUL AX,SI ;Multiply by bytes per record + MOV CX,AX + ADD AX,[DMAADD] ;See if it will fit in one segment + ADC DX,0 + JZ OK ;Must be less than 64K + MOV AX,[DMAADD] + NEG AX ;Amount of room left in segment + JNZ PARTSEG ;All 64K available? + DEC AX ;If so, reduce it by one +PARTSEG: + XOR DX,DX + DIV AX,SI ;How many records will fit? + MOV [RECCNT],AX + MUL AX,SI ;Translate that back into bytes + MOV B,[DSKERR],2 ;Flag that trimming took place + MOV CX,AX + JCXZ NOROOM +OK: + LEA SI,[BP+FAT] + RET + +EOFERR: + MOV B,[DSKERR],1 + XOR CX,CX +NOROOM: + POP BX ;Kill return address + RET + +BREAKDOWN: + +;Inputs: +; DS = CS +; CX = Length of disk transfer in bytes +; BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +;Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +;AX, BX, DX destroyed. No other registers affected. + + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ;Partial first sector? + SUB AX,[BP+SECSIZ] + NEG AX ;Max number of bytes left in first sector + SUB BX,AX ;Subtract from total length + JAE SAVFIR + ADD AX,BX ;Don't use all of the rest of the sector + XOR BX,BX ;And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV AX,[BP+SECSIZ] ;How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ;Bytes remaining for last sector + 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,0FF8H + JAE RET + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +BUFSEC: +; Inputs: +; AL = 0 if buffer must be read, 1 if no pre-read needed +; 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: +; SI = Pointer to buffer +; DI = 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 + MOV [PREREAD],AL + CMP DX,[BUFSECNO] + JNZ GETSEC + MOV AL,[BUFDRVNO] + CMP AL,[BP+DRVNUM] + JZ FINBUF ;Already have it? +GETSEC: + TEST B,[DIRTYBUF],-1 + JZ RDSEC + PUSH DX + PUSH BP + MOV BP,[BUFDRVBP] + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP BP + POP DX +RDSEC: + TEST B,[PREREAD],-1 + JNZ SETBUF + MOV BX,[BUFFER] + MOV CX,1 + PUSH DX + CALL DREAD + POP DX +SETBUF: + MOV [BUFSECNO],DX + MOV AL,[BP+DRVNUM] + MOV AH,0 + MOV [BUFDRVNO],AX + MOV [BUFDRVBP],BP +FINBUF: + MOV B,[TRANS],1 ;A transfer is taking place + MOV DI,[NEXTADD] + MOV SI,DI + MOV CX,[BYTCNT1] + ADD SI,CX + MOV [NEXTADD],SI + MOV SI,[BUFFER] + ADD SI,[BYTSECPOS] + RET + +BUFRD: + XOR AL,AL ;Pre-read necessary + CALL BUFSEC + PUSH ES + MOV ES,[DMAADD+2] + SHR CX + JNC EVENRD + MOVB +EVENRD: + REP + MOVW + POP ES + RET + +BUFWRT: + 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 + MOV AL,0 +NOREAD: + CALL BUFSEC + XCHG DI,SI + PUSH DS + PUSH ES + PUSH CS + POP ES + MOV DS,[DMAADD+2] + SHR CX + JNC EVENWRT + MOVB +EVENWRT: + REP + MOVW + POP ES + POP DS + MOV B,[DIRTYBUF],1 + RET + +NEXTSEC: + TEST B,[TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,[BP+CLUSMSK] + JBE SAVPOS + MOV BX,[CLUSNUM] + CMP BX,0FF8H + JAE NONEXT + LEA SI,[BP+FAT] + CALL UNPACK + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + RET +NONEXT: + STC + RET + +TRANBUF: + LODB + STOB + CMP AL,13 ;Check for carriage return + JNZ NORMCH + MOV B,[SI],10 +NORMCH: + CMP AL,10 + LOOPNZ TRANBUF + JNZ ENDRDCON + CALL OUT ;Transmit linefeed + XOR SI,SI + OR CX,CX + JNZ GETBUF + OR AL,1 ;Clear zero flag--not end of file +ENDRDCON: + MOV [CONTPOS],SI +ENDRDDEV: + MOV [NEXTADD],DI + POP ES + JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + MOV DI,[FCB] + SEG ES + OR B,[DI+FILDIRBLK],80H ;Mark as no more data available +SETFCBJ: + JMP SETFCB + +READDEV: + PUSH ES + LES DI,[DMAADD] + OR BL,BL + JZ READCON + DEC BL + JNZ ENDRDDEV +READAUX: + CALL AUXIN + STOB + CMP AL,1AH + LOOPNZ READAUX + JP ENDRDDEV + +READCON: + PUSH CS + POP DS + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP B,[CONBUF],128 + JZ GETBUF + MOV [CONBUF],0FF80H ;Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,CONBUF + CALL BUFIN ;Get input buffer + POP DI + POP ES + POP CX + MOV SI,CONBUF+2 + CMP B,[SI],1AH ;Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOB + MOV AL,10 + CALL OUT ;Send linefeed + XOR SI,SI + JP ENDRDCON + +RDERR: + XOR CX,CX + JMP WRTERR + +RDLASTJ:JMP RDLAST + +LOAD: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file to read +; CX = No. of records to read +; Outputs: +; DX:AX = Position of last record read +; CX = No. of bytes read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 ;Check for named device I/O + JZ READDEV + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV BX,[DI+FILSIZ+2] + SUB AX,[BYTPOS] + SBC BX,[BYTPOS+2] + JB RDERR + JNZ ENUF + OR AX,AX + JZ RDERR + CMP AX,CX + JAE ENUF + MOV CX,AX +ENUF: + CALL BREAKDOWN + MOV CX,[CLUSNUM] + CALL FNDCLUS + OR CX,CX + JNZ RDERR + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + CALL BUFRD +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + CALL NEXTSEC + JC SETFCB + MOV B,[TRANS],1 ;A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DREAD + POP DS + POP CX + POP BX + JCXZ RDLAST + CMP BX,0FF8H + JAE SETFCB + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP RDLP + +SETFCB: + MOV SI,[FCB] + MOV AX,[NEXTADD] + MOV DI,AX + SUB AX,[DMAADD] ;Number of bytes transfered + XOR DX,DX + SEG ES + MOV CX,[SI+RECSIZ] + DIV AX,CX ;Number of records + CMP AX,[RECCNT] ;Check if all records transferred + JZ FULLREC + MOV B,[DSKERR],1 + OR DX,DX + JZ FULLREC ;If remainder 0, then full record transfered + MOV B,[DSKERR],3 ;Flag partial last record + SUB CX,DX ;Bytes left in last record + PUSH ES + MOV ES,[DMAADD+2] + XCHG AX,BX ;Save the record count temporarily + XOR AX,AX ;Fill with zeros + SHR CX + JNC EVENFIL + STOB +EVENFIL: + REP + STOW + XCHG AX,BX ;Restore record count to AX + POP ES + INC AX ;Add last (partial) record to total +FULLREC: + MOV CX,AX + MOV DI,SI ;ES:DI point to FCB +SETCLUS: + MOV AX,[CLUSNUM] + SEG ES + MOV [DI+LSTCLUS],AX + MOV AX,[LASTPOS] + SEG ES + MOV [DI+CLUSPOS],AX +ADDREC: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + JCXZ RET ;If no records read, don't change pos. + DEC CX + ADD AX,CX ;Update current record position + ADC DX,0 + INC CX + RET + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETFCB + MOV [BYTCNT1],AX + CALL NEXTSEC + JC SETFCB + MOV [BYTSECPOS],0 + CALL BUFRD + JP SETFCB + +WRTDEV: + PUSH DS + LDS SI,[DMAADD] + AND BL,7FH + OR BL,BL + JZ WRTCON + DEC BL + JZ WRTAUX + DEC BL + JNZ ENDWRDEV ;Done if device is NUL +WRTLST: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL LISTOUT + LOOP WRTLST + JP ENDWRDEV + +WRTAUX: + LODB + CALL AUXOUT + CMP AL,1AH + LOOPNZ WRTAUX + JP ENDWRDEV + +WRTCON: + LODB + CMP AL,1AH + JZ ENDWRDEV + CALL OUT + LOOP WRTCON +ENDWRDEV: + POP DS + MOV CX,[RECCNT] + MOV DI,[FCB] + JP ADDREC + +HAVSTART: + MOV CX,AX + CALL SKPCLP + JCXZ DOWRTJ + CALL ALLOCATE + JNC DOWRTJ +WRTERR: + MOV B,[DSKERR],1 +LVDSK: + MOV AX,[RECPOS] + MOV DX,[RECPOS+2] + MOV DI,[FCB] + RET + +DOWRTJ: JMP DOWRT + +WRTEOFJ: + JMP WRTEOF + +STORE: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; DX:AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + MOV B,[DI+DIRTYFIL],1 + CALL SETUP + CALL DATE16 + SEG ES + MOV [DI+FDATE],AX + SEG ES + MOV BX,[DI+FILDIRBLK] + CMP BH,-1 + JZ WRTDEV + CALL BREAKDOWN + MOV AX,[BYTPOS] + MOV DX,[BYTPOS+2] + JCXZ WRTEOFJ + DEC CX + ADD AX,CX + ADC DX,0 ;AX:DX=last byte accessed + DIV AX,[BP+SECSIZ] ;AX=last sector accessed + MOV CL,[BP+CLUSSHFT] + SHR AX,CL ;Last cluster to be accessed + PUSH AX + SEG ES + MOV AX,[DI+FILSIZ] + SEG ES + MOV DX,[DI+FILSIZ+2] + DIV AX,[BP+SECSIZ] + OR DX,DX + JZ NORNDUP + INC AX ;Round up if any remainder +NORNDUP: + MOV [VALSEC],AX ;Number of sectors that have been written + POP AX + MOV CX,[CLUSNUM] ;First cluster accessed + CALL FNDCLUS + MOV [CLUSNUM],BX + MOV [LASTPOS],DX + SUB AX,DX ;Last cluster minus current cluster + JZ DOWRT ;If we have last clus, we must have first + JCXZ HAVSTART ;See if no more data + PUSH CX ;No. of clusters short of first + MOV CX,AX + CALL ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP + CALL SKPCLP +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + CALL BUFWRT +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JZ WRTLAST + ADD [SECPOS],AX + CALL NEXTSEC + MOV B,[TRANS],1 ;A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JP WRTLP +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + CALL NEXTSEC + MOV [BYTSECPOS],0 + CALL BUFWRT +FINWRT: + MOV AX,[NEXTADD] + SUB AX,[DMAADD] + ADD AX,[BYTPOS] + MOV DX,[BYTPOS+2] + ADC DX,0 + MOV CX,DX + MOV DI,[FCB] + SEG ES + CMP AX,[DI+FILSIZ] + SEG ES + SBB CX,[DI+FILSIZ+2] + JB SAMSIZ + SEG ES + MOV [DI+FILSIZ],AX + SEG ES + MOV [DI+FILSIZ+2],DX +SAMSIZ: + MOV CX,[RECCNT] + JMP SETCLUS + + +WRTERRJ:JMP WRTERR + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBC DX,0 + DIV AX,[BP+SECSIZ] + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + JCXZ RELFILE + CALL ALLOCATE + JC WRTERRJ +UPDATE: + MOV DI,[FCB] + MOV AX,[BYTPOS] + SEG ES + MOV [DI+FILSIZ],AX + MOV AX,[BYTPOS+2] + SEG ES + MOV [DI+FILSIZ+2],AX + XOR CX,CX + RET + +RELFILE: + MOV DX,0FFFH + CALL RELBLKS +SETDIRT: + MOV B,[BP+DIRTYFAT],1 + JP UPDATE + +KILLFIL: + XOR BX,BX + SEG ES + XCHG BX,[DI+FIRCLUS] + OR BX,BX + JZ UPDATE + CALL RELEASE + JP SETDIRT + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = sector 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 sector 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 sectors per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of sectors left in first cluster + MOV DX,CX + LEA SI,[BP+FAT] + 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 +;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 sectors still needed + PUSH DX + MOV AX,CX + MUL AX,[BP+SECSIZ] ;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 + CALL FIGREC + MOV BX,SI + RET +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 + JP FINCLUS + + +FIGREC: + +;Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; BP = Base of drive parameters +;Outputs: +; DX = physical sector number +;No other registers affected. + + PUSH CX + MOV CL,[BP+CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP+FIRREC] + POP CX + RET + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; CX = 1 +; DX:AX = Record number determined by EXTENT and NR fields +; DS:DI point to FCB +; No other registers affected. + + MOV DI,DX + CMP B,[DI],-1 + JNZ NORMFCB2 + ADD DI,7 +NORMFCB2: + MOV CX,1 + MOV AL,[DI+NR] + MOV DX,[DI+EXTENT] + SHL AL + SHR DX + RCR AL + MOV AH,DL + MOV DL,DH + MOV DH,0 + 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 bit +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH [SI] + PUSH DX + PUSH CX + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP+MAXCLUS] + JLE TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + POP AX ;No. of clusters requested + SUB AX,CX ;AX=No. of clusters allocated + POP DX + POP [SI] + INC DX ;Position of first cluster allocated + ADD AX,DX ;AX=max no. of cluster in file + MOV DL,[BP+CLUSMSK] + MOV DH,0 + INC DX ;DX=records/cluster + MUL AX,DX ;AX=max no. of records in file + MOV CX,AX + SUB CX,[RECPOS] ;CX=max no. of records that could be written + JA MAXREC + XOR CX,CX ;If CX was negative, zero it +MAXREC: + 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+DIRTYFAT],1 + POP BX + POP CX ;Don't need this stuff since we're successful + POP DX + CALL UNPACK + POP [SI] + XCHG BX,DI + OR DI,DI + JNZ RET + MOV DI,[FCB] + SEG ES + MOV [DI+FIRCLUS],BX + 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,0FF8H + MOV BX,AX + JB 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,0FF8H + JAE RET + MOV BX,DI + JP GETEOF + + +SRCHFRST: ;System call 17 + CALL GETFILE +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + JC KILLSRCH + CMP BH,-1 + JZ SRCHDEV + MOV AX,[LASTENT] + SEG ES + MOV [DI+FILDIRBLK],AX +;Information in directory entry must be copied into the first +; 33 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,[DMAADD] + MOV AX,00FFH + CMP AL,[EXTFCB] + JNZ NORMFCB + STOW + INC AL + STOW + STOW + MOV AL,[ATTRIB] + STOB +NORMFCB: + MOV AL,[BP+DRVNUM] + INC AL + STOB ;Set drive number + MOVB ;Copy first character of name + MOV CX,5 + REP + MOVW ;Copy remaining 10 characters of name + XOR AX,AX + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGENT5 + STOB ;Zero out unused portion + MOV CX,7 + REP + STOW ;Zero a total of 15 bytes + MOVW ;Copy first cluster pointer + MOVW ;Copy low word of length + MOVB ;Copy 3rd byte of length + STOB ;4th byte of length must be zero + RET +BIGENT5: + ENDIF + + MOV CX,10 + REP + MOVW + MOVB + RET + +KILLSRCH: + SEG ES +KILLSRCH1: + MOV [DI+FILDIRBLK],-2 + MOV AL,-1 + RET + +SRCHDEV: + SEG ES + MOV [DI+FILDIRBLK],BX + LES DI,[DMAADD] + XOR AX,AX + STOB ;Zero drive byte + SUB SI,4 ;Point to device name + MOVW + MOVW + MOV AX,2020H + MOV CX,3 + REP + STOW ;Fill with 6 blanks + STOB ;And a 7th + XOR AX,AX + MOV CX,10 + REP + STOW + STOB + RET + +SRCHNXT: ;System call 18 + CALL MOVNAME + MOV DI,DX + JC KILLSRCH1 + PUSH DX + PUSH DS + MOV AX,[DI+FILDIRBLK] + PUSH CS + POP DS + MOV [LASTENT],AX + CALL CONTSRCH + POP ES + POP DI + JMP SAVPLCE + + +FILESIZE: ;System call 35 + CALL GETFILE + MOV AL,-1 + JC RET + ADD DI,33 ;Write size in RR field + SEG ES + MOV CX,[DI-33+RECSIZ] + OR CX,CX + JNZ RECOK + MOV CX,128 +RECOK: + XOR AX,AX + XOR DX,DX ;Intialize size to zero + CMP BH,-1 ;Check for named I/O device + JZ DEVSIZ + INC SI + INC SI ;Point to length field + MOV AX,[SI+2] ;Get high word of size + + IF SMALLDIR + CMP B,[BP+DIRSIZ],-1 + JNZ BIGSIZ + MOV AH,0 +BIGSIZ: + ENDIF + + DIV AX,CX + PUSH AX ;Save high part of result + LODW ;Get low word of size + DIV AX,CX + OR DX,DX ;Check for zero remainder + POP DX + JZ DEVSIZ + INC AX ;Round up for partial record + JNZ DEVSIZ ;Propagate carry? + INC DX +DEVSIZ: + STOW + MOV AX,DX + STOB + MOV AL,0 + CMP CX,64 + JAE RET ;Only 3-byte field if RECSIZ >= 64 + SEG ES + MOV [DI],AH + 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 BP,[CURDRVPT] + CALL FATREAD + LEA BX,[BP+FAT] + MOV AL,[BP+CLUSMSK] + INC AL + MOV DX,[BP+MAXCLUS] + DEC DX + MOV B,[BP+DIRTYFAT],1 + MOV CX,[BP+SECSIZ] + LDS SI,[SPSAVE] + MOV [SI+BXSAVE],BX + MOV [SI+DXSAVE],DX + MOV [SI+CXSAVE],CX + MOV [SI+DSSAVE],CS + RET + + +DSKRESET: ;System call 13 + SEG CS + MOV [DMAADD+2],DS + MOV AX,CS + MOV DS,AX + MOV [DMAADD],80H + MOV AX,[CURDRVPT+2] + MOV [CURDRVPT],AX +WRTFATS: +; DS=CS. Writes back all dirty FATs. All registers destroyed. + MOV AX,[BUFDRVNO] + OR AH,AH + JZ NOBUF + CBW + MOV BX,AX + SHL BX + MOV BP,[BX+DRVTAB] + MOV B,[DIRTYBUF],0 + MOV DX,[BUFSECNO] + MOV BX,BUFFER + MOV CX,1 + CALL DWRITE +NOBUF: + MOV CL,[NUMDRV] + MOV CH,0 + MOV SI,CURDRVPT+2 +WRTFAT: + LODW + PUSH CX + PUSH SI + MOV BP,AX + CALL CHKFATWRT + POP SI + POP CX + LOOP WRTFAT + RET + + +CURDRV: ;System call 25 + SEG CS + MOV BP,[CURDRVPT] + MOV AL,[BP+DRVNUM] + RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+33],AX + MOV [DI+35],DL + CMP [DI+RECSIZ],64 + JAE RET + MOV [DI+36],DH ;Set 4th byte only if record size < 64 + RET + + +SELDSK: ;System call 14 + MOV DH,0 + MOV BX,DX + PUSH CS + POP DS + MOV AL,[NUMDRV] + CMP BL,AL + JNB RET + SHL BX + MOV DX,[BX+CURDRVPT+2] + MOV [CURDRVPT],DX + 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 BACKSPJ + CMP AL,8 + JZ BACKSPJ + CMP AL,13 + JZ ENDLIN + CMP AL,10 + JZ PHYCRLF + CMP AL,"X"-"@" + JZ KILNEW + CMP AL,1BH + JZ KILNEW ;WANT esc TO DO SAME AS cntrl-X + CMP AL,ESCCH + JZ ESC +SAVCH: + CMP DH,DL + JAE BELL + STOB + INC DH + CALL BUFOUT + OR AH,AH + JNZ GETCH + CMP BH,BL + JAE GETCH + INC SI + INC BH + JP GETCH + +BELL: + MOV AL,7 + CALL OUTCH + JP GETCH + +BACKSPJ:JP BACKSP + +ESC: + CALL IN + PUSH DI + MOV CL,ESCTABLEN + MOV DI,ESCTAB + REPNE + SCAB + POP DI + MOV BP,CX + SHL BP + SEG CS ;To work in init + 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 + SEG CS + MOV AL,[STARTPOS] + CALL TAB + 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 + DOWN + 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 + UP + 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 OUT + MOV AL,8 + JMP OUT + +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: + MOV AH,0 ;Turn off insert mode when copying + CMP DH,DL + JZ GETCH2 + CMP BH,BL + JZ GETCH2 + LODB + STOB + CALL BUFOUT + 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 + +TOGGLINS: + NOT AH + JMP GETCH + +CTRLZ: + MOV AL,1AH + JMP SAVCH + +ESCFUNC: + DW GETCH + DW TWOESC + DW TOGGLINS + DW BACKSP + DW REEDIT + DW CTRLZ + DW COPYLIN + DW SKIPSTR + DW COPYSTR + DW SKIPONE + DW COPYONE + DW COPYONE + +BUFOUT: + CMP AL," " + JAE OUT + CMP AL,9 + JZ OUT + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JP OUT + +CONOUT: ;System call 2 + MOV AL,DL +OUT: + CMP AL,20H + JB CTRLOUT + CMP AL,7FH + JZ OUTCH + SEG CS + INC B,[CARPOS] +OUTCH: + PUSH AX + CALL STATCHK + POP AX + CALL BIOSOUT,BIOSSEG + SEG CS + TEST B,[PFLAG],-1 + JZ RET + CALL BIOSPRINT,BIOSSEG + RET + +NOSTOP: + CMP AL,"P"-"@" + JZ INCHK + CMP AL,"C"-"@" + JZ INCHK + RET + +STATCHK: + CALL BIOSSTAT,BIOSSEG + JZ RET + CMP AL,'S'-'@' + JNZ NOSTOP + CALL BIOSIN,BIOSSEG ;Eat Ctrl-S character +INCHK: + CALL BIOSIN,BIOSSEG + CMP AL,'P'-'@' + JZ PRINTOGL + CMP AL,'C'-'@' + JNZ RET +; Ctrl-C handler. +; If function 9 or 10 was in progress, a backslash, CR, and LF are printed +; to show line is canceled. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has +; 1) the interrupt return address should the user CTRL-C handler wish to +; allow processing to continue; 2) the original interrupt return address +; to the code that performed the function call in the first place. If the +; user CTRL-C handler wishes to continue, it must leave all registers +; unchanged and IRET. The function that was interrupted will simply be +; repeated. + SEG CS + MOV AL,[FUNC] ;Get currently executing function + CMP AL,10 ;Check if buffered line input + JZ CANLIN + CMP AL,9 ;Check if buffered line output + JNZ RESTREG +CANLIN: + MOV AL,"\" ;Display cancel line symbol + CALL OUT + CALL CRLF +RESTREG: + DI ;Prepare to play with stack + SEG CS + MOV SS,[SSSAVE] + SEG CS + MOV SP,[SPSAVE] ;User stack now restored + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES ;User registers now restored + INT CONTC ;Execute user Ctrl-C handler + JMP COMMAND ;Repeat command otherwise + +PRINTOGL: + SEG CS + XOR B,[PFLAG],1 + XOR AL,AL ;Set zero flag--character not received + RET +CTRLOUT: + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JNZ OUTCHJ + SEG CS + MOV AL,[CARPOS] + OR AL,0F8H + NEG AL +TAB: + PUSH CX + MOV CL,AL + MOV CH,0 + JCXZ POPTAB +TABLP: + MOV AL," " + CALL OUT + LOOP TABLP +POPTAB: + POP CX + RET + +ZERPOS: + SEG CS + MOV B,[CARPOS],0 +OUTCHJ: JMP OUTCH + +BACKPOS: + SEG CS + DEC B,[CARPOS] + JMP OUTCH + + +CONSTAT: ;System call 11 + CALL BIOSSTAT,BIOSSEG + MOV AL,0 + JZ RET + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL IN + PUSH AX + CALL OUT + POP AX + RET + + +IN: ;Internal input routine + CALL INCHK + JZ IN + RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + CALL BIOSSTAT,BIOSSEG + MOV AL,0 + JZ RET +RAWINP: ;System call 7 + CALL BIOSIN,BIOSSEG + RET +RAWOUT: + CALL BIOSOUT,BIOSSEG + RET + +LIST: ;System call 5 + MOV AL,DL +LISTOUT: + PUSH AX + CALL STATCHK + POP AX + 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 + + +MAKEFCB: ;Interrupt call 41 + MOV DL,0 ;Flag--not ambiguous file name + OR AL,AL ;Scan off separators if not zero + JZ NOSCAN +SCAN: + CALL GETLET + JZ SCAN ;Get rid of leading separators (e.g., blanks) + DEC SI ;Point back to first non-separator +NOSCAN: + MOV AL,0 + CMP B,[SI],20H ;Check for termination character + JB HAVDRV + CMP B,[SI+1],":" ;Check for potential drive specifier + JNZ HAVDRV + CALL GETLET + SUB AL,"@" ;Convert drive letter to binary drive number + JBE BADDRV ;Valid drive numbers are 1-15 + SEG CS + CMP AL,[NUMDRV] + JBE OKDRV +BADDRV: + MOV DL,-1 +OKDRV: + INC SI ;Skip over colon +HAVDRV: + STOB ;Put drive specifier in first byte + MOV CX,8 + CALL GETWORD ;Get 8-letter file name + CMP B,[SI],"." + JNZ NODOT + INC SI ;Skip over dot if present +NODOT: + MOV CX,3 ;Get 3-letter extension + CALL GETWORD + SEG CS + LDS BX,[SPSAVE] + MOV [BX+SISAVE],SI + XOR AX,AX + STOW + STOW + MOV AL,DL + RET + +GETWORD: + CALL GETLET + JZ FILLNAM ;Exit if invalid character + CMP AL," " + JBE FILLNAM + CMP AL,"*" ;Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + DEC CX + REP + STOB ;Fill rest of word with "?" + INC CX +NOSTAR: + STOB + CMP AL,"?" + JNZ NOTQ + OR DL,1 ;Flag ambiguous file name +NOTQ: + LOOP GETWORD + INC SI ;Point to "termination" character +FILLNAM: + MOV AL," " + REP + STOB + DEC SI + RET + +GETLET: + LODB + AND AL,7FH + CMP AL,"a" + JB CHK + CMP AL,"z" + JA CHK + SUB AL,20H ;Convert to upper case +CHK: + CMP AL," " + JZ RET + CMP AL,"=" + JZ RET + CMP AL,"," + JZ RET + CMP AL,";" + JZ RET + CMP AL,"." + JZ RET + CMP AL,":" + JZ RET + CMP AL,'"' + JZ RET + CMP AL,"+" + JZ RET + CMP AL,"/" + JZ RET + CMP AL,"[" + JZ RET + CMP AL,"]" + JZ RET + CMP AL,9 ;Filter out TABs too + RET + + +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 + LDS SI,[SPSAVE] + MOV DS,[SI+CSSAVE] + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP + MOVW + +SETMEM: + +; Inputs: +; 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) +; AX,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,MAXDIF + JBE HAVDIF + MOV CX,MAXDIF +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 + + +SHFTDI7: + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + SHL DI + RET + +DATE16: + PUSH CX + PUSH DX + PUSH BX + CALL READTIME + POP BX + POP DX + POP CX + MOV AX,[MONTH] ;Fetch month and year + SHL AL ;Push month to left to make room for day + SHL AL + SHL AL + SHL AL + SHL AX + OR AL,[DAY] + RET + +READTIME: +;Gets tick count in CX:DX. Causes date rollover if new day has started +;since last call. Destroys AX, BX. + MOV AH,0 ;Request get time + INT 1AH ;Time-of-day interrupt + OR AL,AL ;See if day has changed + JZ RET + ADD AL,[DAY] + MOV [DAY],AL + MOV AH,AL + MOV AL,[MONTH] + MOV BX,DAYTAB-1 ;Table of days in each month + XLAT ;Get number of days in current month + SUB AH,AL ;Have we rolled into next month? + JBE RET + MOV [DAY],AH ;Yes-store day of new month + MOV AL,[MONTH] + INC AL + MOV [MONTH],AL + CMP AL,12 ;Have we rolled into next year? + JBE RET + MOV B,[MONTH],1 ;Set first month to January + MOV AL,[YEAR] + INC AL +SETYEAR: +;Set year with value in AL. Adjust length of February for this year. + MOV [YEAR],AL + AND AL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [DAYTAB+1],AL ;Store for February + RET + +DAYTAB: ;Days of each month + DB 31 ;January + DB 28 ;February--reset each time year changes + DB 31 ;March + DB 30 ;April + DB 31 ;May + DB 30 ;June + DB 31 ;July + DB 31 ;August + DB 30 ;September + DB 31 ;October + DB 30 ;November + DB 31 ;December + +GETDATE: ;Function call 42 + PUSH CS + POP DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] + MOV BX,[DAY] + LDS SI,[SPSAVE] ;Get pointer to user registers + MOV [SI+DXSAVE],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI+CXSAVE],AX ;CX=year + XOR AL,AL + RET + +SETDATE: ;Function call 43 + MOV AL,-1 ;Be ready to flag an error + SUB CX,1980 ;Fix bias in year + JC RET ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET + OR DH,DH + JZ RET + OR DL,DL + JZ RET ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET + PUSH CS + POP DS + CMP DH,2 ;Check for Feb.--needs special handling + JNE DAYCHK + CMP DL,29 + JA RET ;Max 29 days in Feb. + JB DAYOK ;If 28 or less, definitely OK + TEST CL,3 ;Check for leap year + JZ DAYOK ;If it is, 29 days OK + RET ;Error if it's not +DAYCHK: + MOV AL,DH + MOV BX,DAYTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + JB RET ;Error if too many days +DAYOK: + PUSH DX + PUSH CX + MOV AH,0 + INT 1AH ;Read time to clear day overflow + POP AX ;Year + CALL SETYEAR + POP [DAY] ;Set both day and month + XOR AL,AL ;Flag OK + RET + +;*************************************** +; Time Functions +; +; Uses clock with 1,193,180/65536 ticks per second. User sees only +; time in hours, minutes, seconds, and 1/100 second, in registers +; CH, CL, DH, DL respectively. (Each is a binary number.) To +; convert, ticks are multiplied by (5 * 2**16)/59659, which is the +; reciprocal of the tick rate. To convert the other way, 1/100 secs +; is multiplied by 59659/(5 * 2**16). + +GETTIME: ;Function call 44 + PUSH CS + POP DS + CALL READTIME ;Get tick count in CX:DX +;First multiply by 5 + MOV AX,CX + MOV BX,DX + SHL DX + RCL CX ;Times 2 + SHL DX + RCL CX ;Times 4 + ADD DX,BX + ADC AX,CX ;Times 5 + XCHG AX,DX + MOV CX,59659 + DIV AX,CX + MOV BX,AX ;Save quotient + XOR AX,AX ;Extend precision + DIV AX,CX +;Rounding based on the remainder may be added here +;The result in BX:AX is time in 1/100 second. + MOV DX,BX + MOV CX,200 ;Extract 1/100's +;Division by 200 is necessary to ensure no overflow--max result +;is number of seconds in a day/2 = 43200. + DIV AX,CX + CMP DL,100 ;Remainder over 100? + JB NOADJ + SUB DL,100 ;Keep 1/100's less than 100 +NOADJ: + CMC ;If we subtracted 100, carry is now set + MOV BL,DL ;Save 1/100's +;To compensate for dividing by 200 instead of 100, we now multiply +;by two, shifting a one in if the remainder had exceeded 100. + RCL AX + MOV DL,0 + RCL DX + MOV CX,60 ;Divide out seconds + DIV AX,CX + MOV BH,DL ;Save the seconds + DIV AL,CL ;Break into hours and minutes + XCHG AL,AH +;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) + LDS SI,[SPSAVE] ;Get pointer to user registers + MOV [SI+DXSAVE],BX + MOV [SI+CXSAVE],AX + XOR AL,AL + RET + +SETTIME: ;Function call 45 +;Time is in CX:DX in hours, minutes, seconds, 1/100 sec + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET + CMP CL,60 ;Check minutes + JAE RET + CMP DH,60 ;Check seconds + JAE RET + CMP DL,100 ;Check 1/100's + JAE RET + MOV AL,60 + MUL AL,CH ;Hours to minutes + MOV CH,0 + ADD AX,CX ;Total minutes + MOV CX,6000 ;60*100 + MOV BX,DX ;Get out of the way of the multiply + MUL AX,CX ;Convert to 1/100 sec + MOV CX,AX + MOV AL,100 + MUL AL,BH ;Convert seconds to 1/100 sec + ADD CX,AX ;Combine seconds with hours and min. + ADC DX,0 ;Ripple carry + MOV BH,0 + ADD CX,BX ;Combine 1/100 sec + ADC DX,0 +;DX:CX is time in 1/100 sec + XCHG AX,DX + XCHG AX,CX ;Now time is in CX:AX + MOV BX,59659 + MUL AX,BX ;Multiply low half + XCHG DX,CX + XCHG AX,DX ;CX->AX, AX->DX, DX->CX + MUL AX,BX ;Multiply high half + ADD AX,CX ;Combine overlapping products + ADC DX,0 + XCHG AX,DX ;AX:DX=time*59659 + MOV BX,5 + DIV AL,BL ;Divide high half by 5 + MOV CL,AL + MOV CH,0 + MOV AL,AH ;Remainder of divide-by-5 + CBW + XCHG AX,DX ;Use it to extend low half + DIV AX,BX ;Divde low half by 5 + MOV DX,AX +;CX:DX now has time in ticks + MOV AH,1 + INT 1AH ;Set clock + XOR AL,AL ;Return no error + RET + +;***** DATA AREA ***** + +;Device number mapping +;0,1 = CON, AUX (Bidirectional devices) +;2,3 = Printer, bit bucket (output only) + +IONAME: DB "PRN ","LPT1","AUX ","COM1","CON ","NUL " +IONUM: DB 3,0,1,1,2,2 + +CARPOS: DB 0 +INSFLG: DB 0 +STARTPOS:DB 0 +PFLAG: DB 0 +DAY: DB 0 +MONTH: DB 0 +YEAR: DW 0 +DIRTYDIR:DB 0 ;Dirty buffer flag +NUMDRV: DS 1 ;Number of drives +CONTPOS:DW 0 +DMAADD: DW 80H ;User's disk transfer address (disp/seg) + DS 2 +ENDMEM: DS 2 +MAXSEC: DW 0 +BUFFER: DS 2 +BUFSECNO:DW 0 +BUFDRVNO:DB -1 +DIRTYBUF:DB 0 +BUFDRVBP:DS 2 +DIRBUFID:DW -1 +CURDRVPT:DS 2 +DRVTAB: DS 30 ;Enough for 15 drives +INBUF: DS 15 ;Only the first part + +; Init code overlaps with data area below + +INITCODE: + + DS 128-15 ;More of INBUF +CONBUF: DS 130 ;The rest of INBUF and console buffer +FUNC: DS 1 ;Currently executing function code +LASTENT:DS 2 +EXITHOLD:DS 4 +FATBASE:DS 2 +NAME1: DS 11 ;File name buffer +ATTRIB: DS 1 ;Search attributes +NAME2: DS 11 +NAME3: DS 12 +EXTFCB: DS 1 +CREATING:DS 1 +TEMP: +SPSAVE: DS 2 +SSSAVE: DS 2 +CONTSTK:DS 2 +SECCLUSPOS:DS 1 ;Position of first sector within cluster +DSKERR: DS 1 +TRANS: DS 1 +PREREAD:DS 1 ;0 means must preread; 1 means optional +READOP: DS 1 + + ALIGN +FCB: DS 2 ;Address of user FCB +NEXTADD:DS 2 +RECPOS: DS 4 +RECCNT: DS 2 +LASTPOS:DS 2 +CLUSNUM:DS 2 +SECPOS: DS 2 ;Position of first sector accessed +VALSEC: DS 2 ;Number of valid (previously written) sectors +BYTSECPOS:DS 2 ;Position of first byte within sector +BYTPOS: DS 4 ;Byte position in file of access +BYTCNT1:DS 2 ;No. of bytes in first sector +BYTCNT2:DS 2 ;No. of bytes in last sector +SECCNT: DS 2 ;No. of whole sectors + + DS 100H ;Stack space +IOSTACK: + DS 100H +DSKSTACK: + + IF DSKTEST +NSS: DS 2 +NSP: DS 2 + ENDIF + +DIRBUF: + +;Init code below overlaps with data area above + + ORG INITCODE + PUT $+100H + +MOVFAT: +;This section of code is safe from being overwritten by block move + SEG ES + REP + MOVB + UP +FININIT: + CALL SETMEM ;Set up segment + RET L + +DOSINIT: + DI + UP + PUSH CS + POP ES + LODB + SEG ES + MOV [NUMDRV],AL + MOV BX,DRVTAB + MOV DI,MEMSTRT +PERDRV: + SEG ES + MOV [BX],DI + MOV BP,DI + INC BX + INC BX + SEG ES + MOV AL,[DRVCNT] + STOB ;DRVNUM + LODW ;Pointer to DPT + PUSH SI + MOV SI,AX + LODW + STOW ;SECSIZ + MOV DX,AX + SEG ES + CMP AX,[MAXSEC] + JBE NOTMAX + SEG ES + MOV [MAXSEC],AX +NOTMAX: + LODB + DEC AL + STOB ;CLUSMSK + JZ HAVSHFT + CBW +FIGSHFT: + INC AH + SAR AL + JNZ FIGSHFT + MOV AL,AH +HAVSHFT: + STOB ;CLUSSHFT + MOVW ;FIRFAT (= number of reserved sectors) + MOVB ;FATCNT + MOVW ;MAXENT + MOV AX,DX ;SECSIZ again + MOV CL,5 + SHR AX,CL + MOV CX,AX ;Directory entries per sector + DEC AX + SEG ES + ADD AX,[BP+MAXENT] + XOR DX,DX + DIV AX,CX + STOW ;DIRSEC (temporarily) + SHR AX ;Divide by two + ADC AX,0 ;Round up + SEG ES + MOV [SDIRSEC],AX ;Number of directory records for small entries + MOVW ;DSKSIZ (temporarily) +FNDFATSIZ: + MOV AL,1 + MOV DX,1 +GETFATSIZ: + PUSH DX + CALL FIGFATSIZ + POP DX + CMP AL,DL ;Compare newly computed FAT size with trial + JZ HAVFATSIZ ;Has sequence converged? + CMP AL,DH ;Compare with previous trial + MOV DH,DL + MOV DL,AL ;Shuffle trials + JNZ GETFATSIZ ;Continue iterations if not oscillating + SEG ES + DEC [BP+DSKSIZ] ;Damp those oscillations + JP FNDFATSIZ ;Try again +HAVFATSIZ: + STOB ;FATSIZ + SEG ES + MUL AL,[BP+FATCNT] ;Space occupied by all FATs + SEG ES + ADD AX,[BP+FIRFAT] + STOW ;FIRDIR + + IF SMALLDIR-1 + SEG ES + ADD AX,[BP+DIRSEC] + SEG ES + MOV [BP+FIRREC],AX ;Destroys DIRSEC + CALL FIGMAX + SEG ES + MOV [BP+MAXCLUS],CX + ENDIF + + IF SMALLDIR + MOV DX,AX ;Save FIRDIR momentarily + SEG ES + ADD AX,[SDIRSEC] ;Add number of dir. sectors for 16-byte entry + STOW ;FIRREC1 + XCHG AX,CX ;Previously computed MAXCLUS + STOW ;MAXCLUS1 + XCHG DX,AX + SEG ES + ADD AX,[BP+DIRSEC] ;Add number of dir. sectors for 32-byte entry + STOW ;FIRREC2 + CALL FIGMAX + XCHG AX,CX + STOW ;MAXCLUS2 + ENDIF + + MOV AX,0FFH + STOB ;DIRTYFAT + SEG ES + MOV AL,[BP+FATSIZ] + SEG ES + MUL AX,[BP+SECSIZ] + ADD DI,AX ;Allocate FAT + POP SI ;Restore pointer to init. table + SEG ES + MOV AL,[DRVCNT] + INC AL + SEG ES + MOV [DRVCNT],AL + SEG ES + CMP AL,[NUMDRV] + JAE CONTINIT + JMP PERDRV +CONTINIT: + LODW ;Max. buffer size + SEG ES + MOV BX,[MAXSEC] + MOV AX,DIRBUF + ADD AX,BX + SEG ES + MOV [BUFFER],AX ;Start of buffer + PUSH DI ;Save ending location + ADD DI,BX ;Allocate directory buffer + ADD DI,BX ;Allocate buffer space + ADD DI,ADJFAC+15 ;True start of free space + MOV CL,4 + SHR DI,CL ;First free segment + MOV BP,DI + 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 [ENTRYPOINT+1],ENTRY + MOV [ENTRYPOINT+3],AX + MOV CX,9 + REP + STOW ;Set 5 segments (skip 2 between each) + MOV [INTBASE+4],COMMAND + MOV [INTBASE+12],IRET ;CTRL-C exit + MOV [INTBASE+16],IRET ;Fatal error exit + MOV AX,BIOSREAD + STOW + MOV AX,BIOSSEG + STOW + STOW ;Add 2 to DI + STOW + MOV [INTBASE+18H],BIOSWRITE + MOV DX,CS + MOV DS,DX + ADD DX,BP + MOV [DMAADD],80H + MOV [DMAADD+2],DX + MOV AX,[DRVTAB] + MOV [CURDRVPT],AX + INT 12H ;Get memory size--1K blocks in AX + MOV CL,6 + SHL AX,CL ;Convert to 16-byte blocks (segment no.) + SEG CS + MOV [ENDMEM],AX + XOR CX,CX + MOV DS,CX + MOV [EXIT],100H + MOV [EXIT+2],DX + PUSH CS + POP DS + PUSH CS + POP ES + MOV [ENDDOS],DX +;Move FATs into position. Segment of COMMAND still in DX. + POP SI + MOV AX,[MAXSEC] + SHL AX ;Allocate two buffers + ADD AX,ADJFAC + JZ FINJMP + MOV DI,DRVTAB + MOV CX,15 +ADJLP: + ADD [DI],AX + INC DI + INC DI + LOOP ADJLP + MOV CX,SI + MOV SI,MEMSTRT ;Place to move FATs from + SUB CX,SI ;Total length of FATs + MOV DI,AX + ADD DI,SI ;Place to move FATs to + OR AX,AX + JS MOVJMP + DEC CX + ADD DI,CX + ADD SI,CX + INC CX + DOWN +MOVJMP: + JMP MOVFAT +FINJMP: JMP FININIT + +FIGFATSIZ: + SEG ES + MUL AL,[BP+FATCNT] + SEG ES + ADD AX,[BP+FIRFAT] + SEG ES + ADD AX,[SDIRSEC] ;Use small dir. entry to figure FAT size +FIGMAX: +;AX has equivalent of FIRREC + SEG ES + SUB AX,[BP+DSKSIZ] + NEG AX + SEG ES + MOV CL,[BP+CLUSSHFT] + SHR AX,CL + INC AX + MOV CX,AX ;MAXCLUS + INC AX + MOV DX,AX + SHR DX + ADC AX,DX ;Size of FAT in bytes + SEG ES + MOV SI,[BP+SECSIZ] + ADD AX,SI + DEC AX + XOR DX,DX + DIV AX,SI + RET + +DRVCNT: DB 0 +SDIRSEC:DS 1 + +MEMSTRT: +ADJFAC: EQU DIRBUF-MEMSTRT + + DS EXCESS + DB 0 + \ No newline at end of file diff --git a/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-06-15.ASM b/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-06-15.ASM new file mode 100644 index 0000000..3ae688d --- /dev/null +++ b/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-06-15.ASM @@ -0,0 +1,560 @@ +; CHKDSK Version 1.0 03/10/81 + +; Verifies and repairs 86-DOS disk directory. + +SETDRV: EQU 14 +GETDRV: EQU 25 +GETMAP: EQU 27 +OPEN: EQU 15 +CLOSE: EQU 16 +DELETE: EQU 19 +SETDMA: EQU 26 +SRCHFST:EQU 17 +SRCHNXT:EQU 18 +OUTCH: EQU 2 +BLKWRT: EQU 40 +PRINTBUF:EQU 9 + + ORG 100H + PUT 100H + +CHKDSK: + MOV SP,STACK + MOV AH,GETDRV + INT 21H + MOV [CURDRV],AL + MOV DL,[5CH] + OR DL,DL + JZ DRVSET + MOV AH,SETDRV + DEC DL + INT 21H + CMP AL,DL + JA DRVSET + MOV DX,BADDRV +ERROR: + MOV AH,PRINTBUF + INT 33 + INT 32 + +BADDSK: + MOV AX,CS + MOV DS,AX + MOV AH,SETDRV + MOV DL,[CURDRV] + INT 33 + MOV DX,DIRBAD + JP ERROR +DRVSET: + MOV B,[WRKDRV],DL ;Save drive indicator + MOV AH,GETMAP + INT 21H + CMP B,[BX],0FEH ;Check for initialized disk + JNE BADDSK + PUSH DS + PUSH ES + POP DS + MOV [DSKSIZ],DX ;Number of allocation units + MOV [SECSIZ],CX ;Size of physical sector + MOV AH,0 + MOV [CLUSSIZ],AX ;Sectors per cluster + MOV CX,DX + MOV DI,MAP + XOR AX,AX + REP + STOW ;Zero out allocation map + MOV CX,AX + MOV [ALLOC],AX ;Count of allocation units used + MOV [FILECNT],AX ;Number of files found + MOV [DELCNT],AX ;Number of files deleted due to error + MOV BP,DI + MOV [NAMTAB],BP ;First address of file list + MOV DX,DI + MOV AH,SETDMA + INT 21H + MOV AH,SRCHFST + MOV DX,ALLFILE + INT 21H + INC AL + POP ES ;ES:BX point to FAT + JNZ GETFILES + JMP COMPMAP +GETFILES: + INC CX ;Count number of files + ADD DI,44 ;Separate in file in list by 44 bytes + MOV DX,DI + MOV AH,SETDMA + INT 21H + MOV AH,SRCHNXT + MOV DX,ALLFILE + INT 21H + INC AL + JNZ GETFILES ;Loop until all files are in list + MOV [FILECNT],CX + MOV CX,1 ;File number (position in list) + MOV DX,[DSKSIZ] + INC DX ;Maximum cluster number + MOV [MAXCLUS],DX + ADD BP,34 ;Point to "first cluster" entry +EACHFIL: + XOR AX,AX ;No. of clusters in file + MOV SI,[BP] ;First cluster of file + CMP SI,[MAXCLUS] ;Make sure it's legal + MOV DI,BADDIR + JA BADFIRST + OR SI,SI ;Check for zero-length file + JZ HAVENDJ +SCANFAT: + MOV DI,CX + SHL SI + XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. + SHR SI + OR DI,DI ;Should be zero for unallocated cluster + JNZ CROSSLINK + INC AX ;Count cluster as part of this file + CALL UNPACK + JZ FORCEND ;Make sure cluster knows it's allocated + CMP DI,0FF8H ;Bigger than this means End of File +HAVENDJ:JAE HAVEND + CMP DI,[MAXCLUS] ;Make sure it's a legal value + JA FORCEND + MOV SI,DI + JP SCANFAT ;Visit each cluster allocated to file + +BADFIRST: + PUSH AX ;Because FILERR will pop it later + MOV AX,CX + MOV DX,44 + DEC AX + MUL AX,DX ;Get position in file name table + MOV DX,AX + ADD DX,[NAMTAB] + MOV AH,DELETE + INT 21H + OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY + JZ DISKOK + JMP BADDSK +DISKOK: + INC [DELCNT] ;Count one deleted file + MOV DX,BADDIR + JP FILERR + +CROSSLINK: + MOV DX,LINKED + PUSH AX + MOV AH,PRINTBUF + INT 21H + MOV AX,DI + CALL PRINTNAM + MOV DX,FILE2 + MOV AH,PRINTBUF + INT 33 + MOV AX,CX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 33 + POP AX + ADD [ALLOC],AX + JMP SIZSET1 + +FORCEND: +; Come here if a cluster allocated to a file contained an illegal +; link--either a zero (meaning unallocated), or a value larger than +; the maximum cluster number, but not End of File. Put an End of File +; mark there so the FAT will at least be well-formed. + MOV DX,0FFFH + CALL PACK + MOV DX,BADCLUS + PUSH AX + +FILERR: + MOV AH,PRINTBUF + INT 21H + MOV AX,CX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 21H + POP AX + +HAVEND: + ADD [ALLOC],AX ;Total up allocated clusters + MOV SI,AX + MOV AX,[BP+2] + MOV DX,[BP+4] ;AX:DX now have file length + PUSH CX + MOV CX,[CLUSSIZ] + DEC CX + ADD AX,CX + ADC DX,0 + INC CX +SCALE: + SHR CX + JC SCALED + SHR DX + RCR AX + JP SCALE +SCALED: + DIV AX,[SECSIZ] + OR DX,DX + JZ HAVSIZ + INC AX +HAVSIZ: + CMP AX,SI ;See if file size corresponds with allocation + JZ SIZSET + XOR DI,DI + MOV CX,[CLUSSIZ] + CALL UNSCALE + MOV [BP+6],SI + MOV [BP+8],DI + MOV DX,BP + SUB DX,34 + MOV AH,OPEN + INT 21H + OR AL,AL + JZ DISKOK2 + JMP BADDSK +DISKOK2: + MOV AX,[SECSIZ] + MOV [BP-27+14],AX ;Make record size=sector size + MOV CX,0 + MOV AH,BLKWRT + INT 21H + MOV AH,CLOSE ;Write back corrected directory entry + INT 21H + MOV AH,GETMAP + PUSH DS + INT 33 ;Make sure FAT dirty bit is still set + POP DS + MOV DX,BADSIZ + MOV AH,PRINTBUF + INT 21H + POP AX + PUSH AX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 21H +SIZSET: + POP CX +SIZSET1: + ADD BP,44 ;Scan next file + INC CX + CMP CX,[FILECNT] + JA COMPMAP + JMP EACHFIL +; Now compare the allocation map we have made with the FAT. Any +; clusters not allocated in the map will be released. +COMPMAP: + XOR AX,AX ;Keep count of clusters released + MOV BP,MAP + MOV SI,2 ;First usable cluster number + MOV CX,[DSKSIZ] +RELCLUS: + TEST [BP],-1 ;Allocated in our map? + JNZ NXTCLUS ;If so, skip to next + CALL UNPACK + JZ NXTCLUS ;If not allocated, skip to next + XOR DX,DX + CALL PACK ;Change to "Free" status + INC AX ;Count clusters released +NXTCLUS: + INC BP + INC BP + INC SI + LOOP RELCLUS + OR AX,AX ;Any clusters released? + JZ REPORT ;If not, do final report + MOV BX,FREED + CALL DISPCLUS +REPORT: +; Make status report. Include no. of files, total disk space, +; free space on disk, total memory, and free memory. + SEG CS + MOV DL,[CURDRV] + MOV AH,SETDRV + INT 21H + MOV SI,[FILECNT] + SUB SI,[DELCNT] + XOR DI,DI + MOV BX,NUMFIL + CALL DISP32BITS + MOV AX,[DSKSIZ] + MOV BX,DSKSPC + CALL DISPCLUS + MOV AX,[DSKSIZ] + SUB AX,[ALLOC] + MOV BX,FRESPC + CALL DISPCLUS + MOV AX,[2] + MOV DX,16 + MUL AX,DX + MOV SI,AX + MOV DI,DX + MOV BX,TOTMEM + CALL DISP32BITS + MOV AX,[2] + MOV DX,CS + SUB AX,DX + MOV DX,16 + MUL AX,DX + MOV SI,AX + MOV DI,DX + MOV BX,FREMEM + CALL DISP32BITS + CALL WRTFRC ;Force all writes and handle write + ;protect violation + INT 20H ;All done + +WRTFRC: ;******************************************************** + ; This code forces all writes by performing a disk + ; reset (function 13). When the attempt to write + ; the allocation table fails in the case of a write- + ; protected diskette, this logic determines if the + ; allocation table had changed and if no changes were + ; made a normal termination will be forced + ;********************************************************* + MOV AX,DS + PUSH DS ;Must first intercept INT 24H + MOV ES,AX + XOR AX,AX + MOV DS,AX + MOV SI,90H + MOV DI,INT24 ;will move vector to local address + MOV CX,2 + CLD ;So move will increment + REP + MOVW ;Vector now locally stored + MOV AL,24H ; + MOV AH,37 + MOV DX,WRTPRT ; + POP DS ;Get local segment + INT 21H ;Interrupt vector now set + MOV AH,13 + INT 21H + PUSH ES ;Will now reset INT 24H vector + XOR AX,AX + MOV ES,AX + CLD + MOV DI,90H + MOV SI,INT24 + MOV CX,2 + REP + MOVW + POP ES + RET + +WRTPRT: ;********************************************************* + ; This logic is designed to handle the case where + ; CHKDSK found no problems and upon rewriting the + ; allocation table (by the DOS) the disk was write- + ; protected and an error thus occured. With no problems + ; this code will cause normal termination, otherwise + ; normal error handling will occur. + ;********************************************************* + EI ;Run with interrupts live + AND DI,0FFH ;See if write-protect + JNZ WRT100 ;Do normal error handling + CMP AH,3 ;File allocation write? + JNZ WRT100 ;If not do normal handling + SEG CS + CMP [WRKDRV],AL ;Correct drive? + JNZ WRT100 ; + SEG CS + CMP B,[CHGCLS],1 ;Legitimate change? + JZ WRT100 ;If so do normal handling + XOR AL,AL ;Ignore the error + IRET +WRT100: SEG CS + JMP L,[INT24] ;Normal error handling + + + +UNPACK: + MOV DI,SI + SHR DI + ADD DI,SI + SEG ES + MOV DI,[DI+BX] + TEST SI,1 + JZ HAVCLUS + SHR DI + SHR DI + SHR DI + SHR DI +HAVCLUS: + AND DI,0FFFH + RET + +PACK: +;************************************************************* +; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +; SI CLUSTER NUMBER TO BE PACKED +; DX POINTER TO BE PLACED IN CLUSTER (SI) +;************************************************************* + MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED + PUSH SI + MOV DI,SI + SHR SI + ADD SI,BX + ADD SI,DI + SHR DI + SEG ES + MOV DI,[SI] + JNC ALIGNED + SHL DX + SHL DX + SHL DX + SHL DX + AND DI,0FH + JP PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + SEG ES + MOV [SI],DI + POP SI + RET + +UNSCALE: + SHR CX + JC RET + SHL SI + RCL DI + JP UNSCALE + +DISPCLUS: + MUL AX,[SECSIZ] + MOV CX,[CLUSSIZ] + MOV SI,AX + MOV DI,DX + CALL UNSCALE +DISP32BITS: + PUSH BX + XOR AX,AX + MOV BX,AX + MOV BP,AX + MOV CX,32 +CONVLP: + SHL SI + RCL DI + XCHG AX,BP + CALL CONVWRD + XCHG AX,BP + XCHG AX,BX + CALL CONVWRD + XCHG AX,BX + ADC AL,0 + LOOP CONVLP +; Conversion complete. Print 10-digit number with 2 leading blanks. + MOV CX,1B10H + CALL OUTWORD + MOV AX,BX + CALL OUTWORD + MOV AX,BP + CALL OUTWORD + POP DX + MOV AH,PRINTBUF + INT 21H + RET + +OUTWORD: + PUSH AX + MOV DL,AH + CALL OUTBYTE + POP DX +OUTBYTE: + MOV DH,DL + SHR DL + SHR DL + SHR DL + SHR DL + CALL DIGIT + MOV DL,DH +DIGIT: + AND DL,0FH + JZ BLANKZER + MOV CL,0 +BLANKZER: + DEC CH + AND CL,CH + OR DL,30H + SUB DL,CL + MOV AH,OUTCH + INT 21H + RET + +CONVWRD: + ADC AL,AL + DAA + XCHG AL,AH + ADC AL,AL + DAA + XCHG AL,AH + RET + +PRINTNAM: + PUSH CX + DEC AX + MOV CX,44 + MUL AX,CX + MOV SI,AX + ADD SI,[NAMTAB] + ADD SI,8 + MOV CX,8 + MOV AH,OUTCH + CALL PRINTCNT + MOV DL," " + INT 21H + MOV CL,3 + CALL PRINTCNT + POP CX + RET + +PRINTCNT: + LODB + MOV DL,AL + INT 21H + LOOP PRINTCNT + RET + +ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB + DB 0,"???????????" + DS 25 + +FILE2: DB " and $" +BADDRV: DB "Invalid drive specification$" +BADCLUS:DB "Allocation error for file $" +BADDIR: DB "Directory error-file : $" +LINKED: DB "Files cross-linked: " + DB 13,10 + DB " $" +BADSIZ: DB "File size error for file $" +DIRBAD: DB "Diskette not initialized $" +FREED: DB " bytes disk space freed",13,10,13,10,"$" +NUMFIL: DB " disk files",13,10,"$" +DSKSPC: DB " bytes total disk space",13,10,"$" +FRESPC: DB " bytes remain available",13,10,13,10,"$" +TOTMEM: DB " bytes total memory",13,10,"$" +FREMEM: DB " bytes free" +CRLF: DB 13,10,"$" + +DSKSIZ: DS 2 +SECSIZ: DS 2 +CLUSSIZ:DS 2 +CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +WRKDRV: DB 0 +INT24: DS 4 +FILECNT:DS 2 +NAMTAB: DS 2 +ALLOC: DS 2 +MAXCLUS:DS 2 +DELCNT: DS 2 +CURDRV: DS 1 + DS 100H +STACK: + +MAP: + \ No newline at end of file diff --git a/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-07-15.ASM b/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-07-15.ASM new file mode 100644 index 0000000..d5c94cb --- /dev/null +++ b/3_source_code/PC-DOS_1.00_dev/CHKDSK_1981-07-15.ASM @@ -0,0 +1,611 @@ +; CHKDSK Version 1.0 03/10/81 + +; Verifies and repairs 86-DOS disk directory. + +SETDRV: EQU 14 +GETDRV: EQU 25 +GETMAP: EQU 27 +OPEN: EQU 15 +CLOSE: EQU 16 +DELETE: EQU 19 +SETDMA: EQU 26 +SRCHFST:EQU 17 +SRCHNXT:EQU 18 +OUTCH: EQU 2 +BLKWRT: EQU 40 +PRINTBUF:EQU 9 + + ORG 100H + PUT 100H + +CHKDSK: + MOV SP,STACK + OR AL,AL ;SEE IF INVALID DRIVE SPECIFIED + JNZ DRVERR ;IF SO JUST EXIT + CMP B,[5DH],20H ;MAKE SURE TYPED CORRECTLY + JNZ PRMERR ;IF NOT PARAMETER ERROR + MOV AH,GETDRV + INT 21H + MOV [CURDRV],AL + MOV DL,[5CH] + OR DL,DL + JZ DRVMOV + MOV AH,SETDRV + DEC DL + INT 21H + CMP AL,DL + JA DRVSET +DRVERR: MOV DX,BADDRV +ERROR: + MOV AH,PRINTBUF + INT 33 + INT 32 + +PRMERR: MOV DX,INVPRM ;Invalid parameter + JP ERROR +BADDSK: + MOV AX,CS + MOV DS,AX + MOV AH,SETDRV + MOV DL,[CURDRV] + INT 33 + MOV DX,DIRBAD + JP ERROR +DRVMOV: MOV DL,AL ;Correct drive designator +DRVSET: + MOV B,[WRKDRV],DL ;Save drive indicator + INC DL ;FOR FCB SET + MOV B,[ALLDRV],DL ;FCB ok now + DEC DL + CALL DRVXCG ;Change drives and do map read + CMP B,[BX],0FEH ;Check for initialized disk + JNE BADDSK + PUSH DS + PUSH ES + POP DS + MOV [DSKSIZ],DX ;Number of allocation units + MOV [SECSIZ],CX ;Size of physical sector + MOV AH,0 + MOV [CLUSSIZ],AX ;Sectors per cluster + MOV CX,DX + MOV DI,MAP + XOR AX,AX + REP + STOW ;Zero out allocation map + MOV CX,AX + MOV [ALLOC],AX ;Count of allocation units used + MOV [FILECNT],AX ;Number of files found + MOV [DELCNT],AX ;Number of files deleted due to error + MOV BP,DI + MOV [NAMTAB],BP ;First address of file list + MOV DX,DI + MOV AH,SETDMA + INT 21H + MOV AH,SRCHFST + MOV DX,ALLFILE + INT 21H + INC AL + POP ES ;ES:BX point to FAT + JNZ GETFILES + JMP COMPMAP +GETFILES: + INC CX ;Count number of files + ADD DI,44 ;Separate in file in list by 44 bytes + MOV DX,DI + MOV AH,SETDMA + INT 21H + MOV AH,SRCHNXT + MOV DX,ALLFILE + INT 21H + INC AL + JNZ GETFILES ;Loop until all files are in list + MOV [FILECNT],CX + MOV CX,1 ;File number (position in list) + MOV DX,[DSKSIZ] + INC DX ;Maximum cluster number + MOV [MAXCLUS],DX + ADD BP,34 ;Point to "first cluster" entry +EACHFIL: + XOR AX,AX ;No. of clusters in file + MOV SI,[BP] ;First cluster of file + CMP SI,[MAXCLUS] ;Make sure it's legal + MOV DI,BADDIR + JA BADFIRST + OR SI,SI ;Check for zero-length file + JZ HAVENDJ +SCANFAT: + MOV DI,CX + SHL SI + XCHG DI,[SI+MAP-4] ;Xchange current map entry with file no. + SHR SI + OR DI,DI ;Should be zero for unallocated cluster + JNZ CROSSLINK + INC AX ;Count cluster as part of this file + CALL UNPACK + JZ FORCEND ;Make sure cluster knows it's allocated + CMP DI,0FF8H ;Bigger than this means End of File +HAVENDJ:JAE HAVEND + CMP DI,[MAXCLUS] ;Make sure it's a legal value + JA FORCEND + MOV SI,DI + JP SCANFAT ;Visit each cluster allocated to file + +BADFIRST: + PUSH AX ;Because FILERR will pop it later + MOV [BP+2],AX ;AX is zero + MOV [BP+4],AX ;Set size to zero so we won't change it + MOV AX,CX + MOV DX,44 + DEC AX + MUL AX,DX ;Get position in file name table + MOV DX,AX + ADD DX,[NAMTAB] + MOV AH,DELETE + INT 21H + PUSH DS + PUSH CX + PUSH AX + CALL DRVXCG ;Reset dirty bit to rewrite FAT + POP AX + POP CX + POP DS + OR AL,AL ;SEE IF WE HAVE A VALID DIRECTORY + JZ DISKOK + JMP BADDSK +DISKOK: + INC [DELCNT] ;Count one deleted file + MOV DX,BADDIR + JP FILERR + +CROSSLINK: + MOV DX,LINKED + PUSH AX + MOV AH,PRINTBUF + INT 21H + MOV AX,DI + CALL PRINTNAM + MOV DX,FILE2 + MOV AH,PRINTBUF + INT 33 + MOV AX,CX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 33 + POP AX + ADD [ALLOC],AX + JMP SIZSET1 + +FORCEND: +; Come here if a cluster allocated to a file contained an illegal +; link--either a zero (meaning unallocated), or a value larger than +; the maximum cluster number, but not End of File. Put an End of File +; mark there so the FAT will at least be well-formed. + MOV DX,0FFFH + CALL PACK + MOV DX,BADCLUS + PUSH AX + +FILERR: + MOV AH,PRINTBUF + INT 21H + MOV AX,CX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 21H + POP AX + +HAVEND: + ADD [ALLOC],AX ;Total up allocated clusters + MOV SI,AX + MOV AX,[BP+2] + MOV DX,[BP+4] ;AX:DX now have file length + PUSH CX + MOV CX,[CLUSSIZ] + DEC CX + ADD AX,CX + ADC DX,0 + INC CX +SCALE: + SHR CX + JC SCALED + SHR DX + RCR AX + JP SCALE +SCALED: + DIV AX,[SECSIZ] + OR DX,DX + JZ HAVSIZ + INC AX +HAVSIZ: + CMP AX,SI ;See if file size corresponds with allocation + JZ SIZSET + XOR DI,DI + MOV CX,[CLUSSIZ] + CALL UNSCALE + MOV [BP+6],SI + MOV [BP+8],DI + MOV DX,BP + SUB DX,34 + MOV AH,OPEN + INT 21H + OR AL,AL + JZ DISKOK2 + JMP BADDSK +DISKOK2: + MOV AX,[SECSIZ] + MOV [BP-27+14],AX ;Make record size=sector size + MOV CX,0 + MOV AH,BLKWRT + INT 21H + MOV AH,CLOSE ;Write back corrected directory entry + INT 21H + PUSH DS + CALL DRVXCG ;Change the drives and get the map + POP DS + MOV DX,BADSIZ + MOV AH,PRINTBUF + INT 21H + POP AX + PUSH AX + CALL PRINTNAM + MOV DX,CRLF + MOV AH,PRINTBUF + INT 21H +SIZSET: + POP CX +SIZSET1: + ADD BP,44 ;Scan next file + INC CX + CMP CX,[FILECNT] + JA COMPMAP + JMP EACHFIL +; Now compare the allocation map we have made with the FAT. Any +; clusters not allocated in the map will be released. +COMPMAP: + XOR AX,AX ;Keep count of clusters released + MOV BP,MAP + MOV SI,2 ;First usable cluster number + MOV CX,[DSKSIZ] +RELCLUS: + TEST [BP],-1 ;Allocated in our map? + JNZ NXTCLUS ;If so, skip to next + CALL UNPACK + JZ NXTCLUS ;If not allocated, skip to next + XOR DX,DX + CALL PACK ;Change to "Free" status + INC AX ;Count clusters released +NXTCLUS: + INC BP + INC BP + INC SI + LOOP RELCLUS + OR AX,AX ;Any clusters released? + JZ REPORT ;If not, do final report + MOV BX,FREED + CALL DISPCLUS +REPORT: +; Make status report. Include no. of files, total disk space, +; free space on disk, total memory, and free memory. + SEG CS + MOV DL,[CURDRV] + MOV AH,SETDRV + INT 21H + MOV SI,[FILECNT] + SUB SI,[DELCNT] + XOR DI,DI + MOV BX,NUMFIL + CALL DISP32BITS + MOV AX,[DSKSIZ] + MOV BX,DSKSPC + CALL DISPCLUS + MOV AX,[DSKSIZ] + SUB AX,[ALLOC] + MOV BX,FRESPC + CALL DISPCLUS + MOV AX,[2] + MOV DX,16 + MUL AX,DX + MOV SI,AX + MOV DI,DX + MOV BX,TOTMEM + CALL DISP32BITS + MOV AX,[2] + MOV DX,CS + SUB AX,DX + MOV DX,16 + MUL AX,DX + MOV SI,AX + MOV DI,DX + MOV BX,FREMEM + CALL DISP32BITS + CALL WRTFRC ;Force all writes and handle write + ;protect violation + SEG CS + MOV B,DL,[CURDRV] ;Get default + MOV AH,SETDRV ;And make it current again + INT 21H + INT 20H ;All done + +WRTFRC: ;******************************************************** + ; This code forces all writes by performing a disk + ; reset (function 13). When the attempt to write + ; the allocation table fails in the case of a write- + ; protected diskette, this logic determines if the + ; allocation table had changed and if no changes were + ; made a normal termination will be forced + ;********************************************************* + MOV AX,DS + PUSH DS ;Must first intercept INT 24H + MOV ES,AX + XOR AX,AX + MOV DS,AX + MOV SI,90H + MOV DI,INT24 ;will move vector to local address + MOV CX,2 + CLD ;So move will increment + REP + MOVW ;Vector now locally stored + MOV AL,24H ; + MOV AH,37 + MOV DX,WRTPRT ; + POP DS ;Get local segment + INT 21H ;Interrupt vector now set + MOV AH,13 + INT 21H + PUSH ES ;Will now reset INT 24H vector + XOR AX,AX + MOV ES,AX + CLD + MOV DI,90H + MOV SI,INT24 + MOV CX,2 + REP + MOVW + POP ES + RET + +WRTPRT: ;********************************************************* + ; This logic is designed to handle the case where + ; CHKDSK found no problems and upon rewriting the + ; allocation table (by the DOS) the disk was write- + ; protected and an error thus occured. With no problems + ; this code will cause normal termination, otherwise + ; normal error handling will occur. + ;********************************************************* + EI ;Run with interrupts live + AND DI,0FFH ;See if write-protect + JNZ WRT100 ;Do normal error handling + CMP AH,3 ;File allocation write? + JNZ WRT100 ;If not do normal handling + SEG CS + CMP [WRKDRV],AL ;Correct drive? + JNZ WRT100 ; + SEG CS + CMP B,[CHGCLS],1 ;Legitimate change? + JZ WRT100 ;If so do normal handling + XOR AL,AL ;Ignore the error + IRET +WRT100: SEG CS + MOV SI,AX ;Save AX + PUSH DX + MOV DL,[CURDRV] ;Fetch current drive + MOV AH,SETDRV + INT 33 ;Drive now ok + POP DX ;Restore DX + MOV AX,SI ;Restore AX + SEG CS + JMP L,[INT24] ;Do normal recovery + + +DRVXCG: + ;********************************************** + ; WILL CHANGE DEFAULT TO WRKDRV READ THE FAT + ; AND CHANGE THE DEFAULT BACK TO CURDRV + ;********************************************** + SEG CS + MOV DL,[WRKDRV] ;Will change the default to this + MOV AH,SETDRV + INT 33 ;Default now "WRKDRV" + MOV AH,GETMAP + INT 33 + PUSH DX + PUSH AX + SEG CS + MOV DL,[CURDRV] ;Get current drive + MOV AH,SETDRV + INT 33 + POP AX + POP DX + RET + + +UNPACK: + MOV DI,SI + SHR DI + ADD DI,SI + SEG ES + MOV DI,[DI+BX] + TEST SI,1 + JZ HAVCLUS + SHR DI + SHR DI + SHR DI + SHR DI +HAVCLUS: + AND DI,0FFFH + RET + +PACK: +;************************************************************* +; ES:BX POINTER TO THE BASE OF THE ALLOCATION TABLE +; SI CLUSTER NUMBER TO BE PACKED +; DX POINTER TO BE PLACED IN CLUSTER (SI) +;************************************************************* + MOV B,[CHGCLS],1 ;INDICATE CLUSTER CHANGED + PUSH SI + MOV DI,SI + SHR SI + ADD SI,BX + ADD SI,DI + SHR DI + SEG ES + MOV DI,[SI] + JNC ALIGNED + SHL DX + SHL DX + SHL DX + SHL DX + AND DI,0FH + JP PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + SEG ES + MOV [SI],DI + POP SI + RET + +UNSCALE: + SHR CX + JC RET + SHL SI + RCL DI + JP UNSCALE + +DISPCLUS: + MUL AX,[SECSIZ] + MOV CX,[CLUSSIZ] + MOV SI,AX + MOV DI,DX + CALL UNSCALE +DISP32BITS: + PUSH BX + XOR AX,AX + MOV BX,AX + MOV BP,AX + MOV CX,32 +CONVLP: + SHL SI + RCL DI + XCHG AX,BP + CALL CONVWRD + XCHG AX,BP + XCHG AX,BX + CALL CONVWRD + XCHG AX,BX + ADC AL,0 + LOOP CONVLP +; Conversion complete. Print 10-digit number with 2 leading blanks. + MOV CX,1B10H + CALL OUTWORD + MOV AX,BX + CALL OUTWORD + MOV AX,BP + CALL OUTWORD + POP DX + MOV AH,PRINTBUF + INT 21H + RET + +OUTWORD: + PUSH AX + MOV DL,AH + CALL OUTBYTE + POP DX +OUTBYTE: + MOV DH,DL + SHR DL + SHR DL + SHR DL + SHR DL + CALL DIGIT + MOV DL,DH +DIGIT: + AND DL,0FH + JZ BLANKZER + MOV CL,0 +BLANKZER: + DEC CH + AND CL,CH + OR DL,30H + SUB DL,CL + MOV AH,OUTCH + INT 21H + RET + +CONVWRD: + ADC AL,AL + DAA + XCHG AL,AH + ADC AL,AL + DAA + XCHG AL,AH + RET + +PRINTNAM: + PUSH CX + DEC AX + MOV CX,44 + MUL AX,CX + MOV SI,AX + ADD SI,[NAMTAB] + ADD SI,8 + MOV CX,8 + MOV AH,OUTCH + CALL PRINTCNT + MOV DL," " + INT 21H + MOV CL,3 + CALL PRINTCNT + POP CX + RET + +PRINTCNT: + LODB + MOV DL,AL + INT 21H + LOOP PRINTCNT + RET + +ALLFILE:DB -1,0,0,0,0,0,6 ;Extended FCB +ALLDRV: DB 0,"???????????" + DS 25 + +FILE2: DB " and $" +BADDRV: DB "Invalid drive specification$" +INVPRM: DB "Invalid parameter$" +BADCLUS:DB "Allocation error for file $" +BADDIR: DB "Directory error-file : $" +LINKED: DB "Files cross-linked: " + DB 13,10 + DB " $" +BADSIZ: DB "File size error for file $" +DIRBAD: DB "Diskette not initialized $" +FREED: DB " bytes disk space freed",13,10,13,10,"$" +NUMFIL: DB " disk files",13,10,"$" +DSKSPC: DB " bytes total disk space",13,10,"$" +FRESPC: DB " bytes remain available",13,10,13,10,"$" +TOTMEM: DB " bytes total memory",13,10,"$" +FREMEM: DB " bytes free" +CRLF: DB 13,10,"$" + +DSKSIZ: DS 2 +SECSIZ: DS 2 +CLUSSIZ:DS 2 +CHGCLS: DB 0 ;IF RESET TO 1-ALLOCATION TABLE UPDATED +WRKDRV: DB 0 +INT24: DS 4 +FILECNT:DS 2 +NAMTAB: DS 2 +ALLOC: DS 2 +MAXCLUS:DS 2 +DELCNT: DS 2 +CURDRV: DS 1 + DS 100H +STACK: + +MAP: + \ No newline at end of file diff --git a/3_source_code/SCP_ASM/ASM_2.40_dev.ASM b/3_source_code/SCP_ASM/ASM_2.40_dev.ASM new file mode 100644 index 0000000..14553bb --- /dev/null +++ b/3_source_code/SCP_ASM/ASM_2.40_dev.ASM @@ -0,0 +1,3714 @@ +; Seattle Computer Products 8086 Assembler version 2.31 +; by Tim Paterson +; Runs on the 8086 under 86-DOS + +;* * * * * * REVISION HISTORY * * * * * * +; +; 12/29/80 2.01 General release with 86-DOS version 0.34 +; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +; 03/18/81 2.11 General cleanup and more documentation +; 03/24/81 2.20 Modify ESC handling for full 8087 operation +; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +; 04/03/81 2.22 Fix 2.21 buffer handling +; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +; 04/28/81 2.24 Allow nested IFs +; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +; 08/02/81 2.30 Re-write pass 2: +; Always report errors to console +; Exact byte lengths for HEX and PRN files +; 08/23/81 2.40 Add 8087 mnemonics +; +;* * * * * * * * * * * * * * * * * * * * * + +SYMWID: EQU 10 +FCB: EQU 5CH +BUFSIZ: EQU 1024 ;Source code buffer +LSTBUFSIZ:EQU BUFSIZ ;List file buffer +HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +EOL: EQU 13 ;ASCII carriage return +OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS + +;System call function codes +PRINTMES: EQU 9 +OPEN: EQU 15 +CLOSE: EQU 16 +READ: EQU 20 +SETDMA: EQU 26 +MAKE: EQU 22 +BLKWRT: EQU 40 + +;The following equates define some token values returned by GETSYM +UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +CONST: EQU 1 ;Constant (including $) +REG: EQU 2 ;8-bit register +XREG: EQU 3 ;16-bit register (except segment registers) +SREG: EQU 4 ;Segment register + +;Ouput file record definition + ORG 0 +WRTPT: DS 2 ;Pointer to next byte to be written +BUFEND: DS 2 ;Pointer to end of buffer plus one +BUFSTRT:DS 2 ;Address of start of buffer +BUFFCB: DS 37 ;FCB for the file + + ORG 100H + PUT 100H + + JP BEGIN + +HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.31' + DB 13,10,'Copyright 1979,80,81 by Seattle Computer Products, Inc.' + DB 13,10,13,10,'$' + +BEGIN: + MOV SP,STACK + MOV DX,HEADER + MOV AH,PRINTMES + INT 33 + MOV AL,[FCB+17] + MOV [SYMFLG],AL ;Save symbol table request flag + MOV SI,FCB+9 ;Point to file extension + LODB ;Get source drive letter + CALL CHKDSK ;Valid drive? + OR AL,AL + JZ DEFAULT ;If no extension, use existing drive spec + MOV [FCB],AL +DEFAULT: + LODB ;Get HEX file drive letter + CMP AL,'Z' ;Suppress HEX file? + JZ L0000 + CALL CHKDSK +L0000: + MOV [HEXFCB],AL + LODB ;Get PRN file drive letter + MOV AH,0 ;Signal no PRN file + CMP AL,'Z' ;Suppress PRN file? + JZ NOPRN + CMP AL,'Y' ;Print errors only on console? + JZ NOPRN + MOV AH,2 + CMP AL,'X' ;PRN file to console? + JZ NOPRN + MOV AH,4 + CMP AL,'P' ;PRN file to printer? + JZ NOPRN + CALL CHKDSK + MOV AH,80H +NOPRN: + MOV [LSTFCB],AL + MOV [LSTDEV],AH ;Flag device for list ouput + MOV SI,EXTEND + MOV DI,FCB+9 + MOVW + MOVB ;Set extension to ASM + MOVW ;Zero extent field + MOV DX,FCB + MOV AH,OPEN + INT 33 + MOV BX,NOFILE + OR AL,AL + JZ $+5 + JMP PRERR + MOV DX,HEXFCB + CALL MAKFIL + MOV DX,LSTFCB + CALL MAKFIL + MOV B,[FCB+32],0 ;Zero Next Record field + MOV [FCB+14],BUFSIZ ;Set record size + MOV [BUFPT],SRCBUF ;Initialize buffer pointer + MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE + MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE + XOR AX,AX + MOV [PC],AX ;DEFAULT PROGRAM COUNTER + MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL + MOV [RETPT],AX ;Pointer to last RET record + MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF + MOV [CHKLAB],AL ;LOOKUP ALL LABELS + DEC AX + MOV [LSTRET],AX ;Location of last RET + MOV AX,[6] ;HL=END OF MEMORY + MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE + MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE + +;Assemble each line of code + +LOOP: + CALL NEXTCHR ;Get first character on line + CMP AL,1AH + JZ ENDJ + MOV AL,-1 ;Flag that no tokens have been read yet + MOV [SYM],AL + CALL ASMLIN ;Assemble the line + MOV AL,[SYM] + CMP AL,-1 ;Any tokens found on line? + JNZ L0002 + CALL GETSYM ;If no tokens read yet, read first one +L0002: + CMP AL,';' + JZ ENDLN + CMP AL,EOL + JZ ENDLN + MOV AL,14H ;Garbage at end of line error + JP ENDLIN +ENDJ: JMP END + +ENDLN: + XOR AL,AL ;Flag no errors on line +ENDLIN: +;AL = error code for line. Stack depth unknown + MOV SP,STACK + CALL NEXLIN + JP LOOP + +NEXLIN: + MOV CH,0C0H ;Put end of line marker and error code (AL) + CALL PUTCD + CALL GEN1 + MOV AL,[CHR] +GETEOL: + CMP AL,10 + JZ RET + CMP AL,1AH + JZ ENDJ + CALL NEXTCHR ;Scan over comments for linefeed + JP GETEOL + +ABORT: + MOV BX,NOMEM +PRERR: + MOV DX,BX + MOV AH,PRINTMES + INT 33 + INT 32 + +MAKFIL: + MOV SI,DX + LODB ;Get drive select byte + CMP AL,20H ;If not valid, don't make file + JNC RET + MOV CX,4 + MOV DI,SI + MOV SI,FCB+1 + REP + MOVW ;Copy source file name + MOV AH,MAKE + INT 33 + MOV [DI-9+14],1 ;Set record length to 1 byte + MOV BX,NOSPAC + OR AL,AL ;Success? + JNZ PRERR + RET + +CHKDSK: + SUB AL,' ' ;If not present, set zero flag + JZ RET + SUB AL,20H + JZ DSKERR ;Must be in range A-O + CMP AL,'P'-'@' + JC RET +DSKERR: + MOV BX,BADDSK + JP PRERR + +ERROR: + MOV AL,CL + JMP ENDLIN + +NEXTCHR: + MOV SI,[BUFPT] + CMP SI,SRCBUF + JNZ GETCH +;Buffer empty so refill it + PUSH DX + MOV DX,SI + MOV AH,SETDMA + INT 33 + MOV DX,FCB + MOV AH,READ + INT 33 + POP DX + CMP AL,1 + MOV AL,1AH ;Possibly signal End of File + JZ NOMOD ;If nothing read +GETCH: + LODB + CMP SI,SRCBUF+BUFSIZ + JNZ NOMOD + MOV SI,SRCBUF +NOMOD: + MOV [BUFPT],SI + MOV [CHR],AL + RET + + +MROPS: + +; Get two operands and check for certain types, according to flag byte +; in CL. OP code in CH. Returns only if immediate operation. + + PUSH CX ;Save type flags + CALL GETOP + PUSH DX ;Save first operand + CALL GETOP2 + POP BX ;First op in BX, second op in DX + MOV AL,SREG ;Check for a segment register + CMP AL,BH + JZ SEGCHK + CMP AL,DH + JZ SEGCHK + MOV AL,CONST ;Check if the first operand is immediate + MOV CL,26 + CMP AL,BH + JZ ERROR ;Error if so + POP CX ;Restore type flags + CMP AL,DH ;If second operand is immediate, then done + JZ RET + MOV AL,UNDEFID ;Check for memory reference + CMP AL,BH + JZ STORE ;Is destination memory? + CMP AL,DH + JZ LOAD ;Is source memory? + TEST CL,1 ;Check if register-to-register operation OK + MOV CL,27 + JZ ERROR + MOV AL,DH + CMP AL,BH ;Registers must be of same length +RR: + MOV CL,22 + JNZ ERROR +RR1: + AND AL,1 ;Get register length (1=16 bits) + OR AL,CH ;Or in to OP code + CALL PUT ;And write it + POP CX ;Dump return address + MOV AL,BL + ADD AL,AL ;Rotate register number into middle position + ADD AL,AL + ADD AL,AL + OR AL,0C0H ;Set register-to-register mode + OR AL,DL ;Combine with other register number + JMP PUT + +SEGCHK: +;Come here if at least one operand is a segment register + POP CX ;Restore flags + TEST CL,8 ;Check if segment register OK + MOV CL,22 + JZ ERR1 + MOV CX,8E03H ;Segment register move OP code + MOV AL,UNDEFID + CMP AL,DH ;Check if source is memory + JZ LOAD + CMP AL,BH ;Check if destination is memory + JZ STORE + MOV AL,XREG + SUB AL,DH ;Check if source is 16-bit register + JZ RR ;If so, AL must be zero + MOV CH,8CH ;Change direction + XCHG DX,BX ;Flip which operand is first and second + MOV AL,XREG + SUB AL,DH ;Let RR perform finish the test + JP RR + +STORE: + TEST CL,004H ;Check if storing is OK + JNZ STERR + XCHG DX,BX ;If so, flip operands + AND CH,0FDH ; and zero direction bit +LOAD: + MOV DH,25 + CMP AL,BH ;Check if memory-to-memory + JZ MRERR + MOV AL,BH + CMP AL,REG ;Check if 8-bit operation + JNZ XRG + MOV DH,22 + TEST CL,1 ;See if 8-bit operation is OK + JZ MRERR +XRG: + MOV AL,DL + SUB AL,6 ;Check for R/M mode 6 and register 0 + OR AL,BL ; meaning direct load/store of accumulator + JNZ NOTAC + TEST CL,8 ;See if direct load/store of accumulator + JZ NOTAC ; means anything in this case +; Process direct load/store of accumulator + MOV AL,CH + AND AL,2 ;Preserve direction bit only + XOR AL,2 ; but flip it + OR AL,0A0H ;Combine with OP code + MOV CH,AL + MOV AL,BH ;Check byte/word operation + AND AL,1 + OR AL,CH + POP CX ;Dump return address + JMP PUTADD ;Write the address + +NOTAC: + MOV AL,BH + AND AL,1 ;Get byte/word bit + AND AL,CL ;But don't use it in word-only operations + OR AL,CH ;Combine with OP code + CALL PUT + MOV AL,BL + ADD AL,AL ;Rotate to middle position + ADD AL,AL + ADD AL,AL + OR AL,DL ;Combine register field + POP CX ;Dump return address + JMP PUTADD ;Write the address + +STERR: + MOV DH,29 +MRERR: + MOV CL,DH + +ERR1: JMP ERROR + +GETOP2: +;Get the second operand: look for a comma and drop into GETOP + MOV AL,[SYM] + CMP AL,',' + MOV CL,21 + JNZ ERR1 + + +GETOP: + +; Get one operand. Operand may be a memory reference in brackets, a register, +; or a constant. If a flag (such as "B" for byte operation) is encountered, +; it is noted and processing continues to find the operand. +; +; On exit, AL (=DH) has the type of operand. Other information depends +; on the actual operand: +; +; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +; the 8086 R/M format (middle bits zero). The constant part of the address +; is in ADDR. If an undefined label needs to be added to this, a pointer to +; its information fields is in ALABEL, otherwise ALABEL is zero. +; +; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +; to be added to this, a pointer to its information fields is in DLABEL, +; otherwise DLABEL is zero. "$" and "RET" are in this class. +; +; AL=DH=2 8-bit Register. DL has the register number. +; +; AL=DH=3 16-bit Register. DL has the register number. +; +; AL=DH=4 Segment Register. DL has the register number. + + CALL GETSYM +GETOP1: +;Enter here if we don't need a GETSYM first + CMP AL,'[' ;Memory reference? + JZ MEM + CMP AL,5 ;Flag ("B", "W", etc.)? + JZ FLG + CMP AL,REG ;8-Bit register? + JZ NREG + CMP AL,XREG ;16-Bit register? + JZ NREG + CMP AL,SREG ;Segment register? + JZ NREG +VAL: ;Must be immediate + XOR AL,AL ;No addressing modes allowed +VAL1: + CALL GETVAL + MOV AX,[CON] ;Defined part + MOV [DATA],AX + MOV AX,[UNDEF] ;Undefined part + MOV [DLABEL],AX + MOV DL,CH + MOV DH,CONST + MOV AL,DH + RET +NREG: + PUSH DX + CALL GETSYM + POP DX + MOV AL,DH + RET +MEM: + CALL GETSYM + MOV AL,1 + CALL GETVAL + MOV AL,[SYM] + CMP AL,']' + MOV CL,24 + JNZ ERR1 + CALL GETSYM + MOV BX,[CON] + MOV [ADDR],BX + MOV BX,[UNDEF] + MOV [ALABEL],BX + MOV DL,CH + MOV DH,UNDEFID + MOV AL,DH + RET +FLG: + CALL GETSYM + CMP AL,',' + JZ GETOP + JP GETOP1 + + +GETVAL: + +; Expression analyzer. On entry, if AL=0 then do not allow base or index +; registers. If AL=1, we are analyzing a memory reference, so allow base +; and index registers, and compute addressing mode when done. The constant +; part of the expression will be found in CON. If an undefined label is to +; be added to this, a pointer to its information fields will be found in +; UNDEF. + + XCHG AX,BP ;Flag is kept in BP + PUSH BX + MOV BX,0 + MOV [CON],BX + MOV [UNDEF],BX + POP BX + MOV AL,[SYM] + CMP AL,'+' + JZ PLSMNS + CMP AL,'-' + JZ PLSMNS + MOV CL,'+' + PUSH CX + JP OPERATE +PLSMNS: + PUSH AX + OR BP,4 ;Flag that a sign was found + CALL GETSYM +OPERATE: + CMP AL,CONST + JNZ $+5 + JMP CVAL + CMP AL,UNDEFID + JNZ $+5 + JMP UVAL + CMP AL,'"' + JNZ $+5 +STRINGJ:JMP STRING + CMP AL,"'" + JZ STRINGJ + CMP AL,XREG ;Only 16-bit register may index + MOV CL,20 + JNZ ERR2 + TEST BP,1 ;Check to see if indexing is OK + MOV CL,1 + JZ ERR2 + MOV AL,DL + MOV CL,3 + CMP AL,3 ;Check for BX + JZ BXJ + SUB AL,5 ;Check for BP + JZ BPJ + DEC AL ;Check for SI + MOV CL,4 + JZ SIJ + DEC AL ;Check for DI + JZ DIJ + MOV CL,2 ;Invalid base/index register +ERR2: JMP ERROR +DIJ: + XCHG AX,BP + TEST AL,10H ;Check if already seen index register + JNZ ERR2 + OR AL,30H ;Flag seeing index register DI + JP LPCHK +SIJ: + XCHG AX,BP + TEST AL,010H ;Check if already seen index register + JNZ ERR2 + OR AL,010H ;Flag seeing index register SI + JP LPCHK +BXJ: + XCHG AX,BP + TEST AL,080H ;Check if already seen base register + JNZ ERR2 + OR AL,080H ;Flag seeing base register BX + JP LPCHK +BPJ: + XCHG AX,BP + TEST AL,080H ;Check if already seen base register + JNZ ERR2 + OR AL,0C0H ;Flag seeing base register BP +LPCHK: + XCHG AX,BP + POP AX ;Get operator + CMP AL,'-' ;Can't subtract a register + MOV CL,5 + JZ ERR2 +NEXTER: + CALL GETSYM + CMP AL,'+' + JNZ $+5 +PJ: JMP PLSMNS + CMP AL,'-' + JZ PJ + XCHG AX,BP + MOV CH,0 + TEST AL,010H ;Test INDEX bit + RCL AL ;BASE bit (zero flag not affected) + JZ NOIND ;Jump if not indexed, with BASE bit in carry + CMC + RCL CH + RCL AL ;BP bit + RCL CH + RCL AL ;DI bit + RCL CH ;The low 3 bits now have indexing mode +MODE: + OR CH,080H ;If undefined label, force 16-bit displacement + TEST [UNDEF],-1 + JNZ RET + MOV BX,[CON] + CALL SIGNEXT ;Check if 8-bit with sign extended + JNZ RET ;If not, use 16-bit displacement + AND CH,07FH ;Reset 16-bit displacement + OR CH,040H ;Set 8-bit displacement + OR BX,BX + JNZ RET ;Use it if not zero displacement + AND CH,7 ;Specify no displacement + CMP CH,6 ;Check for BP+0 addressing mode + JNZ RET + OR CH,040H ;If BP+0, use 8-bit displacement + RET + +SIGNEXT: +; Return with zero flag set if value in BX is a valid sign-extended +; 8-bit value. AX destroyed + MOV AL,BL + CBW + CMP AX,BX + RET + +NOIND: + MOV CH,6 ;Try direct address mode + JNC RET ;If no base register, that's right + RCL AL ;Check BP bit + JC MODE + INC CH ;If not, must be BX + JP MODE + +CVAL: + POP AX + CMP AL,'-' + JNZ ADDCON + NEG DX +ADDCON: + ADD [CON],DX + JMP NEXTER + +UVAL: + XCHG AX,BP + MOV CL,6 + TEST AL,008H ;Check if undefined label has been seen + JNZ ERR30 + OR AL,008H ;Flag seeing undefined label + XCHG AX,BP + MOV [UNDEF],BX + POP AX + CMP AL,'+' ;Undefined label may only be added + MOV CL,5 + JNZ ERR30 + JMP NEXTER + +ERR30: JMP ERROR + +STRING: + MOV CH,AL + MOV AL,[CHR] + CMP AL,CH + MOV CL,35 + MOV DL,AL + MOV DH,0 + JNZ L0003 + CALL ZERLEN +L0003: + CALL GETCHR + LAHF + XCHG AX,BP + SAHF + MOV CL,37 + TEST AL,002H + JZ ERR30 + TEST AL,004H + MOV CL,38 + JNZ ERR30 + LAHF + XCHG AX,BP + SAHF +STRGDAT: + MOV AL,DL + CMP AL,EOL + MOV CL,39 + JZ ERR30 + CALL PUT + MOV AL,[DATSIZ] + OR AL,AL + JNZ BYTSIZ + MOV AL,DH + CALL PUT +BYTSIZ: + MOV AL,[CHR] + MOV DL,AL + CALL GETCHR + JP STRGDAT +ZERLEN: + CALL NEXTCHR + CMP AL,CH + JNZ ERR30 + RET +GETCHR: + CALL NEXTCHR + CMP AL,CH + JNZ RET + CALL NEXTCHR + CMP AL,CH + JZ RET + POP BX + JMP CVAL + + +GETSYM: + +; The lexical scanner. Used only in the operand field. Returns with the token +; in SYM and AL, sometimes with additional info in BX or DX. +; +; AL=SYM=0 Undefined label. BX has pointer to information fields. +; +; AL=SYM=1 Constant (or defined label). DX has value. +; +; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +; respectively. DL has register number. +; +; AL=SYM=5 A mode flag (such as "B" for byte operation). Also stored in +; appropriate memory location--FLAG or LONG. +; +; All other values are the ASCII code of the character. Note that this may +; never be a letter or number. + + CALL GETSY + MOV AL,[SYM] + RET + +SCANB: + MOV AL,[CHR] +SCANT: + CMP AL,' ' + JZ NEXB + CMP AL,9 + JNZ RET +NEXB: + CALL NEXTCHR + JP SCANT + +DOLLAR: + MOV DX,[OLDPC] + MOV AL,CONST + MOV [SYM],AL +NEXTCHJ: + JMP NEXTCHR + +GETSY: + CALL SCANB + CMP AL,'$' + JZ DOLLAR + MOV [SYM],AL + OR AL,20H + CMP AL,'z'+1 + JNC NEXTCHJ + CMP AL,'a' + JC $+5 + JMP LETTER + CMP AL,'9'+1 + JNC NEXTCHJ + CMP AL,'0' + JC NEXTCHJ + MOV BX,SYM + MOV B,[BX],CONST + CALL READID + DEC BX + MOV AL,[BX] + MOV CL,7 + MOV BX,0 + CMP AL,'h' + JNZ $+5 + JMP HEX + INC CL + MOV [IX],ID +DEC: + MOV SI,[IX] + MOV AL,[SI] + INC [IX] + CMP AL,'9'+1 + JC $+5 + JMP ERROR + SUB AL,'0' + MOV DX,BX + SHL BX + SHL BX + ADD BX,DX + SHL BX + MOV DL,AL + MOV DH,0 + ADD BX,DX + DEC CH + JNZ DEC + XCHG DX,BX + RET + +HEX: + MOV DX,ID + DEC CH +HEX1: + MOV SI,DX + LODB + INC DX + SUB AL,'0' + CMP AL,10 + JC GOTIT + CMP AL,'g'-'0' + JNC ERR4 + SUB AL,'a'-10-'0' +GOTIT: + SHL BX + SHL BX + SHL BX + SHL BX + ADD BL,AL + DEC CH + JNZ HEX1 + XCHG DX,BX + RET + +ERR4: JMP ERROR + +GETLET: + CALL SCANB + CMP AL,EOL + STC + JZ RET + CMP AL,';' + STC + JZ RET + MOV CL,10 + OR AL,20H + CMP AL,'a' + JC ERR4 + CMP AL,'z'+1 + JNC ERR4 +READID: + MOV BX,ID + MOV CH,0 +MOREID: + MOV [BX],AL + INC CH + INC BX + CALL NEXTCHR + CMP AL,'0' + JC NOMORE + OR AL,20H + CMP AL,'z'+1 + JNC NOMORE + CMP AL,'9'+1 + JC MOREID + CMP AL,'a' + JNC MOREID +NOMORE: + MOV CL,AL + MOV AL,CH + MOV [LENID],AL + OR AL,AL + MOV AL,CL + RET + +LETTER: + CALL READID + MOV AL,CH + DEC AL + JNZ NOFLG + MOV AL,[ID] + CMP AL,'l' + MOV CL,0 + MOV DX,LONG + JZ BWFLAG + CMP AL,'b' + MOV DX,FLAG + JZ BWFLAG + CMP AL,'w' + MOV CL,1 + JZ BWFLAG + XOR AL,AL +NOFLG: + DEC AL + PUSH BX + JNZ L0004 + CALL REGCHK +L0004: + POP BX + MOV AL,DH + JZ SYMSAV + CALL LOOKRET +SYMSAV: + MOV [SYM],AL + RET + +BWFLAG: + XCHG DX,BX + MOV AL,[BX] + INC AL + MOV [BX],CL + MOV CL,32 + JZ $+5 + JMP ERROR + MOV AL,5 + JP SYMSAV + +REGCHK: + MOV BX,ID + MOV CL,[BX] + LAHF + INC BX + SAHF + MOV AL,[BX] + MOV BX,REGTAB + MOV DH,XREG + MOV DL,0 + CMP AL,'x' + JZ SCANREG + MOV DH,REG + CMP AL,'l' + JZ SCANREG + MOV DL,4 + CMP AL,'h' + JZ SCANREG + MOV DH,SREG + MOV DL,0 + MOV BX,SEGTAB + CMP AL,'s' + JZ SCANREG + MOV DH,XREG + CMP AL,'p' + JZ PREG + CMP AL,'i' + JNZ RET + MOV DL,6 + MOV AL,CL + CMP AL,'s' + JZ RET + INC DL + CMP AL,'d' + RET +PREG: + MOV DL,4 + MOV AL,CL + CMP AL,'s' + JZ RET + INC DL + CMP AL,'b' + RET +SCANREG: + MOV AL,CL + MOV CX,4 + UP + MOV DI,BX + REPNZ + SCAB + MOV BX,DI + JNZ RET + MOV AL,CL + ADD AL,DL + MOV DL,AL + XOR AL,AL + RET + +REGTAB: DB 'bdca' + +SEGTAB: DB 'dsce' + +LOOK: + MOV CH,[BX] + INC BX + MOV DX,ID + CALL CPSLP + JZ RET + XOR AL,80H + MOV CL,AL + DEC BX + MOV AL,[BX] + XOR AL,80H + CMP AL,CL + JNC SMALL + INC CH + INC CH +SMALL: + MOV DL,CH + MOV DH,0 + ADD BX,DX + MOV DX,[BX] + INC BX + MOV AL,DL + OR AL,DH + STC + JZ RET + XCHG DX,BX + JP LOOK + +LOOKRET: + MOV AL,CH + CMP AL,3 ;RET has 3 letters + JNZ LOOKUP + DEC BX + OR B,[BX],080H + MOV DX,RETSTR+2 +CHKRET: + MOV SI,DX + LODB + CMP AL,[BX] + JNZ LOOKIT + DEC BX + DEC DX + DEC CH + JNZ CHKRET + MOV DX,[LSTRET] + MOV AL,DL + AND AL,DH + INC AL + JZ ALLRET + MOV BX,[PC] + SUB BX,DX + CALL SIGNEXT + MOV AL,1 + JZ RET +ALLRET: + MOV BX,[RETPT] + MOV AL,BH + OR AL,BL + MOV AL,0 + JNZ RET + MOV BX,[HEAP] + DEC BX + DEC BX + DEC BX + MOV [HEAP],BX + XOR AL,AL + MOV [BX],AL + MOV [RETPT],BX + RET + +LOOKUP: + DEC BX + OR B,[BX],080H +LOOKIT: + MOV BX,[BASE] + MOV AL,BH + OR AL,BL + JZ EMPTY + CALL LOOK + JC ENTER + MOV DX,4 + ADD BX,DX + MOV AL,[BX] + OR AL,AL + JZ RET + INC BX + MOV DX,[BX] + INC BX + RET + +ENTER: + PUSH BX ;Save pointer to link field + CALL CREATE ;Add the node + POP SI + MOV [SI-1],DX ;Link new node + RET ;Zero was set by CREATE + +EMPTY: + CALL CREATE + MOV [BASE],DX + RET + + +CREATE: + +; Add a new node to the identifier tree. The identifier is at ID with +; bit 7 of the last character set to one. The length of the identifier is +; in LENID, which is ID-1. +; +; Node format: +; 1. Length of identifier (1 byte) +; 2. Identifier (1-80 bytes) +; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +; 4. Right link (0 if none larger) +; 5. Data field: +; a. Defined flag (0=undefined, 1=defined) +; b. Value (2 bytes) +; +; This routine returns with AL=zero and zero flag set (which indicates +; on return from LOOKUP that it has not yet been defined), DX points +; to start of new node, and BX points to data field of new node. + + MOV AL,[LENID] + ADD AL,8 ;Storage needed for the node + MOV BX,[HEAP] + MOV DL,AL + MOV DH,0 + SUB BX,DX ;Heap grows downward + MOV [HEAP],BX + XCHG DX,BX + MOV BX,[CODE] ;Check to make sure there's enough + CMP BX,DX + JB $+5 + JMP ABORT + PUSH DX + MOV BX,LENID + MOV CL,[BX] + INC CL + MOV CH,0 + UP + MOV SI,BX + MOV DI,DX + REP + MOVB ;Move identifier and length into node + MOV DX,DI + MOV BX,SI + MOV CH,4 + XCHG DX,BX +NILIFY: + MOV [BX],CL ;Zero left and right links + INC BX + DEC CH + JNZ NILIFY + XOR AL,AL ;Set zero flag + MOV [BX],AL ;Zero defined flag + POP DX ;Restore pointer to node + RET + +CPSLP: + MOV SI,DX + LODB + CMP AL,[BX] + LAHF + INC DX + INC BX + SAHF + JNZ RET + DEC CH + JNZ CPSLP + RET + +GETLAB: + MOV BX,0 + MOV [LABPT],BX + MOV AL,-1 + MOV [FLAG],AL + MOV [LONG],AL + MOV DH,0 + MOV AL,[CHR] + CMP AL,' '+1 + JC NOT1 + OR DH,001H +NOT1: + CALL GETLET + JC RET + CMP AL,':' + JNZ LABCHK + CALL NEXTCHR + JP LABEL +LABCHK: + OR AL,AL + TEST DH,001H + JZ RET +LABEL: + MOV AL,[CHKLAB] + OR AL,AL + JZ $+5 + JMP GETLET + CALL LOOKUP + MOV CL,11 + JNZ ERR5 + MOV DX,[PC] + MOV B,[BX],1 + INC BX + MOV [BX],DL + MOV [LABPT],BX + INC BX + MOV [BX],DH + JMP GETLET + +ERR5: JMP ERROR + +ASMLIN: + MOV BX,[PC] + MOV [OLDPC],BX + CALL GETLAB + JNC $+5 + JMP ENDLN + MOV BX,LENID + MOV AL,[BX] + MOV CL,12 + SUB AL,2 + MOV CH,AL + JC ERR5 + INC BX + CMP B,[BX],"f" ;See if an 8087 mnemonic + JZ NDPOP + CMP AL,5 + JNC ERR5 + MOV AL,[BX] + SUB AL,'a' + MOV CL,AL + ADD AL,AL + ADD AL,AL + ADD AL,CL + ADD AL,CH + ADD AL,AL + MOV BX,OPTAB + MOV DL,AL + MOV DH,0 + ADD BX,DX + MOV DL,[BX] + INC BX + MOV DH,[BX] + XCHG DX,BX + INC CH + MOV CL,CH + MOV AL,[BX] + INC BX + OR AL,AL + JZ OPERR +FINDOP: + MOV CH,CL + LAHF + XCHG AX,BP + SAHF + MOV DX,ID+1 + CALL CPSLP + JZ HAVOP + MOV DH,0 + MOV DL,CH + INC DL + INC DL + ADD BX,DX + LAHF + XCHG AX,BP + SAHF + DEC AL + JNZ FINDOP +OPERR: + MOV CL,12 + JMP ERROR + +HAVOP: + MOV AL,[BX+2] ;Get opcode + JMP [BX] + +NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") + INC BX + CMP B,[BX],"n" ;"No-wait" form? + MOV AH,0 + JNZ SAVNFLG + MOV AH,1 + DEC AL + INC BX ;Skip over the "N" +SAVNFLG: + MOV [NOWAIT],AH ;0 for wait, 1 for no wait + CMP AL,1 + JB OPERR ;Not enough char left for valid opcode? + CMP AL,5 + JA OPERR ;Too many? + CBW + XCHG AX,DX ;Save length in DX + MOV SI,DX + OR B,[SI+BX],80H ;Set high bit of last character + MOV AL,[BX] ;Get first char of opcode + INC BX + SUB AL,"a" + JB TRY2XM1 ;Go see if opcode starts with "2" + CMP AL,"z"-"a" + JA OPERR + CBW + SHL AX ;Double to index into address table + XCHG AX,SI ;Put in index register + MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +LOOKNDP: + MOV AH,[DI] ;Number of opcodes starting with this letter + OR AH,AH + JZ OPERR ;Any start with this letter? +FNDNDP: + INC DI + MOV SI,BX ;Pointer to start of opcode + MOV CX,DX ;Get length of opcode + REPE + CMPB ;Compare opcode to table entry + JZ HAVNDP + DEC DI ;Back up in case that was last letter + MOV AL,80H ;Look for char with high bit set +ENDOP: + SCASB + JA ENDOP + INC DI ;Skip over info about opcode + DEC AH + JNZ FNDNDP + JP OPERR + +TRY2XM1: + CMP AL,"2"-"a" + JNZ OPERR + MOV DI,XM1 + JP LOOKNDP + +HAVNDP: + MOV SI,DI + CMP B,[NOWAIT],0 + JNZ NWAIT + MOV AL,9BH ;Wait opcode + CALL PUT +NWAIT: + LODW ;Get opcode info + TEST AL,0F8H ;Any operand bits set? + JZ NOOPS ;If no operands, output code +NOOPS: + OR AL,0D8H ;ESC hook + CALL PUT + MOV AL,AH + JMP PUT + +GRP1: + MOV CX,8A09H + CALL MROPS + MOV CX,0C6H + MOV AL,BH + CMP AL,UNDEFID + JNZ L0006 + CALL STIMM +L0006: + AND AL,1 + JZ BYTIMM + MOV AL,0B8H + OR AL,BL + CALL PUT + JMP PUTWOR + +BYTIMM: + MOV AL,0B0H + OR AL,BL + CALL PUT +PUTBJ: JMP PUTBYT + +IMMED: + MOV AL,BH + CMP AL,UNDEFID + JZ STIMM + MOV AL,BL + OR AL,AL + JZ RET + MOV AL,BH + CALL IMM + OR AL,0C0H + CALL PUT +FINIMM: + MOV AL,CL + POP CX + RCR SI + TEST AL,001H + RCL SI + JZ PUTBJ + CMP AL,83H + JZ PUTBJ + JMP PUTWOR + +STIMM: + MOV AL,[FLAG] + CALL IMM + CALL PUTADD + JP FINIMM + +IMM: + AND AL,1 + OR AL,CL + MOV CL,AL + CALL PUT + MOV AL,CH + AND AL,38H + OR AL,BL + RET + +PUT: +;Save byte in AL as pure code, with intermediate code bits 00. AL and +;DI destroyed, no other registers affected. + PUSH BX + PUSH CX + MOV CH,0 ;Flag as pure code + CALL GEN + POP CX + POP BX + RET + +GEN: +;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. + CALL PUTINC ;Save it and bump code pointer +GEN1: + MOV CL,[RELOC] + ROL CX + ROL CX + MOV [RELOC],CL + MOV BX,BCOUNT + DEC B,[BX] + JNZ RET + MOV B,[BX],4 + MOV BX,RELOC + MOV AL,[BX] + MOV B,[BX],0 + MOV DI,[IY] + MOV [DI],AL + MOV BX,[CODE] + MOV [IY],BX + INC BX + MOV [CODE],BX + RET + +PUTINC: + INC [PC] +PUTCD: + MOV DI,[CODE] + STOB + MOV [CODE],DI + RET + +PUTWOR: +;Save the word value described by [DLABEL] and [DATA] as code. If defined, +;two bytes of pure code will be produced. Otherwise, appropriate intermediate +;code will be generated. + PUSH CX + MOV CH,80H + PUSH DX + PUSH BX + JP PUTBW + +PUTBYT: +;Same as PUTWOR, above, but for byte value. + PUSH CX + MOV CH,40H + PUSH DX + PUSH BX + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ PUTBW + MOV BX,[DATA] + OR AL,BH + JZ PUTBW + INC BH + JZ PUTBW + MOV CL,31 + JMP ERROR +PUTBW: + MOV DX,[DLABEL] + MOV BX,[DATA] +PUTCHK: + MOV AL,DH + OR AL,DL + JZ NOUNDEF + MOV AL,DL + CALL PUTCD + MOV AL,DH + CALL PUTCD + MOV AL,BL + CALL PUTINC + MOV AL,BH + RCR SI + TEST CH,080H + RCL SI + JZ SMPUT + CALL GEN + JP PRET +SMPUT: + CALL PUTCD + CALL GEN1 +PRET: + POP BX + POP DX + POP CX + RET + +NOUNDEF: + MOV AL,BL + MOV CL,BH + PUSH CX + MOV CH,0 + CALL GEN + POP CX + MOV AL,CL + TEST CH,080H + MOV CH,0 + JZ PRET + CALL GEN + JP PRET + +PUTADD: +;Save complete addressing mode. Addressing mode is in AL; if this is a register +;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +;the details of the addressing mode will be investigated and the optional one- +;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. + PUSH CX + PUSH DX + PUSH BX + MOV CH,0 + MOV CL,AL + CALL GEN ;Save the addressing mode as pure code + MOV AL,CL + MOV CH,80H + AND AL,0C7H + CMP AL,6 + JZ TWOBT ;Direct address? + AND AL,0C0H + JZ PRET ;Indirect through reg, no displacement? + CMP AL,0C0H + JZ PRET ;Register to register operation? + MOV CH,AL ;Save whether one- or two-byte displacement +TWOBT: + MOV BX,[ADDR] + MOV DX,[ALABEL] + JP PUTCHK + +GRP2: + CALL GETOP + MOV CX,0FF30H + CMP AL,UNDEFID + JZ PMEM + MOV CH,50H + CMP AL,XREG + JZ PXREG + MOV CH,6 + CMP AL,SREG + JNZ $+5 + JMP PACKREG + MOV CL,20 + JMP ERROR + +PMEM: + MOV AL,CH + CALL PUT + MOV AL,CL + OR AL,DL + JMP PUTADD + +PXREG: + MOV AL,CH + OR AL,DL + JMP PUT + +GRP3: + CALL GETOP + PUSH DX + CALL GETOP2 + POP BX + MOV CX,8614H + MOV AL,SREG + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,CONST + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,UNDEFID + CMP AL,BH + JZ EXMEM + CMP AL,DH + JZ EXMEM1 + MOV AL,BH + CMP AL,DH + MOV CL,22 + JNZ ERR6 + CMP AL,XREG + JZ L0008 + CALL RR1 +L0008: ;RR1 never returns + MOV AL,BL + OR AL,AL + JZ EXACC + XCHG DX,BX + MOV AL,BL + OR AL,AL + MOV AL,BH + JZ EXACC + CALL RR1 +EXACC: + MOV AL,90H + OR AL,DL + JMP PUT + +EXMEM: + XCHG DX,BX +EXMEM1: + CMP AL,BH + JZ ERR6 + MOV CL,1 ;Flag word as OK + CALL NOTAC ;NOTAC never returns +ERR6: JMP ERROR + +GRP4: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETOP + POP CX + CMP AL,CONST + JZ FIXED + SUB AL,XREG + DEC DL + DEC DL + OR AL,DL + MOV CL,20 + JNZ ERR6 + MOV AL,CH + OR AL,8 + JMP PUT +FIXED: + MOV AL,CH + CALL PUT + JMP PUTBYT + +GRP5: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETOP + CMP AL,CONST + JNZ ERR6 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + MOV CL,30 + JNZ ERR6 + MOV BX,[DATA] + POP AX + XCHG AH,AL + SAHF + OR AL,AL + JZ ORG + DEC AL + JZ DSJ + DEC AL + JZ EQU + DEC AL + JZ $+5 + JMP IF +PUTOP: + MOV AL,-3 + JP NEWLOC +ALIGN: + MOV AL,[PC] + AND AL,1 + JZ RET + MOV BX,1 +DSJ: + XCHG DX,BX + MOV BX,[PC] + LAHF + ADD BX,DX + RCR SI + SAHF + RCL SI + MOV [PC],BX + XCHG DX,BX + MOV AL,-4 + JP NEWLOC +EQU: + XCHG DX,BX + MOV BX,[LABPT] + MOV AL,BH + OR AL,BL + MOV CL,34 + JZ ERR7 + MOV [BX],DL + LAHF + INC BX + SAHF + MOV [BX],DH + RET +ORG: + MOV [PC],BX + MOV AL,-2 +NEWLOC: + CALL PUTCD + MOV AL,BL + CALL PUTCD + MOV AL,BH + CALL PUTCD + MOV CH,0C0H + JMP GEN1 +GRP6: + MOV CH,AL + MOV CL,4 + CALL MROPS + MOV CL,23 +ERR7: JMP ERROR +GRP7: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H + MOV DX,[DLABEL] + MOV AL,DH + OR AL,DL + JNZ ACCJ + XCHG DX,BX + MOV BX,[DATA] + CALL SIGNEXT + XCHG DX,BX + JNZ ACCJ + LAHF + OR CL,002H + SAHF +ACCJ: JMP ACCIMM +GRP8: + MOV CL,AL + MOV CH,0FEH + JP ONEOP +GRP9: + MOV CL,AL + MOV CH,0F6H +ONEOP: + PUSH CX + CALL GETOP +ONE: + MOV CL,26 + CMP AL,CONST + JZ ERR7 + CMP AL,SREG + MOV CL,22 + JZ ERR7 + POP CX + CMP AL,UNDEFID + JZ MOP + AND AL,1 + JZ ROP + RCR SI + TEST CL,001H + RCL SI + JZ ROP + MOV AL,CL + AND AL,0F8H + OR AL,DL + JMP PUT +MOP: + MOV AL,[FLAG] + AND AL,1 + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,DL + JMP PUTADD +ROP: + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,0C0H + OR AL,DL + JMP PUT +GRP10: + MOV CL,AL + MOV CH,0F6H + PUSH CX + CALL GETOP + MOV CL,20 + MOV AL,DL + OR AL,AL + JNZ ERRJ1 + MOV AL,DH + CMP AL,XREG + JZ G10 + CMP AL,REG +ERRJ1: JNZ ERR8 +G10: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETOP + POP AX + XCHG AH,AL + SAHF + AND AL,1 + MOV [FLAG],AL + MOV AL,DH +ONEJ: JP ONE +GRP11: + CALL PUT + MOV AL,0AH + JMP PUT +GRP12: + MOV CL,AL + MOV CH,0D0H + PUSH CX + CALL GETOP + MOV AL,[SYM] + CMP AL,',' + MOV AL,DH + JNZ ONEJ + PUSH DX + CALL GETOP + SUB AL,REG + MOV CL,20 + DEC DL + OR AL,DL + JNZ ERR8 + POP DX + MOV AL,DH + POP CX + LAHF + OR CH,002H + SAHF + PUSH CX + JMP ONE +GRP13: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H +ACCIMM: + CALL IMMED + OR CH,004H + AND CH,0FDH +AIMM: + MOV AL,BH + AND AL,1 + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + OR AL,CH + CALL PUT + POP AX + XCHG AH,AL + SAHF + JNZ $+5 + JMP PUTBYT + JMP PUTWOR +ERR8: JMP ERROR +GRP14: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETOP + CMP AL,CONST + JZ DIRECT + MOV CL,20 + CMP AL,REG + JZ ERR8 + CMP AL,SREG + JZ ERR8 + CMP AL,XREG + JNZ NOTRG + OR DL,040H + OR DL,080H +NOTRG: + MOV AL,0FFH + CALL PUT + POP AX + XCHG AH,AL + SAHF + AND AL,38H + OR AL,DL + MOV CH,AL + MOV AL,[LONG] + OR AL,AL + MOV AL,CH + JZ PUTADDJ + AND AL,0F7H +PUTADDJ: + JMP PUTADD +DIRECT: + MOV AL,[SYM] + CMP AL,',' + JZ LONGJ + POP AX + XCHG AH,AL + SAHF + DEC AL + CMP AL,0E9H + JZ GOTOP + MOV AL,0E8H +GOTOP: + CALL PUT + MOV BX,[DATA] + MOV DX,[PC] + INC DX + INC DX + SUB BX,DX + MOV [DATA],BX + JMP PUTWOR +LONGJ: + POP AX + XCHG AH,AL + SAHF + CALL PUT + CALL PUTWOR + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERR8 + JMP PUTWOR +GRP16: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETSYM + CMP AL,5 + JZ LONGR + CMP AL,EOL + JZ NODEC + CMP AL,';' + JZ NODEC +GETSP: + CALL GETOP1 + POP CX + CMP AL,CONST + MOV CL,20 + JNZ ERR9 + MOV AL,CH + AND AL,0FEH + CALL PUT + JMP PUTWOR +LONGR: + MOV AL,[LONG] + OR AL,AL + JNZ NOTLON + POP AX + XCHG AH,AL + SAHF + OR AL,8 + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL +NOTLON: + CALL GETSYM + CMP AL,EOL + JZ DORET + CMP AL,';' + JZ DORET + CMP AL,',' + JNZ L0011 + CALL GETSYM +L0011: + JP GETSP +NODEC: + MOV BX,[PC] + MOV [LSTRET],BX + XCHG DX,BX + MOV BX,[RETPT] + MOV AL,BH + OR AL,BL + JZ DORET + MOV B,[BX],1 + LAHF + INC BX + SAHF + MOV [BX],DL + LAHF + INC BX + SAHF + MOV [BX],DH + MOV BX,0 + MOV [RETPT],BX +DORET: + POP AX + XCHG AH,AL + SAHF + JMP PUT +GRP17: + CALL PUT + CALL GETOP + CMP AL,CONST + MOV CL,20 +ERR9: JNZ ERR10 + MOV BX,[DATA] + MOV DX,[PC] + LAHF + INC DX + SAHF + SBB BX,DX + MOV [DATA],BX + CALL PUTBYT + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ RET + MOV BX,[DATA] + CALL SIGNEXT + JZ RET + MOV CL,31 +ERR10: JMP ERROR + RET +GRP18: + CALL GETOP + CMP AL,CONST + MOV CL,20 + JNZ ERR10 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ GENINT + MOV BX,[DATA] + MOV DX,3 + SBB BX,DX + JNZ GENINT + MOV AL,0CCH + JMP PUT +GENINT: + MOV AL,0CDH + CALL PUT + JMP PUTBYT + +GRP19: ;ESC opcode + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERRJ ;First operand must be immediate + MOV CL,1EH + TEST [DLABEL],-1 ;See if all labels have been defined + JNZ ERRJ + MOV AX,[DATA] + CMP AX,64 ;Must only be 6 bits + MOV CL,1FH + JNB ERRJ + MOV BL,AL ;Save for second byte + SHR AL + SHR AL + SHR AL + OR AL,0D8H ;ESC opcode + CALL PUT + PUSH BX + CALL GETOP2 + POP BX + AND BL,7 ;Low 3 bits of first operand + SHL BL + SHL BL + SHL BL + CMP AL,UNDEFID ;Check for memory operand + JZ ESCMEM + CMP AL,CONST ;Check for another immediate + JZ ESCIMM + MOV CL,20 +ERRJ: JMP ERROR + +ESCMEM: + OR BL,DL ;Combine mode with first operand + MOV AL,BL + JMP PUTADD + +ESCIMM: + MOV CL,1EH + TEST [DLABEL],-1 ;See if second operand is fully defined + JNZ ERRJ + MOV AX,[DATA] + MOV CL,1FH + CMP AX,8 ;Must only be 3 bit value + JNB ERRJ + OR AL,BL ;Combine first and second operands + OR AL,0C0H ;Force "register" mode + JMP PUT + +GRP20: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,0F6H + CALL IMMED + MOV CH,0A8H + JMP AIMM +GRP21: + CALL GETOP + CMP AL,SREG + MOV CL,28 + JNZ ERRJ + MOV CH,26H +PACKREG: + MOV AL,DL + ADD AL,AL + ADD AL,AL + ADD AL,AL + OR AL,CH + JMP PUT +GRP22: + CALL GETOP + MOV CX,8F00H + CMP AL,UNDEFID + JNZ $+5 + JMP PMEM + MOV CH,58H + CMP AL,XREG + JNZ $+5 + JMP PXREG + MOV CH,7 + CMP AL,SREG + JZ PACKREG + MOV CL,20 +ERR11: JMP ERROR +GRP23: + MOV [DATSIZ],AL +GETDAT: + CALL GETSYM + MOV AL,2 + CALL VAL1 + MOV AL,[SYM] + CMP AL,',' + MOV AL,[DATSIZ] + JNZ ENDDAT + CALL SAVDAT + JP GETDAT +ENDDAT: + CMP AL,2 + JNZ SAVDAT + MOV BX,[DATA] + LAHF + OR BL,080H + SAHF + MOV [DATA],BX +SAVDAT: + OR AL,AL + JZ $+5 + JMP PUTBYT + JMP PUTWOR +IF: + OR BX,BX + JZ SKIPCD + INC B,[IFFLG] + RET + +SKIPCD: + INC B,[CHKLAB] +SKIPLP: + XOR AL,AL + CALL NEXLIN + CALL NEXTCHR + CMP AL,1AH + JZ END + CALL GETLAB + JC SKIPLP + MOV DI,LENID + MOV SI,IFEND + MOV CH,0 + MOV CL,[DI] + INC CL + REPE + CMPB + JZ ENDCOND + MOV DI,LENID + MOV SI,IFNEST + MOV CL,[DI] + INC CL + REPE + CMPB + JNZ SKIPLP + INC B,[CHKLAB] + JP SKIPLP + +ENDCOND: + DEC B,[CHKLAB] + JNZ SKIPLP + RET + +ENDIF: + MOV AL,[IFFLG] + MOV CL,36 + DEC AL + JS ERRJMP + MOV [IFFLG],AL + RET + +ERRJMP: JMP ERROR + +;********************************************************************* +; +; PASS 2 +; +;********************************************************************* + +END: + MOV DL,4 +WREND: + MOV CH,0FFH + MOV AL,CH + CALL GEN + DEC DL + JNZ WREND + MOV [BUFPT],SRCBUF + MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY + MOV [LSTPNT],LSTBUF + MOV [HEXPNT],HEXBUF + XOR AX,AX + MOV [ERRCNT],AX + MOV [PC],AX + MOV [LINE],AX ;Current line number + MOV [HEXADD],OBJECT + MOV DX,FCB + MOV AH,OPEN + INT 33 ;Re-open source file + XOR AL,AL + MOV [FCB+20H],AL + MOV [FCB+14],BUFSIZ + MOV [COUNT],AL + MOV CH,1 + MOV SI,START +FIXLINE: + MOV DI,START ;Store code over used up intermediate code + XOR AL,AL + MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) + MOV [ERR],AL ;No second pass errors yet +NEXBT: + SHL CL ;Shift out last bit of previous code + DEC CH ;Still have codes left? + JNZ TESTTYP + LODB ;Get next flag byte + MOV CL,AL + MOV CH,4 +TESTTYP: + SHL CL ;Set flags based on two bits + JO FIXUP + LODB + JC EMARK +OBJBT: + STOB + JP NEXBT + +FIXUP: +;Either a word or byte fixup is needed from a forward reference + LODW ;Get pointer to symbol + XCHG AX,BX + LODW ;Get constant part + ADD AX,[BX+1] ;Add symbol value to constant part + CMP B,[BX],0 ;See if symbol got defined + JNZ HAVDEF + MOV B,[ERR],100 ;Undefined - flag error + XOR AX,AX +HAVDEF: + OR CL,CL ;See if word or byte fixup + JS DEFBYT + STOW + JP NEXBT + +DEFBYT: + MOV DX,AX + CBW ;Extend sign + CMP AX,DX ;See if in range +127 to -128 + JZ OBJBT ;If so, it's always OK + NOT AH ;Check for range +255 to -256 + CMP AH,DH + JNZ RNGERR ;Must always be in this range +;Check for short jump. If so, we're out of range; otherwise we're OK + CMP DI,START+1 ;Only one other byte on line? + JNZ OBJBT ;Can't be short jump if not + MOV AL,[START] ;Get the first byte of this line + CMP AL,0EBH ;Direct short jump? + JZ RNGERR + AND AL,0FCH + CMP AL,0E0H ;LOOP or JCXZ instruction? + JZ RNGERR + AND AL,0F0H + CMP AL,70H ;Conditional jump? + MOV AL,DL ;Get code byte in AL + JNZ OBJBT ;If not, we're OK +RNGERR: + MOV B,[ERR],101 ;Value out of range + JP OBJBT + +FINIJ: JMP FINI + +EMARK: + CMP AL,-1 ;End of file? + JZ FINIJ + CMP AL,-10 ;Special item? + JA SPEND + PUSH CX + PUSH SI + PUSH AX ;Save error code + MOV AH,[LSTDEV] + AND AH,0FEH ;Reset error indicator + OR AL,[ERR] ;See if any errors on this line + JZ NOERR + OR AH,1 ;Send line to console if error occured +NOERR: + MOV [LSTDEV],AH + MOV CX,DI + CALL STRTLIN ;Print address of line + MOV SI,START + SUB CX,SI ;Get count of bytes of code + JZ SHOLIN +CODLP: + LODB + CALL SAVCD ;Ouput code to HEX and PRN files + LOOP CODLP +SHOLIN: + MOV AL,0 + XCHG AL,[COUNT] + MOV CX,7 ;Allow 7 bytes of code per line + SUB CL,AL + MOV AL,' ' + JZ NOFIL +BLNK: ;Put in 3 blanks for each byte not present + CALL LIST + CALL LIST + CALL LIST + LOOP BLNK +NOFIL: + CALL OUTLIN + POP AX ;Restore error code + CALL REPERR + MOV AL,[ERR] + CALL REPERR + POP SI + POP CX + MOV AL,[SPC] ;Any special funtion? + OR AL,AL + JNZ SPCFUN + JMP FIXLINE + +SPEND: + MOV [SPC],AL ;Record special function + LODW ;Get it's data + MOV [DATA],AX + JMP NEXBT + +SPCFUN: + MOV DX,[DATA] + CMP AL,-2 + JZ DORG + CMP AL,-3 + JZ DPUT +DDS: +;Handle DS pseudo-op + ADD [PC],DX + ADD [HEXADD],DX + JMP FIXLINE + +DORG: +;Handle ORG pseudo-op + MOV [PC],DX + JMP FIXLINE + +DPUT: +;Handle PUT pseudo-op + MOV [HEXADD],DX + JMP FIXLINE + +OUTLIN: +;Copy the source line to the ouput device. Line will be preceded by +;assembler-generated line number. This routine may be called several times +;on one line (once for each line of object code bytes), so it sets a flag +;so the line will only be output on the first call. + MOV AL,-1 + XCHG AL,[LINFLG] + OR AL,AL + JNZ CRLF ;Output line only if first time + MOV AX,[LINE] + INC AX + MOV [LINE],AX + MOV BH,0 ;No leading zero suppression + CALL OUT10 + MOV AL," " + CALL LIST + MOV AL,[LSTFCB] + CMP AL,'Z' + JZ CRLF ;Don't call NEXTCHR if listing suppressed + PUSH SI ;Save the only register destroyed by NEXTCHR +OUTLN: + CALL NEXTCHR + CALL LIST + CMP AL,10 ;Output until linefeed found + JNZ OUTLN + POP SI + RET + +PRTCNT: + MOV BX,ERCNTM + CALL PRINT + MOV AX,[ERRCNT] + MOV BH,"0"-" " ;Enable leading zero suppression + CALL OUT10 +CRLF: + MOV AL,13 + CALL LIST + MOV AL,10 + JP LIST + +OUT10: + XOR DX,DX + MOV DI,10000 + DIV AX,DI + OR AL,AL ;>10,000? + JNZ LEAD + SUB AL,"0"-" " ;Convert leading zero to blank +LEAD: + ADD AL,"0" + CALL LIST + XCHG AX,DX + MOV BL,100 + DIV AL,BL + MOV BL,AH + CALL HIDIG ;Convert to decimal and print 1000s digit + CALL DIGIT ;Print 100s digit + MOV AL,BL + CALL HIDIG ;Convert to decimal and print 10s digit + MOV BH,0 ;Ensure leading zero suppression is off + JP DIGIT + +HIDIG: + AAM ;Convert binary to unpacked BCD + OR AX,3030H ;Add "0" bias +DIGIT: + XCHG AL,AH + CMP AL,"0" + JZ SUPZ + MOV BH,0 ;Turn off zero suppression if not zero +SUPZ: + SUB AL,BH ;Convert leading zeros to blanks + JP LIST + +STRTLIN: + MOV B,[LINFLG],0 + MOV BX,[PC] + MOV AL,BH + CALL PHEX + MOV AL,BL +PHEXB: + CALL PHEX + MOV AL,' ' +LIST: + PUSH AX + PUSH DX + AND AL,7FH + MOV DL,AL + TEST B,[LSTDEV],3 ;See if output goes to console + JZ PRNCHK + MOV AH,2 + INT 33 ;Output to console +PRNCHK: + TEST B,[LSTDEV],4 ;See if output goes to printer + JZ FILCHK + MOV AH,4 + INT 33 ;Output to printer +FILCHK: + MOV AL,DL + POP DX + TEST B,[LSTDEV],80H ;See if output goes to a file + JZ LISTRET + CALL WRTBUF +LISTRET: + POP AX + RET + +WRTBUF: + PUSH DI + MOV DI,[LSTPNT] + STOB + CMP DI,LSTBUF+LSTBUFSIZ + JNZ SAVPT + PUSH AX + PUSH CX + PUSH DX + CALL FLUSHBUF + POP DX + POP CX + POP AX +SAVPT: + MOV [LSTPNT],DI + POP DI + RET + +PHEX: + PUSH AX + CALL UHALF + CALL LIST + POP AX + CALL LHALF + JP LIST + +FINI: + OR B,[LSTDEV],1 + CALL PRTCNT + AND B,[LSTDEV],0FEH + MOV AL,[HEXFCB] + CMP AL,'Z' + JZ SYMDMP + MOV AL,[HEXCNT] + CMP AL,-5 + JZ L0012 + CALL ENHEXL +L0012: + MOV AL,':' + CALL PUTCHR + MOV CH,10 +HEXEND: + PUSH CX + MOV AL,'0' + CALL PUTCHR + POP CX + DEC CH + JNZ HEXEND + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR + MOV AL,1AH + CALL PUTCHR + CALL WRTHEX ;Flush HEX file buffer + MOV AX,[FCB+20] + MOV [HEXFCB+20],AX ;Copy date to hex file + MOV DX,HEXFCB + MOV AH,CLOSE + INT 33 +SYMDMP: + MOV AL,[SYMFLG] + CMP AL,'S' + JNZ ENDSYM + MOV BX,SYMMES + CALL PRINT + MOV DX,[BASE] + MOV AL,DH + OR AL,DL + JZ EXIT + MOV BX,[HEAP] + MOV SP,BX + CALL NODE +ENDSYM: + TEST B,[LSTDEV],80H ;Print listing to file? + JZ EXIT + MOV AL,1AH + CALL WRTBUF ;Write end-of-file mark + CALL FLUSHBUF + MOV AX,[FCB+20] ;Get date of source file + MOV [LSTFCB+20],AX + MOV AH,CLOSE + INT 33 +EXIT: JMP 0 + +NODE: + XCHG DX,BX + PUSH BX + MOV DL,[BX] + MOV DH,0 + INC BX + ADD BX,DX + MOV DL,[BX] + INC BX + MOV DH,[BX] + MOV AL,DL + OR AL,DH + JZ L0014 + CALL NODE +L0014: + POP BX + MOV CH,[BX] + INC BX + MOV AL,SYMWID + SUB AL,CH + JNC LENOK + MOV AL,1 +LENOK: + MOV DH,AL +WRTSYM: + MOV AL,[BX] + INC BX + CALL LIST + DEC CH + JNZ WRTSYM + MOV CH,DH + INC CH + MOV AL,' ' +OUTB: + CALL LIST + DEC CH + JNZ OUTB + INC BX + INC BX + PUSH BX + INC BX + INC BX + INC BX + INC BX + MOV AL,[BX] + CALL PHEX + DEC BX + MOV AL,[BX] + CALL PHEX + CALL CRLF + POP BX + MOV DX,[BX] + INC BX + MOV AL,DH + OR AL,DL + JNZ NODE + RET + +SAVCD: + MOV [PREV],AL + PUSH BX + PUSH CX + PUSH AX + PUSH DX + CALL CODBYT + POP DX + MOV BX,COUNT + INC B,[BX] + MOV AL,[BX] + CMP AL,8 + JNZ NOEXT + MOV B,[BX],1 + CALL OUTLIN + MOV AL,' ' + MOV CH,5 +TAB: + CALL LIST + DEC CH + JNZ TAB +NOEXT: + POP AX + CALL PHEXB + POP CX + INC [PC] + INC [HEXADD] + POP BX + RET + +REPERR: + OR AL,AL + JZ RET + PUSH AX + MOV BX,ERRMES + CALL PRINT + POP AX + CALL PHEX + MOV BX,ENDMES + INC [ERRCNT] +PRINT: + MOV AL,[BX] + CALL LIST + OR AL,AL + JS RET + INC BX + JP PRINT + +OUTA: + MOV DL,AL +OUT: + AND DL,7FH + MOV CL,2 +SYSTEM: + CALL 5 + RET + +CODBYT: + CMP B,[HEXFCB],"Z" + JZ RET + PUSH AX + MOV DX,[LASTAD] + MOV BX,[HEXADD] + MOV [LASTAD],BX + INC DX + MOV AL,[HEXCNT] + CMP AL,-5 + JZ NEWLIN + CMP BX,DX + JZ AFHEX + CALL ENHEXL +NEWLIN: + MOV AL,':' + CALL PUTCHR + MOV AL,-4 + MOV [HEXCNT],AL + XOR AL,AL + MOV [CHKSUM],AL + MOV BX,[HEXPNT] + MOV [HEXLEN],BX + CALL HEXBYT + MOV AL,[HEXADD+1] + CALL HEXBYT + MOV AL,[HEXADD] + CALL HEXBYT + XOR AL,AL + CALL HEXBYT +AFHEX: + POP AX +HEXBYT: + MOV CH,AL + MOV BX,CHKSUM + ADD AL,[BX] + MOV [BX],AL + MOV AL,CH + CALL UHALF + CALL PUTCHR + MOV AL,CH + CALL LHALF + CALL PUTCHR + MOV BX,HEXCNT + INC B,[BX] + MOV AL,[BX] + CMP AL,26 + JNZ RET +ENHEXL: + MOV DI,[HEXLEN] + MOV CH,AL + CALL UHALF + STOB + MOV AL,CH + CALL LHALF + STOB + MOV AL,-6 + MOV [HEXCNT],AL + MOV AL,[CHKSUM] + ADD AL,CH + NEG AL + CALL HEXBYT + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR +WRTHEX: +;Write out the line + MOV DX,HEXBUF + MOV [HEXPNT],DX + MOV AH,SETDMA + INT 33 + SUB DI,DX ;Length of buffer + MOV CX,DI + MOV DX,HEXFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JNZ DSKFUL + RET + +PUTCHR: + MOV DI,[HEXPNT] + STOB + MOV [HEXPNT],DI + RET + +FLUSHBUF: + MOV CX,[LSTPNT] + MOV DX,LSTBUF + MOV DI,DX + SUB CX,DX + JZ RET ;Buffer empty? + MOV AH,SETDMA + INT 33 + MOV DX,LSTFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JZ RET +DSKFUL: + MOV BX,WRTERR + JMP PRERR + +UHALF: + RCR AL + RCR AL + RCR AL + RCR AL +LHALF: + AND AL,0FH + OR AL,30H + CMP AL,'9'+1 + JC RET + ADD AL,7 + RET + +NONE: DB 0 + +; 8086 MNEMONIC TABLE + +; This table is actually a sequence of subtables, each starting with a label. +; The label signifies which mnemonics the subtable applies to--A3, for example, +; means all 3-letter mnemonics beginning with A. + +A3: + DB 7 + DB 'dd' + DW GRP7 + DB 2 + DB 'nd' + DW GRP13 + DB 22H + DB 'dc' + DW GRP7 + DB 12H + DB 'aa' + DW PUT + DB 37H + DB 'as' + DW PUT + DB 3FH + DB 'am' + DW GRP11 + DB 0D4H + DB 'ad' + DW GRP11 + DB 0D5H +A5: + DB 1 + DB 'lign' + DW ALIGN + DB 0 +C3: + DB 7 + DB 'mp' + DW GRP7 + DB 3AH + DB 'lc' + DW PUT + DB 0F8H + DB 'ld' + DW PUT + DB 0FCH + DB 'li' + DW PUT + DB 0FAH + DB 'mc' + DW PUT + DB 0F5H + DB 'bw' + DW PUT + DB 98H + DB 'wd' + DW PUT + DB 99H +C4: + DB 3 + DB 'all' + DW GRP14 + DB 9AH + DB 'mpb' + DW PUT + DB 0A6H + DB 'mpw' + DW PUT + DB 0A7H +C5: + DB 2 + DB 'mpsb' + DW PUT + DB 0A6H + DB 'mpsw' + DW PUT + DB 0A7H +D2: + DB 5 + DB 'b' + DW GRP23 + DB 1 + DB 'w' + DW GRP23 + DB 0 + DB 'm' + DW GRP23 + DB 2 + DB 's' + DW GRP5 + DB 1 + DB 'i' + DW PUT + DB 0FAH +D3: + DB 4 + DB 'ec' + DW GRP8 + DB 49H + DB 'iv' + DW GRP10 + DB 30H + DB 'aa' + DW PUT + DB 27H + DB 'as' + DW PUT + DB 2FH +D4: + DB 1 + DB 'own' + DW PUT + DB 0FDH +E2: + DB 1 + DB 'i' + DW PUT + DB 0FBH +E3: + DB 3 + DB 'qu' + DW GRP5 + DB 2 + DB 'sc' + DW GRP19 + DB 0D8H + DB 'nd' + DW END + DB 0 +E5: + DB 1 + DB 'ndif' + DW ENDIF + DB 0 +H3: + DB 1 + DB 'lt' + DW PUT + DB 0F4H +H4: + DB 1 + DB 'alt' + DW PUT + DB 0F4H +I2: + DB 2 + DB 'n' + DW GRP4 + DB 0E4H + DB 'f' + DW GRP5 + DB 4 +I3: + DB 4 + DB 'nc' + DW GRP8 + DB 41H + DB 'nb' + DW GRP4 + DB 0E4H + DB 'nw' + DW GRP4 + DB 0E5H + DB 'nt' + DW GRP18 + DB 0CCH +I4: + DB 4 + DB 'mul' + DW GRP10 + DB 28H + DB 'div' + DW GRP10 + DB 38H + DB 'ret' + DW PUT + DB 0CFH + DB 'nto' + DW PUT + DB 0CEH +J2: + DB 10 + DB 'p' + DW GRP17 + DB 0EBH + DB 'z' + DW GRP17 + DB 74H + DB 'e' + DW GRP17 + DB 74H + DB 'l' + DW GRP17 + DB 7CH + DB 'b' + DW GRP17 + DB 72H + DB 'a' + DW GRP17 + DB 77H + DB 'g' + DW GRP17 + DB 7FH + DB 'o' + DW GRP17 + DB 70H + DB 's' + DW GRP17 + DB 78H + DB 'c' + DW GRP17 + DB 72H +J3: + DB 17 + DB 'mp' + DW GRP14 + DB 0EAH + DB 'nz' + DW GRP17 + DB 75H + DB 'ne' + DW GRP17 + DB 75H + DB 'nl' + DW GRP17 + DB 7DH + DB 'ge' + DW GRP17 + DB 7DH + DB 'nb' + DW GRP17 + DB 73H + DB 'ae' + DW GRP17 + DB 73H + DB 'nc' + DW GRP17 + DB 73H + DB 'ng' + DW GRP17 + DB 7EH + DB 'le' + DW GRP17 + DB 7EH + DB 'na' + DW GRP17 + DB 76H + DB 'be' + DW GRP17 + DB 76H + DB 'pe' + DW GRP17 + DB 7AH + DB 'np' + DW GRP17 + DB 7BH + DB 'po' + DW GRP17 + DB 7BH + DB 'no' + DW GRP17 + DB 71H + DB 'ns' + DW GRP17 + DB 79H +J4: + DB 6 + DB 'mps' + DW GRP17 + DB 0EBH + DB 'cxz' + DW GRP17 + DB 0E3H + DB 'nge' + DW GRP17 + DB 7CH + DB 'nae' + DW GRP17 + DB 72H + DB 'nbe' + DW GRP17 + DB 77H + DB 'nle' + DW GRP17 + DB 7FH +L3: + DB 3 + DB 'ea' + DW GRP6 + DB 8DH + DB 'ds' + DW GRP6 + DB 0C5H + DB 'es' + DW GRP6 + DB 0C4H +L4: + DB 5 + DB 'oop' + DW GRP17 + DB 0E2H + DB 'odb' + DW PUT + DB 0ACH + DB 'odw' + DW PUT + DB 0ADH + DB 'ahf' + DW PUT + DB 9FH + DB 'ock' + DW PUT + DB 0F0H +L5: + DB 4 + DB 'oope' + DW GRP17 + DB 0E1H + DB 'oopz' + DW GRP17 + DB 0E1H + DB 'odsb' + DW PUT + DB 0ACH + DB 'odsw' + DW PUT + DB 0ADH +L6: + DB 2 + DB 'oopne' + DW GRP17 + DB 0E0H + DB 'oopnz' + DW GRP17 + DB 0E0H +M3: + DB 2 + DB 'ov' + DW GRP1 + DB 88H + DB 'ul' + DW GRP10 + DB 20H +M4: + DB 2 + DB 'ovb' + DW PUT + DB 0A4H + DB 'ovw' + DW PUT + DB 0A5H +M5: + DB 2 + DB 'ovsb' + DW PUT + DB 0A4H + DB 'ovsw' + DW PUT + DB 0A5H +N3: + DB 3 + DB 'ot' + DW GRP9 + DB 10H + DB 'eg' + DW GRP9 + DB 18H + DB 'op' + DW PUT + DB 90H +O2: + DB 1 + DB 'r' + DW GRP13 + DB 0AH +O3: + DB 2 + DB 'ut' + DW GRP4 + DB 0E6H + DB 'rg' + DW GRP5 + DB 0 +O4: + DB 2 + DB 'utb' + DW GRP4 + DB 0E6H + DB 'utw' + DW GRP4 + DB 0E7H +P3: + DB 2 + DB 'op' + DW GRP22 + DB 8FH + DB 'ut' + DW GRP5 + DB 3 +P4: + DB 2 + DB 'ush' + DW GRP2 + DB 0FFH + DB 'opf' + DW PUT + DB 9DH +P5: + DB 1 + DB 'ushf' + DW PUT + DB 9CH +R3: + DB 6 + DB 'et' + DW GRP16 + DB 0C3H + DB 'ep' + DW PUT + DB 0F3H + DB 'ol' + DW GRP12 + DB 0 + DB 'or' + DW GRP12 + DB 8 + DB 'cl' + DW GRP12 + DB 10H + DB 'cr' + DW GRP12 + DB 18H +R4: + DB 2 + DB 'epz' + DW PUT + DB 0F3H + DB 'epe' + DW PUT + DB 0F3H +R5: + DB 2 + DB 'epnz' + DW PUT + DB 0F2H + DB 'epne' + DW PUT + DB 0F2H +S3: + DB 11 + DB 'ub' + DW GRP7 + DB 2AH + DB 'bb' + DW GRP7 + DB 1AH + DB 'bc' + DW GRP7 + DB 1AH + DB 'tc' + DW PUT + DB 0F9H + DB 'td' + DW PUT + DB 0FDH + DB 'ti' + DW PUT + DB 0FBH + DB 'hl' + DW GRP12 + DB 20H + DB 'hr' + DW GRP12 + DB 28H + DB 'al' + DW GRP12 + DB 20H + DB 'ar' + DW GRP12 + DB 38H + DB 'eg' + DW GRP21 + DB 26H +S4: + DB 5 + DB 'cab' + DW PUT + DB 0AEH + DB 'caw' + DW PUT + DB 0AFH + DB 'tob' + DW PUT + DB 0AAH + DB 'tow' + DW PUT + DB 0ABH + DB 'ahf' + DW PUT + DB 9EH +S5: + DB 4 + DB 'casb' + DW PUT + DB 0AEH + DB 'casw' + DW PUT + DB 0AFH + DB 'tosb' + DW PUT + DB 0AAH + DB 'tosw' + DW PUT + DB 0ABH +T4: + DB 1 + DB 'est' + DW GRP20 + DB 84H +U2: + DB 1 + DB 'p' + DW PUT + DB 0FCH +W4: + DB 1 + DB 'ait' + DW PUT + DB 9BH +X3: + DB 1 + DB 'or' + DW GRP13 + DB 32H +X4: + DB 2 + DB 'chg' + DW GRP3 + DB 86H + DB 'lat' + DW PUT + DB 0D7H + + +; 8087 MNEMONIC TABLE +; Similar to 8086 table above, except NOT distinguished by opcode length + +XM1: ;F2XM1 + DB 1 ;One opcode + DM "xm1" + DB 1,0F0H + +NDPA: + DB 3 + DM "dd" + DB 0,0C0H + DM "ddp" + DB 6,0C0H + DM "bs" + DB 1,0E0H + +NDPB: + DB 2 + DM "ld" + DB 7,20H + DM "stp" + DB 7,30H + +NDPC: + DB 5 + DM "om" + DB 0,0D0H + DM "omp" + DB 0,18H + DM "hs" + DB 1,0E0H + DM "ompp" + DB 6,0D9H + DM "lex" + DB 3,0E2H + +NDPD: + DB 6 + DM "iv" + DB 0,30H + DM "ivp" + DB 6,0F0H + DM "ivr" + DB 0,38H + DM "ivrp" + DB 6,0F8H + DM "ecstp" + DB 1,0F6H + DM "isi" + DB 3,0E1H + +NDPE: + DB 1 + DM "ni" + DB 3,0E0H + +NDPF: + DB 1 + DM "ree" + DB 5,0C0H + +NDPI: + DB 13 + DM "add" + DB 0,0 + DM "ld" + DB 0,0 + DM "sub" + DB 0,0 + DM "stp" + DB 0,0 + DM "st" + DB 0,0 + DM "mul" + DB 0,0 + DM "div" + DB 0,0 + DM "subr" + DB 0,0 + DM "divr" + DB 0,0 + DM "com" + DB 0,0 + DM "comp" + DB 0,0 + DM "ncstp" + DB 1,0F7H + DM "nit" + DB 3,0E3H + +NDPL: + DB 10 + DM "d" + DB 0,0 + DM "dz" + DB 1,0EEH + DM "d1" + DB 1,0E8H + DM "dpi" + DB 1,0EBH + DM "dl2t" + DB 1,0E9H + DM "dl2e" + DB 1,0EAH + DM "dlg2" + DB 1,0ECH + DM "dln2" + DB 1,0EBH + DM "dcw" + DB 1,0 + DM "denv" + DB 0,0 + +NDPM: + DB 2 + DM "ul" + DB 0,0 + DM "ulp" + DB 0,0 + +NDPP: + DB 3 + DM "rem" + DB 1,0F8H + DM "tan" + DB 1,0F2H + DM "atan" + DB 1,0F3H + +NDPR: + DB 2 + DM "ndint" + DB 1,0FCH + DM "stor" + DB 5,0 + +NDPS: + DB 12 + DM "t" + DB 0,0 + DM "tp" + DB 0,0 + DM "ub" + DB 0,0 + DM "ubp" + DB 0,0 + DM "ubr" + DB 0,0 + DM "ubrp" + DB 0,0 + DM "qrt" + DB 1,0FAH + DM "cale" + DB 1,0FDH + DM "ave" + DB 5,0 + DM "tcw" + DB 5,0 + DM "tenv" + DB 5,0 + DM "tsw" + DB 5,0 + +NDPT: + DB 1 + DM "st" + DB 1,0E4H + +NDPW: + DB 1 + DM "ait" + DB 0,0 + +NDPX: + DB 3 + DM "ch" + DB 1,0C4H + DM "am" + DB 1,0E5H + DM "tract" + DB 1,0F4H + +NDPY: + DB 2 + DM "l2x" + DB 1,0F1H + DM "l2xp1" + DB 1,0F9H + + +OPTAB: +; Table of pointers to mnemonics. For each letter of the alphabet (the +; starting letter of the mnemonic), there are 5 entries. Each entry +; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +; long, respectively. If there are no mnemonics for a given combination +; of first letter and length (such as A-2), then the corresponding entry +; points to NONE. Otherwise, it points to a place in the mnemonic table +; for that type. + +; This table only needs to be modified if a mnemonic is added to a group +; previously marked NONE. Change the NONE to a label made up of the first +; letter of the mnemonic and its length, then add a new subsection to +; the mnemonic table in alphabetical order. + + DW NONE + DW A3 + DW NONE + DW A5 + DW NONE + DW NONE ;B + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;C + DW C3 + DW C4 + DW C5 + DW NONE + DW D2 ;D + DW D3 + DW D4 + DW NONE + DW NONE + DW E2 ;E + DW E3 + DW NONE + DW E5 + DW NONE + DW NONE ;F + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;G + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;H + DW H3 + DW H4 + DW NONE + DW NONE + DW I2 ;I + DW I3 + DW I4 + DW NONE + DW NONE + DW J2 ;J + DW J3 + DW J4 + DW NONE + DW NONE + DW NONE ;K + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;L + DW L3 + DW L4 + DW L5 + DW L6 + DW NONE ;M + DW M3 + DW M4 + DW M5 + DW NONE + DW NONE ;N + DW N3 + DW NONE + DW NONE + DW NONE + DW O2 ;O + DW O3 + DW O4 + DW NONE + DW NONE + DW NONE ;P + DW P3 + DW P4 + DW P5 + DW NONE + DW NONE ;Q + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;R + DW R3 + DW R4 + DW R5 + DW NONE + DW NONE ;S + DW S3 + DW S4 + DW S5 + DW NONE + DW NONE ;T + DW NONE + DW T4 + DW NONE + DW NONE + DW U2 ;U + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;V + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;W + DW NONE + DW W4 + DW NONE + DW NONE + DW NONE ;X + DW X3 + DW X4 + DW NONE + DW NONE + DW NONE ;Y + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;Z + DW NONE + DW NONE + DW NONE + DW NONE + +NDPTAB: +;Lookup table for 8087 mnemonics. There is one entry for each letter of the +;alphabet + DW NDPA + DW NDPB + DW NDPC + DW NDPD + DW NDPE + DW NDPF + DW NONE ;G + DW NONE ;H + DW NDPI + DW NONE ;J + DW NONE ;K + DW NDPL + DW NDPM + DW NONE ;N + DW NONE ;O + DW NDPP + DW NONE ;Q + DW NDPR + DW NDPS + DW NDPT + DW NONE ;U + DW NONE ;V + DW NDPW + DW NDPX + DW NDPY + DW NONE ;Z + + +ERRMES: DM '***** ERROR no. ' +NOSPAC: DB 13,10,'No directory space',13,10,24H +ENDMES: DM 'H',13,10 +NOMEM: DB 13,10,'Insufficient memory',13,10,'$' +NOFILE: DB 13,10,'File not found',13,10,'$' +WRTERR: DB 13,10,'Disk full',13,10,'$' +BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' +ERCNTM: DM 13,10,13,10,'Error Count =' +SYMMES: DM 13,10,'Symbol Table',13,10,13,10 +EXTEND: DB 'ASM',0,0 +IFEND: DB 5,'endif' +IFNEST: DB 2,'if' +RETSTR: DM 'ret' +HEXFCB: DB 0,' HEX',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +LSTFCB: DB 0,' PRN',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +PC: DS 2 +OLDPC: DS 2 +LABPT: DS 2 +FLAG: DS 1 +LONG: DS 1 +ADDR: DS 2 +ALABEL: DS 2 +DATA: DS 2 +DLABEL: DS 2 +CON: DS 2 +UNDEF: DS 2 +LENID: DS 1 +ID: DS 80 +CHR: DS 1 +SYM: DS 1 +BASE: DS 2 +HEAP: DS 2 +SYMFLG: DS 1 +CODE: DS 2 +DATSIZ: DS 1 +RELOC: DS 1 +BCOUNT: DS 1 +COUNT: DS 1 +ERR: DS 1 +LINE: DS 2 +HEXLEN: DS 2 +HEXADD: DS 2 +LASTAD: DS 2 +HEXCNT: DS 1 +CHKSUM: DS 1 +LINFLG: DS 1 +PREV: DS 1 +IFFLG: DS 1 +CHKLAB: DS 1 +ERRCNT: DS 2 +LSTRET: DS 2 +RETPT: DS 2 +LSTDEV: DS 2 +SPC: DS 1 +NOWAIT: DS 1 +IX: DS 2 +IY: DS 2 +HEXPNT: DS 2 +LSTPNT: DS 2 +HEXBUF: DS HEXBUFSIZ +LSTBUF: DS LSTBUFSIZ +BUFPT: DS 2 +SRCBUF: DS BUFSIZ + DS 80 + ALIGN +STACK: EQU $ +START: EQU $ + \ No newline at end of file diff --git a/3_source_code/SCP_ASM/ASM_2.43.ASM b/3_source_code/SCP_ASM/ASM_2.43.ASM new file mode 100644 index 0000000..4408ba6 --- /dev/null +++ b/3_source_code/SCP_ASM/ASM_2.43.ASM @@ -0,0 +1,3992 @@ +; Seattle Computer Products 8086 Assembler version 2.43 +; by Tim Paterson +; Runs on the 8086 under MS-DOS + +;* * * * * * REVISION HISTORY * * * * * * +; +; 12/29/80 2.01 General release with 86-DOS version 0.34 +; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes +; 03/18/81 2.11 General cleanup and more documentation +; 03/24/81 2.20 Modify ESC handling for full 8087 operation +; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling +; 04/03/81 2.22 Fix 2.21 buffer handling +; 04/13/81 2.23 Re-open source file for listing to allow assembling CON: +; 04/28/81 2.24 Allow nested IFs +; 07/30/81 2.25 Add Intel string mnemonics; clean up a little +; 08/02/81 2.30 Re-write pass 2: +; Always report errors to console +; Exact byte lengths for HEX and PRN files +; 11/08/81 2.40 Add 8087 mnemonics; print full error messages; +; allow expressions with *, /, and () +; 07/04/82 2.41 Fix Intel's 8087 "reverse-bit" bug; don't copy date +; 08/18/82 2.42 Increase stack from 80 to 256 (Damn! Overflowed again!) +; 01/05/82 2.43 Correct over-zealous optimization in 2.42 +; +;* * * * * * * * * * * * * * * * * * * * * + +SYMWID: EQU 5 ;5 symbols per line in dump +FCB: EQU 5CH +BUFSIZ: EQU 1024 ;Source code buffer +LSTBUFSIZ:EQU BUFSIZ ;List file buffer +HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA) +EOL: EQU 13 ;ASCII carriage return +OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS + +;System call function codes +PRINTMES: EQU 9 +OPEN: EQU 15 +CLOSE: EQU 16 +READ: EQU 20 +SETDMA: EQU 26 +MAKE: EQU 22 +BLKWRT: EQU 40 + +;The following equates define some token values returned by GETSYM +UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET) +CONST: EQU 1 ;Constant (including $) +REG: EQU 2 ;8-bit register +XREG: EQU 3 ;16-bit register (except segment registers) +SREG: EQU 4 ;Segment register +FREG: EQU 6 ;8087 floating point register + +;Bits to build 8087 opcode table entries +ONEREG: EQU 40H ;Single ST register OK as operand +NEEDOP: EQU 80H ;Must have an operand +INTEGER:EQU 20H ;For integer operations +REAL: EQU 28H ;For real operations +EXTENDED EQU 10H ;For Long integers or Temporary real +MEMORY: EQU 18H ;For general memory operations +STACKOP:EQU 10H ;Two register arithmetic with pop +ARITH: EQU 8 ;Non-pop arithmetic operations + + ORG 100H + PUT 100H + + JMPS BEGIN + +HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.43' + DB 13,10,'Copyright 1979-1982 by Seattle Computer Products, Inc.' + DB 13,10,13,10,'$' + +BEGIN: + MOV SP,STACK + MOV DX,HEADER + MOV AH,PRINTMES + INT 33 + MOV AL,[FCB+17] + MOV [SYMFLG],AL ;Save symbol table request flag + MOV SI,FCB+9 ;Point to file extension + LODB ;Get source drive letter + CALL CHKDSK ;Valid drive? + OR AL,AL + JZ DEFAULT ;If no extension, use existing drive spec + MOV [FCB],AL +DEFAULT: + LODB ;Get HEX file drive letter + CMP AL,'Z' ;Suppress HEX file? + JZ L0000 + CALL CHKDSK +L0000: + MOV [HEXFCB],AL + LODB ;Get PRN file drive letter + MOV AH,0 ;Signal no PRN file + CMP AL,'Z' ;Suppress PRN file? + JZ NOPRN + CMP AL,'Y' ;Print errors only on console? + JZ NOPRN + MOV AH,2 + CMP AL,'X' ;PRN file to console? + JZ NOPRN + MOV AH,4 + CMP AL,'P' ;PRN file to printer? + JZ NOPRN + CALL CHKDSK + MOV AH,80H +NOPRN: + MOV [LSTFCB],AL + MOV [LSTDEV],AH ;Flag device for list ouput + MOV SI,EXTEND + MOV DI,FCB+9 + MOVW + MOVB ;Set extension to ASM + MOVW ;Zero extent field + MOV DX,FCB + MOV AH,OPEN + INT 33 + MOV BX,NOFILE + OR AL,AL + JZ $+5 + JMP PRERR + MOV DX,HEXFCB + CALL MAKFIL + MOV DX,LSTFCB + CALL MAKFIL + XOR AX,AX + MOV [FCB+12],AX ;Zero CURRENT BLOCK field + MOV [FCB+32],AL ;Zero Next Record field + MOV [FCB+14],BUFSIZ ;Set record size + MOV [BUFPT],SRCBUF ;Initialize buffer pointer + MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE + MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE + XOR AX,AX + MOV [PC],AX ;DEFAULT PROGRAM COUNTER + MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL + MOV [RETPT],AX ;Pointer to last RET record + MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF + MOV [CHKLAB],AL ;LOOKUP ALL LABELS + DEC AX + MOV [LSTRET],AX ;Location of last RET + MOV AX,[6] ;HL=END OF MEMORY + MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE + MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE + +;Assemble each line of code + +LOOP: + CALL NEXTCHR ;Get first character on line + CMP AL,1AH + JZ ENDJ + MOV AL,-1 ;Flag that no tokens have been read yet + MOV [SYM],AL + CALL ASMLIN ;Assemble the line + MOV AL,[SYM] + CMP AL,-1 ;Any tokens found on line? + JNZ L0002 + CALL GETSYM ;If no tokens read yet, read first one +L0002: + CMP AL,';' + JZ ENDLN + CMP AL,EOL + JZ ENDLN + MOV AL,14H ;Garbage at end of line error + JP ENDLIN +ENDJ: JMP END + +ENDLN: + XOR AL,AL ;Flag no errors on line +ENDLIN: +;AL = error code for line. Stack depth unknown + MOV SP,STACK + CALL NEXLIN + JP LOOP + +NEXLIN: + MOV CH,0C0H ;Put end of line marker and error code (AL) + CALL PUTCD + CALL GEN1 + MOV AL,[CHR] +GETEOL: + CMP AL,10 + JZ RET + CMP AL,1AH + JZ ENDJ + CALL NEXTCHR ;Scan over comments for linefeed + JP GETEOL + +ABORT: + MOV BX,NOMEM +PRERR: + MOV DX,BX + MOV AH,PRINTMES + INT 33 + INT 32 + +MAKFIL: + MOV SI,DX + LODB ;Get drive select byte + CMP AL,20H ;If not valid, don't make file + JNC RET + MOV CX,4 + MOV DI,SI + MOV SI,FCB+1 + REP + MOVW ;Copy source file name + MOV AH,MAKE + INT 33 + MOV [DI-9+14],1 ;Set record length to 1 byte + MOV BX,NOSPAC + OR AL,AL ;Success? + JNZ PRERR + RET + +CHKDSK: + SUB AL,' ' ;If not present, set zero flag + JZ RET + SUB AL,20H + JZ DSKERR ;Must be in range A-O + CMP AL,'P'-'@' + JC RET +DSKERR: + MOV BX,BADDSK + JP PRERR + +ERROR: + MOV AL,CL + JMP ENDLIN + +NEXTCHR: + MOV SI,[BUFPT] + CMP SI,SRCBUF + JNZ GETCH +;Buffer empty so refill it + PUSH DX + PUSH AX ;AH must be saved + MOV DX,SI + MOV AH,SETDMA + INT 33 + MOV DX,FCB + MOV AH,READ + INT 33 + XCHG AX,DX ;Put error code in DL + POP AX ;Restore AH + MOV AL,DL ;Error code back in AL + POP DX + CMP AL,1 + MOV AL,1AH ;Possibly signal End of File + JZ NOMOD ;If nothing read +GETCH: + LODB + CMP SI,SRCBUF+BUFSIZ + JNZ NOMOD + MOV SI,SRCBUF +NOMOD: + MOV [BUFPT],SI + MOV [CHR],AL + RET + + +MROPS: + +; Get two operands and check for certain types, according to flag byte +; in CL. OP code in CH. Returns only if immediate operation. + + PUSH CX ;Save type flags + CALL GETOP + PUSH DX ;Save first operand + CALL GETOP2 + POP BX ;First op in BX, second op in DX + MOV AL,SREG ;Check for a segment register + CMP AL,BH + JZ SEGCHK + CMP AL,DH + JZ SEGCHK + MOV AL,CONST ;Check if the first operand is immediate + MOV CL,26 + CMP AL,BH + JZ ERROR ;Error if so + POP CX ;Restore type flags + CMP AL,DH ;If second operand is immediate, then done + JZ RET + MOV AL,UNDEFID ;Check for memory reference + CMP AL,BH + JZ STORE ;Is destination memory? + CMP AL,DH + JZ LOAD ;Is source memory? + TEST CL,1 ;Check if register-to-register operation OK + MOV CL,27 + JZ ERROR + MOV AL,DH + CMP AL,BH ;Registers must be of same length +RR: + MOV CL,22 + JNZ ERROR +RR1: + AND AL,1 ;Get register length (1=16 bits) + OR AL,CH ;Or in to OP code + CALL PUT ;And write it + POP CX ;Dump return address + MOV AL,BL + ADD AL,AL ;Rotate register number into middle position + ADD AL,AL + ADD AL,AL + OR AL,0C0H ;Set register-to-register mode + OR AL,DL ;Combine with other register number + JMP PUT + +SEGCHK: +;Come here if at least one operand is a segment register + POP CX ;Restore flags + TEST CL,8 ;Check if segment register OK + MOV CL,22 + JZ ERR1 + MOV CX,8E03H ;Segment register move OP code + MOV AL,UNDEFID + CMP AL,DH ;Check if source is memory + JZ LOAD + CMP AL,BH ;Check if destination is memory + JZ STORE + MOV AL,XREG + SUB AL,DH ;Check if source is 16-bit register + JZ RR ;If so, AL must be zero + MOV CH,8CH ;Change direction + XCHG DX,BX ;Flip which operand is first and second + MOV AL,XREG + SUB AL,DH ;Let RR perform finish the test + JP RR + +STORE: + TEST CL,004H ;Check if storing is OK + JNZ STERR + XCHG DX,BX ;If so, flip operands + AND CH,0FDH ; and zero direction bit +LOAD: + MOV DH,25 + CMP AL,BH ;Check if memory-to-memory + JZ MRERR + MOV AL,BH + CMP AL,REG ;Check if 8-bit operation + JNZ XRG + MOV DH,22 + TEST CL,1 ;See if 8-bit operation is OK + JZ MRERR +XRG: + MOV AL,DL + SUB AL,6 ;Check for R/M mode 6 and register 0 + OR AL,BL ; meaning direct load/store of accumulator + JNZ NOTAC + TEST CL,8 ;See if direct load/store of accumulator + JZ NOTAC ; means anything in this case +; Process direct load/store of accumulator + MOV AL,CH + AND AL,2 ;Preserve direction bit only + XOR AL,2 ; but flip it + OR AL,0A0H ;Combine with OP code + MOV CH,AL + MOV AL,BH ;Check byte/word operation + AND AL,1 + OR AL,CH + POP CX ;Dump return address + JMP PUTADD ;Write the address + +NOTAC: + MOV AL,BH + AND AL,1 ;Get byte/word bit + AND AL,CL ;But don't use it in word-only operations + OR AL,CH ;Combine with OP code + CALL PUT + MOV AL,BL + ADD AL,AL ;Rotate to middle position + ADD AL,AL + ADD AL,AL + OR AL,DL ;Combine register field + POP CX ;Dump return address + JMP PUTADD ;Write the address + +STERR: + MOV DH,29 +MRERR: + MOV CL,DH + +ERR1: JMP ERROR + +GETOP2: +;Get the second operand: look for a comma and drop into GETOP + MOV AL,[SYM] + CMP AL,',' + MOV CL,21 + JNZ ERR1 + + +GETOP: + +; Get one operand. Operand may be a memory reference in brackets, a register, +; or a constant. If a flag (such as "B" for byte operation) is encountered, +; it is noted and processing continues to find the operand. +; +; On exit, AL (=DH) has the type of operand. Other information depends +; on the actual operand: +; +; AL=DH=0 Memory Reference. DL has the address mode properly prepared in +; the 8086 R/M format (middle bits zero). The constant part of the address +; is in ADDR. If an undefined label needs to be added to this, a pointer to +; its information fields is in ALABEL, otherwise ALABEL is zero. +; +; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs +; to be added to this, a pointer to its information fields is in DLABEL, +; otherwise DLABEL is zero. "$" and "RET" are in this class. +; +; AL=DH=2 8-bit Register. DL has the register number. +; +; AL=DH=3 16-bit Register. DL has the register number. +; +; AL=DH=4 Segment Register. DL has the register number. + + CALL GETSYM +GETOP1: +;Enter here if we don't need a GETSYM first + CMP AL,'[' ;Memory reference? + JZ MEM + CMP AL,5 ;Flag ("B", "W", etc.)? + JZ FLG + CMP AL,REG ;8-Bit register? + JZ NREG + CMP AL,XREG ;16-Bit register? + JZ NREG + CMP AL,SREG ;Segment register? + JZ NREG +VAL: ;Must be immediate + XOR AL,AL ;No addressing modes allowed +VAL1: + CALL GETVAL + MOV AX,[CON] ;Defined part + MOV [DATA],AX + MOV AX,[UNDEF] ;Undefined part + MOV [DLABEL],AX + MOV DL,CH + MOV DH,CONST + MOV AL,DH + RET +NREG: + PUSH DX + CALL GETSYM + POP DX + MOV AL,DH + RET +MEM: + CALL GETSYM + MOV AL,1 + CALL GETVAL + MOV AL,[SYM] + CMP AL,']' + MOV CL,24 + JNZ ERR1 + CALL GETSYM + MOV BX,[CON] + MOV [ADDR],BX + MOV BX,[UNDEF] + MOV [ALABEL],BX + MOV DL,CH + MOV DH,UNDEFID + MOV AL,DH + RET +FLG: + CMP DL,[MAXFLG] ;Invalid flag for this operation? + MOV CL,27H + JG ERR1 + CALL GETSYM + CMP AL,',' + JZ GETOP + JP GETOP1 + + +GETVAL: + +; Expression analyzer. On entry, if AL=0 then do not allow base or index +; registers. If AL=1, we are analyzing a memory reference, so allow base +; and index registers, and compute addressing mode when done. The constant +; part of the expression will be found in CON. If an undefined label is to +; be added to this, a pointer to its information fields will be found in +; UNDEF. + + MOV AH,AL ;Flag is kept in AH + MOV [UNDEF],0 + MOV AL,[SYM] + CALL EXPRESSION + MOV [CON],DX + MOV AL,AH + MOV CH,0 ;Initial mode + TEST AL,10H ;Test INDEX bit + RCL AL ;BASE bit (zero flag not affected) + JZ NOIND ;Jump if not indexed, with BASE bit in carry + CMC + RCL CH ;Rotate in BASE bit + RCL AL ;BP bit + RCL CH + RCL AL ;DI bit + RCL CH ;The low 3 bits now have indexing mode +MODE: + OR CH,080H ;If undefined label, force 16-bit displacement + TEST [UNDEF],-1 + JNZ RET + MOV BX,[CON] + MOV AL,BL + CBW ;Extend sign + CMP AX,BX ;Is it a signed 8-bit number? + JNZ RET ;If not, use 16-bit displacement + AND CH,07FH ;Reset 16-bit displacement + OR CH,040H ;Set 8-bit displacement + OR BX,BX + JNZ RET ;Use it if not zero displacement + AND CH,7 ;Specify no displacement + CMP CH,6 ;Check for BP+0 addressing mode + JNZ RET + OR CH,040H ;If BP+0, use 8-bit displacement + RET + +NOIND: + MOV CH,6 ;Try direct address mode + JNC RET ;If no base register, that's right + RCL AL ;Check BP bit + JC MODE + INC CH ;If not, must be BX + JP MODE + +EXPRESSION: +;Analyze arbitrary expression. Flag byte in AH. +;On exit, AL has type byte: 0=register or undefined label + MOV CH,-1 ;Initial type + MOV DI,DX + XOR DX,DX ;Initial value + CMP AL,'+' + JZ PLSMNS + CMP AL,'-' + JZ PLSMNS + MOV CL,'+' + PUSH DX + PUSH CX + MOV DX,DI + JP OPERATE +PLSMNS: + MOV CL,AL + PUSH DX + PUSH CX + OR AH,4 ;Flag that a sign was found + CALL GETSYM +OPERATE: + CALL TERM + POP CX ;Recover operator + POP BX ;Recover current value + XCHG DX,BX + AND CH,AL + OR AL,AL ;Is it register or undefined label? + JZ NOCON ;If so, then no constant part + CMP CL,"-" ;Subtract it? + JNZ ADD + NEG BX +ADD: + ADD DX,BX +NEXTERM: + MOV AL,[SYM] + CMP AL,'+' + JZ PLSMNS + CMP AL,'-' + JZ PLSMNS + MOV AL,CH + RET +NOCON: + CMP CL,"-" + JNZ NEXTERM +BADOP: + MOV CL,5 + JMP ERROR + +TERM: + CALL FACTOR +MULOP: + PUSH DX ;Save value + PUSH AX ;Save type + CALL GETSYM + POP CX + CMP AL,"*" + JZ GETFACT + CMP AL,"/" + JNZ ENDTERM +GETFACT: + OR CL,CL ;Can we operate on this type? + JZ BADOP + PUSH AX ;Save operator + CALL GETSYM ;Get past operator + CALL FACTOR + OR AL,AL + JZ BADOP + POP CX ;Recover operator + POP BP ;And current value + XCHG AX,BP ;Save AH in BP + CMP CL,"/" ;Do we divide? + JNZ DOMUL + OR DX,DX ;Dividing by zero? + MOV CL,29H + JZ ERR2 + MOV BX,DX + XOR DX,DX ;Make 32-bit dividend + DIV AX,BX + JMPS NEXFACT +DOMUL: + MUL AX,DX +NEXFACT: + MOV DX,AX ;Result in DX + XCHG AX,BP ;Restore flags to AH + MOV AL,-1 ;Indicate a number + JMPS MULOP +ENDTERM: + POP DX + MOV AL,CL + RET + +FACTOR: + MOV AL,[SYM] + CMP AL,CONST + JZ RET + CMP AL,UNDEFID + JZ UVAL + CMP AL,"(" + JZ PAREN + CMP AL,'"' + JZ STRING + CMP AL,"'" + JZ STRING + CMP AL,XREG ;Only 16-bit register may index + MOV CL,20 + JNZ ERR2 + TEST AH,1 ;Check to see if indexing is OK + MOV CL,1 + JZ ERR2 + MOV AL,DL + MOV CL,3 + SUB AL,3 ;Check for BX + JZ BXJ + SUB AL,2 ;Check for BP + JZ BPJ + DEC AL ;Check for SI + MOV CL,4 + JZ SIJ + DEC AL ;Check for DI + JZ DIJ + MOV CL,2 ;Invalid base/index register +ERR2: JMP ERROR + +DIJ: + OR AH,20H ;Flag seeing index register DI +SIJ: + TEST AH,10H ;Check if already seen index register + JNZ ERR2 + OR AH,10H ;Flag seeing index register + RET + +BPJ: + OR AH,40H ;Flag seeing base register BP +BXJ: + TEST AH,80H ;Check if already seen base register + JNZ ERR2 + OR AH,80H ;Flag seeing base register + RET + +PAREN: + CALL GETSYM ;Eat the "(" + CALL EXPRESSION + CMP B,[SYM],")" ;Better have closing paren + MOV CL,20 + JNZ ERR30 + RET + +UVAL: + MOV CL,6 + TEST AH,8 ;Check if undefined label has been seen + JNZ ERR30 + OR AH,8 ;Flag seeing undefined label + MOV [UNDEF],BX + RET + +ERR30: JMP ERROR + +STRING: + MOV CH,AL + MOV AL,[CHR] + CMP AL,CH + MOV CL,35 + MOV DL,AL + MOV DH,0 + JNZ L0003 + CALL ZERLEN +L0003: + CALL GETCHR + MOV CL,37 + TEST AH,2 + JZ ERR30 + TEST AH,4 + MOV CL,38 + JNZ ERR30 +STRGDAT: + MOV AL,DL + CMP AL,EOL + MOV CL,39 + JZ ERR30 + CALL PUT + MOV AL,[DATSIZ] + OR AL,AL + JNZ BYTSIZ + MOV AL,DH + CALL PUT +BYTSIZ: + MOV AL,[CHR] + MOV DL,AL + CALL GETCHR + JP STRGDAT + +ZERLEN: + CALL NEXTCHR + CMP AL,CH + JNZ ERR30 + RET + +GETCHR: + CALL NEXTCHR + CMP AL,CH + JNZ RET + CALL NEXTCHR + CMP AL,CH + JZ RET + POP BX ;Kill return address to STRGDAT loop + MOV AL,-1 ;Flag type as constant + RET + + +GETSYM: + +; The lexical scanner. Used only in the operand field. Returns with the token +; in SYM and AL, sometimes with additional info in BX or DX. +; +; AL=SYM=0 Undefined label. BX has pointer to information fields. +; +; AL=SYM=1 Constant (or defined label). DX has value. +; +; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register, +; respectively. DL has register number. +; +; AL=SYM=5 A mode flag (such as "B" for byte operation). Type of flag in DL +; and also stored in FLAG: -1=no flags, 0=B, 1=W, 2=S, 3=L, 4=T. +; +; AL=SYM=6 8087 floating point register, ST(n) or ST. DL has register number. +; +; All other values are the ASCII code of the character. Note that this may +; never be a letter or number. + + PUSH AX ;Save AH + CALL GETSY + POP AX + MOV AL,[SYM] + RET + +SCANB: + MOV AL,[CHR] +SCANT: + CMP AL,' ' + JZ NEXB + CMP AL,9 + JNZ RET +NEXB: + CALL NEXTCHR + JP SCANT + +DOLLAR: + MOV DX,[OLDPC] + MOV AL,CONST + MOV [SYM],AL +NEXTCHJ: + JMP NEXTCHR + +GETSY: + CALL SCANB + CMP AL,'$' + JZ DOLLAR + MOV [SYM],AL + OR AL,20H + CMP AL,'z'+1 + JNC NEXTCHJ + CMP AL,'a' + JC $+5 + JMP LETTER + CMP AL,'9'+1 + JNC NEXTCHJ + CMP AL,'0' + JC NEXTCHJ + MOV BX,SYM + MOV B,[BX],CONST + CALL READID + DEC BX + MOV AL,[BX] + MOV CL,7 + MOV BX,0 + CMP AL,'h' + JNZ $+5 + JMP HEX + INC CL + MOV [IX],ID +DEC: + MOV SI,[IX] + MOV AL,[SI] + INC [IX] + CMP AL,'9'+1 + JC $+5 + JMP ERROR + SUB AL,'0' + MOV DX,BX + SHL BX + SHL BX + ADD BX,DX + SHL BX + MOV DL,AL + MOV DH,0 + ADD BX,DX + DEC CH + JNZ DEC + XCHG DX,BX + RET + +HEX: + MOV DX,ID + DEC CH +HEX1: + MOV SI,DX + LODB + INC DX + SUB AL,'0' + CMP AL,10 + JC GOTIT + CMP AL,'g'-'0' + JNC ERR4 + SUB AL,'a'-10-'0' +GOTIT: + SHL BX + SHL BX + SHL BX + SHL BX + ADD BL,AL + DEC CH + JNZ HEX1 + XCHG DX,BX + RET + +ERR4: JMP ERROR + +GETLET: + CALL SCANB + CMP AL,EOL + STC + JZ RET + CMP AL,';' + STC + JZ RET + MOV CL,10 + OR AL,20H + CMP AL,'a' + JC ERR4 + CMP AL,'z'+1 + JNC ERR4 +READID: + MOV BX,ID + MOV CH,0 +MOREID: + MOV [BX],AL + INC CH + INC BX + CALL NEXTCHR + CMP AL,'0' + JC NOMORE + OR AL,20H + CMP AL,'z'+1 + JNC NOMORE + CMP AL,'9'+1 + JC MOREID + CMP AL,'a' + JNC MOREID +NOMORE: + MOV CL,AL + MOV AL,CH + MOV [LENID],AL + OR AL,AL + MOV AL,CL + RET + +LETTER: + CALL READID + MOV AL,CH + DEC AL + JNZ NOFLG + MOV AL,[ID] + MOV CX,5 + MOV DI,FLGTAB + UP + REPNE + SCAB ;See if one of B,W,S,L,T + JZ SAVFLG ;Go save flag + XOR AL,AL + MOV CH,[LENID] +NOFLG: + DEC AL + PUSH BX + JNZ L0004 + CALL REGCHK +L0004: + POP BX + MOV AL,DH + JZ SYMSAV + CALL LOOKRET +SYMSAV: + MOV [SYM],AL + RET + +SAVFLG: + MOV DL,CL ;Need flag type in DL + XCHG [FLAG],CL + CMP CL,-1 + MOV CL,32 + MOV AL,5 + JZ SYMSAV +ERRJ3: JMP ERROR + +FLGTAB: DB "tlswb" + +FPREG: +;Have detected "ST" for 8087 floating point stack register + MOV DL,0 ;Default is ST(0) + CALL SCANB ;Get next character + CMP AL,"(" ;Specifying register number? + JNZ HAVREG +;Get register number + CALL NEXTCHR ;Skip over the "(" + CALL GETOP ;A little recursion never hurt anybody + CMP AL,CONST ;Better have found a constant + MOV CL,20 ;Operand error if not + JNZ ERRJ3 + CMP [DLABEL],0 ;Constant must be defined + MOV CL,30 + JNZ ERRJ3 + MOV DX,[DATA] ;Get constant + CMP DX,7 ;Constant must be in range 0-7 + MOV CL,31 + JA ERRJ3 + MOV AL,[SYM] + CMP AL,")" + MOV CL,24 + JNZ ERRJ3 +HAVREG: + MOV DH,FREG + XOR AL,AL ;Zero set means register found + RET + +REGCHK: + MOV BX,ID + CMP [BX],"s"+7400H ;"st" + JZ FPREG + MOV CL,[BX] + INC BX + MOV AL,[BX] + MOV BX,REGTAB + MOV DH,XREG + MOV DL,0 + CMP AL,'x' + JZ SCANREG + MOV DH,REG + CMP AL,'l' + JZ SCANREG + MOV DL,4 + CMP AL,'h' + JZ SCANREG + MOV DH,SREG + MOV DL,0 + MOV BX,SEGTAB + CMP AL,'s' + JZ SCANREG + MOV DH,XREG + CMP AL,'p' + JZ PREG + CMP AL,'i' + JNZ RET + MOV DL,6 + MOV AL,CL + CMP AL,'s' + JZ RET + INC DL + CMP AL,'d' + RET +PREG: + MOV DL,4 + MOV AL,CL + CMP AL,'s' + JZ RET + INC DL + CMP AL,'b' + RET +SCANREG: + MOV AL,CL + MOV CX,4 + UP + MOV DI,BX + REPNZ + SCAB + MOV BX,DI + JNZ RET + MOV AL,CL + ADD AL,DL + MOV DL,AL + XOR AL,AL + RET + +REGTAB: DB 'bdca' + +SEGTAB: DB 'dsce' + +LOOK: + MOV CH,[BX] + INC BX + MOV DX,ID + CALL CPSLP + JZ RET + XOR AL,80H + ROL AL ;Make end-of-symbol bit least significant + MOV CL,AL + DEC BX + MOV AL,[BX] + XOR AL,80H + ROL AL + CMP AL,CL + JNC SMALL + INC CH + INC CH +SMALL: + MOV DL,CH + MOV DH,0 + ADD BX,DX + MOV DX,[BX] + INC BX + MOV AL,DL + OR AL,DH + STC + JZ RET + XCHG DX,BX + JP LOOK + +LOOKRET: + MOV AL,CH + CMP AL,3 ;RET has 3 letters + JNZ LOOKUP + DEC BX + OR B,[BX],080H + MOV DX,RETSTR+2 +CHKRET: + MOV SI,DX + LODB + CMP AL,[BX] + JNZ LOOKIT + DEC BX + DEC DX + DEC CH + JNZ CHKRET + MOV DX,[LSTRET] + MOV AL,DL + AND AL,DH + INC AL + JZ ALLRET + MOV BX,[PC] + SUB BX,DX + MOV AL,BL + CBW + CMP AX,BX ;Signed 8-bit number? + MOV AL,1 + JZ RET +ALLRET: + MOV BX,[RETPT] + MOV AL,BH + OR AL,BL + MOV AL,0 + JNZ RET + MOV BX,[HEAP] + DEC BX + DEC BX + DEC BX + MOV [HEAP],BX + XOR AL,AL + MOV [BX],AL + MOV [RETPT],BX + RET + +LOOKUP: + DEC BX + OR B,[BX],080H +LOOKIT: + MOV BX,[BASE] + MOV AL,BH + OR AL,BL + JZ EMPTY + CALL LOOK + JC ENTER + MOV DX,4 + ADD BX,DX + MOV AL,[BX] + OR AL,AL + JZ RET + INC BX + MOV DX,[BX] + INC BX + RET + +ENTER: + PUSH BX ;Save pointer to link field + CALL CREATE ;Add the node + POP SI + MOV [SI-1],DX ;Link new node + RET ;Zero was set by CREATE + +EMPTY: + CALL CREATE + MOV [BASE],DX + RET + + +CREATE: + +; Add a new node to the identifier tree. The identifier is at ID with +; bit 7 of the last character set to one. The length of the identifier is +; in LENID, which is ID-1. +; +; Node format: +; 1. Length of identifier (1 byte) +; 2. Identifier (1-80 bytes) +; 3. Left link (2-byte pointer to alphabetically smaller identifiers) +; 4. Right link (0 if none larger) +; 5. Data field: +; a. Defined flag (0=undefined, 1=defined) +; b. Value (2 bytes) +; +; This routine returns with AL=zero and zero flag set (which indicates +; on return from LOOKUP that it has not yet been defined), DX points +; to start of new node, and BX points to data field of new node. + + MOV AL,[LENID] + ADD AL,8 ;Storage needed for the node + MOV BX,[HEAP] + MOV DL,AL + MOV DH,0 + SUB BX,DX ;Heap grows downward + MOV [HEAP],BX + XCHG DX,BX + MOV BX,[CODE] ;Check to make sure there's enough + CMP BX,DX + JB $+5 + JMP ABORT + PUSH DX + MOV BX,LENID + MOV CL,[BX] + INC CL + MOV CH,0 + UP + MOV SI,BX + MOV DI,DX + REP + MOVB ;Move identifier and length into node + MOV DX,DI + MOV BX,SI + MOV CH,4 + XCHG DX,BX +NILIFY: + MOV [BX],CL ;Zero left and right links + INC BX + DEC CH + JNZ NILIFY + XOR AL,AL ;Set zero flag + MOV [BX],AL ;Zero defined flag + POP DX ;Restore pointer to node + RET + +CPSLP: + MOV SI,DX + LODB + CMP AL,[BX] + LAHF + INC DX + INC BX + SAHF + JNZ RET + DEC CH + JNZ CPSLP + RET + +GETLAB: + MOV BX,0 + MOV [LABPT],BX + MOV B,[FLAG],-1 + MOV DH,0 + MOV AL,[CHR] + CMP AL,' '+1 + JC NOT1 + OR DH,001H +NOT1: + CALL GETLET + JC RET + CMP AL,':' + JNZ LABCHK + CALL NEXTCHR + JP LABEL +LABCHK: + OR AL,AL + TEST DH,001H + JZ RET +LABEL: + MOV AL,[CHKLAB] + OR AL,AL + JZ $+5 + JMP GETLET + CALL LOOKUP + MOV CL,11 + JNZ ERR5 + MOV DX,[PC] + MOV B,[BX],1 + INC BX + MOV [BX],DX + MOV [LABPT],BX + JMP GETLET + +ERR5: JMP ERROR + +ASMLIN: + MOV B,[MAXFLG],1 ;Allow only B and W flags normally + MOV BX,[PC] + MOV [OLDPC],BX + CALL GETLAB + JNC $+5 + JMP ENDLN + MOV BX,LENID + MOV AL,[BX] + MOV CL,12 + SUB AL,2 + MOV CH,AL + JC ERR5 + INC BX + CMP B,[BX],"f" ;See if an 8087 mnemonic + JZ NDPOP + CMP AL,5 + JNC ERR5 + MOV AL,[BX] + SUB AL,'a' + MOV CL,AL + ADD AL,AL + ADD AL,AL + ADD AL,CL + ADD AL,CH + ADD AL,AL + MOV BX,OPTAB + MOV DL,AL + MOV DH,0 + ADD BX,DX + MOV BX,[BX] + INC CH + MOV CL,CH + MOV AH,[BX] + INC BX + OR AH,AH + JZ OPERR +FINDOP: + MOV CH,CL + MOV DX,ID+1 + XCHG AX,BP ;Save count of opcodes in BP + CALL CPSLP + JZ HAVOP + XCHG AX,BP + MOV DH,0 + MOV DL,CH + INC DX + INC DX + ADD BX,DX + DEC AH + JNZ FINDOP +OPERR: + MOV CL,12 + JMP ERROR + +HAVOP: + MOV AL,[BX+2] ;Get opcode + JMP [BX] + +NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor") + MOV B,[MAXFLG],4 ;Allow all type flags + INC BX + CMP B,[BX],"n" ;"No-wait" form? + MOV AH,0 + JNZ SAVNFLG + MOV AH,1 + DEC AL + INC BX ;Skip over the "N" +SAVNFLG: + MOV [NOWAIT],AH ;0 for wait, 1 for no wait + CMP AL,1 + JB OPERR ;Not enough char left for valid opcode? + CMP AL,5 + JA OPERR ;Too many? + CBW + XCHG AX,DX ;Save length in DX + MOV SI,DX + OR B,[SI+BX],80H ;Set high bit of last character + MOV AL,[BX] ;Get first char of opcode + INC BX + SUB AL,"a" + JB TRY2XM1 ;Go see if opcode starts with "2" + CMP AL,"z"-"a" + JA OPERR + CBW + SHL AX ;Double to index into address table + XCHG AX,SI ;Put in index register + MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter +LOOKNDP: + MOV AH,[DI] ;Number of opcodes starting with this letter + OR AH,AH + JZ OPERR ;Any start with this letter? +FNDNDP: + INC DI + MOV SI,BX ;Pointer to start of opcode + MOV CX,DX ;Get length of opcode + REPE + CMPB ;Compare opcode to table entry + JZ HAVNDP + DEC DI ;Back up in case that was last letter + MOV AL,80H ;Look for char with high bit set +ENDOP: + SCASB + JA ENDOP + INC DI ;Skip over info about opcode + DEC AH + JNZ FNDNDP +OPERRJ: JP OPERR + +TRY2XM1: + CMP AL,"2"-"a" + JNZ OPERR + MOV DI,XM1 + JP LOOKNDP + +SPECIALOP: + AND AL,7 ;Mask to special op number + JZ FWAIT ;If zero, go handle FWAIT +;Handle FNOP + CMP B,[NOWAIT],0 ;Was "N" present (If not opcode was "FOP") + JZ OPERR + MOV AL,9BH ;Need Wait opcode after all + CALL PUT + MOV AL,0D9H + CALL PUT + MOV AL,0D0H + JMP PUT + +FWAIT: + CMP B,[NOWAIT],0 ;"FNWAIT" not legal + JNZ OPERRJ + RET ;Nothing to do - "WAIT" already sent + +HAVNDP: + MOV SI,DI + CMP B,[NOWAIT],0 + JNZ NWAIT + MOV AL,9BH ;Wait opcode + CALL PUT +NWAIT: + LODW ;Get opcode info + TEST AL,0F8H ;Any operand bits set? + JZ NOOPS ;If no operands, output code + TEST AL,78H ;Special case? + JZ SPECIALOP + PUSH AX + CALL GETSYM ;See if any operands + POP CX + CMP AL,";" + JZ NOOPCHK + CMP AL,EOL + JZ NOOPCHK + CMP AL,FREG ;Is it 8087 register? + JNZ MEMOP + XCHG AX,CX + TEST AL,ONEREG ;One register OK as operand? + JNZ PUTREG ;Yes - save it + TEST AL,20H ;Memory-only operation? + MOV CL,20 + JNZ ERRJ4 + TEST AL,18H ;Two-register operation? + JPE ERRJ4 ;Must be exactly one bit set + PUSH DX ;Save register number + PUSH AX ;Save opcode + CALL GETSYM + CMP AL,"," + MOV CL,15H + JNZ ERRJ4 + CALL GETSYM + MOV CL,20 + CMP AL,FREG + JNZ ERRJ4 + POP AX + POP BX + XOR AL,2 ;Flip "POP" bit + AND AL,0FBH ;Reset direction bit to ST(0) + OR BL,BL ;Is first register ST(0)? + JZ ST0DEST + XCHG DX,BX + OR BL,BL ;One of these must be ST(0) + JNZ ERRJ4 + XOR AL,4 ;Flip direction + JMPS PUTREG +ST0DEST: + TEST AL,2 ;Is POP bit set? + JNZ ERRJ4 ;Don't allow destination ST(0) then pop +PUTREG: + AND AH,0F8H ;Zero out register field + OR AH,DL + OR AH,0C0H + PUSH AX + CALL GETSYM ;Get to next symbol + POP AX + JMPS NOOPS + +NOOPCHK: + XCHG AX,CX + TEST AL,80H ;Is no operands OK? + MOV CL,20 + JNZ ERRJ4 +NOOPS: +;First test for FDIV or FSUB and reverse "R" bit if "D" bit is set + PUSH AX + AND AX,0E005H + CMP AX,0E004H + POP AX + JNZ NOREV + XOR AH,8 ;Reverse "R" bit +NOREV: + AND AL,7 + OR AL,0D8H ;ESC hook + CALL PUT + MOV AL,AH + JMP PUT + +BADFLAG: + MOV CL,20H +ERRJ4: JMP ERROR + +MEMOP: + PUSH CX ;Save opcode + CALL GETOP1 ;Get memory operand + CMP AL,UNDEFID ;Is it? + MOV CL,20 + JNZ ERRJ4 + POP AX + TEST AL,20H ;Does it have memory format field? + JNZ GETFORMAT + TEST AL,8 ;Check if any memory operand legal + JZ ERRJ4 + TEST AL,10H ;Check for 2-op arithmetic + JNZ PUTMEM ;If not, just use as plain memory op +GETFORMAT: + AND AL,0F9H ;Zero memory format bits + MOV CL,[FLAG] + DEC CL ;Must now be in range 0-3 + JL BADFLAG + MOV CH,AL ;Save opcode byte + SHR AL ;Put format bits in bits 2 & 3 + AND AL,0CH + OR AL,CL ;Combine format bits with flag + MOV BX,FORMATTAB + XLAT + OR AL,AL ;Valid combination? + JS BADFLAG + OR AH,AL ;Possibly set new bits in second byte + OR AL,CH ;Set memory format bits +PUTMEM: + AND AL,7 + OR AL,0D8H + CALL PUT + MOV AL,AH + AND AL,38H + OR AL,DL ;Combine addressing mode + JMP PUTADD + +FORMATTAB: +;There are 16 entries in this table. The 4-bit index is built like this: +; Bit 3 0 for normal memory ops, 1 if extended is OK +; Bit 2 0 for integer, 1 for real +; Bit 0 & 1 Flag: 00=W, 01=S, 10=L, 11=T +; +;The entries in the table are used as two 3-bit fields. Bits 0-2 are ORed +;into the first byte of the opcode for the Memory Format field. Bits 3-6 +;are ORed into the second byte to modify the opcode for extended operands. +;If bit 7 is set, then that combination is illegal. + + DB 6,2,80H,80H ;Normal integers + DB 80H,0,4,80H ;Normal reals + DB 6,2,2EH,80H ;Extended integers + DB 80H,0,4,2BH ;Extended reals + +GRP1: + MOV CX,8A09H + CALL MROPS + MOV CX,0C6H + MOV AL,BH + CMP AL,UNDEFID + JNZ L0006 + CALL STIMM +L0006: + AND AL,1 + JZ BYTIMM + MOV AL,0B8H + OR AL,BL + CALL PUT + JMP PUTWOR + +BYTIMM: + MOV AL,0B0H + OR AL,BL + CALL PUT +PUTBJ: JMP PUTBYT + +IMMED: + MOV AL,BH + CMP AL,UNDEFID + JZ STIMM + MOV AL,BL + OR AL,AL + JZ RET + MOV AL,BH + CALL IMM + OR AL,0C0H + CALL PUT +FINIMM: + MOV AL,CL + POP CX + TEST AL,1 + JZ PUTBJ + CMP AL,83H + JZ PUTBJ + JMP PUTWOR + +STIMM: + MOV AL,[FLAG] + CALL IMM + CALL PUTADD + JP FINIMM + +IMM: + AND AL,1 + OR AL,CL + MOV CL,AL + CALL PUT + MOV AL,CH + AND AL,38H + OR AL,BL + RET + +PUT: +;Save byte in AL as pure code, with intermediate code bits 00. AL and +;DI destroyed, no other registers affected. + PUSH BX + PUSH CX + MOV CH,0 ;Flag as pure code + CALL GEN + POP CX + POP BX + RET + +GEN: +;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH. + CALL PUTINC ;Save it and bump code pointer +GEN1: + MOV AL,[RELOC] + RCL CH + RCL AL + RCL CH + RCL AL + MOV [RELOC],AL + MOV BX,BCOUNT + DEC B,[BX] + JNZ RET + MOV B,[BX],4 + MOV BX,RELOC + MOV AL,[BX] + MOV B,[BX],0 + MOV DI,[IY] + MOV [DI],AL + MOV BX,[CODE] + MOV [IY],BX + INC BX + MOV [CODE],BX + RET + +PUTINC: + INC [PC] +PUTCD: + MOV DI,[CODE] + STOB + MOV [CODE],DI + RET + +PUTWOR: +;Save the word value described by [DLABEL] and [DATA] as code. If defined, +;two bytes of pure code will be produced. Otherwise, appropriate intermediate +;code will be generated. + PUSH CX + MOV CH,80H + PUSH DX + PUSH BX + JP PUTBW + +PUTBYT: +;Same as PUTWOR, above, but for byte value. + PUSH CX + MOV CH,40H + PUSH DX + PUSH BX + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ PUTBW + MOV BX,[DATA] + OR AL,BH + JZ PUTBW + INC BH + JZ PUTBW + MOV CL,31 + JMP ERROR +PUTBW: + MOV DX,[DLABEL] + MOV BX,[DATA] +PUTCHK: + OR DX,DX + JZ NOUNDEF + MOV AL,DL + CALL PUTCD + MOV AL,DH + CALL PUTCD + MOV AL,BL + CALL PUTINC + MOV AL,BH + TEST CH,080H + JZ SMPUT + CALL GEN + JP PRET +SMPUT: + CALL PUTCD + CALL GEN1 +PRET: + POP BX + POP DX + POP CX + RET + +NOUNDEF: + MOV AL,BL + MOV CL,BH + PUSH CX + MOV CH,0 + CALL GEN + POP CX + MOV AL,CL + TEST CH,080H + MOV CH,0 + JZ PRET + CALL GEN + JP PRET + +PUTADD: +;Save complete addressing mode. Addressing mode is in AL; if this is a register +;operation (>=C0), then the one byte will be saved as pure code. Otherwise, +;the details of the addressing mode will be investigated and the optional one- +;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. + PUSH CX + PUSH DX + PUSH BX + MOV CH,0 + MOV CL,AL + CALL GEN ;Save the addressing mode as pure code + MOV AL,CL + MOV CH,80H + AND AL,0C7H + CMP AL,6 + JZ TWOBT ;Direct address? + AND AL,0C0H + JZ PRET ;Indirect through reg, no displacement? + CMP AL,0C0H + JZ PRET ;Register to register operation? + MOV CH,AL ;Save whether one- or two-byte displacement +TWOBT: + MOV BX,[ADDR] + MOV DX,[ALABEL] + JP PUTCHK + +GRP2: + CALL GETOP + MOV CX,0FF30H + CMP AL,UNDEFID + JZ PMEM + MOV CH,50H + CMP AL,XREG + JZ PXREG + MOV CH,6 + CMP AL,SREG + JNZ $+5 + JMP PACKREG + MOV CL,20 + JMP ERROR + +PMEM: + MOV AL,CH + CALL PUT + MOV AL,CL + OR AL,DL + JMP PUTADD + +PXREG: + MOV AL,CH + OR AL,DL + JMP PUT + +GRP3: + CALL GETOP + PUSH DX + CALL GETOP2 + POP BX + MOV CX,8614H + MOV AL,SREG + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,CONST + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,UNDEFID + CMP AL,BH + JZ EXMEM + CMP AL,DH + JZ EXMEM1 + MOV AL,BH + CMP AL,DH + MOV CL,22 + JNZ ERR6 + CMP AL,XREG + JZ L0008 + CALL RR1 +L0008: ;RR1 never returns + MOV AL,BL + OR AL,AL + JZ EXACC + XCHG DX,BX + MOV AL,BL + OR AL,AL + MOV AL,BH + JZ EXACC + CALL RR1 +EXACC: + MOV AL,90H + OR AL,DL + JMP PUT + +EXMEM: + XCHG DX,BX +EXMEM1: + CMP AL,BH + JZ ERR6 + MOV CL,1 ;Flag word as OK + CALL NOTAC ;NOTAC never returns +ERR6: JMP ERROR + +GRP4: + PUSH AX + CALL GETOP + POP CX + XCHG CL,CH + CMP AL,CONST + JZ FIXED + SUB AL,XREG + DEC DL + DEC DL + OR AL,DL + MOV CL,20 + JNZ ERR6 + MOV AL,CH + OR AL,8 + JMP PUT +FIXED: + MOV AL,CH + CALL PUT + JMP PUTBYT + +GRP5: + PUSH AX + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERR6 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + MOV CL,30 + JNZ ERR6 + MOV BX,[DATA] + POP AX + OR AL,AL + JZ ORG + DEC AL + JZ DSJ + DEC AL + JZ EQU + DEC AL + JZ $+5 + JMP IF +PUTOP: + MOV AL,-3 + JP NEWLOC +ALIGN: + MOV AL,[PC] + AND AL,1 + JZ RET + MOV BX,1 +DSJ: + XCHG DX,BX + MOV BX,[PC] + ADD BX,DX + MOV [PC],BX + XCHG DX,BX + MOV AL,-4 + JP NEWLOC +EQU: + XCHG DX,BX + MOV BX,[LABPT] + MOV AL,BH + OR AL,BL + MOV CL,34 + JZ ERR7 + MOV [BX],DL + INC BX + MOV [BX],DH + RET +ORG: + MOV [PC],BX + MOV AL,-2 +NEWLOC: + CALL PUTCD + MOV AL,BL + CALL PUTCD + MOV AL,BH + CALL PUTCD + MOV CH,0C0H + JMP GEN1 +GRP6: + MOV CH,AL + MOV CL,4 + CALL MROPS + MOV CL,23 +ERR7: JMP ERROR +GRP7: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H + MOV DX,[DLABEL] + MOV AL,DH + OR AL,DL + JNZ ACCJ + XCHG DX,BX + MOV BX,[DATA] + MOV AL,BL + CBW + CMP AX,BX + XCHG DX,BX + JNZ ACCJ + OR CL,002H +ACCJ: JMP ACCIMM +GRP8: + MOV CL,AL + MOV CH,0FEH + JP ONEOP +GRP9: + MOV CL,AL + MOV CH,0F6H +ONEOP: + PUSH CX + CALL GETOP +ONE: + MOV CL,26 + CMP AL,CONST + JZ ERR7 + CMP AL,SREG + MOV CL,22 + JZ ERR7 + POP CX + CMP AL,UNDEFID + JZ MOP + AND AL,1 + JZ ROP + TEST CL,001H + JZ ROP + MOV AL,CL + AND AL,0F8H + OR AL,DL + JMP PUT +MOP: + MOV AL,[FLAG] + AND AL,1 + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,DL + JMP PUTADD +ROP: + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,0C0H + OR AL,DL + JMP PUT +GRP10: + MOV CL,AL + MOV CH,0F6H + PUSH CX + CALL GETOP + MOV CL,20 + MOV AL,DL + OR AL,AL + JNZ ERRJ1 + MOV AL,DH + CMP AL,XREG + JZ G10 + CMP AL,REG +ERRJ1: JNZ ERR8 +G10: + PUSH AX + CALL GETOP + POP AX + AND AL,1 + MOV [FLAG],AL + MOV AL,DH +ONEJ: JP ONE +GRP11: + CALL PUT + MOV AL,0AH + JMP PUT +GRP12: + MOV CL,AL + MOV CH,0D0H + PUSH CX + CALL GETOP + MOV AL,[SYM] + CMP AL,',' + MOV AL,DH + JNZ ONEJ + PUSH DX + CALL GETOP + SUB AL,REG + MOV CL,20 + DEC DL + OR AL,DL + JNZ ERR8 + POP DX + MOV AL,DH + POP CX + OR CH,002H + PUSH CX + JMP ONE +GRP13: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H +ACCIMM: + CALL IMMED + OR CH,004H + AND CH,0FDH +AIMM: + MOV AL,BH + AND AL,1 + LAHF + PUSH AX + OR AL,CH + CALL PUT + POP AX + SAHF + JNZ $+5 + JMP PUTBYT + JMP PUTWOR + +ERR8: JMP ERROR + +GRP14: +;JMP and CALL mnemonics + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + MOV B,[MAXFLG],3 ;Allow "L" flag + CALL GETOP + CMP AL,CONST + JZ DIRECT + MOV CL,20 + CMP AL,REG + JZ ERR8 + CMP AL,SREG + JZ ERR8 + CMP AL,XREG + JNZ NOTRG + OR DL,0C0H +NOTRG: +;Indirect jump. DL has addressing mode. + MOV AL,0FFH + CALL PUT + POP AX + XCHG AH,AL + SAHF + AND AL,38H + OR AL,DL + MOV CH,[FLAG] + CMP CH,3 ;Flag "L" present? + JZ PUTADDJ ;If so, do inter-segment + MOV CL,27H + CMP CH,-1 ;Better not be a flag + JNZ ERR8 + AND AL,0F7H ;Convert to intra-segment +PUTADDJ: + JMP PUTADD +DIRECT: + MOV AL,[SYM] + CMP AL,',' + JZ LONGJ + POP AX + XCHG AH,AL + SAHF + DEC AL + CMP AL,0E9H + JZ GOTOP + MOV AL,0E8H +GOTOP: + CALL PUT + MOV DX,[PC] + INC DX + INC DX + SUB [DATA],DX + JMP PUTWOR +LONGJ: + POP AX + XCHG AH,AL + SAHF + CALL PUT + CALL PUTWOR + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERR8 + JMP PUTWOR + +GRP16: +;RET mnemonic + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETSYM + CMP AL,5 + JZ LONGR + CMP AL,EOL + JZ NODEC + CMP AL,';' + JZ NODEC +GETSP: + CALL GETOP1 + POP CX + CMP AL,CONST + MOV CL,20 + JNZ ERR9 + MOV AL,CH + AND AL,0FEH + CALL PUT + JMP PUTWOR +LONGR: + CMP DL,3 ;Is flag "L"? + MOV CL,27H + JNZ ERR10 ;If not, bad flag + POP AX + XCHG AH,AL + SAHF + OR AL,8 + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL +NOTLON: + CALL GETSYM + CMP AL,EOL + JZ DORET + CMP AL,';' + JZ DORET + CMP AL,',' + JNZ L0011 + CALL GETSYM +L0011: + JP GETSP +NODEC: +;Return is intra-segment (short) without add to SP. +;Record position for RET symbol. + MOV BX,[PC] + MOV [LSTRET],BX + XCHG DX,BX + MOV BX,[RETPT] + MOV AL,BH + OR AL,BL + JZ DORET + MOV B,[BX],1 + INC BX + MOV [BX],DX + MOV BX,0 + MOV [RETPT],BX +DORET: + POP AX + XCHG AH,AL + SAHF + JMP PUT + +GRP17: + CALL PUT + CALL GETOP + CMP AL,CONST + MOV CL,20 +ERR9: JNZ ERR10 + MOV BX,[DATA] + MOV DX,[PC] + INC DX + SUB BX,DX + MOV [DATA],BX + CALL PUTBYT + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ RET + MOV BX,[DATA] + MOV AL,BL + CBW + CMP AX,BX ;Signed 8-bit number? + JZ RET + MOV CL,31 +ERR10: JMP ERROR + RET +GRP18: + CALL GETOP + CMP AL,CONST + MOV CL,20 + JNZ ERR10 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ GENINT + MOV BX,[DATA] + MOV DX,3 + SBB BX,DX + JNZ GENINT + MOV AL,0CCH + JMP PUT +GENINT: + MOV AL,0CDH + CALL PUT + JMP PUTBYT + +GRP19: ;ESC opcode + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERRJ ;First operand must be immediate + MOV CL,1EH + TEST [DLABEL],-1 ;See if all labels have been defined + JNZ ERRJ + MOV AX,[DATA] + CMP AX,64 ;Must only be 6 bits + MOV CL,1FH + JNB ERRJ + MOV BL,AL ;Save for second byte + SHR AL + SHR AL + SHR AL + OR AL,0D8H ;ESC opcode + CALL PUT + PUSH BX + CALL GETOP2 + POP BX + AND BL,7 ;Low 3 bits of first operand + SHL BL + SHL BL + SHL BL + CMP AL,UNDEFID ;Check for memory operand + JZ ESCMEM + CMP AL,CONST ;Check for another immediate + JZ ESCIMM + MOV CL,20 +ERRJ: JMP ERROR + +ESCMEM: + OR BL,DL ;Combine mode with first operand + MOV AL,BL + JMP PUTADD + +ESCIMM: + MOV CL,1EH + TEST [DLABEL],-1 ;See if second operand is fully defined + JNZ ERRJ + MOV AX,[DATA] + MOV CL,1FH + CMP AX,8 ;Must only be 3 bit value + JNB ERRJ + OR AL,BL ;Combine first and second operands + OR AL,0C0H ;Force "register" mode + JMP PUT + +GRP20: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,0F6H + CALL IMMED + MOV CH,0A8H + JMP AIMM +GRP21: + CALL GETOP + CMP AL,SREG + MOV CL,28 + JNZ ERRJ + MOV CH,26H +PACKREG: + MOV AL,DL + ADD AL,AL + ADD AL,AL + ADD AL,AL + OR AL,CH + JMP PUT +GRP22: + CALL GETOP + MOV CX,8F00H + CMP AL,UNDEFID + JNZ $+5 + JMP PMEM + MOV CH,58H + CMP AL,XREG + JNZ $+5 + JMP PXREG + MOV CH,7 + CMP AL,SREG + JZ PACKREG + MOV CL,20 +ERR11: JMP ERROR +GRP23: + MOV [DATSIZ],AL +GETDAT: + CALL GETSYM + MOV AL,2 + CALL VAL1 + MOV AL,[SYM] + CMP AL,',' + MOV AL,[DATSIZ] + JNZ ENDDAT + CALL SAVDAT + JP GETDAT +ENDDAT: + CMP AL,2 + JNZ SAVDAT + MOV BX,[DATA] + LAHF + OR BL,080H + SAHF + MOV [DATA],BX +SAVDAT: + OR AL,AL + JZ $+5 + JMP PUTBYT + JMP PUTWOR +IF: + OR BX,BX + JZ SKIPCD + INC B,[IFFLG] + RET + +SKIPCD: + INC B,[CHKLAB] +SKIPLP: + XOR AL,AL + CALL NEXLIN + CALL NEXTCHR + CMP AL,1AH + JZ END + CALL GETLAB + JC SKIPLP + MOV DI,LENID + MOV SI,IFEND + MOV CH,0 + MOV CL,[DI] + INC CL + REPE + CMPB + JZ ENDCOND + MOV DI,LENID + MOV SI,IFNEST + MOV CL,[DI] + INC CL + REPE + CMPB + JNZ SKIPLP + INC B,[CHKLAB] + JP SKIPLP + +ENDCOND: + DEC B,[CHKLAB] + JNZ SKIPLP + RET + +ENDIF: + MOV AL,[IFFLG] + MOV CL,36 + DEC AL + JS ERRJMP + MOV [IFFLG],AL + RET + +ERRJMP: JMP ERROR + +;********************************************************************* +; +; PASS 2 +; +;********************************************************************* + +END: + MOV DL,4 +WREND: + MOV CH,0FFH + MOV AL,CH + CALL GEN + DEC DL + JNZ WREND + MOV [BUFPT],SRCBUF + MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY + MOV [LSTPNT],LSTBUF + MOV [HEXPNT],HEXBUF + XOR AX,AX + MOV [ERRCNT],AX + MOV [PC],AX + MOV [LINE],AX ;Current line number + MOV [HEXADD],OBJECT + MOV DX,FCB + MOV AH,OPEN + INT 33 ;Re-open source file + XOR AX,AX + MOV [FCB+12],AX ;Set CURRENT BLOCK to zero + MOV [FCB+20H],AL ;Set NEXT RECORD field to zero + MOV [FCB+14],BUFSIZ + MOV [COUNT],AL + MOV CH,1 + MOV SI,START +FIXLINE: + MOV DI,START ;Store code over used up intermediate code + XOR AL,AL + MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) + MOV [ERR],AL ;No second pass errors yet +NEXBT: + SHL CL ;Shift out last bit of previous code + DEC CH ;Still have codes left? + JNZ TESTTYP + LODB ;Get next flag byte + MOV CL,AL + MOV CH,4 +TESTTYP: + SHL CL ;Set flags based on two bits + JO FIXUP + LODB + JC EMARK +OBJBT: + STOB + JP NEXBT + +FIXUP: +;Either a word or byte fixup is needed from a forward reference + LODW ;Get pointer to symbol + XCHG AX,BX + LODW ;Get constant part + ADD AX,[BX+1] ;Add symbol value to constant part + CMP B,[BX],0 ;See if symbol got defined + JNZ HAVDEF + MOV B,[ERR],100 ;Undefined - flag error + XOR AX,AX +HAVDEF: + OR CL,CL ;See if word or byte fixup + JS DEFBYT + STOW + JP NEXBT + +DEFBYT: + MOV DX,AX + CBW ;Extend sign + CMP AX,DX ;See if in range +127 to -128 + JZ OBJBT ;If so, it's always OK + NOT AH ;Check for range +255 to -256 + CMP AH,DH + JNZ RNGERR ;Must always be in this range +;Check for short jump. If so, we're out of range; otherwise we're OK + CMP DI,START+1 ;Only one other byte on line? + JNZ OBJBT ;Can't be short jump if not + MOV AL,[START] ;Get the first byte of this line + CMP AL,0EBH ;Direct short jump? + JZ RNGERR + AND AL,0FCH + CMP AL,0E0H ;LOOP or JCXZ instruction? + JZ RNGERR + AND AL,0F0H + CMP AL,70H ;Conditional jump? + MOV AL,DL ;Get code byte in AL + JNZ OBJBT ;If not, we're OK +RNGERR: + MOV B,[ERR],101 ;Value out of range + JP OBJBT + +FINIJ: JMP FINI + +EMARK: + CMP AL,-1 ;End of file? + JZ FINIJ + CMP AL,-10 ;Special item? + JA SPEND + PUSH CX + PUSH SI + PUSH AX ;Save error code + MOV AH,[LSTDEV] + AND AH,0FEH ;Reset error indicator + OR AL,[ERR] ;See if any errors on this line + JZ NOERR + OR AH,1 ;Send line to console if error occured +NOERR: + MOV [LSTDEV],AH + MOV CX,DI + CALL STRTLIN ;Print address of line + MOV SI,START + SUB CX,SI ;Get count of bytes of code + JZ SHOLIN +CODLP: + LODB + CALL SAVCD ;Ouput code to HEX and PRN files + LOOP CODLP +SHOLIN: + MOV AL,0 + XCHG AL,[COUNT] + MOV CX,7 ;Allow 7 bytes of code per line + SUB CL,AL + MOV AL,' ' + JZ NOFIL +BLNK: ;Put in 3 blanks for each byte not present + CALL LIST + CALL LIST + CALL LIST + LOOP BLNK +NOFIL: + CALL OUTLIN + POP AX ;Restore error code + CALL REPERR + MOV AL,[ERR] + CALL REPERR + POP SI + POP CX + MOV AL,[SPC] ;Any special funtion? + OR AL,AL + JNZ SPCFUN + JMP FIXLINE + +SPEND: + MOV [SPC],AL ;Record special function + LODW ;Get it's data + MOV [DATA],AX + JMP NEXBT + +SPCFUN: + MOV DX,[DATA] + CMP AL,-2 + JZ DORG + CMP AL,-3 + JZ DPUT +DDS: +;Handle DS pseudo-op + ADD [PC],DX + ADD [HEXADD],DX + JMP FIXLINE + +DORG: +;Handle ORG pseudo-op + MOV [PC],DX + JMP FIXLINE + +DPUT: +;Handle PUT pseudo-op + MOV [HEXADD],DX + JMP FIXLINE + +OUTLIN: +;Copy the source line to the ouput device. Line will be preceded by +;assembler-generated line number. This routine may be called several times +;on one line (once for each line of object code bytes), so it sets a flag +;so the line will only be output on the first call. + MOV AL,-1 + XCHG AL,[LINFLG] + OR AL,AL + JNZ CRLF ;Output line only if first time + MOV AX,[LINE] + INC AX + MOV [LINE],AX + MOV BH,0 ;No leading zero suppression + CALL OUT10 + MOV AL," " + CALL LIST + MOV AL,[LSTFCB] + CMP AL,'Z' + JZ CRLF ;Don't call NEXTCHR if listing suppressed + PUSH SI ;Save the only register destroyed by NEXTCHR +OUTLN: + CALL NEXTCHR + CALL LIST + CMP AL,10 ;Output until linefeed found + JNZ OUTLN + POP SI + RET + +PRTCNT: + MOV BX,ERCNTM + CALL PRINT + MOV AX,[ERRCNT] + MOV BH,"0"-" " ;Enable leading zero suppression + CALL OUT10 +CRLF: + MOV AL,13 + CALL LIST + MOV AL,10 + JP LIST + +OUT10: + XOR DX,DX + MOV DI,10000 + DIV AX,DI + OR AL,AL ;>10,000? + JNZ LEAD + SUB AL,"0"-" " ;Convert leading zero to blank +LEAD: + ADD AL,"0" + CALL LIST + XCHG AX,DX + MOV BL,100 + DIV AL,BL + MOV BL,AH + CALL HIDIG ;Convert to decimal and print 1000s digit + CALL DIGIT ;Print 100s digit + MOV AL,BL + CALL HIDIG ;Convert to decimal and print 10s digit + MOV BH,0 ;Ensure leading zero suppression is off + JP DIGIT + +HIDIG: + AAM ;Convert binary to unpacked BCD + OR AX,3030H ;Add "0" bias +DIGIT: + XCHG AL,AH + CMP AL,"0" + JZ SUPZ + MOV BH,0 ;Turn off zero suppression if not zero +SUPZ: + SUB AL,BH ;Convert leading zeros to blanks + JP LIST + +STRTLIN: + MOV B,[LINFLG],0 + MOV BX,[PC] + MOV AL,BH + CALL PHEX + MOV AL,BL +PHEXB: + CALL PHEX + MOV AL,' ' +LIST: + PUSH AX + PUSH DX + AND AL,7FH + MOV DL,AL + TEST B,[LSTDEV],3 ;See if output goes to console + JZ PRNCHK + MOV AH,2 + INT 33 ;Output to console +PRNCHK: + TEST B,[LSTDEV],4 ;See if output goes to printer + JZ FILCHK + MOV AH,5 + INT 33 ;Output to printer +FILCHK: + MOV AL,DL + POP DX + TEST B,[LSTDEV],80H ;See if output goes to a file + JZ LISTRET + CALL WRTBUF +LISTRET: + POP AX + RET + +WRTBUF: + PUSH DI + MOV DI,[LSTPNT] + STOB + CMP DI,LSTBUF+LSTBUFSIZ + JNZ SAVPT + PUSH AX + PUSH CX + PUSH DX + CALL FLUSHBUF + POP DX + POP CX + POP AX +SAVPT: + MOV [LSTPNT],DI + POP DI + RET + +PHEX: + PUSH AX + CALL UHALF + CALL LIST + POP AX + CALL LHALF + JP LIST + +FINI: + OR B,[LSTDEV],1 + CALL PRTCNT + AND B,[LSTDEV],0FEH + MOV AL,[HEXFCB] + CMP AL,'Z' + JZ SYMDMP + MOV AL,[HEXCNT] + CMP AL,-5 + JZ L0012 + CALL ENHEXL +L0012: + MOV AL,':' + CALL PUTCHR + MOV CH,10 +HEXEND: + PUSH CX + MOV AL,'0' + CALL PUTCHR + POP CX + DEC CH + JNZ HEXEND + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR + MOV AL,1AH + CALL PUTCHR + CALL WRTHEX ;Flush HEX file buffer + MOV DX,HEXFCB + MOV AH,CLOSE + INT 33 +SYMDMP: + MOV AL,[SYMFLG] + CMP AL,'S' + JNZ ENDSYM + MOV AL,[LSTDEV] + OR AL,AL ;Any output device for symbol table dump? + JNZ DOSYMTAB + OR AL,1 ;If not, send it to console + MOV [LSTDEV],AL +DOSYMTAB: + MOV BX,SYMMES + CALL PRINT + MOV DX,[BASE] + MOV AL,DH + OR AL,DL + JZ ENDSYM + MOV B,[SYMLIN],SYMWID ;No symbols on this line yet + MOV BX,[HEAP] + MOV SP,BX ;Need maximum stack for recursive tree walk + CALL NODE +ENDSYM: + TEST B,[LSTDEV],80H ;Print listing to file? + JZ EXIT + MOV AL,1AH + CALL WRTBUF ;Write end-of-file mark + MOV DI,[LSTPNT] + CALL FLUSHBUF + MOV AH,CLOSE + INT 33 +EXIT: JMP 0 + +NODE: + XCHG DX,BX + PUSH BX + MOV DL,[BX] + MOV DH,0 + INC BX + ADD BX,DX + MOV DX,[BX] + OR DX,DX + JZ L0014 + CALL NODE +L0014: + POP BX + MOV AL,[BX] + INC BX + MOV CH,AL + ADD AL,24 + SHR AL + SHR AL + SHR AL + MOV CL,AL + INC CL ;Invert last bit + AND CL,1 ;Number of extra tabs needed (0 or 1) + SHR AL ;Number of positions wide this symbol needs + SUB [SYMLIN],AL + JNC WRTSYM ;Will it fit? + SUB AL,SYMWID + NEG AL + MOV [SYMLIN],AL + CALL CRLF ;Start new line if not +WRTSYM: + MOV AL,[BX] + INC BX + CALL LIST + DEC CH + JNZ WRTSYM + INC CL +TABVAL: + MOV AL,9 + CALL LIST + LOOP TABVAL + INC BX + INC BX + PUSH BX + MOV AL,[BX+4] + CALL PHEX + MOV AL,[BX+3] + CALL PHEX + CMP B,[SYMLIN],0 ;Will any more fit on line? + JZ NEXSYMLIN + MOV AL,9 + CALL LIST + JP RIGHTSON +NEXSYMLIN: + CALL CRLF + MOV B,[SYMLIN],SYMWID +RIGHTSON: + POP BX + MOV DX,[BX] + OR DX,DX + JNZ NODE + RET + +SAVCD: + MOV [PREV],AL + PUSH BX + PUSH CX + PUSH AX + PUSH DX + CALL CODBYT + POP DX + MOV BX,COUNT + INC B,[BX] + MOV AL,[BX] + CMP AL,8 + JNZ NOEXT + MOV B,[BX],1 + CALL OUTLIN + MOV AL,' ' + MOV CH,5 +TAB: + CALL LIST + DEC CH + JNZ TAB +NOEXT: + POP AX + CALL PHEXB + POP CX + INC [PC] + INC [HEXADD] + POP BX + RET + +REPERR: + OR AL,AL ;Did an error occur? + JZ RET + INC [ERRCNT] + PUSH AX + MOV BX,ERRMES ;Print "ERROR" + CALL PRINT + POP AX +;We have error number in AL. See if there's an error message for it + MOV DI,ERRTAB + MOV BL,80H +ERRLOOK: + SCASB ;Do we have the error message + JBE HAVMES ;Quit looking if we have it or passed it + XCHG AX,BX ;Put 80H in AL to look for end of this message +NEXTMES: + SCASB ;Look for high bit set in message + JA NEXTMES ; which means we've reached the end + XCHG AX,BX ;Restore error number to AL + JMPS ERRLOOK ;Keep looking + +HAVMES: + MOV BX,DI ;Put address of message in BX + JZ PRNERR ;Do we have a message for this error? + CALL PHEX ;If not, just print error number + JMP CRLF + +PRNERR: + CALL PRINT + JMP CRLF + +PRINT: + MOV AL,[BX] + CALL LIST + OR AL,AL + JS RET + INC BX + JP PRINT + +OUTA: + MOV DL,AL +OUT: + AND DL,7FH + MOV CL,2 +SYSTEM: + CALL 5 + RET + +CODBYT: + CMP B,[HEXFCB],"Z" + JZ RET + PUSH AX + MOV DX,[LASTAD] + MOV BX,[HEXADD] + MOV [LASTAD],BX + INC DX + MOV AL,[HEXCNT] + CMP AL,-5 + JZ NEWLIN + CMP BX,DX + JZ AFHEX + CALL ENHEXL +NEWLIN: + MOV AL,':' + CALL PUTCHR + MOV AL,-4 + MOV [HEXCNT],AL + XOR AL,AL + MOV [CHKSUM],AL + MOV BX,[HEXPNT] + MOV [HEXLEN],BX + CALL HEXBYT + MOV AL,[HEXADD+1] + CALL HEXBYT + MOV AL,[HEXADD] + CALL HEXBYT + XOR AL,AL + CALL HEXBYT +AFHEX: + POP AX +HEXBYT: + MOV CH,AL + MOV BX,CHKSUM + ADD AL,[BX] + MOV [BX],AL + MOV AL,CH + CALL UHALF + CALL PUTCHR + MOV AL,CH + CALL LHALF + CALL PUTCHR + MOV BX,HEXCNT + INC B,[BX] + MOV AL,[BX] + CMP AL,26 + JNZ RET +ENHEXL: + MOV DI,[HEXLEN] + MOV CH,AL + CALL UHALF + STOB + MOV AL,CH + CALL LHALF + STOB + MOV AL,-6 + MOV [HEXCNT],AL + MOV AL,[CHKSUM] + ADD AL,CH + NEG AL + CALL HEXBYT + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR +WRTHEX: +;Write out the line + MOV DX,HEXBUF + MOV [HEXPNT],DX + MOV AH,SETDMA + INT 33 + SUB DI,DX ;Length of buffer + MOV CX,DI + MOV DX,HEXFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JNZ DSKFUL + RET + +PUTCHR: + MOV DI,[HEXPNT] + STOB + MOV [HEXPNT],DI + RET + +FLUSHBUF: + MOV CX,DI + MOV DX,LSTBUF + MOV DI,DX + SUB CX,DX + JZ RET ;Buffer empty? + MOV AH,SETDMA + INT 33 + MOV DX,LSTFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JZ RET +DSKFUL: + MOV BX,WRTERR + JMP PRERR + +UHALF: + RCR AL + RCR AL + RCR AL + RCR AL +LHALF: + AND AL,0FH + OR AL,30H + CMP AL,'9'+1 + JC RET + ADD AL,7 + RET + +NONE: DB 0 + +; 8086 MNEMONIC TABLE + +; This table is actually a sequence of subtables, each starting with a label. +; The label signifies which mnemonics the subtable applies to--A3, for example, +; means all 3-letter mnemonics beginning with A. + +A3: + DB 7 + DB 'dd' + DW GRP7 + DB 2 + DB 'nd' + DW GRP13 + DB 22H + DB 'dc' + DW GRP7 + DB 12H + DB 'aa' + DW PUT + DB 37H + DB 'as' + DW PUT + DB 3FH + DB 'am' + DW GRP11 + DB 0D4H + DB 'ad' + DW GRP11 + DB 0D5H +A5: + DB 1 + DB 'lign' + DW ALIGN + DB 0 +C3: + DB 7 + DB 'mp' + DW GRP7 + DB 3AH + DB 'lc' + DW PUT + DB 0F8H + DB 'ld' + DW PUT + DB 0FCH + DB 'li' + DW PUT + DB 0FAH + DB 'mc' + DW PUT + DB 0F5H + DB 'bw' + DW PUT + DB 98H + DB 'wd' + DW PUT + DB 99H +C4: + DB 3 + DB 'all' + DW GRP14 + DB 9AH + DB 'mpb' + DW PUT + DB 0A6H + DB 'mpw' + DW PUT + DB 0A7H +C5: + DB 2 + DB 'mpsb' + DW PUT + DB 0A6H + DB 'mpsw' + DW PUT + DB 0A7H +D2: + DB 5 + DB 'b' + DW GRP23 + DB 1 + DB 'w' + DW GRP23 + DB 0 + DB 'm' + DW GRP23 + DB 2 + DB 's' + DW GRP5 + DB 1 + DB 'i' + DW PUT + DB 0FAH +D3: + DB 4 + DB 'ec' + DW GRP8 + DB 49H + DB 'iv' + DW GRP10 + DB 30H + DB 'aa' + DW PUT + DB 27H + DB 'as' + DW PUT + DB 2FH +D4: + DB 1 + DB 'own' + DW PUT + DB 0FDH +E2: + DB 1 + DB 'i' + DW PUT + DB 0FBH +E3: + DB 3 + DB 'qu' + DW GRP5 + DB 2 + DB 'sc' + DW GRP19 + DB 0D8H + DB 'nd' + DW END + DB 0 +E5: + DB 1 + DB 'ndif' + DW ENDIF + DB 0 +H3: + DB 1 + DB 'lt' + DW PUT + DB 0F4H +H4: + DB 1 + DB 'alt' + DW PUT + DB 0F4H +I2: + DB 2 + DB 'n' + DW GRP4 + DB 0E4H + DB 'f' + DW GRP5 + DB 4 +I3: + DB 4 + DB 'nc' + DW GRP8 + DB 41H + DB 'nb' + DW GRP4 + DB 0E4H + DB 'nw' + DW GRP4 + DB 0E5H + DB 'nt' + DW GRP18 + DB 0CCH +I4: + DB 4 + DB 'mul' + DW GRP10 + DB 28H + DB 'div' + DW GRP10 + DB 38H + DB 'ret' + DW PUT + DB 0CFH + DB 'nto' + DW PUT + DB 0CEH +J2: + DB 10 + DB 'p' + DW GRP17 + DB 0EBH + DB 'z' + DW GRP17 + DB 74H + DB 'e' + DW GRP17 + DB 74H + DB 'l' + DW GRP17 + DB 7CH + DB 'b' + DW GRP17 + DB 72H + DB 'a' + DW GRP17 + DB 77H + DB 'g' + DW GRP17 + DB 7FH + DB 'o' + DW GRP17 + DB 70H + DB 's' + DW GRP17 + DB 78H + DB 'c' + DW GRP17 + DB 72H +J3: + DB 17 + DB 'mp' + DW GRP14 + DB 0EAH + DB 'nz' + DW GRP17 + DB 75H + DB 'ne' + DW GRP17 + DB 75H + DB 'nl' + DW GRP17 + DB 7DH + DB 'ge' + DW GRP17 + DB 7DH + DB 'nb' + DW GRP17 + DB 73H + DB 'ae' + DW GRP17 + DB 73H + DB 'nc' + DW GRP17 + DB 73H + DB 'ng' + DW GRP17 + DB 7EH + DB 'le' + DW GRP17 + DB 7EH + DB 'na' + DW GRP17 + DB 76H + DB 'be' + DW GRP17 + DB 76H + DB 'pe' + DW GRP17 + DB 7AH + DB 'np' + DW GRP17 + DB 7BH + DB 'po' + DW GRP17 + DB 7BH + DB 'no' + DW GRP17 + DB 71H + DB 'ns' + DW GRP17 + DB 79H +J4: + DB 6 + DB 'mps' + DW GRP17 + DB 0EBH + DB 'cxz' + DW GRP17 + DB 0E3H + DB 'nge' + DW GRP17 + DB 7CH + DB 'nae' + DW GRP17 + DB 72H + DB 'nbe' + DW GRP17 + DB 77H + DB 'nle' + DW GRP17 + DB 7FH +L3: + DB 3 + DB 'ea' + DW GRP6 + DB 8DH + DB 'ds' + DW GRP6 + DB 0C5H + DB 'es' + DW GRP6 + DB 0C4H +L4: + DB 5 + DB 'oop' + DW GRP17 + DB 0E2H + DB 'odb' + DW PUT + DB 0ACH + DB 'odw' + DW PUT + DB 0ADH + DB 'ahf' + DW PUT + DB 9FH + DB 'ock' + DW PUT + DB 0F0H +L5: + DB 4 + DB 'oope' + DW GRP17 + DB 0E1H + DB 'oopz' + DW GRP17 + DB 0E1H + DB 'odsb' + DW PUT + DB 0ACH + DB 'odsw' + DW PUT + DB 0ADH +L6: + DB 2 + DB 'oopne' + DW GRP17 + DB 0E0H + DB 'oopnz' + DW GRP17 + DB 0E0H +M3: + DB 2 + DB 'ov' + DW GRP1 + DB 88H + DB 'ul' + DW GRP10 + DB 20H +M4: + DB 2 + DB 'ovb' + DW PUT + DB 0A4H + DB 'ovw' + DW PUT + DB 0A5H +M5: + DB 2 + DB 'ovsb' + DW PUT + DB 0A4H + DB 'ovsw' + DW PUT + DB 0A5H +N3: + DB 3 + DB 'ot' + DW GRP9 + DB 10H + DB 'eg' + DW GRP9 + DB 18H + DB 'op' + DW PUT + DB 90H +O2: + DB 1 + DB 'r' + DW GRP13 + DB 0AH +O3: + DB 2 + DB 'ut' + DW GRP4 + DB 0E6H + DB 'rg' + DW GRP5 + DB 0 +O4: + DB 2 + DB 'utb' + DW GRP4 + DB 0E6H + DB 'utw' + DW GRP4 + DB 0E7H +P3: + DB 2 + DB 'op' + DW GRP22 + DB 8FH + DB 'ut' + DW GRP5 + DB 3 +P4: + DB 2 + DB 'ush' + DW GRP2 + DB 0FFH + DB 'opf' + DW PUT + DB 9DH +P5: + DB 1 + DB 'ushf' + DW PUT + DB 9CH +R3: + DB 6 + DB 'et' + DW GRP16 + DB 0C3H + DB 'ep' + DW PUT + DB 0F3H + DB 'ol' + DW GRP12 + DB 0 + DB 'or' + DW GRP12 + DB 8 + DB 'cl' + DW GRP12 + DB 10H + DB 'cr' + DW GRP12 + DB 18H +R4: + DB 2 + DB 'epz' + DW PUT + DB 0F3H + DB 'epe' + DW PUT + DB 0F3H +R5: + DB 2 + DB 'epnz' + DW PUT + DB 0F2H + DB 'epne' + DW PUT + DB 0F2H +S3: + DB 11 + DB 'ub' + DW GRP7 + DB 2AH + DB 'bb' + DW GRP7 + DB 1AH + DB 'bc' + DW GRP7 + DB 1AH + DB 'tc' + DW PUT + DB 0F9H + DB 'td' + DW PUT + DB 0FDH + DB 'ti' + DW PUT + DB 0FBH + DB 'hl' + DW GRP12 + DB 20H + DB 'hr' + DW GRP12 + DB 28H + DB 'al' + DW GRP12 + DB 20H + DB 'ar' + DW GRP12 + DB 38H + DB 'eg' + DW GRP21 + DB 26H +S4: + DB 5 + DB 'cab' + DW PUT + DB 0AEH + DB 'caw' + DW PUT + DB 0AFH + DB 'tob' + DW PUT + DB 0AAH + DB 'tow' + DW PUT + DB 0ABH + DB 'ahf' + DW PUT + DB 9EH +S5: + DB 4 + DB 'casb' + DW PUT + DB 0AEH + DB 'casw' + DW PUT + DB 0AFH + DB 'tosb' + DW PUT + DB 0AAH + DB 'tosw' + DW PUT + DB 0ABH +T4: + DB 1 + DB 'est' + DW GRP20 + DB 84H +U2: + DB 1 + DB 'p' + DW PUT + DB 0FCH +W4: + DB 1 + DB 'ait' + DW PUT + DB 9BH +X3: + DB 1 + DB 'or' + DW GRP13 + DB 32H +X4: + DB 2 + DB 'chg' + DW GRP3 + DB 86H + DB 'lat' + DW PUT + DB 0D7H + + +; 8087 MNEMONIC TABLE +; Similar to 8086 table above, except NOT distinguished by opcode length + +XM1: ;F2XM1 + DB 1 ;One opcode + DM "xm1" + DB 1,0F0H + +NDPA: + DB 3 + DM "dd" + DB 6+ARITH,0C1H + DM "ddp" + DB NEEDOP+STACKOP,0 + DM "bs" + DB 1,0E1H + +NDPB: + DB 2 + DM "ld" + DB 7+NEEDOP+MEMORY,20H + DM "stp" + DB 7+NEEDOP+MEMORY,30H + +NDPC: + DB 5 + DM "om" + DB 0+ONEREG+REAL,0D1H + DM "omp" + DB 0+ONEREG+REAL,0D9H + DM "hs" + DB 1,0E0H + DM "ompp" + DB 6,0D9H + DM "lex" + DB 3,0E2H + +NDPD: + DB 6 + DM "iv" + DB 6+ARITH,0F1H + DM "ivp" + DB NEEDOP+STACKOP,30H + DM "ivr" + DB 6+ARITH,0F9H + DM "ivrp" + DB NEEDOP+STACKOP,38H + DM "ecstp" + DB 1,0F6H + DM "isi" + DB 3,0E1H + +NDPE: + DB 1 + DM "ni" + DB 3,0E0H + +NDPF: + DB 1 + DM "ree" + DB 5+NEEDOP+ONEREG,0 + +NDPI: + DB 13 + DM "add" + DB 2+NEEDOP+INTEGER,0 + DM "ld" + DB 3+NEEDOP+INTEGER+EXTENDED,0 + DM "sub" + DB 2+NEEDOP+INTEGER,20H + DM "stp" + DB 3+NEEDOP+INTEGER+EXTENDED,18H + DM "st" + DB 3+NEEDOP+INTEGER,10H + DM "mul" + DB 2+NEEDOP+INTEGER,8 + DM "div" + DB 2+NEEDOP+INTEGER,30H + DM "subr" + DB 2+NEEDOP+INTEGER,28H + DM "divr" + DB 2+NEEDOP+INTEGER,38H + DM "com" + DB 2+NEEDOP+INTEGER,10H + DM "comp" + DB 2+NEEDOP+INTEGER,18H + DM "ncstp" + DB 1,0F7H + DM "nit" + DB 3,0E3H + +NDPL: + DB 10 + DM "d" + DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0 + DM "dz" + DB 1,0EEH + DM "d1" + DB 1,0E8H + DM "dpi" + DB 1,0EBH + DM "dl2t" + DB 1,0E9H + DM "dl2e" + DB 1,0EAH + DM "dlg2" + DB 1,0ECH + DM "dln2" + DB 1,0EDH + DM "dcw" + DB 1+NEEDOP+MEMORY,28H + DM "denv" + DB 1+NEEDOP+MEMORY,20H + +NDPM: + DB 2 + DM "ul" + DB 6+ARITH,0C9H + DM "ulp" + DB NEEDOP+STACKOP,8 + +NDPO: + DB 1 + DM "p" + DB NEEDOP+1,0 ;Flag special handling + +NDPN: + DB 1 + DM "op" + DB 1,0D0H + +NDPP: + DB 3 + DM "rem" + DB 1,0F8H + DM "tan" + DB 1,0F2H + DM "atan" + DB 1,0F3H + +NDPR: + DB 2 + DM "ndint" + DB 1,0FCH + DM "stor" + DB 5+NEEDOP+MEMORY,20H + +NDPS: + DB 12 + DM "t" + DB 5+NEEDOP+ONEREG+REAL,0D0H + DM "tp" + DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H + DM "ub" + DB 6+ARITH,0E1H + DM "ubp" + DB NEEDOP+STACKOP,0E0H + DM "ubr" + DB 6+ARITH,0E9H + DM "ubrp" + DB NEEDOP+STACKOP,0E8H + DM "qrt" + DB 1,0FAH + DM "cale" + DB 1,0FDH + DM "ave" + DB 5+NEEDOP+MEMORY,30H + DM "tcw" + DB 1+NEEDOP+MEMORY,38H + DM "tenv" + DB 1+NEEDOP+MEMORY,30H + DM "tsw" + DB 5+NEEDOP+MEMORY,38H + +NDPT: + DB 1 + DM "st" + DB 1,0E4H + +NDPW: + DB 1 + DM "ait" + DB NEEDOP,0 ;Flag special handling + +NDPX: + DB 3 + DM "ch" + DB 1+ONEREG,0C9H + DM "am" + DB 1,0E5H + DM "tract" + DB 1,0F4H + +NDPY: + DB 2 + DM "l2x" + DB 1,0F1H + DM "l2xp1" + DB 1,0F9H + + +OPTAB: +; Table of pointers to mnemonics. For each letter of the alphabet (the +; starting letter of the mnemonic), there are 5 entries. Each entry +; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +; long, respectively. If there are no mnemonics for a given combination +; of first letter and length (such as A-2), then the corresponding entry +; points to NONE. Otherwise, it points to a place in the mnemonic table +; for that type. + +; This table only needs to be modified if a mnemonic is added to a group +; previously marked NONE. Change the NONE to a label made up of the first +; letter of the mnemonic and its length, then add a new subsection to +; the mnemonic table in alphabetical order. + + DW NONE + DW A3 + DW NONE + DW A5 + DW NONE + DW NONE ;B + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;C + DW C3 + DW C4 + DW C5 + DW NONE + DW D2 ;D + DW D3 + DW D4 + DW NONE + DW NONE + DW E2 ;E + DW E3 + DW NONE + DW E5 + DW NONE + DW NONE ;F + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;G + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;H + DW H3 + DW H4 + DW NONE + DW NONE + DW I2 ;I + DW I3 + DW I4 + DW NONE + DW NONE + DW J2 ;J + DW J3 + DW J4 + DW NONE + DW NONE + DW NONE ;K + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;L + DW L3 + DW L4 + DW L5 + DW L6 + DW NONE ;M + DW M3 + DW M4 + DW M5 + DW NONE + DW NONE ;N + DW N3 + DW NONE + DW NONE + DW NONE + DW O2 ;O + DW O3 + DW O4 + DW NONE + DW NONE + DW NONE ;P + DW P3 + DW P4 + DW P5 + DW NONE + DW NONE ;Q + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;R + DW R3 + DW R4 + DW R5 + DW NONE + DW NONE ;S + DW S3 + DW S4 + DW S5 + DW NONE + DW NONE ;T + DW NONE + DW T4 + DW NONE + DW NONE + DW U2 ;U + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;V + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;W + DW NONE + DW W4 + DW NONE + DW NONE + DW NONE ;X + DW X3 + DW X4 + DW NONE + DW NONE + DW NONE ;Y + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;Z + DW NONE + DW NONE + DW NONE + DW NONE + +NDPTAB: +;Lookup table for 8087 mnemonics. There is one entry for each letter of the +;alphabet + DW NDPA + DW NDPB + DW NDPC + DW NDPD + DW NDPE + DW NDPF + DW NONE ;G + DW NONE ;H + DW NDPI + DW NONE ;J + DW NONE ;K + DW NDPL + DW NDPM + DW NDPN + DW NDPO + DW NDPP + DW NONE ;Q + DW NDPR + DW NDPS + DW NDPT + DW NONE ;U + DW NONE ;V + DW NDPW + DW NDPX + DW NDPY + DW NONE ;Z + +;Error message table + +ERRTAB: + DM 1,"Register not allowed in immediate value" + DM 2,"Index or base register must be BP, BX, SI, or DI" + DM 3,"Only one base register (BX, BP) allowed" + DM 4,"Only one index register (SI or DI) allowed" + DM 5,"Only addition allowed on register or undefined label" + DM 6,"Only one undefined label per expression allowed" + DM 7,"Illegal digit in hexadecimal number" + DM 8,"Illegal digit in decimal number" + DM 10,"Illegal character in label or opcode" + DM 11,"Label defined twice" + DM 12,"Opcode not recognized" + DM 20,"Invalid operand" + DM 21,'"," and second operand expected' + DM 22,"Register mismatch" + DM 23,"Immediate operand not allowed" + DM 24,'"]" expected' + DM 25,"Two memory operands not allowed" + DM 26,"Destination must not be immediate value" + DM 27,"Both operands must not be registers" + DM 28,"Operand must be segment register" + DM 29,"First operand must be register" + DM 30,"Undefined label not allowed" + DM 31,"Value out of range" + DM 32,"Missing or illegal operand size flag" + DM 33,"Must have label on same line" + DM 35,"Zero-length string illegal" + DM 36,"ENDIF without IF" + DM 37,"One-character strings only" + DM 38,"Illegal expression" + DM 39,"End of string not found" + DM 100,"Undefined label" + DM 101,"Value out of range (forward)" + DB 255 + +ERRMES: DM '***** ERROR: ' +NOSPAC: DB 13,10,'File creation error',13,10,"$" +NOMEM: DB 13,10,'Insufficient memory',13,10,'$' +NOFILE: DB 13,10,'File not found',13,10,'$' +WRTERR: DB 13,10,'Disk full',13,10,'$' +BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' +ERCNTM: DM 13,10,13,10,'Error Count =' +SYMMES: DM 13,10,'Symbol Table',13,10,13,10 +EXTEND: DB 'ASM',0,0 +IFEND: DB 5,'endif' +IFNEST: DB 2,'if' +RETSTR: DM 'ret' +HEXFCB: DB 0,' HEX',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +LSTFCB: DB 0,' PRN',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +PC: DS 2 +OLDPC: DS 2 +LABPT: DS 2 +FLAG: DS 1 +MAXFLG: DS 1 +ADDR: DS 2 +ALABEL: DS 2 +DATA: DS 2 +DLABEL: DS 2 +CON: DS 2 +UNDEF: DS 2 +LENID: DS 1 +ID: DS 80 +CHR: DS 1 +SYM: DS 1 +BASE: DS 2 +HEAP: DS 2 +SYMFLG: DS 1 +SYMLIN: DS 1 +CODE: DS 2 +DATSIZ: DS 1 +RELOC: DS 1 +BCOUNT: DS 1 +COUNT: DS 1 +ERR: DS 1 +LINE: DS 2 +HEXLEN: DS 2 +HEXADD: DS 2 +LASTAD: DS 2 +HEXCNT: DS 1 +CHKSUM: DS 1 +LINFLG: DS 1 +PREV: DS 1 +IFFLG: DS 1 +CHKLAB: DS 1 +ERRCNT: DS 2 +LSTRET: DS 2 +RETPT: DS 2 +LSTDEV: DS 2 +SPC: DS 1 +NOWAIT: DS 1 +IX: DS 2 +IY: DS 2 +HEXPNT: DS 2 +LSTPNT: DS 2 +HEXBUF: DS HEXBUFSIZ +LSTBUF: DS LSTBUFSIZ +BUFPT: DS 2 +SRCBUF: DS BUFSIZ + DS 100H + ALIGN +STACK: EQU $ +START: EQU $ + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c974c01 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +# Paterson Listings +Tim Paterson's DOS listings, containing source code of 86-DOS 1.00 kernel, +various PC-DOS 1.00 pre-release kernels and utilities, and the Microsoft +BASIC-86 Compiler runtime library. + +

+ +

+ +The DOS-related portions have been transcribed and turned into compilable +source code. + +## Downloads and Layout +- [`1_transcription`](./1_transcription/) ([download](https://github.com/DOS-History/Paterson-Listings/releases/latest/download/paterson_listings_transcription.zip)) - +transcription of the listings, essentially the raw printer output +- [`2_printed_files`](./2_printed_files/) ([download](https://github.com/DOS-History/Paterson-Listings/releases/latest/download/paterson_listings_printed_files.zip)) - +the original files that were printed, extracted from the raw printer output +above +- [`3_source_code`](./3_source_code/) ([download](https://github.com/DOS-History/Paterson-Listings/releases/latest/download/paterson_listings_source_code.zip)) - +compilable source code extracted from the printed files above + +If you just want to browse the source code or compile/assemble it, choose +[`3_source_code`](./3_source_code/). The original scans, in PDF and PNG +formats, are available at https://archive.org/details/paterson_listings. + +Further details about these listings, including technical writeups, can be +found at: +- https://thebrokenpipe.com/dos/paterson_listings +- http://cini.classiccmp.org/recoveryblog.htm + +## Listing Content +Paterson's stack of DOS listings contains 10 bundles of continuous-feed paper, +from top to bottom: + +- [Bundle 01](https://archive.org/download/paterson_listings/bundle01.pdf) +(86 pages): + - [`MSDOS.LST`](./2_printed_files/bundle_01/MSDOS.LST) +- [Bundle 02](https://archive.org/download/paterson_listings/bundle02.pdf) +(62 pages): + - [`86DOS.A86`](./2_printed_files/bundle_02/86DOS.A86) + (created: 1981/07/07 17:06:59, printed: 1981/07/08 13:49:52) +- [Bundle 03](https://archive.org/download/paterson_listings/bundle03.pdf) +(18 pages): + - [`EDLIN.DIF`](./2_printed_files/bundle_03/EDLIN.DIF) + (created: 1981/07/28 14:21:18, printed: 1981/07/28 14:40:48) + - [`CHKDSK.A86`](./2_printed_files/bundle_03/CHKDSK.A86) + (created: 1981/07/15 12:19:22, printed: 1981/07/28 14:41:25) +- [Bundle 04](https://archive.org/download/paterson_listings/bundle04.pdf) +(58 pages): + - [`86DOS.ASM`](./2_printed_files/bundle_04/86DOS.ASM) + (created: 1981/06/15 03:18:51, printed: 1981/06/16 15:17:17) +- [Bundle 05](https://archive.org/download/paterson_listings/bundle05.pdf) +(57 pages): + - [`ASM.PRN`](./2_printed_files/bundle_05/ASM.PRN) +- [Bundle 06](https://archive.org/download/paterson_listings/bundle06.pdf) +(71 pages): + - [`ASM.PRN`](./2_printed_files/bundle_06/ASM.PRN) +- [Bundle 07](https://archive.org/download/paterson_listings/bundle07.pdf) +(10 pages): + - [`CHKDSK.A86`](./2_printed_files/bundle_07/CHKDSK.A86) + (created: 1981/06/15 04:10:28, printed: 1981/06/16 15:32:54) +- [Bundle 08](https://archive.org/download/paterson_listings/bundle08.pdf) +(32 pages): + - [`86DOS.DIF`](./2_printed_files/bundle_08/86DOS.DIF) + (created: 1981/06/16 15:11:47, printed: 1981/06/16 15:13:47) +- [Bundle 09](https://archive.org/download/paterson_listings/bundle09.pdf) +(459 pages): + - `LIBLST.LOG` + (created: 1981/11/13 01:10:16, printed: 1981/11/13 01:17:42) + - `BASLIB.PRT` + (created: 1981/11/13 01:09:35, printed: 1981/11/13 01:19:29) +- [Bundle 10](https://archive.org/download/paterson_listings/bundle10.pdf) +(20 pages): + - `PAINT.ASM` + (created: 1982/01/06 22:20:26, printed: 1982/02/06 20:58:03) + - `CIRCLE.ASM` + (created: 1982/02/04 11:51:32, printed: 1982/02/06 20:58:44) + +Bundles 9 and 10 have not yet been transcribed. If you wish to help transcribe +them, please submit a +[pull request](https://github.com/DOS-History/Paterson-Listings/pulls). Only +contributions that provide direct transcriptions of the listings or correct +typos in existing transcriptions will be merged. + +## Compiling/Assembling +Most of the sources here target Seattle Computer Products' ASM assembler, so +you will need a copy. It can be obtained from any release of 86-DOS or MS-DOS +by Seattle Computer Products. You will also need the `HEX2BIN` utility from +Seattle Computer Products to convert Intel HEX objects produced by the +assembler into binaries. + +The simplest way to assemble a source file is to run +`ASM `, followed by `HEX2BIN `. +For example, to assemble `86DOS.ASM` into the binary `86DOS.COM`, run: +``` +A:ASM 86DOS + +Seattle Computer Products 8086 Assembler Version 2.24 +Copyright 1979,80,81 by Seattle Computer Products, Inc. + + + +Error Count = 0 + +A:HEX2BIN 86DOS + +A: +``` diff --git a/Tim_Paterson_24Apr2025_emails.txt b/Tim_Paterson_24Apr2025_emails.txt new file mode 100644 index 0000000..c5c8b83 --- /dev/null +++ b/Tim_Paterson_24Apr2025_emails.txt @@ -0,0 +1,94 @@ +From: Yufeng Gao +To: Tim Paterson +Date: Thu, 24 Apr 2025 11:17:51 +0000 +Subject: 86-DOS Printouts + + +Dear Mr. Paterson, + +I hope you've had a wonderful Easter. I'm reaching out to you regarding 86-DOS +source code printouts. I'm a huge fan of 86-DOS, and just over a year ago, I +completed a full source code reconstruction of 86-DOS 0.11 - the earliest +surviving version of DOS. + +Recently, Bill Gates released a scanned listing of Altair BASIC 1.3, which +brought to mind the "6-inch stack of printouts" you mentioned in your email to +Len Shustek. A friend of mine, Rich Cini, suggested that your printouts might +include the original source code for 86-DOS 1.00. I wanted to ask whether you +still have those printouts, and if so, whether you'd be open to having them +scanned and digitised. + +As 86-DOS approaches its 45th anniversary, I believe this would be a timely +opportunity to preserve and revive the original source code. To make this +happen, I'm more than happy to assist in any way I can. I have the equipment +and time to produce high-DPI scans and to transcribe the listings manually. + +Thank you for considering this request, and I hope to hear from you soon. + +Best regards, +Yufeng Gao + +------------------------------------------------------------------------------- + +From: Tim Paterson +To: Yufeng Gao +Cc: Richard Cini +Date: Thu, 24 Apr 2025 17:30:43 +0000 +Subject: RE: 86-DOS Printouts + + +The listing stack is actually only 3.5" (I found a bunch of blank paper at the +bottom). Here is the inventory: + - DOS 1.25 + - DOS snapshot 7/8/81 + - DOS snapshot 6/16/81 + - DOS diff: 5/5/81 vs. 6/16/81 + - EDLIN diff: 5/5/81 vs. 7/1/81 + - CHKDSK snapshot 7/28/81 + - CHKDSK snapshot 6/16/81 + - SCP Assembler 2.40 + - SCP Assembler 2.43 + - MS BASIC compiler runtime library 11/13/81 + +The last item was my area of responsibility at MS at the time, and takes up +half the stack. Most of the listings are from an MS line printer, and print +quality is not great. + +Getting around to packing and shipping is the hard part. + +Tim Paterson + +------------------------------------------------------------------------------- + +From: Richard Cini +To: Tim Paterson +Cc: Yufeng Gao +Date: Thu, 24 Apr 2025 18:26:22 +0000 +Subject: RE: 86-DOS Printouts + + +That's wonderful, Tim, thanks for taking a look at that stack. That's some +great stuff to archive. The various DOS snapshot dates seem unfamiliar to me. +Do you remember the significance of 5/5/81 versus the other two dates? I do +remember reading in a book that there was some last minute bug squashing so +maybe that's it. + +Rich + +------------------------------------------------------------------------------- + +From: Tim Paterson +To: Richard Cini +Cc: Yufeng Gao +Date: Thu, 24 Apr 2025 18:32:58 +0000 +Subject: RE: 86-DOS Printouts + + +There was ongoing work on DOS so the date is the OS file time stamp of the last +change. It does not correspond to any release or version. + +The 5/5/81 date should be very close if not identical to the v1.00 release +dated 4/28/81. The difference could be the date it was uploaded to the MS +server. + +Tim Paterson