diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 889c0b7..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,9 +0,0 @@ -[MS-DOS 1.25 & 2.0 Source] -Copyright (c) Microsoft Corporation -All rights reserved. -MIT License -Permission is hereby granted, freeof charge, to any person obtaining a copy of this software and associateddocumentation files (the Software), to deal in the Software withoutrestriction, including without limitation the rights to use, copy, modify,merge, publish, distribute, sublicense, and/or sell copies of the Software, andto permit persons to whom the Software is furnished to do so, subject to thefollowing conditions: - -The above copyright notice andthis permission notice shall be included in all copies or substantial portionsof the Software. - -THE SOFTWARE IS PROVIDED *AS IS*,WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TOTHE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLEFOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE ORTHE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index c1ebe0d..0000000 --- a/README.md +++ /dev/null @@ -1,16 +0,0 @@ -MS-DOS logo - -# MS-DOS v1.25 and v2.0 Source Code -This repo contains the original source-code and compiled binaries for MS-DOS 1.25 and MS-DOS 2.0. - -These are the same files [originally shared at the Computer History Museum on March 25th 2014]( http://www.computerhistory.org/atchm/microsoft-ms-dos-early-source-code/) and are being (re)published in this repo to make them easier to find, reference-to in external writing and works, and to allow exploration and experimentation for those interested in early PC Operating Systems. - -# License -All files within this repo are released under the [MIT (OSI) License]( https://en.wikipedia.org/wiki/MIT_License) as per the [LICENSE file](https://githib.com/microsoft/msdos/license.txt) stored in the root of this repo. - -# Contribute! -The source files in this repo are for historical reference and will be kept static, so please don’t send Pull Requests suggesting any modifications to the source files, but feel free to fork this repo and experiment 😊. - -If, however, you’d like to submit additional non-source content or modifications to non-source files (e.g. this README), please submit via PR and we’ll review and consider. - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/msdos-logo.png b/msdos-logo.png deleted file mode 100644 index fe77581..0000000 Binary files a/msdos-logo.png and /dev/null differ diff --git a/msdos-logo_250x250.png b/msdos-logo_250x250.png deleted file mode 100644 index c57865a..0000000 Binary files a/msdos-logo_250x250.png and /dev/null differ diff --git a/v1.25/Tim_Paterson_16Dec2013_email.txt b/v1.25/Tim_Paterson_16Dec2013_email.txt deleted file mode 100644 index 45c4055..0000000 --- a/v1.25/Tim_Paterson_16Dec2013_email.txt +++ /dev/null @@ -1,23 +0,0 @@ -From: Tim Paterson -To: Len Shustek -Date: Mon, 16 Dec 2013 10:34:17 -0800 -Subject: RE: Source code to MS-DOS 1.0 - - -I have found and attached the source code for MS-DOS 1.25 as shipped by Seattle Computer Products. Version 1.25 was the first general release to OEM customers other than IBM so was used by all the first clone manufacturers. - -IBM's DOS 1.1 corresponds to MS-DOS 1.24. There is one minor difference between 1.24 and 1.25, as noted in the revision history at the top of MSDOS.ASM. - -Of the file attached, only STDDOS.ASM/MSDOS.ASM (DOS main code) and COMMAND.ASM (command processor) would have been used by an OEM other than Seattle Computer. The other files: - -IO.ASM - I/O system unique to SCP (equivalent to ibmbio.sys). -ASM.ASM & HEX2BIN.ASM - Old 8086 assembler developed by SCP (used to assemble older version of DOS). -TRANS.ASM - Z80 to 8086 assembly source code translator developed by SCP. - -I also have a 6” stack of printouts of assembly listings for some of these and probably other related programs. - -Tim Paterson -Paterson Technology -http://www.patersontech.com/ - - diff --git a/v1.25/bin/ART.BAS b/v1.25/bin/ART.BAS deleted file mode 100644 index 2de324a..0000000 Binary files a/v1.25/bin/ART.BAS and /dev/null differ diff --git a/v1.25/bin/BALL.BAS b/v1.25/bin/BALL.BAS deleted file mode 100644 index 132087a..0000000 Binary files a/v1.25/bin/BALL.BAS and /dev/null differ diff --git a/v1.25/bin/BASIC.COM b/v1.25/bin/BASIC.COM deleted file mode 100644 index d6b32cf..0000000 Binary files a/v1.25/bin/BASIC.COM and /dev/null differ diff --git a/v1.25/bin/BASICA.COM b/v1.25/bin/BASICA.COM deleted file mode 100644 index dc08578..0000000 Binary files a/v1.25/bin/BASICA.COM and /dev/null differ diff --git a/v1.25/bin/CALENDAR.BAS b/v1.25/bin/CALENDAR.BAS deleted file mode 100644 index 34860ec..0000000 Binary files a/v1.25/bin/CALENDAR.BAS and /dev/null differ diff --git a/v1.25/bin/CHKDSK.COM b/v1.25/bin/CHKDSK.COM deleted file mode 100644 index bf88ed2..0000000 Binary files a/v1.25/bin/CHKDSK.COM and /dev/null differ diff --git a/v1.25/bin/CIRCLE.BAS b/v1.25/bin/CIRCLE.BAS deleted file mode 100644 index 611fc0d..0000000 Binary files a/v1.25/bin/CIRCLE.BAS and /dev/null differ diff --git a/v1.25/bin/COLORBAR.BAS b/v1.25/bin/COLORBAR.BAS deleted file mode 100644 index 067792c..0000000 Binary files a/v1.25/bin/COLORBAR.BAS and /dev/null differ diff --git a/v1.25/bin/COMM.BAS b/v1.25/bin/COMM.BAS deleted file mode 100644 index ef3439a..0000000 Binary files a/v1.25/bin/COMM.BAS and /dev/null differ diff --git a/v1.25/bin/COMMAND.COM b/v1.25/bin/COMMAND.COM deleted file mode 100644 index 751326f..0000000 Binary files a/v1.25/bin/COMMAND.COM and /dev/null differ diff --git a/v1.25/bin/COMP.COM b/v1.25/bin/COMP.COM deleted file mode 100644 index 0d16119..0000000 Binary files a/v1.25/bin/COMP.COM and /dev/null differ diff --git a/v1.25/bin/DEBUG.COM b/v1.25/bin/DEBUG.COM deleted file mode 100644 index b502552..0000000 Binary files a/v1.25/bin/DEBUG.COM and /dev/null differ diff --git a/v1.25/bin/DISKCOMP.COM b/v1.25/bin/DISKCOMP.COM deleted file mode 100644 index 08c595b..0000000 Binary files a/v1.25/bin/DISKCOMP.COM and /dev/null differ diff --git a/v1.25/bin/DISKCOPY.COM b/v1.25/bin/DISKCOPY.COM deleted file mode 100644 index e2436d1..0000000 Binary files a/v1.25/bin/DISKCOPY.COM and /dev/null differ diff --git a/v1.25/bin/DONKEY.BAS b/v1.25/bin/DONKEY.BAS deleted file mode 100644 index 8b6ac8a..0000000 Binary files a/v1.25/bin/DONKEY.BAS and /dev/null differ diff --git a/v1.25/bin/EDLIN.COM b/v1.25/bin/EDLIN.COM deleted file mode 100644 index 5ed5148..0000000 Binary files a/v1.25/bin/EDLIN.COM and /dev/null differ diff --git a/v1.25/bin/EXE2BIN.EXE b/v1.25/bin/EXE2BIN.EXE deleted file mode 100644 index d43a3f2..0000000 Binary files a/v1.25/bin/EXE2BIN.EXE and /dev/null differ diff --git a/v1.25/bin/FORMAT.COM b/v1.25/bin/FORMAT.COM deleted file mode 100644 index c1cc45e..0000000 Binary files a/v1.25/bin/FORMAT.COM and /dev/null differ diff --git a/v1.25/bin/LINK.EXE b/v1.25/bin/LINK.EXE deleted file mode 100644 index 499b7b2..0000000 Binary files a/v1.25/bin/LINK.EXE and /dev/null differ diff --git a/v1.25/bin/MODE.COM b/v1.25/bin/MODE.COM deleted file mode 100644 index b9f69e3..0000000 Binary files a/v1.25/bin/MODE.COM and /dev/null differ diff --git a/v1.25/bin/MORTGAGE.BAS b/v1.25/bin/MORTGAGE.BAS deleted file mode 100644 index 80c062e..0000000 Binary files a/v1.25/bin/MORTGAGE.BAS and /dev/null differ diff --git a/v1.25/bin/MUSIC.BAS b/v1.25/bin/MUSIC.BAS deleted file mode 100644 index bd0ae0d..0000000 Binary files a/v1.25/bin/MUSIC.BAS and /dev/null differ diff --git a/v1.25/bin/PIECHART.BAS b/v1.25/bin/PIECHART.BAS deleted file mode 100644 index 943b398..0000000 Binary files a/v1.25/bin/PIECHART.BAS and /dev/null differ diff --git a/v1.25/bin/SAMPLES.BAS b/v1.25/bin/SAMPLES.BAS deleted file mode 100644 index 2d2b2aa..0000000 Binary files a/v1.25/bin/SAMPLES.BAS and /dev/null differ diff --git a/v1.25/bin/SETCLOCK.COM b/v1.25/bin/SETCLOCK.COM deleted file mode 100644 index 3bf8501..0000000 Binary files a/v1.25/bin/SETCLOCK.COM and /dev/null differ diff --git a/v1.25/bin/SPACE.BAS b/v1.25/bin/SPACE.BAS deleted file mode 100644 index 52ba147..0000000 Binary files a/v1.25/bin/SPACE.BAS and /dev/null differ diff --git a/v1.25/bin/SYS.COM b/v1.25/bin/SYS.COM deleted file mode 100644 index 7f478fa..0000000 Binary files a/v1.25/bin/SYS.COM and /dev/null differ diff --git a/v1.25/source/ASM.ASM b/v1.25/source/ASM.ASM deleted file mode 100644 index d870d97..0000000 --- a/v1.25/source/ASM.ASM +++ /dev/null @@ -1,4006 +0,0 @@ -; Seattle Computer Products 8086 Assembler version 2.44 -; 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/83 2.43 Correct over-zealous optimization in 2.42 -; 05/09/83 2.44 Add memory usage report -; -;* * * * * * * * * * * * * * * * * * * * * - -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.44' - DB 13,10,'Copyright 1979-1983 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 AX,[ERRCNT] - MOV BX,ERCNTM -PRNT10: - PUSH AX - CALL PRINT - POP AX - 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 - MOV BX,SYMSIZE - MOV AX,[6] - SUB AX,[HEAP] ;Size of symbol table - CALL PRNT10 - MOV BX,FRESIZE - MOV AX,[HEAP] - SUB AX,[CODE] ;Free space remaining - CALL PRNT10 - 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 =' -SYMSIZE DM 13,10,'Symbol Table size = ' -FRESIZE DM 'Free space = ' -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/v1.25/source/COMMAND.ASM b/v1.25/source/COMMAND.ASM deleted file mode 100644 index 830bf73..0000000 --- a/v1.25/source/COMMAND.ASM +++ /dev/null @@ -1,2166 +0,0 @@ -; COMMAND version 1.17 -; -; This version of COMMAND is divided into three distinct parts. First -; is the resident portion, which includes handlers for interrupts -; 22H (terminate), 23H (Cntrl-C), 24H (fatal error), and 27H (stay -; resident); it also has code to test and, if necessary, reload the -; transient portion. Following the resident is the init code, which is -; overwritten after use. Then comes the transient portion, which -; includes all command processing (whether internal or external). -; The transient portion loads at the end of physical memory, and it may -; be overlayed by programs that need as much memory as possible. When -; the resident portion of command regains control from a user program, -; a checksum is performed on the transient portion to see if it must be -; reloaded. Thus programs which do not need maximum memory will save -; the time required to reload COMMAND when they terminate. - -;Use the following booleans to set assembly flags -FALSE EQU 0 -TRUE EQU NOT FALSE - -IBMVER EQU FALSE ;Switch to build IBM version of Command -MSVER EQU TRUE ;Switch to build MS-DOS version of Command - -HIGHMEM EQU TRUE ;Run resident part above transient (high memory) - -LINPERPAG EQU 23 -NORMPERLIN EQU 1 -WIDEPERLIN EQU 5 - - IF IBMVER -SYM EQU ">" -COMDRV EQU 1 - ENDIF - - IF MSVER -SYM EQU ":" -COMDRV EQU 0 - ENDIF - -FCB EQU 5CH -DSKRESET EQU 13 -SETBASE EQU 38 -SRCHFRST EQU 17 -SRCHNXT EQU 18 -RENAM EQU 23 -INCHAR EQU 1 -GETFAT EQU 27 -OPEN EQU 15 -CLOSE EQU 16 -MAKE EQU 22 -DELETE EQU 19 -RDBLK EQU 39 -WRBLK EQU 40 -SETDMA EQU 26 -SELDRV EQU 14 -GETDRV EQU 25 -PRINTBUF EQU 9 -OUTCH EQU 2 -INBUF EQU 10 -GETDATE EQU 2AH -SETDATE EQU 2BH -GETTIME EQU 2CH -SETTIME EQU 2DH -RR EQU 33 -RECLEN EQU 14 -FILLEN EQU 16 -OFFDATE EQU 20 - - -;The following are all of the segments used in the load order - -CODERES SEGMENT -CODERES ENDS - -DATARES SEGMENT BYTE -DATARES ENDS - -INIT SEGMENT BYTE -INIT ENDS - -TAIL SEGMENT PARA -TAIL ENDS - -TRANCODE SEGMENT PARA -TRANCODE ENDS - -TRANDATA SEGMENT BYTE -TRANDATA ENDS - -TRANSPACE SEGMENT BYTE -TRANSPACE ENDS - -RESGROUP GROUP CODERES,DATARES,INIT,TAIL -TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE - -;Data for resident portion - -DATARES SEGMENT BYTE - ORG 0 -ZERO = $ -MESBAS DW OFFSET RESGROUP:ERR0 - DW OFFSET RESGROUP:ERR2 - DW OFFSET RESGROUP:ERR4 - DW OFFSET RESGROUP:ERR6 - DW OFFSET RESGROUP:ERR8 - DW OFFSET RESGROUP:ERR10 - DW OFFSET RESGROUP:ERR12 -ERR0 DB "Write protect$" -ERR2 DB "Not ready$" -ERR4 DB "Data$" -ERR6 DB "Seek$" -ERR8 DB "Sector not found$" -ERR10 DB "Write fault$" -ERR12 DB "Disk$" -READ DB "read$" -WRITE DB "writ$" -ERRMES DB " error " -IOTYP DB "writing" -DRVNUM DB " drive " -DRVLET DB "A" -NEWLIN DB 13,10,"$" -REQUEST DB "Abort, Retry, Ignore? $" -BADFAT DB 13,10,"File allocation table bad,$" -COMBAD DB 13,10,"Invalid COMMAND.COM" -NEEDCOM DB 13,10,"Insert DOS disk in " - IF IBMVER - DB "drive A" - ELSE - DB "default drive" - ENDIF -PROMPT DB 13,10,"and strike any key when ready",13,10,"$" -NEEDBAT DB 13,10,"Insert disk with batch file$" -ENDBATMES DB 13,10,"Terminate batch job (Y/N)? $" -LOADING DB 0 -BATFCB DB 1,"AUTOEXECBAT" - DB 21 DUP(?) - DW 0 - DW 0 ;Initialize RR field to zero -PARMTAB DW 10 DUP(-1) ;No parameters initially -BATCH DB 1 ;Assume batch mode initially -COMFCB DB COMDRV,"COMMAND COM" - DB 25 DUP(?) -TRANS DW OFFSET TRANGROUP:COMMAND -TRNSEG DW ? -BATBYT DB ? -MEMSIZ DW ? -SUM DW ? -INITADD DB 4 DUP(?) -RESDATASIZE EQU $-ZERO -DATARES ENDS - -;Data for transient portion - -TRANDATA SEGMENT BYTE - ORG 0 -ZERO EQU $ -BADNAM DB "Bad command or file name",13,10,"$" -MISNAM DB "Missing file name$" -RENERR DB "Duplicate file name or " -NOTFND DB "File not found$" -EXEBAD DB "Error in EXE file$" -NOSPACE DB "Insufficient disk space",13,10,"$" -FULDIR DB "File creation error",13,10,"$" -OVERWR DB "File cannot be copied onto itself",13,10,"$" -LOSTERR DB "Content of destination lost before copy",13,10,"$" -COPIED DB " File(s) copied$" -DIRMES DB " File(s)$" -TOOBIG DB "Program too big to fit in memory$" -BADDRV DB "Invalid drive specification$" -PAUSMES DB "Strike a key when ready . . . $" -BADSWT DB "Illegal switch",13,10,"$" -WEEKTAB DB "SunMonTueWedThuFriSat" -BADDAT DB 13,10,"Invalid date$" -CURDAT DB "Current date is $" -NEWDAT DB 13,10,"Enter new date: $" -BADTIM DB 13,10,"Invalid time$" -CURTIM DB "Current time is $" -NEWTIM DB 13,10,"Enter new time: $" -SUREMES DB "Are you sure (Y/N)? $" - -COMTAB DB 4,"DIR",1 - DW OFFSET TRANGROUP:CATALOG - DB 7,"RENAME",1 - DW OFFSET TRANGROUP:RENAME - DB 4,"REN",1 - DW OFFSET TRANGROUP:RENAME - DB 6,"ERASE",1 - DW OFFSET TRANGROUP:ERASE - DB 4,"DEL",1 - DW OFFSET TRANGROUP:ERASE - DB 5,"TYPE",1 - DW OFFSET TRANGROUP:TYPEFIL - DB 4,"REM",1 - DW OFFSET TRANGROUP:COMMAND - DB 5,"COPY",1 - DW OFFSET TRANGROUP:COPY - DB 6,"PAUSE",1 - DW OFFSET TRANGROUP:PAUSE - DB 5,"DATE",0 - DW OFFSET TRANGROUP:DATE - DB 5,"TIME",0 - DW OFFSET TRANGROUP:TIME - DB 0 ;Terminate command table - -COMBUF DB 128,1,13 - -TRANDATASIZE EQU $-ZERO -TRANDATA ENDS - -;Uninitialized transient data -TRANSPACE SEGMENT BYTE - ORG 0 -ZERO = $ - DB 128 DUP(?) -TPA DW 1 DUP(?) -RESSEG DW 1 DUP(?) -CHKDRV DB 1 DUP(?) -FILTYP DB 1 DUP(?) -CURDRV DB 1 DUP(?) -PARM1 DB 1 DUP(?) -PARM2 DB 1 DUP(?) -COMSW DW 1 DUP(?) -ARG1S DW 1 DUP(?) -ARG2S DW 1 DUP(?) -FLAGER DB 1 DUP(?) -CFLAG DB 1 DUP(?) -SPECDRV DB 1 DUP(?) -BYTCNT DW 1 DUP(?) -NXTADD DW 1 DUP(?) -LINCNT DB 1 DUP(?) -LINLEN DB 1 DUP(?) -FILECNT DW 1 DUP(?) -EXEFCB LABEL WORD -IDLEN DB 1 DUP(?) -ID DB 8 DUP(?) -COM DB 3 DUP(?) -DEST DB 37 DUP(?) -DESTNAME DB 11 DUP(?) -DIRBUF DB 37 DUP(?) -BITS DW 1 DUP(?) -FULLSCR DW 1 DUP(?) -EXEEND DW 1 DUP(?) -;Header variables for EXE file load -;These are overlapped with COPY variables, below -RUNVAR LABEL WORD -RELPT DW 1 DUP(?) -RELSEG DW 1 DUP(?) -PSIZE LABEL WORD -PAGES DW 1 DUP(?) -RELCNT DW 1 DUP(?) -HEADSIZ DW 1 DUP(?) - DW 1 DUP(?) -LOADLOW DW 1 DUP(?) -INITSS DW 1 DUP(?) -INITSP DW 1 DUP(?) - DW 1 DUP(?) -INITIP DW 1 DUP(?) -INITCS DW 1 DUP(?) -RELTAB DW 1 DUP(?) -RUNVARSIZ EQU $-RUNVAR - - DB 80H DUP(?) -STACK LABEL WORD - -PRETRLEN EQU $-ZERO ;Used later to compute TRNLEN - - ORG RUNVAR-ZERO ;Overlaps EXE variables - -SRCPT DW 1 DUP(?) -INEXACT DB 1 DUP(?) -APPEND DB 1 DUP(?) -NOWRITE DB 1 DUP(?) -ASCII DB 1 DUP(?) -PLUS DB 1 DUP(?) -SOURCE DB 11 DUP(?) -TRANSPACESIZE EQU $-ZERO -TRANSPACE ENDS - - -;START OF RESIDENT PORTION - -CODERES SEGMENT -ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP - ORG 0 -ZERO = $ -PARMBUF LABEL WORD - - ORG 100H - -RSTACK LABEL WORD - -PROGSTART: - JMP CONPROC - -LTPA DW 0 ;WILL STORE TPA SEGMENT HERE -MYSEG DW 0 ;Put our own segment here - -CONTC: - MOV AX,CS - MOV DS,AX - MOV SS,AX - MOV SP,OFFSET RESGROUP:RSTACK - STI - CALL SETVECT - MOV AH,DSKRESET - INT 33 ;Reset disks in case files were open - TEST [BATCH],-1 - JZ LODCOM -ASKEND: - MOV DX,OFFSET RESGROUP:ENDBATMES - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR - INT 33 - AND AL,5FH - CMP AL,"N" - JZ LODCOM - CMP AL,"Y" - JNZ ASKEND - MOV [BATCH],0 -LODCOM: - MOV AX,CS - MOV SS,AX - MOV SP,OFFSET RESGROUP:RSTACK - MOV DS,AX - CALL SETVECT - CALL CHKSUM - CMP DX,[SUM] - JZ HAVCOM - MOV [LOADING],1 - CALL LOADCOM -CHKSAME: - CALL CHKSUM - CMP DX,[SUM] - JZ HAVCOM - CALL WRONGCOM - JMP SHORT CHKSAME -HAVCOM: - MOV [LOADING],0 - MOV SI,OFFSET RESGROUP:LTPA - MOV DI,OFFSET TRANGROUP:TPA - MOV ES,[TRNSEG] - CLD - MOVSW ;Move TPA segment to transient storage - MOVSW ;Move resident segment too - MOV AX,[MEMSIZ] - MOV WORD PTR ES:[2],AX - JMP DWORD PTR [TRANS] - -RESIDENT: - ADD DX,15 - MOV CL,4 - SHR DX,CL ;Number of paragraphs of new addition - ADD CS:[LTPA],DX - XOR AX,AX - MOV DS,AX - JMP DWORD PTR DS:[80H] ;Pretend user executed INT 20H - -DSKERR: - ;****************************************************** - ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE - ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO - ; INTERCEPT INTERRUPT 24H. - ;****************************************************** - STI - PUSH DS - PUSH CS - POP DS ;Set up local data segment - PUSH DX - CALL CRLF - POP DX - ADD AL,"A" ;Compute drive letter - MOV [DRVLET],AL - TEST AH,80H ;Check if hard disk error - JNZ FATERR - MOV SI,OFFSET RESGROUP:READ - TEST AH,1 - JZ SAVMES - MOV SI,OFFSET RESGROUP:WRITE -SAVMES: - LODSW - MOV WORD PTR [IOTYP],AX - LODSW - MOV WORD PTR [IOTYP+2],AX - AND DI,0FFH - CMP DI,12 - JBE HAVCOD - MOV DI,12 -HAVCOD: - MOV DI,WORD PTR [DI+MESBAS] ;Get pointer to error message - XCHG DI,DX ;May need DX later - MOV AH,PRINTBUF - INT 33 ;Print error type - MOV DX,OFFSET RESGROUP:ERRMES - INT 33 - CMP [LOADING],0 - JNZ GETCOMDSK -ASK: - MOV DX,OFFSET RESGROUP:REQUEST - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR - INT 33 ;Get response - CALL CRLF - OR AL,20H ;Convert to lower case - MOV AH,0 ;Return code for ignore - CMP AL,"i" ;Ignore? - JZ EXIT - INC AH - CMP AL,"r" ;Retry? - JZ EXIT - INC AH - CMP AL,"a" ;Abort? - JNZ ASK -EXIT: - MOV AL,AH - MOV DX,DI - POP DS - IRET - -FATERR: - MOV DX,OFFSET RESGROUP:BADFAT - MOV AH,PRINTBUF - INT 33 - MOV DX,OFFSET RESGROUP:DRVNUM - INT 33 - MOV AL,2 ;Abort - POP DS - IRET - -GETCOMDSK: - MOV DX,OFFSET RESGROUP:NEEDCOM - MOV AH,PRINTBUF - INT 33 - MOV AX,0C07H ;Get char without testing or echo - INT 33 - JMP LODCOM - -CRLF: - MOV DX,OFFSET RESGROUP:NEWLIN - PUSH AX - MOV AH,PRINTBUF - INT 33 - POP AX -RET10: RET - -LOADCOM: - PUSH DS - MOV DS,[TRNSEG] - MOV DX,100H - MOV AH,SETDMA - INT 33 - POP DS - MOV DX,OFFSET RESGROUP:COMFCB - MOV AH,OPEN - INT 33 ;Open COMMAND.COM - OR AL,AL - JZ READCOM - MOV DX,OFFSET RESGROUP:NEEDCOM -PROMPTCOM: - MOV AH,PRINTBUF - INT 33 - MOV AX,0C07H ;Get char without testing or echo - INT 33 - JMP SHORT LOADCOM -READCOM: - MOV WORD PTR[COMFCB+RR],OFFSET RESGROUP:TRANSTART - XOR AX,AX - MOV WORD PTR[COMFCB+RR+2],AX - MOV [COMFCB],AL ;Use default drive - INC AX - MOV WORD PTR[COMFCB+RECLEN],AX - MOV CX,COMLEN - MOV DX,OFFSET RESGROUP:COMFCB - MOV AH,RDBLK - INT 33 - OR AL,AL - JZ RET10 -WRONGCOM: - MOV DX,OFFSET RESGROUP:COMBAD - JMP SHORT PROMPTCOM - -CHKSUM: - CLD - PUSH DS - MOV DS,[TRNSEG] - MOV SI,100H - MOV CX,COMLEN - SHR CX,1 - XOR DX,DX -CHK: - LODSW - ADD DX,AX - LOOP CHK - POP DS - RET - -SETVECT: - MOV DX,OFFSET RESGROUP:LODCOM - MOV AX,2522H ;Set Terminate address - INT 21H - MOV DX,OFFSET RESGROUP:CONTC - MOV AX,2523H ;Set Ctrl-C address - INT 21H - MOV DX,OFFSET RESGROUP:DSKERR - MOV AX,2524H ;Set Hard Disk Error address - INT 33 - MOV DX,OFFSET RESGROUP:RESIDENT - MOV AX,2527H ;Set Terminate and Stay Resident address - INT 33 - RET -RESCODESIZE EQU $-ZERO -CODERES ENDS - -;******************************************************************* -;START OF INIT PORTION -;This code is overlayed the first time the TPA is used. - -INIT SEGMENT BYTE - - ORG 0 -ZERO = $ -CONPROC: - MOV SP,OFFSET RESGROUP:RSTACK - - IF HIGHMEM - MOV AX,WORD PTR DS:[2] - SUB AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Subtract size of resident - MOV WORD PTR DS:[2],AX - MOV ES,AX - MOV SI,100H - MOV DI,SI - MOV CX,((RESCODESIZE+RESDATASIZE)-100H+1)/2 ;Length of resident in words - REP MOVSW ;Move to end of memory - MOV DS,AX - MOV [LTPA],CS - ENDIF - - IF NOT HIGHMEM - MOV AX,CS - ADD AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Compute segment of TPA - MOV [LTPA],AX - MOV AX,WORD PTR DS:[2] - ENDIF - - MOV [MYSEG],DS - MOV [MEMSIZ],AX - SUB AX,TRNLEN ;Subtract size of transient - MOV [TRNSEG],AX - CALL SETVECT - CALL LOADCOM - CALL CHKSUM - MOV [SUM],DX - - IF MSVER - IF HIGHMEM - PUSH DS - PUSH CS - POP DS - ENDIF - MOV DX,OFFSET RESGROUP:HEADER - MOV AH,PRINTBUF - INT 33 - IF HIGHMEM - POP DS - ENDIF - ENDIF - - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,OPEN - INT 33 ;See if AUTOEXEC.BAT exists - MOV WORD PTR[BATFCB+RECLEN],1 ;Set record length to 1 - OR AL,AL ;Zero means file found - JZ DRV0 - MOV [BATCH],0 ;Not found--turn off batch job - MOV AX,OFFSET TRANGROUP:DATINIT - MOV WORD PTR[INITADD],AX - MOV AX,[TRNSEG] - MOV WORD PTR[INITADD+2],AX - CALL DWORD PTR DS:[INITADD] - - IF IBMVER - MOV DX,OFFSET RESGROUP:HEADER - MOV AH,PRINTBUF - INT 33 - ENDIF - -DRV0: - JMP HAVCOM - - - IF MSVER -HEADER DB 13,10,"Command v. 1.17" - IF HIGHMEM - DB "H" - ENDIF - DB 13,10,"$" - ENDIF - - IF IBMVER -HEADER DB 13,10,13,10,"The IBM Personal Computer DOS",13,10 - DB "Version 1.10 (C)Copyright IBM Corp 1981, 1982",13,10,"$" - DB "Licensed Material - Program Property of IBM" - ENDIF - -INITSIZE EQU $-ZERO -INIT ENDS - -;This TAIL segment is used to produce a PARA aligned label in the resident -; group which is the location where the transient segments will be loaded -; initialy. - -TAIL SEGMENT PARA - ORG 0 -TRANSTART LABEL WORD -TAIL ENDS - -;******************************************************************** -;START OF TRANSIENT PORTION -;This code is loaded at the end of memory and may be overwritten by -;memory-intensive user programs. - -TRANCODE SEGMENT PARA -ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:TRANGROUP - -WSWITCH EQU 1 ;Wide display during DIR -PSWITCH EQU 2 ;Pause (or Page) mode during DIR -VSWITCH EQU 4 ;Verify during COPY -ASWITCH EQU 8 ;ASCII mode during COPY -BSWITCH EQU 10H ;Binary mode during COPY - - ORG 0 -ZERO = $ - - ORG 100H ;Allow for 100H parameter area - -SETDRV: - MOV AH,SELDRV - INT 21H -COMMAND: - CLD - MOV AX,CS - MOV SS,AX - MOV SP,OFFSET TRANGROUP:STACK - MOV ES,AX - MOV DS,AX - STI - MOV AX,46*100H - MOV DL,0 - INT 33 ;Turn off verify after write - MOV AX,CS ;Get segment we're in - SUB AX,[TPA] ;AX=size ot TPA in paragraphs - MOV DX,16 - MUL DX ;DX:AX=size of TPA in bytes - OR DX,DX ;See if over 64K - JZ SAVSIZ ;OK if not - MOV AX,-1 ;If so, limit to 65535 bytes -SAVSIZ: - MOV [BYTCNT],AX ;Max no. of bytes that can be buffered - CALL CRLF2 -GETCOM: - MOV AH,GETDRV - INT 21H - MOV [CURDRV],AL - ADD AL,"A" - CALL OUT ;Print letter for default drive - MOV AL,SYM - CALL OUT - MOV DS,[RESSEG] ;All batch work must use resident seg. -ASSUME DS:RESGROUP - TEST [BATCH],-1 - JNZ READBAT - PUSH CS - POP DS ;Need local segment to point to buffer -ASSUME DS:TRANGROUP - MOV DX,OFFSET TRANGROUP:COMBUF - MOV AH,INBUF - INT 21H ;Get a command - JMP DOCOM - -;All batch proccessing has DS set to segment of resident portion -ASSUME DS:RESGROUP -NEEDPARM: - CALL GETBATBYT - CMP AL,"%" ;Check for two consecutive % - JZ SAVBATBYT - CMP AL,13 ;Check for end-of-line - JZ SAVBATBYT - SUB AL,"0" - JB RDBAT ;Ignore parameter reference if invalid - CMP AL,9 - JA RDBAT - CBW - MOV SI,AX - SHL SI,1 ;Two bytes per entry - MOV SI,[SI+OFFSET RESGROUP:PARMTAB] ;Get pointer to corresponding parameter - CMP SI,-1 ;Check if parameter exists - JZ RDBAT ;Ignore if it doesn't - MOV AH,OUTCH -RDPARM: - LODSB ;From resident segment - CMP AL,0DH ;Check for end of parameter - JZ RDBAT - STOSB ;To transient segment - MOV DL,AL - INT 33 ;Display paramters too - JMP SHORT RDPARM - -PROMPTBAT: - MOV AH,PRINTBUF - MOV DX,OFFSET RESGROUP:NEEDBAT - INT 33 ;Prompt for batch file - MOV AH,PRINTBUF - MOV DX,OFFSET RESGROUP:PROMPT - INT 33 - MOV AX,0C00H+INCHAR - INT 33 - JMP COMMAND - -BADCOMJ1:JMP BADCOM - -READBAT: - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,OPEN - INT 33 ;Make sure batch file still exists - OR AL,AL - JNZ PROMPTBAT ;If OPEN fails, prompt for disk - MOV WORD PTR [BATFCB+RECLEN],1 - MOV DX,OFFSET RESGROUP:BATBYT - MOV AH,SETDMA - INT 33 - MOV DI,OFFSET TRANGROUP:COMBUF+2 -RDBAT: - CALL GETBATBYT - CMP AL,"%" ;Check for parameter - JZ NEEDPARM -SAVBATBYT: - STOSB - CALL OUT ;Display batched command line - CMP AL,0DH - JNZ RDBAT - SUB DI,OFFSET TRANGROUP:COMBUF+3 - MOV AX,DI - MOV ES:[COMBUF+1],AL ;Set length of line - CALL GETBATBYT ;Eat linefeed - PUSH CS - POP DS ;Go back to local segment -ASSUME DS:TRANGROUP -DOCOM: -;All segments are local for command line processing - MOV AL,10 - CALL OUT - MOV SI,OFFSET TRANGROUP:COMBUF+2 - MOV DI,OFFSET TRANGROUP:IDLEN - MOV AX,2901H ;Make FCB with blank scan-off - INT 21H - CMP AL,1 ;Check for ambiguous command name - JZ BADCOMJ1 ;Ambiguous commands not allowed - CMP AL,-1 - JNZ DRVGD - JMP DRVBAD -DRVGD: - MOV AL,[DI] - MOV [SPECDRV],AL - MOV AL," " - MOV CX,9 - INC DI - REPNE SCASB ;Count no. of letters in command name - MOV AL,9 - SUB AL,CL - MOV [IDLEN],AL - MOV DI,81H - MOV CX,0 - PUSH SI -COMTAIL: - LODSB - STOSB ;Move command tail to 80H - CMP AL,13 - LOOPNZ COMTAIL - NOT CL - MOV BYTE PTR DS:[80H],CL - POP SI -;If the command has 0 parameters must check here for -;any switches that might be present. -;SI -> first character after the command. - MOV [FLAGER],0 ;Set error flag before any calls to switch - CALL SWITCH ;Is the next character a "/" - MOV [COMSW],AX - MOV DI,FCB - MOV AX,2901H - INT 21H - MOV [PARM1],AL ;Save result of parse - CALL SWITCH - MOV [ARG1S],AX - MOV DI,FCB+10H - MOV AX,2901H - INT 21H ;Parse file name - MOV [PARM2],AL ;Save result - CALL SWITCH - MOV [ARG2S],AX - MOV AL,[IDLEN] - MOV DL,[SPECDRV] - OR DL,DL ;Check if drive was specified - JZ OK - JMP DRVCHK -OK: DEC AL ;Check for null command - JNZ FNDCOM - JMP GETCOM - -RETSW: - XCHG AX,BX ;Put switches in AX - RET - -SWITCH: - XOR BX,BX ;Initialize - no switches set -SWLOOP: - CALL SCANOFF ;Skip any delimiters - CMP AL,"/" ;Is it a switch specifier? - JNZ RETSW ;No -- we're finished - INC SI ;Skip over "/" - CALL SCANOFF - INC SI -;Convert lower case input to upper case - CMP AL,"a" - JB SAVCHR - CMP AL,"z" - JA SAVCHR - SUB AL,20H ;Lower-case changed to upper-case -SAVCHR: - MOV DI,OFFSET TRANGROUP:SWLIST - MOV CX,SWCOUNT - REPNE SCASB ;Look for matching switch - JNZ BADSW - MOV AX,1 - SHL AX,CL ;Set a bit for the switch - OR BX,AX - JMP SHORT SWLOOP - -BADSW: - MOV [FLAGER],1 ;Record error in switch - JMP SHORT SWLOOP - -SWLIST DB "BAVPW" -SWCOUNT EQU $-SWLIST - -DRVBAD: - MOV DX,OFFSET TRANGROUP:BADDRV - JMP ERROR - -FNDCOM: - MOV SI,OFFSET TRANGROUP:COMTAB ;Prepare to search command table - MOV CH,0 -FINDCOM: - MOV DI,OFFSET TRANGROUP:IDLEN - MOV CL,[SI] - JCXZ EXTERNAL - REPE CMPSB - LAHF - ADD SI,CX ;Bump to next position without affecting flags - SAHF - LODSB ;Get flag for drive check - MOV [CHKDRV],AL - LODSW ;Get address of command - JNZ FINDCOM - MOV DX,AX - CMP [CHKDRV],0 - JZ NOCHECK - MOV AL,[PARM1] - OR AL,[PARM2] ;Check if either parm. had invalid drive - CMP AL,-1 - JZ DRVBAD -NOCHECK:CALL DX -COMJMP: JMP COMMAND - -BADCOMJ:JMP BADCOM - -SETDRV1: - JMP SETDRV - -DRVCHK: - DEC DL ;Adjust for correct drive number - DEC AL ;Check if anything else is on line - JZ SETDRV1 -EXTERNAL: - MOV AL,[SPECDRV] - MOV [IDLEN],AL - MOV WORD PTR[COM],4F00H+"C" ;"CO" - MOV BYTE PTR[COM+2],"M" - MOV DX,OFFSET TRANGROUP:IDLEN - MOV AH,OPEN - INT 33 ;Check if command to be executed - MOV [FILTYP],AL ;0 for COM files, -1 for EXE files - OR AL,AL - JZ EXECUTE - MOV WORD PTR[COM],5800H+"E" ;"EX" - MOV BYTE PTR[COM+2],"E" - INT 33 ;Check for EXE file - OR AL,AL - JZ EXECUTE - MOV WORD PTR[COM],4100H+"B" ;"BA" - MOV BYTE PTR[COM+2],"T" - INT 33 ;Check if batch file to be executed - OR AL,AL - JNZ BADCOMJ -BATCOM: -;Batch parameters are read with ES set to segment of resident part - MOV ES,[RESSEG] -ASSUME ES:RESGROUP - MOV DI,OFFSET RESGROUP:PARMTAB - MOV AX,-1 - MOV CX,10 - REP STOSW ;Zero parameter pointer table - MOV SI,OFFSET TRANGROUP:COMBUF+2 - MOV DI,OFFSET RESGROUP:PARMBUF - MOV BX,OFFSET RESGROUP:PARMTAB -EACHPARM: - CALL SCANOFF - CMP AL,0DH - JZ HAVPARM - MOV ES:[BX],DI ;Set pointer table to point to actual parameter - INC BX - INC BX -MOVPARM: - LODSB - CALL DELIM - JZ ENDPARM ;Check for end of parameter - STOSB - CMP AL,0DH - JZ HAVPARM - JMP SHORT MOVPARM -ENDPARM: - MOV AL,0DH - STOSB ;End-of-parameter marker - CMP BX,OFFSET RESGROUP:PARMTAB+20 ;Maximum number of parameters? - JB EACHPARM -HAVPARM: - MOV SI,OFFSET TRANGROUP:IDLEN - MOV DI,OFFSET RESGROUP:BATFCB - MOV CX,16 - REP MOVSW ;Move into private batch FCB - XOR AX,AX - PUSH ES - POP DS ;Simply batch FCB setup -ASSUME DS:RESGROUP - MOV WORD PTR[BATFCB+RR],AX - MOV WORD PTR[BATFCB+RR+2],AX ;Zero RR field - INC AX - MOV WORD PTR[BATFCB+RECLEN],AX ;Set record length to 1 byte - MOV [BATCH],AL ;Flag batch job in progress - JMP COMMAND -ASSUME DS:TRANGROUP,ES:TRANGROUP - -EXECUTE: - MOV AX,WORD PTR[IDLEN+16] - OR AX,WORD PTR[IDLEN+18] ;See if zero length - JZ BADCOM ;If so, error - XOR AX,AX - MOV WORD PTR[IDLEN+RR],AX - MOV WORD PTR[IDLEN+RR+2],AX ;Set RR field to zero - INC AX - MOV WORD PTR[IDLEN+RECLEN],AX ;Set record length field to 1 - MOV DX,[TPA] - MOV BX,DX - MOV AH,SETBASE - INT 21H - TEST [FILTYP],-1 ;Check if file is COM or EXE - JZ COMLOAD - JMP EXELOAD -COMLOAD:PUSH DS - MOV DS,DX - MOV DX,100H - MOV AH,SETDMA - INT 21H - POP DS - MOV CX,[BYTCNT] - SUB CX,100H - MOV DX,OFFSET TRANGROUP:IDLEN - MOV AH,RDBLK - INT 21H - DEC AL - MOV DX,OFFSET TRANGROUP:TOOBIG - JNZ ERROR -;Set up exit conditions - MOV CX,[BYTCNT] - MOV DS,BX - MOV ES,BX - CLI - MOV SS,BX - MOV SP,CX - STI - SUB CX,100H ;Allow some stack space - XOR AX,AX - PUSH AX - MOV AX,100H - PUSH BX - PUSH AX - CALL SETUP -XXX PROC FAR - RET -XXX ENDP -BADCOM: - MOV DX,OFFSET TRANGROUP:BADNAM -ERROR: - MOV AH,PRINTBUF - INT 21H - JMP COMMAND - -CHKCNT: - TEST [FILECNT],-1 - JNZ ENDDIR - MOV DX,OFFSET TRANGROUP:NOTFND - JMP ERROR - -ENDDIR: -;Make sure last line ends with CR/LF - MOV AL,[LINLEN] - CMP AL,[LINCNT] ;Will be equal if just had CR/LF - JZ MESSAGE - CALL CRLF2 -MESSAGE: - MOV SI,[FILECNT] - XOR DI,DI - CALL DISP32BITS - MOV DX,OFFSET TRANGROUP:DIRMES - MOV AH,PRINTBUF - INT 21H - RET - -CATALOG: - MOV AL,"?" ;*.* is default file spec. - MOV DI,5DH - MOV CX,11 - REP STOSB - MOV SI,81H - CALL SWITCH - MOV DI,5CH - MOV AX,41*100H+0DH ;Parse with default name and extension - INT 33 - -;Begin by processing any switches that may have been specified. -;BITS will contain any information about switches that was -;found when the command line was parsed. - -SETSWT: - MOV AX,[COMSW] ;Get switches from command - OR AX,[ARG1S] ;OR in switches from first parameter - MOV [BITS],AX - MOV BYTE PTR[FULLSCR],LINPERPAG - TEST AL,1 ;Look for /W - MOV AL,NORMPERLIN - JZ DIR - MOV AL,WIDEPERLIN -DIR: - MOV [LINLEN],AL ;Set number of entries per line - MOV [LINCNT],AL - MOV [FILECNT],0 ;Keep track of how many files found - MOV DX,OFFSET TRANGROUP:DIRBUF ;Set Disk transfer address - MOV AH,SETDMA - INT 21H - MOV AH,SRCHFRST -SHOWDIR: - MOV DX,5CH ;DX -> Unopened FCB - INT 21H ;Search for a file to match FCB - INC AL ;FF = file not found - JNZ AGAIN ;Either an error or we are finished - JMP CHKCNT -AGAIN: - INC [FILECNT] ;Keep track of how many we find - MOV SI,OFFSET TRANGROUP:DIRBUF+1 ;SI -> information returned by sys call - CALL SHONAME - TEST BYTE PTR[BITS],1 ;/W set? - JNZ NEXENT ;If so, no size, date, or time - CALL DISPSIZE ;Print size of file - CALL TWOSPC - MOV AX,WORD PTR[DIRBUF+25] ;Get date - OR AX,AX - JZ NEXENT ;Skip if no date - MOV DX,AX - MOV CL,5 - SHR AX,CL ;Align month - AND AL,0FH - MOV BH,"0"-" " ;Enable zero suppression - CALL OUT2 - MOV AL,"-" - CALL OUT - MOV AL,DL - AND AL,1FH ;Mask to day - CALL OUT2 - MOV AL,"-" - CALL OUT - MOV AL,DH - SHR AL,1 ;Align year - ADD AX,80 ;Relative 1980 - CMP AL,100 - JB MILLENIUM - SUB AL,100 -MILLENIUM: - CALL OUT2 - MOV BX,WORD PTR[DIRBUF+23] ;Get time - OR BX,BX ;Time field present? - JZ NEXENT - CALL TWOSPC - SHR BX,1 - SHR BX,1 - SHR BX,1 - SHR BL,1 - SHR BL,1 ;Hours in BH, minutes in BL - MOV AL,BH - MOV DH,"a" ;Assume A.M. - CMP AL,12 ;In the afternoon? - JB MORN - MOV DH,"p" - JE MORN - SUB AL,12 ;Keep it to 12 hours or less -MORN: - OR AL,AL ;Before 1 am? - JNZ SHOHOURS - MOV AL,12 -SHOHOURS: - MOV BH,"0"-" " ;Enable zero suppression - CALL OUT2 - MOV AL,":" - CALL OUT - MOV AL,BL ;Output minutes - CALL OUT2 - MOV AL,DH ;Get "a" or "p" - CALL OUT -NEXENT: - DEC [LINCNT] - JNZ SAMLIN -NEXLIN: - MOV AL,[LINLEN] - MOV [LINCNT],AL - CALL CRLF2 - TEST BYTE PTR[BITS],2 ;/P switch present? - JZ SCROLL ;If not, just continue - DEC BYTE PTR[FULLSCR] - JNZ SCROLL - MOV BYTE PTR[FULLSCR],LINPERPAG - MOV AH,PRINTBUF - MOV DX,OFFSET TRANGROUP:PAUSMES - INT 33 - MOV AX,0C08H ;Wait for any character to be typed - INT 21H - CALL CRLF2 -SCROLL: - MOV AH,SRCHNXT - JMP SHOWDIR - -SAMLIN: - MOV AL,9 ;Output a tab - CALL OUT - JMP SHORT SCROLL - -SHONAME: - MOV CX,8 - CALL OUTCNT - CALL ONESPC - MOV CX,3 -OUTCNT: - LODSB - CALL OUT - LOOP OUTCNT - RET - -TWOSPC: - CALL ONESPC -ONESPC: - MOV AL," " - JMP OUT - -CRLF2: - MOV AL,13 - CALL OUT - MOV AL,10 - JMP OUT - -DISPSIZE: - MOV SI,WORD PTR[DIRBUF+29] - MOV DI,WORD PTR[DIRBUF+31] -DISP32BITS: -;Prints the 32-bit number DI:SI on the console in decimal. Uses a total -;of 9 digit positions with leading blanks. - XOR AX,AX - MOV BX,AX - MOV BP,AX - MOV CX,32 -CONVLP: - SHL SI,1 - RCL DI,1 - XCHG AX,BP - CALL CONVWRD - XCHG AX,BP - XCHG AX,BX - CALL CONVWRD - XCHG AX,BX - ADC AL,0 - LOOP CONVLP -; Conversion complete. Print 9-digit number. - MOV CX,1810H ;Allow leading zero blanking for 8 digits - XCHG DX,AX - CALL DIGIT - XCHG AX,BX - CALL OUTWORD - XCHG AX,BP -OUTWORD: - PUSH AX - MOV DL,AH - CALL OUTBYTE - POP DX -OUTBYTE: - MOV DH,DL - SHR DL,1 - SHR DL,1 - SHR DL,1 - SHR DL,1 - 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 -RET20: RET - -ERASE: - MOV CX,11 - MOV SI,FCB+1 -AMBSPEC: - LODSB - CMP AL,"?" - JNZ ALLFIL - LOOP AMBSPEC -ALLFIL: - CMP CX,0 - JNZ NOPRMPT -ASKAGN: - MOV DX,OFFSET TRANGROUP:SUREMES ;"Are you sure (Y/N)?" - MOV AH,PRINTBUF - INT 21H - MOV AX,0C00H+INCHAR - INT 21H - AND AL,5FH - CMP AL,"N" - JZ RET20 - CMP AL,"Y" - CALL CRLF2 - JZ NOPRMPT - JMP SHORT ASKAGN -NOPRMPT: - MOV AH,DELETE - MOV BX,OFFSET TRANGROUP:NOTFND - CMP BYTE PTR DS:[FCB+1]," " ;Check if parameter exists - JMP SHORT OPFILE -RENAME: - MOV AH,RENAM - MOV BX,OFFSET TRANGROUP:RENERR - CMP BYTE PTR DS:[FCB+16+1]," " ;Check if parameter exists -OPFILE: - MOV DX,OFFSET TRANGROUP:MISNAM - JZ ERRJ ;Error if missing parameter - MOV DX,FCB - INT 21H - INC AL - JNZ RET20 - MOV DX,BX -ERRJ: JMP ERROR - -TYPEFIL: - MOV DS,[TPA] - XOR DX,DX - MOV AH,SETDMA - INT 21H - PUSH CS - POP DS - MOV DX,FCB - MOV AH,OPEN - INT 21H - OR AL,AL - MOV DX,OFFSET TRANGROUP:NOTFND - JNZ ERRJ - XOR AX,AX - MOV WORD PTR DS:[FCB+RR],AX ;Set RR field - MOV WORD PTR DS:[FCB+RR+2],AX - INC AX - MOV WORD PTR DS:[FCB+RECLEN],AX ;Set record length - MOV ES,[TPA] -TYPELP: - MOV DX,FCB - MOV CX,[BYTCNT] - MOV AH,RDBLK - INT 21H - JCXZ RET30 - XOR SI,SI ;Start at 0 in TPA -OUTLP: - LODS BYTE PTR ES:[SI] ;In TPA segment - CMP AL,1AH - JZ RET30 - MOV AH,OUTCH - MOV DL,AL - INT 21H - LOOP OUTLP - JMP SHORT TYPELP - -RET30: RET ;Need a nearby RET - -COPY: - XOR AX,AX - MOV [PLUS],AL ;Will keep track of "+"s - MOV [FILECNT],AX - MOV SI,81H ;Point to input line - CALL SWITCH ;Skip over switches on command - MOV BP,AX - MOV DI,FCB - CALL PARSNAM ;Scan first source - MOV [PARM1],DL ;Save ambiguous flag - MOV [SRCPT],SI ;Save pointer to command line -;Parse each name to find destination and check for /V switch -SCANNAM: - CALL PARSE - JNZ SCANNAM -GETDEST: - MOV DI,OFFSET TRANGROUP:DEST - MOV BX,BP ;Remeber switches so far - XOR BP,BP ;Must have dest. swtiches alone - CALL PARSNAM - MOV [ARG2S],BP ;Remember switches on destination - JNZ HAVDESTNAM ;File name present? - INC DI ;Point to file name spot - MOV AL,"?" ;Substitute *.* - MOV CX,11 - REP STOSB -HAVDESTNAM: - OR BX,BP ;BX = all switches combined - AND BL,VSWITCH ;Verify requested? - JZ NOVER - MOV AX,46*100H+1 ;Set verify - MOV DL,0 - INT 33 -NOVER: - MOV DI,OFFSET TRANGROUP:DESTNAME - MOV SI,OFFSET TRANGROUP:DEST+1 - MOV BX,FCB+1 - CALL BUILDNAME ;See if we can make it unambiguous - MOV DI,OFFSET TRANGROUP:DESTNAME - MOV AL,"?" - MOV CX,11 - REPNE SCASB ;Scan for "?" to see if ambiguous - MOV AL,1 ;Flag if ambig. - JZ AMBIG - DEC AX ;AL=0 if unambig. -AMBIG: - MOV DL,AL - MOV AH,[PLUS] ;1=found "+" - XOR AL,1 ;0=ambig, 1=unambig destination - AND AL,[PARM1] ;Source ambig. AND dest unambig. - OR AL,AH ;OR found "+" means concatenation - MOV [ASCII],AL ;Concatenation implies ASCII mode - MOV [INEXACT],AL ;ASCII implies inexact copy - SHL AL,1 - OR AL,DL ;Combine multiple and concat flags - MOV [PARM2],AL - MOV AL,BYTE PTR[COMSW] - CALL SETASC ;Check /A,/B on command - MOV AL,BYTE PTR[ARG1S] - CALL SETASC ;Check for ASCII on first filename - MOV BYTE PTR[COMSW],AL ;Save starting switch values - MOV AH,SRCHFRST - CALL SEARCH ;Search for first source name -MULTDEST: - JZ FIRSTSRC ;Find a first source name? - TEST [PARM2],1 ;If multiple, we're done - JNZ ENDCOPY - XOR AX,AX - MOV [NXTADD],AX - MOV [CFLAG],AL ;Flag nothing read yet -NEXTSNG: - MOV DI,FCB - MOV SI,[SRCPT] - CALL PARSESRC ;Parse next file name into FCB - MOV [PARM1],DL ;Remember if it's ambiguous - MOV [SRCPT],SI - JZ SNGCLOS - MOV AH,SRCHFRST - CALL SEARCH ;Search for new file name - JNZ NEXTSNG ;If none, skip it and move to next name -READSNG: - CALL CHECKREAD -SNGLOOP: - CALL SEARCHNEXT ;See if any more of this name - JZ READSNG - JMP SHORT NEXTSNG - -SNGCLOS: - CALL CLOSEFIL -ENDCOPY: - MOV SI,[FILECNT] - XOR DI,DI - CALL DISP32BITS - MOV DX,OFFSET TRANGROUP:COPIED - MOV AH,PRINTBUF - INT 21H - JMP COMMAND ;Stack could be messed up - -FIRSTSRC: - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - MOV DI,OFFSET TRANGROUP:SOURCE - MOV CX,11 - REP MOVSB ;Copy first source name to SOURCE - MOV SI,OFFSET TRANGROUP:DESTNAME - MOV DI,OFFSET TRANGROUP:DEST+1 - MOV BX,OFFSET TRANGROUP:SOURCE - CALL BUILDNAME ;Build destination name - XOR AX,AX - MOV [NXTADD],AX - MOV [CFLAG],AL - MOV [APPEND],AL - MOV [NOWRITE],AL - TEST [PARM2],1 ;Multiple destinations? - JZ NOPRT - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - CALL SHONAME ;If so, show first source - CALL CRLF2 -NOPRT: - CALL COMPNAME ;Source and dest. the same? - JNZ DOREAD ;If not, read source in - TEST [PARM2],2 ;Concatenation? - MOV DX,OFFSET TRANGROUP:OVERWR - JZ COPERRJ ;If not, overwrite error - MOV [APPEND],1 ;Set physical append - MOV AH,OPEN - MOV DX,OFFSET TRANGROUP:DEST - INT 33 ;Open (existing) destination - CMP [ASCII],0 ;ASCII flag set? - JZ BINARYAPP -;ASCII append. Must find logical EOF, then seek there with dest. FCB - MOV [NOWRITE],1 - CALL READIN ;Find EOF - CALL FLSHFIL ;Seek there - MOV [NOWRITE],0 - CALL FLSHFIL ;Truncate file - JMP SHORT SNGLCHK - -SNGLOOPJ:JMP SNGLOOP - -COPERRJ:JMP COPERR - -BINARYAPP: - MOV WORD PTR[DEST+RECLEN],1 ;Set record length to 1 - MOV SI,OFFSET TRANGROUP:DEST+16 ;Point to file size - MOV DI,OFFSET TRANGROUP:DEST+RR - MOVSW - MOVSW ;Seek to end of file - MOV [CFLAG],1 - JMP SHORT SNGLCHK -DOREAD: - CALL READIN -SNGLCHK: - TEST [PARM2],1 ;Single or multiple destinations? - JZ SNGLOOPJ - MOV SI,[SRCPT] -MULTAPP: - CALL PARSE - JZ MULTCLOS - PUSH SI - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - MOV DI,SI - MOV BX,OFFSET TRANGROUP:SOURCE - CALL BUILDNAME - CALL CHECKREAD - POP SI - JMP SHORT MULTAPP -MULTCLOS: - CALL CLOSEFIL - MOV AL,BYTE PTR[COMSW] - MOV [ASCII],AL ;Restore ASCII flag - CALL SEARCHNEXT - JMP MULTDEST - -PARSE: - MOV DI,OFFSET TRANGROUP:DIRBUF -PARSESRC: - CALL SCANOFF - CMP AL,"+" - JNZ RETZF - MOV [PLUS],1 ;Keep track of "+" signs - INC SI ;Skip over it -PARSNAM: - MOV AX,2901H - INT 33 ;Parse file name - CMP AL,-1 ;Illegal? - MOV DX,OFFSET TRANGROUP:BADDRV - JZ COPERRJ - XCHG AX,DX ;Save parse flag in DL - MOV AL,BYTE PTR[DI] ;Get drive number - OR AL,AL ;Is it default? - JNZ PARSW - MOV AL,[CURDRV] ;Substitute actual drive - INC AX - MOV BYTE PTR[DI],AL -PARSW: - PUSH BX - PUSH DI - CALL SWITCH ;Process switches - OR BP,AX ;Combine all switches - CALL SETASC ;Check for /A or /B - POP DI - POP BX - CMP BYTE PTR[DI+1]," " ;Did we even get a file name? - RET - -RETZF: - XOR AX,AX -RET35: RET - -SEARCHNEXT: - MOV AL,[PARM1] ;Is name ambiguous? - DEC AL - JNZ RET35 ;Don't perform search if not - MOV AH,SRCHNXT -SEARCH: - PUSH AX - MOV AH,SETDMA - MOV DX,OFFSET TRANGROUP:DIRBUF - INT 33 ;Put result of search in DIRBUF - POP AX ;Restore search first/next command - MOV DX,FCB - INT 33 ;Do the search - OR AL,AL - RET - -SETASC: -;Given switch vector in AX, -; Set ASCII switch if /A is set -; Clear ASCII switch if /B is set -; Leave ASCII unchanged if neither or both are set -; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set - AND AL,ASWITCH+BSWITCH - JPE LOADSW ;PE means both or neither are set - AND AL,ASWITCH - MOV [ASCII],AL - OR [INEXACT],AL -LOADSW: - MOV AL,[ASCII] - OR AL,AL - RET - -BUILDNAME: -; [SI] = Ambiguous input file name -; [BX] = Source of replacement characters -; [DI] = Destination -; File name is copied from [SI] to [DI]. If "?"s are encountered, -; they are replaced with the character in the same position at [BX]. - MOV CX,11 -BUILDNAM: - LODSB - CMP AL,"?" - JNZ NOTAMBIG - MOV AL,BYTE PTR[BX] -NOTAMBIG: - STOSB - INC BX - LOOP BUILDNAM - RET - -COMPNAME: - MOV SI,OFFSET TRANGROUP:DEST - MOV DI,OFFSET TRANGROUP:DIRBUF - MOV CX,6 - REPE CMPSW - RET - -CHECKREAD: -;Read file in (with READIN) if not identical to destination - CALL COMPNAME ;See if source and destination the same - JNZ READIN - CMP [APPEND],0 ;If physical append, it's OK - JNZ RET40 - MOV DX,OFFSET TRANGROUP:LOSTERR ;Tell him he's not going to get it - MOV AH,PRINTBUF - INT 33 -RET40: RET - -READIN: -;Open source file and read it in. If memory fills up, flush it out to -;destination and keep reading. If /A switch set, chop file at first ^Z. -; Inputs/Outputs: -; [NXTADD] has current pointer in buffer -; [CFLAG] <>0 if destination has been created - - MOV DX,OFFSET TRANGROUP:DIRBUF - MOV AH,OPEN - INT 21H - OR AL,AL ;Successful open? - JNZ RET40 ;If not, just ignore it - XOR AX,AX - MOV WORD PTR[DIRBUF+RR],AX - MOV WORD PTR[DIRBUF+RR+2],AX - INC AX - MOV WORD PTR[DIRBUF+RECLEN],AX -COPYLP: - MOV DX,[NXTADD] - MOV AH,SETDMA - PUSH DS - MOV DS,[TPA] - INT 33 - POP DS - MOV CX,[BYTCNT] - SUB CX,DX ;Compute available space - MOV DX,OFFSET TRANGROUP:DIRBUF - MOV AH,RDBLK ;Read in source file - INT 21H - JCXZ RET40 - CMP [ASCII],0 - JZ BINREAD - MOV DX,CX - MOV DI,[NXTADD] - MOV AL,1AH - PUSH ES - MOV ES,[TPA] - REPNE SCASB ;Scan for EOF - POP ES - JNZ USEALL - INC CX -USEALL: - SUB DX,CX - MOV CX,DX -BINREAD: - ADD CX,[NXTADD] - MOV [NXTADD],CX - CMP CX,[BYTCNT] ;Is buffer full? - JB RET40 ;If not, we must have found EOF - CALL FLSHFIL - JMP SHORT COPYLP - -CLOSEFIL: - MOV AX,[NXTADD] - MOV BX,AX - OR AL,AH ;See if any data is loaded - OR AL,[CFLAG] ; or file was created - JZ RET50 ;Don't close or count if not created - MOV AL,BYTE PTR[ARG2S] - CALL SETASC ;Check for /B or /A on destination - JZ BINCLOS - CMP BX,[BYTCNT] ;Is memory full? - JNZ PUTZ - CALL FLSHFIL ;Empty it to make room for 1 lousy byte - XOR BX,BX -PUTZ: - PUSH DS - MOV DS,[TPA] - MOV WORD PTR[BX],1AH ;Add End-of-file mark (Ctrl-Z) - POP DS - INC [NXTADD] -BINCLOS: - CALL FLSHFIL - CMP [INEXACT],0 ;Copy not exact? - JNZ NODATE ;If so, don't copy date & time - MOV SI,OFFSET TRANGROUP:DIRBUF+OFFDATE - MOV DI,OFFSET TRANGROUP:DEST+OFFDATE ;Make date & time same as original - MOVSW ;Copy date - MOVSW ;Copy time -NODATE: - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,CLOSE - INT 21H - INC [FILECNT] -RET50: RET - -FLSHFIL: -;Write out any data remaining in memory. -; Inputs: -; [NXTADD] = No. of bytes to write -; [CFLAG] <>0 if file has been created -; Outputs: -; [NXTADD] = 0 - - MOV AL,1 - XCHG [CFLAG],AL - OR AL,AL - JNZ EXISTS - CMP [NOWRITE],0 - JNZ SKPMAK ;Don't actually create if NOWRITE set - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,MAKE - INT 21H - MOV DX,OFFSET TRANGROUP:FULDIR - OR AL,AL - JNZ COPERR -SKPMAK: - XOR AX,AX - MOV WORD PTR[DEST+RR],AX - MOV WORD PTR[DEST+RR+2],AX - INC AX - MOV WORD PTR[DEST+RECLEN],AX -EXISTS: - XOR CX,CX - XCHG CX,[NXTADD] - CMP [NOWRITE],0 ;If NOWRITE set, just seek CX bytes - JNZ SEEKEND - XOR DX,DX - PUSH DS - MOV DS,[TPA] - MOV AH,SETDMA - INT 33 - POP DS - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,WRBLK - INT 21H - OR AL,AL - JZ RET60 - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,CLOSE - INT 21H - MOV AH,DELETE - INT 33 - MOV DX,OFFSET TRANGROUP:NOSPACE -COPERR: - MOV AH,9 - INT 21H - JMP ENDCOPY - -SEEKEND: - ADD WORD PTR[DEST+RR],CX - ADC WORD PTR[DEST+RR+2],0 ;Propagate carry -RET60: RET - -GETBATBYT: -;Get one byte from the batch file and return it in AL. End-of-file -;returns and ends batch mode. DS must be set to resident segment. -;AH, CX, DX destroyed. -ASSUME DS:RESGROUP - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,RDBLK - MOV CX,1 - INT 33 ;Get one more byte from batch file - JCXZ BATEOF - MOV AL,[BATBYT] - CMP AL,1AH - JNZ RET70 -BATEOF: - MOV AL,0DH ;If end-of-file, then end of line - MOV [BATCH],0 ;And turn off batch mode -RET70: RET -ASSUME DS:TRANGROUP - -SCANOFF: - LODSB - CALL DELIM - JZ SCANOFF - DEC SI ;Point to first non-delimiter - RET - -DELIM: - CMP AL," " - JZ RET80 - CMP AL,"=" - JZ RET80 - CMP AL,"," - JZ RET80 - CMP AL,9 ;Check for TAB character -RET80: RET - -PAUSE: - MOV DX,OFFSET TRANGROUP:PAUSMES - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR ;Get character with KB buffer flush - INT 33 -RET90: RET - -;Date and time are set during initialization and use -;this routines since they need to do a long return - -DATINIT: - PUSH ES - PUSH DS ;Going to use the previous stack - MOV AX,CS ;Set up the appropriate segment registers - MOV ES,AX - MOV DS,AX - MOV WORD PTR DS:[81H],13 ;Want to prompt for date during initialization - CALL DATE - CALL TIME - POP DS - POP ES -YYY PROC FAR - RET -YYY ENDP - -; DATE - Gets and sets the time - -DATE: - MOV SI,81H ;Accepting argument for date inline - CALL SCANOFF - CMP AL,13 - JZ PRMTDAT - MOV BX,2F00H+"-" ;"/-" - CALL INLINE - JMP COMDAT - -PRMTDAT: - MOV DX,OFFSET TRANGROUP:CURDAT - MOV AH,PRINTBUF - INT 33 ;Print "Current date is " - MOV AH,GETDATE - INT 33 ;Get date in CX:DX - CBW - MOV SI,AX - SHL SI,1 - ADD SI,AX ;SI=AX*3 - ADD SI,OFFSET TRANGROUP:WEEKTAB - MOV BX,CX - MOV CX,3 - CALL OUTCNT - MOV AL," " - CALL OUT - MOV AX,BX - MOV CX,DX - MOV DL,100 - DIV DL - XCHG AL,AH - XCHG AX,DX - MOV BL,"-" - CALL SHOW -GETDAT: - MOV DX,OFFSET TRANGROUP:NEWDAT - MOV BX,2F00H+"-" ;"/-" in BX - CALL GETBUF -COMDAT: JZ RET90 - JC DATERR - LODSB - CMP AL,BL - JZ SEPGD - CMP AL,BH - JNZ DATERR -SEPGD: CALL GETNUM - JC DATERR - MOV CX,1900 - CMP BYTE PTR[SI],13 - JZ BIAS - MOV AL,100 - MUL AH - MOV CX,AX - CALL GETNUM - JC DATERR -BIAS: - MOV AL,AH - MOV AH,0 - ADD CX,AX - LODSB - CMP AL,13 - JNZ DATERR - MOV AH,SETDATE - INT 33 - OR AL,AL - JNZ DATERR - JMP RET90 -DATERR: - MOV DX,OFFSET TRANGROUP:BADDAT - MOV AH,PRINTBUF - INT 33 - JMP GETDAT - -; TIME gets and sets the time - -TIME: - MOV SI,81H ;Accepting argument for time inline - CALL SCANOFF - CMP AL,13 - JZ PRMTTIM - MOV BX,3A00H+":" - CALL INLINE - JMP COMTIM - -PRMTTIM: - MOV DX,OFFSET TRANGROUP:CURTIM - MOV AH,PRINTBUF - INT 33 ;Print "Current time is " - MOV AH,GETTIME - INT 33 ;Get time in CX:DX - MOV BL,":" - CALL SHOW -GETTIM: - XOR CX,CX ;Initialize hours and minutes to zero - MOV DX,OFFSET TRANGROUP:NEWTIM - MOV BX,3A00H+":" - CALL GETBUF -COMTIM: JZ RET100 ;If no time present, don't change it - JC TIMERR - MOV CX,DX - XOR DX,DX - LODSB - CMP AL,13 - JZ SAVTIM - CMP AL,BL - JNZ TIMERR - MOV BL,"." - CALL GETNUM - JC TIMERR - MOV DH,AH ;Position seconds - LODSB - CMP AL,13 - JZ SAVTIM - CMP AL,BL - JNZ TIMERR - CALL GETNUM - JC TIMERR - MOV DL,AH - LODSB - CMP AL,13 - JNZ TIMERR -SAVTIM: - MOV AH,SETTIME - INT 33 - OR AL,AL - JZ RET100 ;Error in time? -TIMERR: - MOV DX,OFFSET TRANGROUP:BADTIM - MOV AH,PRINTBUF - INT 33 ;Print error message - JMP GETTIM ;Try again - -GETBUF: - MOV AH,PRINTBUF - INT 33 ;Print "Enter new date: " - MOV AH,INBUF - MOV DX,OFFSET TRANGROUP:COMBUF - INT 33 ;Get input line - CALL CRLF2 - MOV SI,OFFSET TRANGROUP:COMBUF+2 - CMP BYTE PTR[SI],13 ;Check if new date entered - JZ RET100 -INLINE: - CALL GETNUM ;Get one or two digit number - JC RET100 - MOV DH,AH ;Put in position - LODSB - CMP AL,BL - JZ NEXT - CMP BL,":" ;Is it a date seperator? - JNZ DATESEP - DEC SI - MOV DL,0 -RET100: RET ;Time may have only an hour specified -DATESEP: - CMP AL,BH - STC - JNZ RET100 -NEXT: CALL GETNUM - MOV DL,AH ;Put in position - RET - -GETNUM: - CALL INDIG - JC RET100 - MOV AH,AL ;Save first digit - CALL INDIG ;Another digit? - JC OKRET - AAD ;Convert unpacked BCD to decimal - MOV AH,AL -OKRET: - OR AL,1 -RET110: RET - -INDIG: - MOV AL,BYTE PTR[SI] - SUB AL,"0" - JC RET110 - CMP AL,10 - CMC - JC RET110 - INC SI - RET - -SHOW: - MOV AL,CH - MOV BH,"0"-" " ;Enable leading zero suppression - CALL OUT2 - MOV AL,BL - CALL OUT - MOV AL,CL - CALL OUT2 - MOV AL,BL - CALL OUT - MOV AL,DH - CALL OUT2 - CMP BL,":" ;Are we outputting time? - JNZ SKIPIT - MOV AL,"." - CALL OUT -SKIPIT: MOV AL,DL -OUT2: ;Output binary number as two ASCII digits - AAM ;Convert binary to unpacked BCD - XCHG AL,AH - OR AX,3030H ;Add "0" bias to both digits - CMP AL,"0" ;Is MSD zero? - JNZ NOSUP - SUB AL,BH ;Suppress leading zero if enabled -NOSUP: - MOV BH,0 ;Disable zero suppression - CALL OUT - MOV AL,AH -OUT: -;Print char in AL without affecting registers - XCHG AX,DX - PUSH AX - MOV AH,OUTCH - INT 33 - POP AX - XCHG AX,DX - RET - -EXELOAD: - MOV AX,CS - ADD AX,LOADSEG - MOV [EXEEND],AX ;Store in EXEEND - MOV DX,OFFSET TRANGROUP:RUNVAR ;Read header in here - MOV AH,SETDMA - INT 33 - MOV CX,RUNVARSIZ ;Amount of header info we need - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV AH,RDBLK - INT 33 ;Read in header - OR AL,AL - JNZ BADEXE ;Must not reach EOF - MOV AX,[HEADSIZ] ;Size of header in paragraphs -;Convert header size to 512-byte pages by multiplying by 32 & rounding up - ADD AX,31 ;Round up first - MOV CL,5 - SHR AX,CL ;Multiply by 32 - MOV [EXEFCB+RR],AX ;Position in file of program - MOV WORD PTR[EXEFCB+RECLEN],512 ;Set record size - ADD BX,10H ;First paragraph above parameter area - MOV DX,[PAGES] ;Total size of file in 512-byte pages - SUB DX,AX ;Size of program in pages - MOV [PSIZE],DX - SHL DX,CL ;Convert pages back to paragraphs - MOV AX,DX - ADD DX,BX ;Size + start = minimum memory (paragr.) - MOV CX,[EXEEND] ;Get memory size in paragraphs - CMP DX,CX ;Enough memory? - JA SHRTERR - MOV DX,[INITSP] - ADD DX,15 - SHR DX,1 - SHR DX,1 - SHR DX,1 - SHR DX,1 - ADD DX,[INITSS] - ADD DX,BX ;Adjusted value of SP - CMP DX,CX ;Is it valid? - JA SHRTERR - CMP [LOADLOW],-1 ;Load low or high? - JZ LOAD ;If low, load at segment BX - SUB CX,AX ;Memory size - program size = load addr. - MOV BX,CX -LOAD: - MOV BP,BX ;Save load segment -LOAD1: -LOADSEG EQU (LOAD1-ZERO)/16 - PUSH DS - MOV DS,BX - XOR DX,DX ;Address 0 in segment - MOV AH,SETDMA - INT 33 ;Set load address - POP DS - MOV CX,[PSIZE] ;Number of records to read - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV AH,RDBLK - INT 33 ;Read in up to 64K - SUB [PSIZE],CX ;Decrement count by amount read - JZ HAVEXE ;Did we get it all? - TEST AL,1 ;Check return code if not - JNZ BADEXE ;Must be zero if more to come - ADD BX,1000H-20H ;Bump data segment 64K minus one record - JMP SHORT LOAD1 ;Get next 64K block - -BADEXE: - MOV DX,OFFSET TRANGROUP:EXEBAD - JMP ERROR - -SHRTERR: - MOV DX,OFFSET TRANGROUP:TOOBIG - JMP ERROR - -HAVEXE: - MOV AX,[RELTAB] ;Get position of table - MOV [EXEFCB+RR],AX ;Set in random record field - MOV WORD PTR[EXEFCB+RECLEN],1 ;Set one-byte record - MOV DX,OFFSET TRANGROUP:RELPT ;4-byte buffer for relocation address - MOV AH,SETDMA - INT 33 - CMP [RELCNT],0 - JZ NOREL -RELOC: - MOV AH,RDBLK - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV CX,4 - INT 33 ;Read in one relocation pointer - OR AL,AL ;Check return code - JNZ BADEXE - MOV DI,[RELPT] ;Get offset of relocation pointer - MOV AX,[RELSEG] ;Get segment - ADD AX,BP ;Bias segment with actual load segment - MOV ES,AX - ADD WORD PTR ES:[DI],BP ;Relocate - DEC [RELCNT] ;Count off - JNZ RELOC -;Set up exit conditions -NOREL: - MOV AX,[INITSS] - ADD AX,BP - CLI - MOV SS,AX ;Initialize SS - MOV SP,[INITSP] - STI - ADD [INITCS],BP - MOV AX,[TPA] ;Get pointer to parameter area - MOV CX,[BYTCNT] ;Size of TPA segment - MOV ES,AX - MOV DS,AX ;Set segment registers to point to it - CALL SETUP - JMP DWORD PTR CS:[INITIP] ;Long jump to program - -SETUP: - AND CL,0F0H ;Adjust to even paragraph boundary - MOV AX,WORD PTR DS:[6] ;Get current memory size - SUB AX,CX ;Find out how much we're changing it - MOV WORD PTR DS:[6],CX - MOV CL,4 - SAR AX,CL ;Convert to a segment address - ADD WORD PTR DS:[8],AX ;Adjust long jump to go to same place - MOV DX,80H - MOV AH,SETDMA - INT 33 ;Set default disk transfer address - MOV AX,WORD PTR CS:[PARM1] ;Pass on info about FCBs - XOR CX,CX - MOV DX,CX ;Assume no batch file -ASSUME CS:RESGROUP - TEST CS:[BATCH],-1 ;Batch file in progress? -ASSUME CS:TRANGROUP - JZ RET120 ;If not, all set up - MOV CX,CS:[RESSEG] - MOV DX,OFFSET RESGROUP:BATFCB ;CX:DX points to batch FCB -RET120: RET -TRANCODESIZE EQU $-ZERO -TRANCODE ENDS -COMLEN EQU TRANDATASIZE+TRANCODESIZE-102H ;End of COMMAND load. ZERO Needed to make COMLEN absolute -TRNLEN EQU (PRETRLEN+TRANCODESIZE+TRANDATASIZE+15)/16 ;Length of transient in paragraphs - END PROGSTART - \ No newline at end of file diff --git a/v1.25/source/HEX2BIN.ASM b/v1.25/source/HEX2BIN.ASM deleted file mode 100644 index d7ba742..0000000 --- a/v1.25/source/HEX2BIN.ASM +++ /dev/null @@ -1,214 +0,0 @@ -; HEX2BIN version 1.02 -; Converts Intel hex format files to straight binary - -FCB: EQU 5CH -READ: EQU 20 -SETDMA: EQU 26 -OPEN: EQU 15 -CLOSE: EQU 16 -CREATE: EQU 22 -DELETE: EQU 19 -BLKWRT: EQU 40 -GETSEG: EQU 38 -BUFSIZ: EQU 1024 - - ORG 100H - PUT 100H - -HEX2BIN: - MOV DI,FCB+9 - CMP B,[DI]," " - JNZ HAVEXT - MOV SI,HEX - MOVB - MOVW -HAVEXT: -;Get load offset (default is -100H) - MOV CL,4 ;Needed for shifts - MOV [OFFSET],-100H - MOV SI,FCB+11H ;Scan second FCB for offset - LODB - CMP AL," " ;Check if offset present - JZ HAVOFF - MOV B,[SIGN],0 ;Assume positive sign for now - CMP AL,"+" - JZ GETOFF ;Get a positive offset - CMP AL,"-" - JNZ GETOFF1 ;If not + or -, then not signed - MOV B,[SIGN],1 ;Flag as negative offset -GETOFF: - LODB ;Eat sign -GETOFF1: - CALL HEXCHK ;Check for valid hex character - JC HAVOFF ;No offset if not valid - XOR BX,BX ;Intialize offset sum to 0 -CONVOFF: - SHL BX,CL ;Multiply current sum by 16 - OR BL,AL ;Add in current hex digit - LODB ;Get next digit - CALL HEXCHK ;And convert it to binary - JNC CONVOFF ;Loop until all hex digits read - TEST B,[SIGN],-1 ;Check if offset was to be negative - JZ SAVOFF - NEG BX -SAVOFF: - MOV [OFFSET],BX -HAVOFF: - MOV DX,STARTSEG - MOV AX,DS - ADD DX,AX ;Compute load segment - MOV AH,GETSEG - INT 33 - MOV ES,DX - SEG ES - MOV CX,[6] ;Get size of segment - MOV [SEGSIZ],CX - XOR AX,AX - MOV DI,AX - MOV BP,AX - SHR CX - REP - STOW ;Fill entire segment with zeros - MOV AH,OPEN - MOV DX,FCB - INT 21H - OR AL,AL - JNZ NOFIL - MOV B,[FCB+32],0 - MOV [FCB+14],BUFSIZ ;Set record size to buffer size - MOV DX,BUFFER - MOV AH,SETDMA - INT 33 - MOV AH,READ - MOV DX,FCB ;All set up for sequential reads - MOV SI,BUFFER+BUFSIZ ;Flag input buffer as empty -READHEX: - CALL GETCH - CMP AL,":" ;Search for : to start line - JNZ READHEX - CALL GETBYT ;Get byte count - MOV CL,AL - MOV CH,0 - JCXZ DONE - CALL GETBYT ;Get high byte of load address - MOV BH,AL - CALL GETBYT ;Get low byte of load address - MOV BL,AL - ADD BX,[OFFSET] ;Add in offset - MOV DI,BX - CALL GETBYT ;Throw away type byte -READLN: - CMP DI,[SEGSIZ] - JAE ADERR - CALL GETBYT ;Get data byte - STOB - CMP DI,BP ;Check if this is the largest address so far - JBE HAVBIG - MOV BP,DI ;Save new largest -HAVBIG: - LOOP READLN - JP READHEX - -NOFIL: - MOV DX,NOFILE -QUIT: - MOV AH,9 - INT 21H - INT 20H - -ADERR: - MOV DX,ADDR - JMP SHOWERR - -GETCH: - CMP SI,BUFFER+BUFSIZ - JNZ NOREAD - INT 21H - CMP AL,1 - JZ ERROR - MOV SI,BUFFER -NOREAD: - LODB - CMP AL,1AH - JZ DONE - RET - -GETBYT: - CALL HEXDIG - MOV BL,AL - CALL HEXDIG - SHL BL - SHL BL - SHL BL - SHL BL - OR AL,BL - RET - -HEXCHK: - SUB AL,"0" - JC RET - CMP AL,10 - JC CMCRET - SUB AL,"A"-"0"-10 - JC RET - CMP AL,16 -CMCRET: - CMC - RET - -HEXDIG: - CALL GETCH - CALL HEXCHK - JNC RET -ERROR: - MOV DX,ERRMES -SHOWERR: - MOV AH,9 - INT 21H -DONE: - MOV [FCB+9],4F00H+"C" ;"CO" - MOV B,[FCB+11],"M" - MOV DX,FCB - MOV AH,CREATE - INT 21H - OR AL,AL - JNZ NOROOM - XOR AX,AX - MOV [FCB+33],AX - MOV [FCB+35],AX ;Set RR field - INC AX - MOV [FCB+14],AX ;Set record size - XOR DX,DX - PUSH DS - PUSH ES - POP DS ;Get load segment - MOV AH,SETDMA - INT 21H - POP DS - MOV CX,BP - MOV AH,BLKWRT - MOV DX,FCB - INT 21H - MOV AH,CLOSE - INT 21H -EXIT: - INT 20H - -NOROOM: - MOV DX,DIRFUL - JMP QUIT - -HEX: DB "HEX" -ERRMES: DB "Error in HEX file--conversion aborted$" -NOFILE: DB "File not found$" -ADDR: DB "Address out of range--conversion aborted$" -DIRFUL: DB "Disk directory full$" - -OFFSET: DS 2 -SEGSIZ: DS 2 -SIGN: DS 1 -BUFFER: DS BUFSIZ - -START: -STARTSEG EQU (START+15)/16 - \ No newline at end of file diff --git a/v1.25/source/IO.ASM b/v1.25/source/IO.ASM deleted file mode 100644 index 3b9f181..0000000 --- a/v1.25/source/IO.ASM +++ /dev/null @@ -1,1934 +0,0 @@ -; I/O System for 86-DOS version 1.20 and later. Revised 8-02-82. -; -; Assumes a CPU Support card at F0 hex for character I/O, -; with disk drivers for SCP, Tarbell, or Cromemco controllers. -; -; Select whether console input is interrupt-driven or polled. -INTINP: EQU 1 -; -; Select whether the auxiliary port is the Support Card parallel port -; or on channel 1 of a Multiport Serial card addressed at 10H. -PARALLELAUX: EQU 1 -SERIALAUX: EQU 0 -; -; Select whether the printer is connected to the Support card parallel -; output port (standard) or channel 0 of a Multiport Serial card -; addressed at 10H. -PARALLELPRN: EQU 1 -SERIALPRN: EQU 0 -; -; If the Multiport Serial was chosen for either the auxiliary or the -; printer, select the baud rate here. Refer to Multiport Serial manual -; page 11 to pick the correct value for a given baud rate. -PRNBAUD:EQU 7 ; 1200 baud -AUXBAUD:EQU 0FH ; 19200 baud -; -; Select disk controller here. -SCP: EQU 1 -TARBELLSD: EQU 0 -TARBELLDD: EQU 0 -CROMEMCO4FDC: EQU 0 -CROMEMCO16FDC: EQU 0 -; -; Select if you want a special conversion version which can read/write -; both the new Microsoft format and the old SCP format. -; For a two drive system, drives A and B are the new Microsoft format, -; and drives C and D are the old SCP format (where C is the same physical -; drive as A, and D is the same drive as B). CONVERT has no effect -; on 5.25-inch drives. -CONVERT:EQU 1 -; -; Select disk configuration: -LARGE: EQU 1 ; Large drives. -COMBIN: EQU 0 ; Two 8-inch and one 5.25-inch. -SMALL: EQU 0 ; Three 5.25-inch drives. -CUSTOM: EQU 0 ; User defined. -; -; If 8-inch drives are PerSci, select FASTSEEK here: -; (Fastseek with Tarbell controllers doesn't work yet). -FASTSEEK: EQU 1 -; -; For double-density controllers, select double-sided operation of -; 8-inch disks in double-density mode. -LARGEDS: EQU 0 -; -; For double-density controllers, select double-sided operation of -; 5.25-inch disks in double-density mode. -SMALLDS: EQU 0 -; -; Use table below to select head step speed. Step times for 5" drives -; are double that shown in the table. Times for Fast Seek mode (using -; PerSci drives) is very small - 200-400 microseconds. -; -; Step value 1771 1793 -; -; 0 6ms 3ms -; 1 6ms 6ms -; 2 10ms 10ms -; 3 20ms 15ms -; -STPSPD: EQU 0 -; -; ****** End of selections ******************************************** -; -BIOSSEG:EQU 40H ; I/O system segment. -BIOSLEN:EQU 2048 ; Maximum length of I/O system. -DOSLEN: EQU 8192 ; Maximum length of MS-DOS. -QSIZE: EQU 80 ; Input queue size. -PBUFSIZ:EQU 128 ; Size of print buffer -BASE: EQU 0F0H ; CPU Support card base port number. -SIOBASE:EQU 10H ; Base port number of Multiport Serial card. -STAT: EQU BASE+7 ; Serial I/O status port. -DATA: EQU BASE+6 ; Serial I/O data port. -DAV: EQU 2 ; Data available bit. -TBMT: EQU 1 ; Transmitter buffer empty bit. -SERIAL: EQU SERIALPRN+SERIALAUX -STCDATA:EQU BASE+4 ; Ports for 9513 Timer chip. -STCCOM: EQU BASE+5 - - IF SERIALAUX -AUXSTAT:EQU SIOBASE+3 -AUXDATA:EQU SIOBASE+2 - ENDIF - - IF PARALLELAUX -AUXSTAT:EQU BASE+13 -AUXDATA:EQU BASE+12 - ENDIF - - IF SERIALPRN -PRNSTAT:EQU SIOBASE+1 -PRNDATA:EQU SIOBASE+0 - ENDIF - - IF PARALLELPRN -PRNSTAT:EQU BASE+13 -PRNDATA:EQU BASE+12 - ENDIF - - ORG 0 - PUT 100H - - JMP INIT - JMP STATUS - JMP INP - JMP OUTP - JMP PRINT - JMP AUXIN - JMP AUXOUT - JMP READ - JMP WRITE - JMP DSKCHG - JMP SETDATE - JMP SETTIME - JMP GETTIME - JMP FLUSH - JMP MAPDEV -MAPDEV: - RET L - -INIT: - XOR BP,BP ; Set up stack just below I/O system. - MOV SS,BP - MOV SP,BIOSSEG*16 - - IF INTINP-1 - MOV AL,0FFH ; Mask all interrupts. - OUTB BASE+3 - ENDIF - - IF INTINP - DI ; Set up keyboard interrupt vector. - MOV [BP+64H],KBINT - MOV [BP+66H],CS - EI - ENDIF - - MOV [BP+4*38H],PRNFCB - MOV [BP+4*38H+2],CS - PUSH CS - POP DS -; -; Initialize time-of-day clock. -; - MOV SI,STCTAB - MOV CX,4 ;Initialize 4 registers - UP -INITSTC: - LODB - OUT STCCOM ;Select register to initialize - LODB - OUT STCDATA - LODB - OUT STCDATA - LOOP INITSTC - - IF SERIAL - MOV CX,4 -SERINIT: - LODB - OUT SIOBASE+1 - OUT SIOBASE+3 - LOOP SERINIT - LODB ;Baud rate for channel 0 - OUT SIOBASE+8 - LODB ;Baud rate for channel 1 - OUT SIOBASE+9 - ENDIF -; -; Move MS-DOS down to the first segment just above the I/O system. -; - MOV SI,BIOSLEN ; Source points to where MS-DOS currently is. - MOV AX,DOSSEG ; Destination is beginning of DOSSEG. - MOV ES,AX - SUB DI,DI - MOV CX,DOSLEN/2 ; CX is number of words to move. - REP - MOVSW - - MOV SI,INITTAB - MOV DX,1 ; Do auto memory scan. - CALL 0,DOSSEG -; -; Change disk read and write vectors (INT 37 and INT 38) to go to -; DIRECTREAD and DIRECTWRITE rather than READ and WRITE. -; - SUB BP,BP - MOV W,[BP+37*4],DIRECTREAD - MOV W,[BP+38*4],DIRECTWRITE - - MOV DX,100H - MOV AH,26 ;Set DMA address - INT 33 - MOV CX,[6] ;Get size of segment - MOV BX,DS ;Save segment for later -; -; DS must be set to CS so we can point to the FCB. -; - MOV AX,CS - MOV DS,AX - MOV DX,FCB ;File Control Block for COMMAND.COM - MOV AH,15 - INT 33 ;Open COMMAND.COM - OR AL,AL - JNZ COMERR ;Error if file not found - XOR AX,AX - MOV [FCB+33],AX ; Set 4-byte Random Record field to - MOV [FCB+35],AX ; beginning of file. - INC AX - MOV [FCB+14],AX ;Set record length field - MOV AH,39 ;Block read (CX already set) - INT 33 - JCXZ COMERR ;Error if no records read - TEST AL,1 - JZ COMERR ;Error if not end-of-file -; -; Make all segment registers the same. -; - MOV DS,BX - MOV ES,BX - MOV SS,BX - MOV SP,5CH ;Set stack to standard value - XOR AX,AX - PUSH AX ;Put zero on top of stack for return - MOV DX,80H - MOV AH,26 - INT 33 ;Set default transfer address (DS:0080) - PUSH BX ;Put segment on stack - MOV AX,100H - PUSH AX ;Put address to execute within segment on stack - RET L ;Jump to COMMAND - -COMERR: - MOV DX,BADCOM - MOV AH,9 ;Print string - INT 33 - EI -STALL: JP STALL - -STCTAB: DB 17H ;Select master mode register - DW 84F3H ;Enable time-of-day - DB 1 ;Counter 1 mode register - DW 0138H - DB 2 - DW 0038H - DB 3 - DW 0008H ;Set counter 3 to count days - - IF SERIAL - DB 0B7H, 77H, 4EH, 37H, PRNBAUD, AUXBAUD - ENDIF - -BADCOM: DB 13,10,"Error in loading Command Interpreter",13,10,"$" -FCB: DB 1,"COMMAND COM" - DS 25 -; -; ************ Time and Date ************ -; -GETTIME: - MOV AL,0A7H ;Save counters 1,2,3 - OUT STCCOM - MOV AL,0E0H ;Enable data pointer sequencing - OUT STCCOM - MOV AL,19H ;Select hold 1 / hold cycle - OUT STCCOM - CALL STCTIME ;Get seconds & 1/100's - XCHG AX,DX - CALL STCTIME ;Get hours & minutes - XCHG AX,CX - IN STCDATA - MOV AH,AL - IN STCDATA - XCHG AL,AH ;Count of days - JP POINTSTAT - -STCTIME: - CALL STCBYTE - MOV CL,AH -STCBYTE: - IN STCDATA - MOV AH,AL - SHR AH - SHR AH - SHR AH - SHR AH - AND AL,0FH ;Unpack BCD digits - AAD ;Convert to binary - MOV AH,AL - MOV AL,CL - RET - -SETTIME: - PUSH CX - PUSH DX - CALL LOAD0 ;Put 0 into load registers to condition timer - MOV AL,43H ;Load counters 1 & 2 - OUT STCCOM - POP DX - POP CX - CALL LOAD - MOV AL,43H - OUT STCCOM ;Load counters 1&2 - CALL LOAD0 - MOV AL,27H ;Arm counters 1,2,3 - OUT STCCOM - JP POINTSTAT - -LOAD0: - XOR CX,CX - MOV DX,CX -LOAD: - MOV AL,09 ;Counter 1 load register - CALL OUTDX - MOV AL,0AH ;Counter 2 load register - MOV DX,CX -OUTDX: - OUT STCCOM ;Select a load register - MOV AL,DL - CALL OUTBCD - MOV AL,DH -OUTBCD: - AAM ;Convert binary to unpacked BCD - SHL AH - SHL AH - SHL AH - SHL AH - OR AL,AH ;Packed BCD - OUT STCDATA - RET - -SETDATE: - XCHG AX,DX ;Put date in DX - MOV AL,0BH ;Select Counter 3 load register - OUT STCCOM - XCHG AX,DX - OUT STCDATA - MOV AL,AH - OUT STCDATA - MOV AL,44H ;Load counter 3 - OUT STCCOM -POINTSTAT: - PUSH AX - MOV AL,1FH ;Point to status register - OUT STCCOM ; so power-off glitches won't hurt - POP AX - RET L -; -; ************ CONSOLE INPUT ************ -; - - IF INTINP-1 ; Non-interrupt driven input. -STATUS: - IN STAT - AND AL,DAV - JZ NOTHING ; Jump if nothing there. - PUSHF ; Save Z flag. - INB DATA - AND AL,7FH - SEG CS - MOV [QUEUE],AL ; Put new character in buffer. - POPF ; Return with Z flag clear. - RET L -NOTHING: - SEG CS - MOV AL,[QUEUE] ; See if there's anything in the buffer. - NOT AL ; Set up the Z flag. - TEST AL,80H - PUSHF - NOT AL - POPF - RET L - -INP: - MOV AL,-1 - SEG CS - XCHG AL,[QUEUE] ; Remove the character from the buffer. - AND AL,AL - JNS INRET ; Return if we have a character. -INLOOP: - IN STAT ; Wait till a character is available. - AND AL,DAV - JZ INLOOP - IN DATA - AND AL,7FH -INRET: -FLUSH: - RET L - -QUEUE: DB -1 ; For storing characters from STATUS to INP. - ENDIF - - IF INTINP ; Interrupt-driven input. -; -; Console keyboard interrupt handler. -; -KBINT: - PUSH AX - PUSH SI - MOV AL,20H ;End of Interrupt command - OUT BASE+2 ;Send to slave - IN DATA ;Get the character - AND AL,7FH - CMP AL,"C"-"@" - JZ FLSH - CMP AL,"S"-"@" - JZ FLSH - CMP AL,"F"-"@" - JNZ SAVKY -FLSH: - CALL 13*3,BIOSSEG ; Call I/O system keyboard buffer flush. -SAVKY: - SEG CS - MOV SI,[REAR] ;Pointer to rear of queue - CALL INCQ - SEG CS - CMP SI,[FRONT] ;Any room in queue? - JZ QFULL - SEG CS - MOV [SI],AL ;Put character in queue - SEG CS - MOV [REAR],SI ;Save pointer -LEAVINT: - POP SI - POP AX - IRET -QFULL: - MOV AL,7 ; BELL character. - CALL 3*3,BIOSSEG ; Call I/O system console output function. - JMPS LEAVINT - -STATUS: - PUSH SI -;See if printer ready - IN PRNSTAT - AND AL,TBMT - JZ NOPRN - SEG CS - MOV SI,[PFRONT] - SEG CS - CMP SI,[PREAR] ;Anything in print queue? - JNZ SENDPRN - SEG CS - CMP B,[PRNFCB],-1 ;Print spooling in progress? - JZ NOPRN ;If not, nothing to print -;Print spooling in progress. Get next buffer - PUSH DS - PUSH CS - POP DS - PUSH AX - PUSH CX - PUSH DX - PUSH [STKSAV] - PUSH [STKSAV+2] - PUSH [DMAADD] - PUSH [DMAADD+2] - MOV DX,PQUEUE - MOV AH,26 ;Set DMA address - INT 33 - MOV DX,PRNFCB - MOV CX,PBUFSIZ - MOV AH,39 ;Read buffer - INT 33 - OR AL,AL - JZ NOTEOF - MOV B,[PRNFCB],-1 ;Turn off print spooling at EOF -NOTEOF: - POP [DMAADD+2] - POP [DMAADD] - POP [STKSAV+2] - POP [STKSAV] - MOV SI,CX - POP DX - POP CX - POP AX - POP DS - OR SI,SI - JZ NOPRN - ADD SI,PQUEUE-1 - SEG CS - MOV [PREAR],SI - MOV SI,ENDPQ-1 -SENDPRN: - CALL INCPQ - SEG CS - MOV [PFRONT],SI - SEG CS - LODSB ;Get character to print - OUT PRNDATA -NOPRN: - DI ; Disable interrupts while checking queue. - SEG CS - MOV SI,[FRONT] - SEG CS - CMP SI,[REAR] ; Anything in queue? - JZ NOCHR ; Jump if nothing in queue. - CALL INCQ - SEG CS - LODSB ;Get character (if there is one) - OR SI,SI ;Reset zero flag -NOCHR: - EI - POP SI - RET L ;Zero clear if we have a character - -INP: - CALL STATUS,BIOSSEG ; Get I/O system console input status. - JZ INP - PUSH SI - DI ; Disable interrupts while changing queue pointers. - SEG CS - MOV SI,[FRONT] - CALL INCQ ; Permanently remove char from queue - SEG CS - MOV [FRONT],SI - EI - POP SI - RET L - -FLUSH: - DI - SEG CS - MOV [REAR],QUEUE - SEG CS - MOV [FRONT],QUEUE - EI - RET L - -INCQ: - INC SI - CMP SI,ENDQ ;Exceeded length of queue? - JB RET - MOV SI,QUEUE - RET - -INCPQ: - INC SI - CMP SI,ENDPQ ;Exceeded length of queue? - JB RET - MOV SI,PQUEUE - RET - -FRONT: DW QUEUE -REAR: DW QUEUE -QUEUE: DS QSIZE -ENDQ: EQU $ -PFRONT: DW PQUEUE -PREAR: DW PQUEUE -PQUEUE: DS PBUFSIZ -ENDPQ: EQU $ -PRNFCB: DB -1 - DS 36 - ENDIF - -; -; ************ Console and Printer Output ************ -; -OUTP: - PUSH AX -OUTLP: - IN STAT - AND AL,TBMT - JZ OUTLP - POP AX - OUT DATA - RET L - -PRINT: - PUSH SI - SEG CS - MOV SI,[PREAR] - CALL INCPQ -PRINLP: - SEG CS - CMP SI,[PFRONT] - JNZ PRNCHR -;Print queue is full - PUSH AX - CALL STATUS,BIOSSEG ;Poll and maybe print something - POP AX - JMPS PRINLP -PRNCHR: - SEG CS - MOV [PREAR],SI - SEG CS - MOV [SI],AL - POP SI - RET L -; -; ************ Auxiliary I/O ************ -; -AUXIN: - IN AUXSTAT - AND AL,DAV - JZ AUXIN - IN AUXDATA - RET L - -AUXOUT: - PUSH AX -AUXLP: - IN AUXSTAT - AND AL,TBMT - JZ AUXLP - POP AX - OUT AUXDATA - RET L -; -; ************ 1771/1793-type controller disk I/O ************ -; -TARBELL:EQU TARBELLSD+TARBELLDD -CROMEMCO:EQU CROMEMCO4FDC+CROMEMCO16FDC - -WD1791: EQU SCP+TARBELLDD+CROMEMCO16FDC -WD1771: EQU TARBELLSD+CROMEMCO4FDC - - IF WD1791 -READCOM:EQU 80H -WRITECOM:EQU 0A0H - ENDIF - - IF WD1771 -READCOM:EQU 88H -WRITECOM:EQU 0A8H - ENDIF - - IF SCP -SMALLBIT:EQU 10H -BACKBIT:EQU 04H -DDENBIT:EQU 08H -DONEBIT:EQU 01H -DISK: EQU 0E0H - ENDIF - - IF TARBELL -BACKBIT:EQU 40H -DDENBIT:EQU 08H -DONEBIT:EQU 80H -DISK: EQU 78H - ENDIF - - IF CROMEMCO -SMALLBIT:EQU 10H -BACKBIT:EQU 0FDH ; Send this to port 4 to select back. -DDENBIT:EQU 40H -DONEBIT:EQU 01H -DISK: EQU 30H - ENDIF - - IF SMALLDS-1 -SMALLDDSECT: EQU 8 - ENDIF - - IF SMALLDS -SMALLDDSECT: EQU 16 - ENDIF - - IF LARGEDS-1 -LARGEDDSECT: EQU 8 - ENDIF - - IF LARGEDS -LARGEDDSECT: EQU 16 - ENDIF -; -; Disk change function. -; On entry: -; AL = disk drive number. -; On exit: -; AH = -1 (FF hex) if disk is changed. -; AH = 0 if don't know. -; AH = 1 if not changed. -; -; CF clear if no disk error. -; AL = disk I/O driver number. -; -; CF set if disk error. -; AL = disk error code (see disk read below). -; - IF WD1771 -DSKCHG: - MOV AH,0 ; AH = 0 in case we don't know. - SEG CS - CMP AL,[CURDRV] - JNZ RETL - PUSH AX ; Save drive number. - - IF CROMEMCO - INB DISK+4 - ENDIF - - IF TARBELL - INB DISK - ENDIF - - AND AL,20H ; Look at head load bit - POP AX - JZ RETL - MOV AH,1 ; AH = 1, disk not changed. -RETL: - CLC ; No disk error. - RET L - ENDIF ; End of 1771 DSKCHG. - - IF WD1791 -DSKCHG: - MOV AH,0 ; AH = 0 in case we don't know. - SEG CS - CMP AL,[CURDRV] - JNZ DENSCHK ; Check density if not same drive. - PUSH AX - - IF SCP+CROMEMCO - INB DISK+4 - ENDIF - - IF TARBELL - INB DISK - ENDIF - - AND AL,20H ; Look at head load bit - POP AX - JZ DENSCHK ; Check density if head not loaded. - MOV AH,1 ; AH = 1, disk not changed. - MOV BX,PREVDENS - SEG CS - XLAT ; Get previous density - CLC ; No disk error. - RET L -DENSCHK: - CALL CHKNEW ; Unload head if selecting new drive. - CBW - XCHG AX,SI - ADD SI,PREVDENS - MOV CX,4 ; Try each density twice - MOV AH,0 ; Disk may not have been changed. -CHKDENS: - SEG CS - MOV AL,[SI] ; Get previous disk I/O driver number. - MOV BX,DRVTAB - SEG CS - XLAT ; Get drive select byte for previous density - - IF CROMEMCO16FDC - CALL MOTOR ; Wait for motor to come up to speed. - ENDIF - - OUT DISK+4 ; Select disk - MOV AL,0C4H ; READ ADDRESS command - CALL DCOM - AND AL,98H - IN DISK+3 ; Eat last byte to reset DRQ - JZ HAVDENS ; Jump if no error in reading address. - NOT AH ; AH = -1 (disk changed) if new density works. - SEG CS - XOR B,[SI],1 ; Try other density - LOOP CHKDENS - MOV AX,2 ; Couldn't read disk at all, AH = 0 for don't - STC ; know if disk changed, AL = error code 2 - - RET L ; disk not ready, carry set to indicate error. - -HAVDENS: - SEG CS - LODSB ; AL = disk I/O driver number. - CLC ; No disk error. - RET L - -PREVDENS:DB 1,3,5,7,9,11,13 ; Table of previous disk I/O driver numbers. - ENDIF ; End of 1793 DSKCHG function. - -CHKNEW: - MOV AH,AL ; Save disk drive number in AH. - SEG CS ; AL = previous disk drive number, - XCHG AL,[CURDRV] ; make new drive current. - CMP AL,AH ; Changing drives? - JZ RET -; -; If changing drives, unload head so the head load delay one-shot will -; fire again. Do it by seeking to the same track with the H bit reset. -; - IN DISK+1 ; Get current track number - OUT DISK+3 ; Make it the track to seek to - MOV AL,10H ; Seek and unload head - CALL DCOM - MOV AL,AH ; Restore current drive number - RET - - IF CROMEMCO16FDC -MOTOR: - PUSH AX - MOV AH,AL - IN DISK+4 ; See if the motor is on. - TEST AL,08H - MOV AL,AH - OUTB DISK+4 ; Select drive & start motor. - JNZ MOTORSON ; No delay if motors already on. - PUSH CX - MOV CX,43716 ; Loop count for 1 second. -MOTORDELAY: ; (8 MHz, 16-bit memory). - AAM ; 83 clocks. - AAM ; 83 clocks. - LOOP MOTORDELAY ; 17 clocks. - POP CX -MOTORSON: - POP AX - RET - ENDIF -; -; Disk read function. -; -; On entry: -; AL = Disk I/O driver number -; BX = Disk transfer address in DS -; CX = Number of sectors to transfer -; DX = Logical record number of transfer -; On exit: -; CF clear if transfer complete -; -; CF set if hard disk error. -; CX = number of sectors left to transfer. -; AL = disk error code -; 0 = write protect error -; 2 = not ready error -; 4 = "data" (CRC) error -; 6 = seek error -; 8 = sector not found -; 10 = write fault -; 12 = "disk" (none of the above) error -; -READ: - CALL SEEK ;Position head - JC ERROR - PUSH ES ; Make ES same as DS. - MOV BX,DS - MOV ES,BX -RDLP: - CALL READSECT ;Perform sector read - JC POPESERROR - INC DH ;Next sector number - LOOP RDLP ;Read each sector requested - CLC ; No errors. - POP ES ; Restore ES register. - RET L -; -; Disk write function. -; Registers same on entry and exit as read above. -; -WRITE: - CALL SEEK ;Position head - JC ERROR -WRTLP: - CALL WRITESECT ;Perform sector write - JC ERROR - INC DH ;Bump sector counter - LOOP WRTLP ;Write CX sectors - CLC ; No errors. -WRITERET: - RET L - -POPESERROR: - POP ES ; Restore ES register. -ERROR: - MOV BL,-1 - SEG CS - MOV [DI],BL ; Indicate we don't know where head is. - MOV SI,ERRTAB -GETCOD: - INC BL ; Increment to next error code. - SEG CS - LODB - TEST AH,AL ; See if error code matches disk status. - JZ GETCOD ; Try another if not. - MOV AL,BL ; Now we've got the code. - SHL AL ; Multiply by two. - STC - RET L - -ERRTAB: - DB 40H ;Write protect error - DB 80H ;Not ready error - DB 8 ;CRC error - DB 2 ;Seek error - DB 10H ;Sector not found - DB 20H ;Write fault - DB 7 ;"Disk" error -; -; Direct disk read and write from INT 37 and INT 38. Subroutine GETIODRIVER -; calls DSKCHG to convert disk drive number to I/O driver number. -; -; Setting CURDRV to -1 before calling DSKCHG forces DSKCHG to check the disk's -; density before returning the I/O driver number. This is necessary because -; programs such as FORMAT could change the density of a disk and leave the -; head loaded. If the head is loaded DSKCHG assumes the disk hasn't been -; changed and returns the old I/O driver number which could be wrong. -; -; CURDRV is set to -1 before returning so when DSKCHG is called by the -; operating system, it will tell the operating system the disk may have -; been changed (because it may have been). -; -DIRECTREAD: - - IF WD1791 - CALL GETIODRIVER ; Convert drive number to I/O driver number. - JC DIRECTRET ; Return if DSKCHG returned error. - ENDIF - - CALL 7*3,BIOSSEG ; Call READ. - JMPS DIRECTRET - -DIRECTWRITE: - - IF WD1791 - CALL GETIODRIVER ; Convert drive number to I/O driver number. - JC DIRECTRET ; Return if DSKCHG returned error. - ENDIF - - CALL 8*3,BIOSSEG ; Call WRITE. -DIRECTRET: - SEG CS - MOV B,[CURDRV],-1 ; Force DSKCHG to do density check. - RET L - - IF WD1791 -GETIODRIVER: - SEG CS - MOV B,[CURDRV],-1 ; Force DSKCHG to do density check. - PUSH BX - PUSH CX - CALL 9*3,BIOSSEG ; Call DSKCHG. - POP CX - POP BX - RET - ENDIF -; -; Function: -; Seeks to proper track. -; On entry: -; Same as for disk read or write above. -; On exit: -; AH = Drive select byte -; DL = Track number -; DH = Sector number -; SI = Disk transfer address in DS -; DI = pointer to drive's track counter in CS -; CX unchanged (number of sectors) -; -SEEK: - MOV SI,BX ; Save transfer address - CBW - MOV BX,AX ; Prepare to index on drive number - - IF WD1791 ; If two disk formats per drive. - SHR AL ; Convert to physical disk drive number. - ENDIF - - CALL CHKNEW ; Unload head if changing drives. - SEG CS - MOV AL,[BX+DRVTAB] ; Get drive-select byte. - - IF CROMEMCO16FDC - CALL MOTOR ; Wait for the motors to come up to speed. - ENDIF - - OUTB DISK+4 ; Select drive. - - IF CROMEMCO - OR AL,80H ; Set auto-wait bit. - ENDIF - - MOV AH,AL ; Save drive-select byte in AH. - XCHG AX,DX ; AX = logical sector number. - MOV DL,26 ; 26 sectors/track unless changed below - - IF SCP - TEST DH,SMALLBIT ; Check if small disk. - JZ BIGONE ; Jump if big disk. - MOV DL,18 ; Assume 18 sectors on small track. - TEST DH,DDENBIT ; Check if double-density. - JZ HAVSECT ; Jump if not. - MOV DL,SMALLDDSECT ; Number of sectors on small DD track. - JP HAVSECT -BIGONE: - TEST DH,DDENBIT ; Check if double-density. - JZ HAVSECT ; Jump if not. - MOV DL,LARGEDDSECT ; Number of sectors on big DD track. - ENDIF - - IF TARBELLDD ; Tarbell DD controller. - TEST DH,DDENBIT ; Check for double-density. - JZ HAVSECT - MOV DL,LARGEDDSECT ; Number of sectors on DD track. - ENDIF - - IF CROMEMCO4FDC - TEST DH,SMALLBIT ; Check if small disk. - JNZ HAVSECT ; Jump if not. - MOV DL,18 ; 18 sectors on small disk track. - ENDIF - - IF CROMEMCO16FDC - TEST DH,SMALLBIT ; Check if small disk. - JNZ BIGONE ; Jump if big disk. - MOV DL,18 ; Assume 18 sectors on small track. - TEST DH,DDENBIT ; Check if double-density. - JZ HAVSECT ; Jump if not. - MOV DL,SMALLDDSECT ; Number of sectors on small DD track. - JP HAVSECT -BIGONE: - TEST DH,DDENBIT ; Check if double-density. - JZ HAVSECT ; Jump if not. - MOV DL,LARGEDDSECT ; Number of sectors on big DD track. - ENDIF - -HAVSECT: - DIV AL,DL ; AL = track, AH = sector. - XCHG AX,DX ; AH has drive-select byte, DX = track & sector. - INC DH ; Sectors start at one, not zero. - SEG CS - MOV BL,[BX+TRKPT] ; Get this drive's displacement into track table. - ADD BX,TRKTAB ; BX now points to track counter for this drive. - MOV DI,BX - MOV AL,DL ; Move new track number into AL. - SEG CS - XCHG AL,[DI] ; Xchange current track with desired track - OUT DISK+1 ; Inform controller chip of current track - CMP AL,DL ; See if we're at the right track. - JZ RET - MOV BH,2 ; Seek retry count - CMP AL,-1 ; Head position known? - JNZ NOHOME ; If not, home head -TRYSK: - CALL HOME - JC SEEKERR -NOHOME: - MOV AL,DL ; AL = new track number. - OUT DISK+3 - MOV AL,1CH+STPSPD ; Seek command. - CALL MOVHEAD - AND AL,98H ; Accept not ready, seek, & CRC error bits. - JZ RET - JS SEEKERR ; No retries if not ready - DEC BH - JNZ TRYSK -SEEKERR: - MOV AH,AL ; Put status in AH. - TEST AL,80H ; See if it was a Not Ready error. - STC - JNZ RET ; Status is OK for Not Ready error. - MOV AH,2 ; Everything else is seek error. - RET - -SETUP: - MOV BL,DH ; Move sector number to BL to play with - - IF SCP+CROMEMCO16FDC - TEST AH,DDENBIT ; Check for double density. - JZ CHECKSMALL ; Not DD, check size for SD. - ENDIF - - IF TARBELLDD - TEST AH,DDENBIT ; Check for double density. - JZ CHECK26 ; Not DD. - ENDIF - - IF WD1791 - - IF (SCP+TARBELL)*LARGEDS+SCP*SMALLDS - MOV AL,AH ; Select front side of disk. - OUT DISK+4 - ENDIF - - IF CROMEMCO*(LARGEDS+SMALLDS) - MOV AL,0FFH ; Select front side of disk. - OUT 04H - ENDIF - - CMP BL,8 ; See if legal DD sector number. - JBE PUTSEC ; Jump if ok. - - IF (LARGEDS-1)*((SMALLDS*(SCP+CROMEMCO))-1) - JP STEP ; If only SS drives, we gotta step. - ENDIF - - IF SCP*LARGEDS*(SMALLDS-1) - TEST AH,SMALLBIT ; Check for 5.25 inch disk. - JNZ STEP ; Jump if small because SMALLDS is off. - ENDIF - - IF SCP*SMALLDS*(LARGEDS-1) - TEST AH,SMALLBIT ; Check for 8 inch disk. - JZ STEP ; Jump if large because LARGEDS is off. - ENDIF - - IF CROMEMCO16FDC*LARGEDS*(SMALLDS-1) - TEST AH,SMALLBIT ; Check for 5.25 inch disk. - JZ STEP ; Jump if small because SMALLDS is off. - ENDIF - - IF CROMEMCO16FDC*SMALLDS*(LARGEDS-1) - TEST AH,SMALLBIT ; Check for 8 inch disk. - JNZ STEP ; Jump if large because LARGEDS is off. - ENDIF - - IF LARGEDS+SMALLDS*(SCP+CROMEMCO) - SUB BL,8 ; Find true sector for back side. - CMP BL,8 ; See if ok now. - JA STEP ; Have to step if still too big. - - IF SCP+TARBELLDD - MOV AL,AH ; Move drive select byte into AL. - OR AL,BACKBIT ; Select back side. - OUT DISK+4 - ENDIF - - IF CROMEMCO16FDC - MOV AL,BACKBIT ; Select back side. - OUT 04H - ENDIF - - JP PUTSEC - ENDIF - - ENDIF - - IF SCP -CHECKSMALL: - TEST AH,SMALLBIT ; See if big disk. - JZ CHECK26 ; Jump if big. - ENDIF - - IF CROMEMCO -CHECKSMALL: - TEST AH,SMALLBIT ; See if big disk. - JNZ CHECK26 ; Jump if big. - ENDIF - - IF SCP+CROMEMCO - CMP BL,18 ; See if legal small SD/SS sector. - JA STEP ; Jump if not. - ENDIF - -CHECK26: - CMP BL,26 ; See if legal large SD/SS sector. - JBE PUTSEC ; Jump if ok. -STEP: - INC DL ; Increment track number. - MOV AL,58H ; Step in with update. - CALL DCOM - SEG CS - INC B,[DI] ; Increment the track pointer. - MOV DH,1 ; After step, do first sector. - MOV BL,DH ; Fix temporary sector number also. -PUTSEC: - MOV AL,BL ; Output sector number to controller. - OUT DISK+2 - DI ; Interrupts not allowed until I/O done - - IF SCP+CROMEMCO - INB DISK+4 ; Get head-load bit. - ENDIF - - IF TARBELL - INB DISK - ENDIF - - NOT AL - AND AL,20H ; Check head load status - JZ RET - MOV AL,4 - RET - -READSECT: - CALL SETUP - MOV BL,10 ; Retry count for hard error. - XCHG DI,SI ; Transfer address to DI. - PUSH DX ; Save track & sector number. - MOV DL,DISK+3 ; Disk controller data port. -RDAGN: - OR AL,READCOM - OUT DISK - - IF CROMEMCO - MOV AL,AH ; Turn on auto-wait. - OUT DISK+4 - ENDIF - - MOV BP,DI ; Save address for retry. - JMPS RLOOPENTRY -RLOOP: - STOB ; Write into memory. -RLOOPENTRY: - - IF SCP - IN DISK+5 ; Wait for DRQ or INTRQ. - ENDIF - - IF TARBELL+CROMEMCO - IN DISK+4 - ENDIF - - IF TARBELL - SHL AL - INB DX ; Read data from disk controller chip. - JC RLOOP - ENDIF - - IF SCP+CROMEMCO - SHR AL - INB DX ; Read data from disk controller chip. - JNC RLOOP - ENDIF - - EI ; Interrupts OK now - CALL GETSTAT - AND AL,9CH - JZ RDPOP - MOV DI,BP ; Get origainal address back for retry. - MOV BH,AL ; Save error status for report - MOV AL,0 - DEC BL - JNZ RDAGN - MOV AH,BH ; Put error status in AH. - STC -RDPOP: - POP DX ; Get back track & sector number. - XCHG SI,DI ; Address back to SI. - - IF TARBELL -FORCINT: - MOV AL,0D0H ; Tarbell controllers need this Force Interrupt - OUT DISK ; so that Type I status is always available - MOV AL,10 ; at the 1771/1793 status port so we can find -INTDLY: ; out if the head is loaded. SCP and Cromemco - DEC AL ; controllers have head-load status available - JNZ INTDLY ; at the DISK+4 status port. - ENDIF - - RET - -WRITESECT: - CALL SETUP - MOV BL,10 - PUSH DX ; Save track & sector number. - MOV DL,DISK+3 ; Disk controller data port. -WRTAGN: - OR AL,WRITECOM - OUT DISK - - IF CROMEMCO - MOV AL,AH ; Turn on auto-wait. - OUT DISK+4 - ENDIF - - MOV BP,SI -WRLOOP: - - IF SCP - INB DISK+5 - ENDIF - - IF TARBELL+CROMEMCO - INB DISK+4 - ENDIF - - IF SCP+CROMEMCO - SHR AL - LODB ; Get data from memory. - OUTB DX ; Write to disk. - JNC WRLOOP - ENDIF - - IF TARBELL - SHL AL - LODB ; Get data from memory. - OUTB DX ; Write to disk. - JC WRLOOP - ENDIF - - EI ; Interrupts OK now. - DEC SI - CALL GETSTAT - AND AL,0FCH - JZ WRPOP - MOV SI,BP - MOV BH,AL - MOV AL,0 - DEC BL - JNZ WRTAGN - MOV AH,BH ; Error status to AH. - STC -WRPOP: - POP DX ; Get back track & sector number. - - IF TARBELL - JMPS FORCINT - ENDIF - - IF SCP+CROMEMCO - RET - ENDIF -; -; Subroutine to restore the read/write head to track 0. -; - IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1) -HOME: - ENDIF - - IF FASTSEEK*CROMEMCO - TEST AH,SMALLBIT ; Check for large disk. - JNZ RESTORE ; Big disks are fast seek PerSci. - ENDIF - - MOV BL,3 -TRYHOM: - - IF SCP*FASTSEEK - MOV AL,AH ; Turn on Restore to PerSci. - OR AL,80H - OUTB DISK+4 - ENDIF - - MOV AL,0CH+STPSPD ; Restore with verify command. - CALL DCOM - AND AL,98H - - IF SCP*FASTSEEK - MOV AL,AH ; Restore off. - OUTB DISK+4 - ENDIF - - JZ RET - JS HOMERR ; No retries if not ready - MOV AL,58H+STPSPD ; Step in with update - CALL DCOM - DEC BL - JNZ TRYHOM -HOMERR: - STC - RET -; -; RESTORE for PerSci drives. -; Doesn't exist yet for Tarbell controllers. -; - IF FASTSEEK*TARBELL -HOME: -RESTORE: - RET - ENDIF - - IF FASTSEEK*CROMEMCO4FDC -RESTORE: - MOV AL,0C4H ;READ ADDRESS command to keep head loaded - OUT DISK - MOV AL,77H - OUT 4 -CHKRES: - IN 4 - AND AL,40H - JZ RESDONE - IN DISK+4 - TEST AL,DONEBIT - JZ CHKRES - IN DISK - JP RESTORE ;Reload head -RESDONE: - MOV AL,7FH - OUT 4 - CALL GETSTAT - MOV AL,0 - OUT DISK+1 ;Tell 1771 we're now on track 0 - RET - ENDIF - - IF FASTSEEK*CROMEMCO16FDC -RESTORE: - MOV AL,0D7H ; Turn on Drive-Select and Restore. - OUTB 4 - PUSH AX - AAM ; 10 uS delay. - POP AX -RESWAIT: - INB 4 ; Wait till Seek Complete is active. - TEST AL,40H - JNZ RESWAIT - MOV AL,0FFH ; Turn off Drive-Select and Restore. - OUTB 4 - SUB AL,AL ; Tell 1793 we're on track 0. - OUTB DISK+1 - RET - ENDIF -; -; Subroutine to move the read/write head to the desired track. -; Usually falls through to DCOM unless special handling for -; PerSci drives is required in which case go to FASTSK. -; - IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1) -MOVHEAD: - ENDIF - - IF CROMEMCO*FASTSEEK - TEST AH,SMALLBIT ; Check for PerSci. - JNZ FASTSK - ENDIF - -DCOM: - OUT DISK - PUSH AX - AAM ;Delay 10 microseconds - POP AX -GETSTAT: - IN DISK+4 - TEST AL,DONEBIT - - IF TARBELL - JNZ GETSTAT - ENDIF - - IF SCP+CROMEMCO - JZ GETSTAT - ENDIF - - IN DISK - RET -; -; Fast seek code for PerSci drives. -; Tarbell not installed yet. -; - IF FASTSEEK*TARBELL -MOVHEAD: -FASTSK: - RET - ENDIF - - IF FASTSEEK*CROMEMCO -FASTSK: - MOV AL,6FH - OUT 4 - MOV AL,18H - CALL DCOM -SKWAIT: - IN 4 - TEST AL,40H - JNZ SKWAIT - MOV AL,7FH - OUT 4 - MOV AL,0 - RET - ENDIF - -CURDRV: DB -1 -; -; Explanation of tables below. -; -; DRVTAB is a table of bytes which are sent to the disk controller as drive- -; select bytes to choose which physical drive is selected for each disk I/O -; driver. It also selects whether the disk is 5.25-inch or 8-inch, single- -; density or double-density. Always select side 0 in the drive-select byte if -; a side-select bit is available. There should be one entry in the DRVTAB -; table for each disk I/O driver. Exactly which bits in the drive-select byte -; do what depends on which disk controller is used. -; -; TRKTAB is a table of bytes used to store which track the read/write -; head of each drive is on. Each physical drive should have its own -; entry in TRKTAB. -; -; TRKPT is a table of bytes which indicates which TRKTAB entry each -; disk I/O driver should use. Since each physical drive may be used for -; more than one disk I/O driver, more than one entry in TRKPT may point -; to the same entry in TRKTAB. Drives such as PerSci 277s which use -; the same head positioner for more than one drive should share entrys -; in TRKTAB. -; -; INITTAB is the initialization table for 86-DOS as described in the -; 86-DOS Programer's Manual under "Customizing the I/O System." -; - IF SCP*COMBIN*FASTSEEK -; -; A PerSci 277 or 299 and one 5.25-inch drive. -; -DRVTAB: DB 00H,08H,01H,09H,10H,18H,00H,08H,01H,09H -TRKPT: DB 0,0,0,0,1,1,0,0,0,0 -TRKTAB: DB -1,-1 -INITTAB: - IF CONVERT-1 - DB 6 ; Number of disk I/O drivers. - ENDIF - - IF CONVERT - DB 10 - ENDIF - - DB 0 ; Disk I/O driver 0 uses disk drive 0. - DW LSDRIVE ; Disk I/O driver 0 is 8-inch single-density. - DB 0 ; Disk I/O driver 1 uses disk drive 0. - DW LDDRIVE ; Disk I/O driver 1 is 8-inch double-density. - DB 1 ; Etc. - DW LSDRIVE - DB 1 - DW LDDRIVE - DB 2 - DW SSDRIVE - DB 2 - DW SDDRIVE - - IF CONVERT - DB 3 - DW OLDLSDRIVE - DB 3 - DW OLDLDDRIVE - DB 4 - DW OLDLSDRIVE - DB 4 - DW OLDLDDRIVE - ENDIF - ENDIF - - IF SCP*LARGE*FASTSEEK -; -; PerSci 277 or 299. -; -DRVTAB: DB 00H,08H,01H,09H,00H,08H,01H,09H -TRKPT: DB 0,0,0,0,0,0,0,0 -TRKTAB: DB -1 -INITTAB: - IF CONVERT-1 - DB 4 - ENDIF - - IF CONVERT - DB 8 - ENDIF - - DB 0 - DW LSDRIVE - DB 0 - DW LDDRIVE - DB 1 - DW LSDRIVE - DB 1 - DW LDDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 2 - DW OLDLDDRIVE - DB 3 - DW OLDLSDRIVE - DB 3 - DW OLDLDDRIVE - ENDIF - ENDIF - - IF TARBELLDD -; -; Two 8-inch Shugart-type drives. -; -DRVTAB: DB 0,8,10H,18H,0,8,10H,18H -TRKPT: DB 0,0,1,1,0,0,1,1 -TRKTAB: DB -1,-1 -INITTAB: - - IF CONVERT-1 - DB 4 - ENDIF - - IF CONVERT - DB 8 - ENDIF - - DB 0 - DW LSDRIVE - DB 0 - DW LDDRIVE - DB 1 - DW LSDRIVE - DB 1 - DW LDDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 2 - DW OLDLDDRIVE - DB 3 - DW OLDLSDRIVE - DB 3 - DW OLDLDDRIVE - ENDIF - ENDIF - - IF TARBELLSD -; -; Four 8-inch Shugart-type drives. -; -DRVTAB: DB 0F2H,0E2H,0F2H,0E2H -TRKPT: DB 0,1,0,1 -TRKTAB: DB -1,-1 -INITTAB: - - IF CONVERT-1 - DB 2 - ENDIF - - IF CONVERT - DB 4 - ENDIF - - DB 0 - DW LSDRIVE - DB 1 - DW LSDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 3 - DW OLDLSDRIVE - ENDIF - ENDIF -; -; Cromemco drive select byte is derived as follows: -; Bit 7 = 0 -; Bit 6 = 1 if double density (if 16FDC) -; Bit 5 = 1 (motor on) -; Bit 4 = 0 for 5", 1 for 8" drives -; Bit 3 = 1 for drive 3 -; Bit 2 = 1 for drive 2 -; Bit 1 = 1 for drive 1 -; Bit 0 = 1 for drive 0 -; - IF CROMEMCO4FDC*LARGE -; -; PerSci 277 drive. -; -DRVTAB: DB 31H,32H,31H,32H -TRKPT: DB 0,0,0,0 -TRKTAB: DB -1 -INITTAB: - - IF CONVERT-1 - DB 2 - ENDIF - - IF CONVERT - DB 4 - ENDIF - - DB 0 - DW LSDRIVE - DB 1 - DW LSDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 3 - DW OLDLSDRIVE - ENDIF - ENDIF - - IF CROMEMCO4FDC*COMBIN -; -; A PerSci 277 and one 5.25-inch drive. -; -DRVTAB: DB 31H,32H,24H,31H,32H -TRKPT: DB 0,0,1,0,0 -TRKTAB: DB -1,-1 -INITTAB: - - IF CONVERT-1 - DB 3 - ENDIF - - IF CONVERT - DB 5 - ENDIF - - DB 0 - DW LSDRIVE - DB 1 - DW LSDRIVE - DB 2 - DW SSDRIVE - - IF CONVERT - DB 3 - DW OLDLSDRIVE - DB 4 - DW OLDLSDRIVE - ENDIF - ENDIF - - IF CROMEMCO4FDC*SMALL -; -; Three 5.25-inch drives. -; -DRVTAB: DB 21H,22H,24H -TRKPT: DB 0,1,2 -TRKTAB: DB -1,-1,-1 -INITTAB:DB 3 - DB 0 - DW SSDRIVE - DB 1 - DW SSDRIVE - DB 2 - DW SSDRIVE - ENDIF - - IF CUSTOM -; -; Cromemco 4FDC with two 8-inch Shugart-type drives. -; -DRVTAB: DB 31H,32H,31H,32H -TRKPT: DB 0,1,0,1 -TRKTAB: DB -1,-1 -INITTAB: - IF CONVERT-1 - DB 2 - ENDIF - - IF CONVERT - DB 4 - ENDIF - - DB 0 - DW LSDRIVE - DB 1 - DW LSDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 3 - DW OLDLSDRIVE - ENDIF - ENDIF - - IF CROMEMCO16FDC*SMALL -; -; Three 5.25-inch drives. -; -DRVTAB: DB 21H,61H,22H,62H,24H,64H -TRKPT: DB 0,0,1,1,2,2 -TRKTAB: DB -1,-1,-1 -INITTAB:DB 6 - DB 0 - DW SSDRIVE - DB 0 - DW SDDRIVE - DB 1 - DW SSDRIVE - DB 1 - DW SDDRIVE - DB 2 - DW SSDRIVE - DB 2 - DW SDDRIVE - ENDIF - - IF CROMEMCO16FDC*COMBIN -; -; A PerSci 277 or 299 and one 5.25-inch drive. -; -DRVTAB: DB 31H,71H,32H,72H,24H,64H,31H,71H,32H,72H -TRKPT: DB 0,0,0,0,1,1,0,0,0,0 -TRKTAB: DB -1,-1 -INITTAB: - IF CONVERT-1 - DB 6 - ENDIF - - IF CONVERT - DB 10 - ENDIF - - DB 0 - DW LSDRIVE - DB 0 - DW LDDRIVE - DB 1 - DW LSDRIVE - DB 1 - DW LDDRIVE - DB 2 - DW SSDRIVE - DB 2 - DW SDDRIVE - - IF CONVERT - DB 3 - DW OLDLSDRIVE - DB 3 - DW OLDLDDRIVE - DB 4 - DW OLDLSDRIVE - DB 4 - DW OLDLDDRIVE - ENDIF - ENDIF - - IF CROMEMCO16FDC*LARGE -; -; A PerSci 277 or 299. -; -DRVTAB: DB 31H,71H,32H,72H,31H,71H,32H,72H -TRKPT: DB 0,0,0,0,0,0,0,0 -TRKTAB: DB -1 -INITTAB: - IF CONVERT-1 - DB 4 - ENDIF - - IF CONVERT - DB 8 - ENDIF - - DB 0 - DW LSDRIVE - DB 0 - DW LDDRIVE - DB 1 - DW LSDRIVE - DB 1 - DW LDDRIVE - - IF CONVERT - DB 2 - DW OLDLSDRIVE - DB 2 - DW OLDLDDRIVE - DB 3 - DW OLDLSDRIVE - DB 3 - DW OLDLDDRIVE - ENDIF - ENDIF - - IF SMALL+COMBIN -SSDRIVE: - DW 128 ; Sector size in bytes. - DB 2 ; Sector per allocation unit. - DW 54 ; Reserved sectors. - DB 2 ; Number of allocation tables. - DW 64 ; Number of directory entrys. - DW 720 ; Number of sectors on the disk. - - IF SMALLDS-1 -SDDRIVE: ; This is the IBM Personal Computer - DW 512 ; disk format. - DB 1 - DW 1 - DB 2 - DW 64 - DW 320 - ENDIF - - IF SMALLDS -SDDRIVE: - DW 512 - DB 2 - DW 1 - DB 2 - DW 112 - DW 640 - ENDIF - ENDIF ; End of small drive DPTs. - - IF COMBIN+LARGE -LSDRIVE: - DW 128 ; Size of sector in bytes. - DB 4 ; Sectors per allocation unit. - DW 1 ; Number of reserved sectors. - DB 2 ; Number of File Allocation Tables. - DW 68 ; Number of directory entrys. - DW 77*26 ; Number of sectors on the disk. - - IF CONVERT -OLDLSDRIVE: - DW 128 - DB 4 - DW 52 ; Old format had two tracks reserved. - DB 2 - DW 64 ; 64 directory entrys. - DW 77*26 - ENDIF - - IF LARGEDS-1 -OLDLDDRIVE: -LDDRIVE: - DW 1024 - DB 1 - DW 1 - DB 2 - DW 96 - DW 77*8 - ENDIF - - IF LARGEDS -LDDRIVE: - DW 1024 - DB 1 - DW 1 - DB 2 - DW 192 ; 192 directory entrys in new 8-inch DD/DS format. - DW 77*8*2 - - IF CONVERT -OLDLDDRIVE: - DW 1024 - DB 1 - DW 1 - DB 2 - DW 128 ; 128 directory entrys in old 8-inch DD/DS format. - DW 77*8*2 - ENDIF - ENDIF - - ENDIF ; End of large drive DPTs. - -DOSSEG: EQU ($+15)/16+BIOSSEG ; Compute segment to use for 86-DOS. -DOSDIF: EQU 16*(DOSSEG-BIOSSEG) -STKSAV: EQU 1701H+DOSDIF -DMAADD: EQU 15B4H+DOSDIF - END - \ No newline at end of file diff --git a/v1.25/source/MSDOS.ASM b/v1.25/source/MSDOS.ASM deleted file mode 100644 index 8538b76..0000000 --- a/v1.25/source/MSDOS.ASM +++ /dev/null @@ -1,4031 +0,0 @@ -; 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/v1.25/source/STDDOS.ASM b/v1.25/source/STDDOS.ASM deleted file mode 100644 index 1216b4c..0000000 --- a/v1.25/source/STDDOS.ASM +++ /dev/null @@ -1,23 +0,0 @@ - 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/v1.25/source/TRANS.ASM b/v1.25/source/TRANS.ASM deleted file mode 100644 index 6b06619..0000000 --- a/v1.25/source/TRANS.ASM +++ /dev/null @@ -1,1213 +0,0 @@ -; Z80 to 8086 Translator version 2.21 -; Runs on the 8086 under 86-DOS -; by Tim Paterson -; - ORG 100H -EOF: EQU 1AH ;End of file -EOL: EQU 0DH -FCB: EQU 5CH -SYSTEM: EQU 5 -OPEN: EQU 15 -CLOSE: EQU 16 -SETDMA: EQU 26 -CREATE: EQU 22 -DELETE: EQU 19 -READ: EQU 20 -WRITE: EQU 21 -PRNBUF: EQU 9 - MOV SP,STACK - MOV DX,HEADER - MOV CL,9 - CALL SYSTEM - MOV BX,FCB+12 - XOR AL,AL - MOV CH,4 -CLRFCB: - MOV [BX],AL - INC BX - DEC CH - JNZ CLRFCB - MOV [FCB+32],AL - MOV BX,FCB - MOV DX,PUTFCB - MOV CX,16 - UP - MOV SI,BX - MOV DI,DX - REP - MOVB - MOV DX,DI - MOV BX,SI - MOV [PUTFCB+32],AL - MOV BX,"A"+5300H ;"AS" - MOV [PUTFCB+9],BX - MOV AL,'M' - MOV [PUTFCB+11],AL - MOV DX,FCB - MOV CL,OPEN - CALL SYSTEM - INC AL - MOV DX,NOFILE - JZ ABORTJ - MOV DX,PUTFCB - MOV CL,DELETE - CALL SYSTEM - MOV DX,PUTFCB - MOV CL,CREATE - CALL SYSTEM - INC AL - MOV DX,NOROOM -ABORTJ: - JZ ABORT - MOV DX,PUTFCB - MOV CL,OPEN - CALL SYSTEM - MOV BX,PUTBUF - MOV [PUTPT],BX - MOV BX,GETBUF+80H - MOV [GETPT],BX -TRANLN: - XOR AL,AL - MOV [OP1],AL - MOV [OP2],AL - MOV BX,OPCODE - CALL LOAD - MOV BX,OP1 - CALL GETOP - MOV B,[BX],0 - MOV BX,OP2 - CALL GETOP -DOLIN: - MOV B,[BX],0 - CALL FINDOP -ENLIN: - MOV SP,STACK - MOV AL,[CHAR] - CMP AL,';' - JNZ NOCOM - MOV AL,9 - CALL PUTCH - MOV AL,';' -NOCOM: - CALL PUTCH -PUTLIN: - CMP AL,EOF - JZ END - CALL GETCH - CALL PUTCH - CMP AL,10 - JNZ PUTLIN - JP TRANLN -END: - MOV CH,127 - MOV AL,1AH -FILL: - CALL PUTCH - DEC CH - JNZ FILL - MOV DX,PUTFCB - MOV CL,CLOSE - CALL SYSTEM - MOV DX,ENDMES -ABORT: - MOV CL,PRNBUF - CALL SYSTEM - JMP 0 -DELIM: - CALL GETCH -DELCHK: - CMP AL,EOL - JZ DOLIN - CMP AL,EOF - JZ DOLIN - CMP AL,';' - JZ DOLIN - CMP AL,' ' - JZ RET - CMP AL,':' - JZ RET - CMP AL,',' - JZ RET - CMP AL,9 - RET -HEX: - AND AL,0FH - ADD AL,90H - DAA - ADC AL,40H - DAA -PUTCH: - PUSH BX - PUSH DX - PUSH CX - LAHF - XCHG AH,AL - PUSH AX - XCHG AH,AL - AND AL,7FH - MOV BX,[PUTPT] - MOV [BX],AL - INC BX - MOV [PUTPT],BX - CMP BX,PUTBUF+80H - JNZ POPRET - MOV DX,PUTBUF - MOV [PUTPT],DX - MOV CL,SETDMA - CALL SYSTEM - MOV DX,PUTFCB - MOV CL,WRITE - CALL SYSTEM - OR AL,AL - MOV DX,WRTERR - JNZ ABORT -POPRET: - POP AX - XCHG AH,AL - SAHF -NOTAF: - POP CX - POP DX - POP BX - RET -; -; Get character from source file. -; -GETCH: - PUSH BX - PUSH DX - PUSH CX - MOV BX,[GETPT] ; Get buffer pointer. - CMP BX,GETBUF+80H ; Past end-of-buffer? - JNZ GETIT ; Jump if not. - MOV DX,GETBUF ; Set `DMA address'. - MOV CL,SETDMA - CALL SYSTEM - MOV DX,FCB ; Read the next record from source file. - MOV CL,READ - CALL SYSTEM - CMP AL,0 ; Entire record read OK? - JE OKRECORD - CMP AL,3 ; Partial record read? - JE OKRECORD - MOV AL,EOF ; Force end-of-file character in case - JP TESEND ; there is nothing in the record. -OKRECORD: - MOV BX,GETBUF ; Reset buffer pointer. -GETIT: - MOV AL,[BX] ; Get next character from buffer. - INC BX ; Point to next character. - MOV [GETPT],BX ; Save new pointer. -TESEND: - MOV [CHAR],AL - JP NOTAF ; Pop registers and return. -LOAD: - CALL DELIM - JZ LOADOP -EATLAB: - CALL PUTCH - CALL DELIM - JNZ EATLAB -ENLAB: - MOV AL,':' - CALL PUTCH -LOADOP: - MOV BX,OPCODE -EATEM: - CALL DELIM - JZ EATEM -LOADLP: - CALL IDCHK - JNC $+5 - JMP OPERR - MOV [BX],AL - INC BX - CALL DELIM - JNZ LOADLP - MOV B,[BX],0 - CMP AL,':' - JNZ RET - MOV BX,OPCODE - CALL TRANS - JP ENLAB -GETOP: - XOR AL,AL - LAHF - XCHG AX,BP - SAHF -GETLP: - CALL DELIM - JZ GETLP -OPCHAR: - CMP AL,'(' - JNZ NOTLEF - LAHF - XCHG AX,BP - SAHF - INC AL - LAHF - XCHG AX,BP - SAHF - MOV B,[BX],'[' - JP NEXCH -NOTLEF: - CMP AL,')' - JNZ NOTRIT - LAHF - XCHG AX,BP - SAHF - DEC AL - LAHF - XCHG AX,BP - SAHF - MOV B,[BX],']' - JP NEXCH -NOTRIT: - MOV [BX],AL - CMP AL,'''' - JZ EATQUO - CALL IDCHK - JNC GETID -NEXCH: - INC BX - CALL GETCH -IDRET: - CALL DELCHK - JNZ OPCHAR - CMP AL,' ' - JZ OPCHAR - RET -EATQUO: - INC BX - CALL GETCH - MOV [BX],AL - CMP AL,';' - JZ L0000 - CALL DELCHK -L0000: - CMP AL,'''' - JNZ EATQUO - JP NEXCH -IDCHK: - CMP AL,'0' - JC RET - CMP AL,'9'+1 - CMC - JNC RET - CMP AL,40H - JC RET - AND AL,5FH - CMP AL,'A' - JC RET - CMP AL,'Z'+1 - CMC - RET -GETID: - MOV [BX],AL - MOV CH,1 -LODID: - INC BX - CALL GETCH - CALL IDCHK - JC RWCHK - MOV [BX],AL - INC CH - JP LODID -RWCHK: - LAHF - XCHG AH,AL - PUSH AX - XCHG AH,AL - PUSH BX - DEC BX - DEC CH - MOV DL,CH - JZ LOOKRW - MOV DL,[BX] - DEC BX - DEC CH - JNZ NORW -LOOKRW: - MOV AL,[BX] - MOV DH,AL - PUSH BX - MOV BX,RWTAB - MOV CX,LENRW -RWLK: - UP - MOV DI,BX - REPNZ - SCAB - MOV BX,DI - JNZ NOTRW - PUSH BX - PUSH CX - MOV CX,LENRW-1 - LAHF - ADD BX,CX - RCR SI - SAHF - RCL SI - MOV AL,[BX] - POP CX - POP BX - CMP AL,DL - JZ HAVRW - MOV AL,CL - OR AL,AL - MOV AL,DH - JNZ RWLK -NOTRW: - POP BX -NORW: - POP BX -ENDRW: - POP AX - XCHG AH,AL - SAHF - JMP IDRET -HAVRW: - POP BX - INC CL - MOV [BX],CL - INC BX - POP DX - PUSH BX - MOV AL,CL - MOV BX,IXSI - CMP AL,RSI - JZ IXIY - MOV BX,IYDI - CMP AL,RDI - JNZ NORW -IXIY: - LAHF - XCHG AX,BP - SAHF - JZ NOTENC - LAHF - XCHG AX,BP - SAHF - CALL OUTSTR - JP NORW -NOTENC: - LAHF - XCHG AX,BP - SAHF - POP BX - DEC BX - MOV B,[BX],'[' - INC BX - ADD AL,RIX-1 - MOV [BX],AL - INC BX - MOV B,[BX],']' - INC BX - JP ENDRW - RET -FINDOP: - MOV BX,OPCODE - MOV CX,5 - XOR AL,AL - UP - MOV DI,BX - REPNZ - SCAB - MOV BX,DI - JNZ OPERR - MOV AL,4 - SUB AL,CL - JZ RET - DEC AL - JZ OPERR - MOV CL,AL - DEC BX - DEC BX - OR B,[BX],080H - MOV AL,[OPCODE] - SUB AL,'A' - JC OPERR - ADD AL,AL - MOV DL,AL - MOV DH,0 - MOV BX,OPTAB - LAHF - ADD BX,DX - RCR SI - SAHF - RCL SI - MOV DL,[BX] - INC BX - MOV DH,[BX] - XCHG DX,BX - MOV AL,9 - CALL PUTCH -LOOKOP: - MOV AL,[BX] - OR AL,AL - JZ OPERR - MOV DX,OPCODE+1 - MOV CH,CL -LOOKLP: - MOV SI,DX - LODB - CMP AL,[BX] - JNZ NEXOP - INC DX - INC BX - DEC CH - JNZ LOOKLP - MOV DX,[BX] - MOV BX,[BX+2] - JMP DX -NEXOP: - RCR SI - TEST B,[BX],080H - RCL SI - LAHF - INC BX - SAHF - JZ NEXOP - MOV DX,4 - LAHF - ADD BX,DX - RCR SI - SAHF - RCL SI - JP LOOKOP -OPERR: - MOV BX,OPCODE - CALL OUTSTR - CALL TWOOPS - MOV BX,OPCDER - CALL OUTSTR - JMP ENLIN -LD: - CALL OUTSTR - MOV BX,OP1 - MOV DX,OP2+1 - CALL LCHECK - JNZ $+5 - JMP LDAX - XCHG DX,BX - DEC BX - INC DX - CALL LCHECK - JNZ $+5 - JMP STAX -;If immediate move, check for byte memory reference - MOV AL,[OP2] - CMP AL,20H ;Could be immediate? - MOV AL,9 - JC L0001 - CALL BYTCHK ;Add "B," if memory reference -L0001: - CALL TRAN1 - JP TRNOP2 -TWOOPS: - CALL TRNOP1 -TRNOP2: - MOV AL,',' -TRAN2: - MOV BX,OP2 -PTRANS: - CALL PUTCH -TRANS: - MOV AL,[BX] - LAHF - INC BX - SAHF - OR AL,AL - JZ RET - CALL TRNTOK - JP TRANS -LCHECK: - MOV AL,[BX] - CMP AL,RAL - JNZ RET - MOV SI,DX - LODB - CMP AL,RCX - JZ RET - CMP AL,RDX - RET - -ONEOP: - CALL OUTSTR - MOV AL,9 - CALL BYTCHK ;If memory reference, add "B," flag - JMPS TRAN1 - -TRNOP1: - MOV AL,9 -TRAN1: - MOV BX,OP1 - JP PTRANS -IN: - MOV AL,[OP1] - CMP AL,RAL - XCHG DX,BX - MOV BX,OP2 - JZ GETPORT - MOV BX,SAVEAX - CALL OUTSTR - CALL OUTSTR - MOV BX,OP2 - CALL GETPORT - MOV BX,MOV0 - CALL ONEOP - MOV AL,',' - CALL PUTCH - MOV AL,RAL - CALL TRNTOK -IODONE: - MOV BX,RESTAX - JMP OUTSTR -OUT: - MOV AL,[OP2] - XCHG DX,BX - MOV BX,OP1 - CMP AL,RAL - JZ GETOUT - MOV BX,SAVEAX - CALL OUTSTR - MOV BX,MOVAL - CALL OUTSTR - CALL TRNOP2 - MOV BX,CRLFTB - CALL OUTSTR - MOV BX,OP1 - CALL GETOUT - JP IODONE -GETPORT: - MOV AL,[BX] - CMP AL,'[' - JNZ NOBRAK - LAHF - INC BX - SAHF - PUSH BX - MOV CX,80 - MOV AL,']' - UP - MOV DI,BX - REPNZ - SCAB - MOV BX,DI - LAHF - DEC BX - SAHF - MOV B,[BX],0 - POP BX -NOBRAK: - MOV AL,[BX] - CMP AL,RGCL - JNZ FIXPOR - MOV BX,IO1 - CALL OUTSTR - XCHG DX,BX - CALL OUTSTR - MOV AL,RDX - CALL TRNTOK - MOV BX,IO2 - JMP OUTSTR -GETOUT: - CALL GETPORT - JNC RET - MOV BX,BADIO - JMP OUTSTR -FIXPOR: - XCHG DX,BX - CALL OUTSTR - XCHG DX,BX - JMP TRANS -LDAX: - MOV BX,LDAX1 -LSAX: - CALL OUTSTR - MOV SI,DX - LODB - CALL TRNTOK - JP OUTSTR -STAX: - MOV BX,STAX1 - JP LSAX -TRNTOK: - CMP AL,' ' - JC $+5 - JMP PUTCH - PUSH BX - PUSH CX - MOV CL,AL - MOV CH,0 - MOV BX,TOKTAB-2 - LAHF - ADD BX,CX - RCR SI - SAHF - RCL SI - LAHF - ADD BX,CX - RCR SI - SAHF - RCL SI - MOV AL,[BX] - CALL PUTCH - INC BX - MOV AL,[BX] - POP CX - POP BX - OR AL,AL - JZ RET - JMP PUTCH -PUSH: - MOV DX,PUSHAF - JP AFCHK -POP: - MOV DX,POPAF -AFCHK: - MOV AL,[OP1] - CMP AL,RAX - JNZ ONEOPJ - XCHG DX,BX -OUTSTR: - MOV AL,[BX] - OR AL,AL - JNZ L0002 - CALL NEWOP -L0002: - CALL PUTCH - INC BX - ADD AL,AL - JNC OUTSTR - RET -NEWOP: - MOV AL,13 - CALL PUTCH - MOV AL,10 - CALL PUTCH - MOV AL,9 - RET -LDDR: - CALL OUTSTR - MOV BX,BLMOVE - JP OUTSTR -CPDR: - CALL OUTSTR - MOV BX,CMPREP - JP OUTSTR -ADD: - MOV AL,[OP1] - CMP AL,RBX - JZ DAD -ARITH: - CALL OUTSTR - MOV AL,[OP2] - OR AL,AL - JZ $+5 - JMP TWOOPS - MOV AL,9 - CALL PUTCH - MOV AL,RAL - CALL TRNTOK - MOV AL,',' - JMP TRAN1 -ACCUM: - CALL OUTSTR - MOV AL,9 - CALL PUTCH - MOV AL,RAL - JMP TRNTOK -ONEOPJ: JMP ONEOP -DAD: - MOV BX,DAD1 - CALL OUTSTR - CALL TWOOPS - MOV BX,DAD2 - JP OUTSTR - -INCDEC: - MOV AL,[OP1] - CMP AL,RCX+1 ;16-bit? - JNC ONEOPJ - MOV BX,LAHF - CALL OUTSTR - XCHG DX,BX - MOV BX,OPCODE-1 - CALL ONEOP - XCHG DX,BX -OUTSTRJ: - JMP OUTSTR -JUMP: - MOV AL,[OP1] - CMP AL,'[' - JNZ DIRECT - MOV AL,[OP1+1] - MOV [OP1],AL - XOR AL,AL - MOV [OP1+1],AL -DIRECT: - MOV AL,[OP2] - OR AL,AL - JZ ONEOPJ - CALL FIXCON - MOV BX,OP2 -OUTCON: - MOV CH,AL - MOV AL,'J' - CALL PUTCH - MOV AL,CH - CALL TRNTOK - MOV AL,9 - CALL PTRANS - MOV AL,CH - CMP AL,ODDPAR - MOV BX,WARNPA - JZ OUTSTRJ - CMP AL,EVEPAR - JZ OUTSTRJ - RET -FIXCON: - MOV AL,[OP1] - CMP AL,RGCL - JNZ RET - MOV AL,CY - RET -RETURN: - MOV AL,[OP1] - OR AL,AL - JZ OUTSTRJ - MOV BX,'R'+4500H ;"RE" - MOV [OP2],BX - MOV BX,'T' - MOV [OP2+2],BX - JP DIRECT -ONEOPJ1: - JMP ONEOP -DOCALL: - MOV AL,[OP2] - OR AL,AL - JZ ONEOPJ1 - CALL FIXCON - DEC AL - XOR AL,1 - INC AL - MOV BX,LABEL - CALL OUTCON - MOV BX,OPCODE-1 - CALL OUTSTR - MOV AL,[OP2] - OR AL,AL - MOV AL,9 - MOV BX,OP2 - JZ L0003 - CALL PTRANS -L0003: - MOV BX,CRLF - CALL OUTSTR - CALL TRANS - CALL OUTSTR - MOV BX,LABEL+4 -NEXLAB: - INC [BX] - MOV AL,[BX] - CMP AL,'9'+1 - JNZ RET - MOV B,[BX],'0' - LAHF - DEC BX - SAHF - JP NEXLAB -EX: - MOV AL,[OP1] - CMP AL,RAX - JZ OUTSTRJ1 - MOV AL,[OP1+1] - CMP AL,STP - JZ XTHL - MOV BX,XCHG - CALL OUTSTR - JMP TWOOPS -XTHL: - MOV BX,XTHL1 - CALL OUTSTR - CALL TRNOP2 - MOV BX,XTHL2 -OUTSTRJ1: - JMP OUTSTR -PSEUDO: - CALL ONEOP - MOV AL,[OP2] - OR AL,AL - JZ RET - JMP TRNOP2 - RET -BITSET: - MOV CL,0 - JP SETRES -RES: - MOV CL,-1 -SETRES: - CALL OUTSTR - PUSH BX - MOV AL,[OP2] - CMP AL,'[' - MOV AL,9 - JNZ L0004 - CALL BFLAG -L0004: - CALL TRAN2 - MOV AL,',' - CALL PUTCH - CALL GETBIT - MOV BX,BITERR - JNC L0005 - CALL OUTSTR -L0005: - POP BX - JMP OUTSTR - -BYTCHK: -;Check if memory reference and add "B," for byte mode - CMP B,[OP1],"[" ;Memory reference? - JNZ RET - CMP B,[OP1+1],RIX ;Referencing IX as a word? - JZ RET - CMP B,[OP1+1],RIY - JZ RET -BFLAG: - CALL PUTCH - MOV AL,'B' - CALL PUTCH - MOV AL,',' - RET - -GETBIT: - MOV AL,[OP1+1] - OR AL,AL - STC - JNZ RET - MOV AL,[OP1] - SUB AL,'0' - JC RET - CMP AL,8 - CMC - JC RET - MOV CH,AL - INC CH - XOR AL,AL - STC -SHFT: - RCL AL - DEC CH - JNZ SHFT - XOR AL,CL - MOV CH,AL - MOV AL,'0' - CALL PUTCH - MOV AL,CH - RCR AL - RCR AL - RCR AL - RCR AL - CALL HEX - MOV AL,CH - CALL HEX - MOV AL,'H' - JMP PUTCH -OPTAB: - DW AOPS,BOPS,COPS,DOPS,EOPS - DW FOPS,GOPS,HOPS,IOPS,JOPS - DW KOPS,LOPS,MOPS,NOPS,OOPS - DW POPS,QOPS,ROPS,SOPS,TOPS - DW UOPS,VOPS,WOPS,XOPS,YOPS - DW ZOPS -AOPS: - DM 'DD' - DW ADD,OPCODE - DM 'DC' - DW ARITH,OPCODE - DM 'ND' - DW ARITH,OPCODE - DB 0 -BOPS: - DM 'IT' - DW BITSET,TESBIT - DB 0 -COPS: - DM 'ALL' - DW DOCALL,OPCODE - DM 'P' - DW ARITH,CMP - DM 'PL' - DW ACCUM,NOT - DM 'PIR' - DW OUTSTR,CPIR - DM 'PDR' - DW CPDR,DOWN - DM 'CF' - DW OUTSTR,CMC - DB 0 -DOPS: - DM 'EC' - DW INCDEC,OPCODE - DM 'JNZ' - DW ONEOP,DJNZ - DM 'AA' - DW OUTSTR,OPCODE - DM 'I' - DW OUTSTR,OPCODE - DM 'W' - DW PSEUDO,OPCODE - DM 'B' - DW PSEUDO,OPCODE - DM 'M' - DW PSEUDO,OPCODE - DM 'S' - DW ONEOP,OPCODE - DB 0 -EOPS: - DM 'X' - DW EX,EXAF - DM 'I' - DW OUTSTR,OPCODE - DM 'XX' - DW OUTSTR,EXX - DM 'QU' - DW ONEOP,OPCODE - DM 'NDIF' - DW OUTSTR,OPCODE - DB 0 -FOPS: - DB 0 -GOPS: - DB 0 -HOPS: - DM 'ALT' - DW OUTSTR,HLT - DB 0 -IOPS: - DM 'NC' - DW INCDEC,OPCODE - DM 'N' - DW IN,INB - DM 'F' - DW ONEOP,OPCODE - DB 0 -JOPS: - DM 'R' - DW JUMP,JR - DM 'P' - DW JUMP,JMP - DB 0 -KOPS: - DB 0 -LOPS: - DM 'D' - DW LD,MOV - DM 'DIR' - DW OUTSTR,UP - DM 'DDR' - DW LDDR,DOWN - DB 0 -MOPS: - DB 0 -NOPS: - DM 'EG' - DW ACCUM,OPCODE - DB 0 -OOPS: - DM 'R' - DW ARITH,OPCODE - DM 'UT' - DW OUT,OUTB - DM 'RG' - DW ONEOP,OPCODE - DB 0 -POPS: - DM 'OP' - DW POP,OPCODE - DM 'USH' - DW PUSH,OPCODE - DB 0 -QOPS: - DB 0 -ROPS: - DM 'ET' - DW RETURN,OPCODE - DM 'LA' - DW ACCUM,RCL - DM 'RA' - DW ACCUM,RCR - DM 'LCA' - DW ACCUM,ROL - DM 'RCA' - DW ACCUM,ROR - DM 'L' - DW ONEOP,RCL - DM 'R' - DW ONEOP,RCR - DM 'LC' - DW ONEOP,ROL - DM 'RC' - DW ONEOP,ROR - DM 'ES' - DW RES,RESBIT - DM 'ETI' - DW OUTSTR,IRET - DM 'ETN' - DW OUTSTR,IRET - DM 'ST' - DW ONEOP,CALL - DB 0 -SOPS: - DM 'UB' - DW ARITH,OPCODE - DM 'BC' - DW ARITH,SBB - DM 'LA' - DW ONEOP,SAL - DM 'RA' - DW ONEOP,SAR - DM 'RL' - DW ONEOP,SHR - DM 'CF' - DW OUTSTR,STC - DM 'ET' - DW BITSET,SETBIT - DB 0 -TOPS: - DB 0 -UOPS: - DB 0 -VOPS: - DB 0 -WOPS: - DB 0 -XOPS: - DM 'OR' - DW ARITH,OPCODE - DB 0 -YOPS: - DB 0 -ZOPS: - DB 0 -LDAX1: DM 9,'SI,' - DM 0,'LODB' -STAX1: DM 9,'DI,' - DM 0,'STOB' -PUSHAF: DB 'LAHF',0,'XCHG',9,'AH,AL',0,'PUSH',9,'AX',0 - DM 'XCHG',9,'AH,AL' -POPAF: DM 'POP',9,'AX',0,'XCHG',9,'AH,AL',0,'SAHF' -DOWN: DM 'DOWN' -UP: DB 'UP' -BLMOVE: DB 0,'MOV',9,'SI,BX',0,'MOV',9,'DI,DX' - DB 0,'REP',0,'MOVB',0,'MOV',9,'DX,DI' - DM 0,'MOV',9,'BX,SI' -CPIR: DB 'UP' -CMPREP: DB 0,'MOV',9,'DI,BX',0,'REPNZ',0,'SCAB' - DM 0,'MOV',9,'BX,DI' -DAD1: DM 'LAHF',0,'ADD' -DAD2: DM 0,'RCR',9,'SI',0,'SAHF',0,'RCL',9,'SI' -LAHF: DM 'LAHF' - DM 0,'SAHF' -DJNZ: DB 'DEC',9,'CH',13,10 - DB '; *** WARNING: DJNZ does not affect flags - DEC does.',0 - DM 'JNZ' -WARNPA: DM 13,10,'; *** WARNING: Parity flag not always same as Z80.' -IO1: DB 'MOV',9,'DI,DX',0,'MOV',9,'DL,CL',0 - DM 'XOR',9,'DH,DH',13,10,9 -IO2: DM 0,'MOV',9,'DX,DI' -BADIO: DM 13,10,'; *** WARNING: Flags not same as Z80.' -BITERR: DM 13,10,' *** ERROR: Cannot determine bit number.' -SETBIT: DM 'LAHF',0,'OR' - DM 0,'SAHF' -RESBIT: DM 'LAHF',0,'AND' - DM 0,'SAHF' -TESBIT: DM 'RCR',9,'AH',0,'TEST' - DM 0,'RCL',9,'AH' -XTHL1: DM 'POP',9,'SI',0,'XCHG',9,'SI' -XTHL2: DM 0,'PUSH',9,'SI' -EXX: DB 'XCHG',9,'BX,[HL]',0,'XCHG',9,'DX,[DE]',0 - DM 'XCHG',9,'CX,[BC]' -EXAF: DM 'LAHF',0,'XCHG',9,'AX,BP',0,'SAHF' -MOVAL: DM 0,'MOV',9,'AL' -IXSI: DM 9,'MOV',9,'SI,[IX]',13,10 -IYDI: DM 9,'MOV',9,'DI,[IY]',13,10 -RESTAX: DB 0 -SAVEAX: DM 'XCHG',9,'AX,SI' -CRLFTB: DM 13,10,9 -INB: DM 'INB',9 -OUTB: DM 'OUTB',9 -XCHG: DM 'XCHG' -JMP: DM 'JMP' -JR: DM 'JMPS' -RCL: DM 'RCL' -RCR: DM 'RCR' -ROL: DM 'ROL' -ROR: DM 'ROR' -SAL: DM 'SAL' -SAR: DM 'SAR' -SHR: DM 'SHR' -STC: DM 'STC' -IRET: DM 'IRET' -HLT: DM 'HLT' -CMC: DM 'CMC' -NOT: DM 'NOT' -MOV0: DB 0 -MOV: DM 'MOV' -CMP: DM 'CMP' -SBB: DM 'SBB' -CALL: DM 'CALL' -TOKTAB: - DB 'SIDI' - DB 'PEPOS',0,'NSNZZ',0,'NCC',0 - DB 'AXSPBXDXCX' - DB 'BLBHDLDHCLCHALIXIY' -RWTAB: - DB 'ABCDEHLBDHSACNZNPMPPII' -LENRW: EQU $-RWTAB - DB 0,0,0,0,0,0,0,'CELPF',0,'C',0,'Z',0,0,'OEYX' -HEADER: DB 13,10,'Z80 to 8086 Translator version 2.21',13,10,'$' -NOROOM: DB 13,10,'File creation error',13,10,'$' -NOFILE: DB 13,10,'File not found',13,10,'$' -ENDMES: DB 13,10,'Translation complete',13,10,'$' -WRTERR: DB 13,10,'Out of disk space',13,10,'$' -OPCDER: DM 13,10,'*** Opcode Error ' -CRLF: DM 13,10 -LABEL: DB 'L0000',0 - DM ':',9 -PUTPT: DS 2 -GETPT: DS 2 -CHAR: DS 1 - DB 0 -OPCODE: DS 80 -OP1: DS 80 -OP2: DS 80 -PUTBUF: DS 128 -GETBUF: DS 128 -PUTFCB: DS 33 - DS 50 -STACK: EQU $ - ORG 1 ;This is really just for equates without EQU -RSI: DS 1 -RDI: DS 1 -ODDPAR: DS 1 -EVEPAR: DS 1 - DS 5 ;MINUS,PLUS,NOT ZERO,ZERO,NOT CARRY -CY: DS 1 -RAX: DS 1 -STP: DS 1 -RBX: DS 1 -RDX: DS 1 -RCX: DS 1 -RBL: DS 1 -RBH: DS 1 -RDL: DS 1 -RDH: DS 1 -RGCL: DS 1 -RCH: DS 1 -RAL: DS 1 -RIX: DS 1 -RIY: DS 1 - \ No newline at end of file diff --git a/v2.0/bin/ANSI.DOC b/v2.0/bin/ANSI.DOC deleted file mode 100644 index 040d9d2..0000000 Binary files a/v2.0/bin/ANSI.DOC and /dev/null differ diff --git a/v2.0/bin/CHKDSK.COM b/v2.0/bin/CHKDSK.COM deleted file mode 100644 index 152bc38..0000000 Binary files a/v2.0/bin/CHKDSK.COM and /dev/null differ diff --git a/v2.0/bin/COMMAND.COM b/v2.0/bin/COMMAND.COM deleted file mode 100644 index 820f393..0000000 Binary files a/v2.0/bin/COMMAND.COM and /dev/null differ diff --git a/v2.0/bin/CONFIG.DOC b/v2.0/bin/CONFIG.DOC deleted file mode 100644 index bfb1985..0000000 Binary files a/v2.0/bin/CONFIG.DOC and /dev/null differ diff --git a/v2.0/bin/CREF.EXE b/v2.0/bin/CREF.EXE deleted file mode 100644 index a88c2fa..0000000 Binary files a/v2.0/bin/CREF.EXE and /dev/null differ diff --git a/v2.0/bin/DEBUG.COM b/v2.0/bin/DEBUG.COM deleted file mode 100644 index 41d127b..0000000 Binary files a/v2.0/bin/DEBUG.COM and /dev/null differ diff --git a/v2.0/bin/DEVDRIV.DOC b/v2.0/bin/DEVDRIV.DOC deleted file mode 100644 index 3c82793..0000000 --- a/v2.0/bin/DEVDRIV.DOC +++ /dev/null @@ -1,802 +0,0 @@ - MS-DOS 2.0 Device Drivers - -INTRODUCTION - - In the past, DOS-device driver (BIOS for those who are -familiar with CP/M) communication has been mediated with -registers and a fixed-address jump-table. This approach -has suffered heavily from the following two observations: - - o The old jump-table ideas of the past are fixed in - scope and allow no extensibility. - - o The past device driver interfaces have been written - without regard for the true power of the hardware. - When a multitasking system or interrupt driven - hardware is installed a new BIOS must be written - largely from scratch. - - In MSDOS 2.0, the DOS-device driver interface has changed -from the old jump-table style to one in which the device -drivers are linked together in a list. This allows new -drivers for optional hardware to be installed (and even -written) in the field by other vendors or the user himself. -This flexibility is one of the major new features of MS-DOS -2.0. - - Each driver in the chain defines two entry points; the -strategy routine and the interrupt routine. The 2.0 DOS -does not really make use of two entry points (it simply calls -strategy, then immediately calls interrupt). This dual entry -point scheme is designed to facilitate future multi-tasking -versions of MS-DOS. In multi-tasking environments I/O must -be asynchronous, to accomplish this the strategy routine -will be called to queue (internally) a request and return -quickly. It is then the responsibility of the interrupt -routine to perform the actual I/O at interrupt time by picking -requests off the internal queue (set up by the strategy -routine), and process them. When a request is complete, -it is flagged as "done" by the interrupt routine. The DOS -periodically scans the list of requests looking for ones -flagged as done, and "wakes up" the process waiting for the -completion of the request. - - In order for requests to be queued as above it is no -longer sufficient to pass I/O information in registers, since -many requests may be pending at any one time. Therefore -the new device interface uses data "packets" to pass request -information. A device is called with a pointer to a packet, -this packet is linked into a global chain of all pending -I/O requests maintained by the DOS. The device then links -the packet into its own local chain of requests for this -particular device. The device interrupt routine picks -requests of the local chain for processing. The DOS scans -the global chain looking for completed requests. These -packets are composed of two pieces, a static piece which -has the same format for all requests (called the static -request header), which is followed by information specific -to the request. Thus packets have a variable size and format. - - At this points it should be emphasized that MS-DOS 2.0 -does not implement most of these features, as future versions -will. There is no global or local queue. Only one request -is pending at any one time, and the DOS waits for this current -request to be completed. For 2.0 it is sufficient for the -strategy routine to simply store the address of the packet -at a fixed location, and for the interrupt routine to then -process this packet by doing the request and returning. -Remember: the DOS just calls the strategy routine and then -immediately calls the interrupt routine, it is assumed that -the request is completed when the interrupt routine returns. -This additional functionality is defined at this time so -that people will be aware and thinking about the future. - - -FORMAT OF A DEVICE DRIVER - - A device driver is simply a relocatable memory image -with all of the code in it to implement the device (like -a .COM file, but not ORGed at 100 Hex). In addition it has -a special header at the front of it which identifies it as -a device, defines the strategy and interrupt entry points, -and defines various attributes. It should also be noted -that there are two basic types of devices. - - The first is character devices. These are devices which -are designed to do character I/O in a serial manner like -CON, AUX, and PRN. These devices are named (ie. CON, AUX, -CLOCK, etc.), and users may open channels (FCBs) to do I/O -to them. - - The second class of devices is block devices. These -devices are the "disk drives" on the system, they can do -random I/O in pieces called blocks (usually the physical -sector size) and hence the name. These devices are not -"named" as the character devices are, and therefore cannot -be "opened" directly. Instead they are "mapped" via the -drive letters (A,B,C, etc.). - - Block devices also have units. In other words a single -driver may be responsible for one or more disk drives. For -instance block device driver ALPHA (please note that we cannot -actually refer to block devices by a name!) may be -responsible for drives A,B,C and D, this simply means that -it has four units (0-3) defined and therefore takes up four -drive letters. Which units correspond to which drive letters -is determined by the position of the driver in the chain -of all drivers: if driver ALPHA is the first block driver -in the device chain, and it defines 4 units (0-3), then they -will be A,B,C and D. If BETA is the second block driver -and defines three units (0-2), then they will be E,F and -G and so on. MS-DOS 2.0 is not limited to 16 block device -units, as previous versions were. The theoretical limit -is 63 (2^6 - 1), but it should be noted that after 26 the -drive letters get a little strange (like ] \ and ^). NOTE: -Character devices cannot define multiple units (this because -they have only one name). - - -Here is what that special device header looks like: - - +--------------------------------------+ - | DWORD Pointer to next device | - | (Must be set to -1) | - +--------------------------------------+ - | WORD Attributes | - | Bit 15 = 1 if char device 0 if blk | - | if bit 15 is 1 | - | Bit 0 = 1 if Current sti device | - | Bit 1 = 1 if Current sto output | - | Bit 2 = 1 if Current NUL device | - | Bit 3 = 1 if Current CLOCK dev | - | Bit 4 = 1 if SPECIAL | - | Bit 14 is the IOCTL bit (see below) | - | Bit 13 is the NON IBM FORMAT bit | - +--------------------------------------+ - | WORD Pointer to Device strategy | - | entry point | - +--------------------------------------+ - | WORD Pointer to Device interrupt | - | entry point | - +--------------------------------------+ - | 8-BYTE character device name field | - | Character devices set a device name | - | For block devices the first byte is | - | The number of units | - +--------------------------------------+ - - Note that the device entry points are words. They must -be offsets from the same segment number used to point to -this table. Ie. if XXX.YYY points to the start of this -table, then XXX.strategy and XXX.interrupt are the entry -points. - - A word about the Attribute field. This field is used -most importantly to tell the system whether this device is -a block or character device (bit 15). Most of other bits -are used to give selected character devices certain special -treatment (NOTE: these bits mean nothing on a block device). -Let's say a user has a new device driver which he wants to -be the standard input and output. Besides just installing -the driver he needs to tell SYSINIT (and the DOS) that he -wishes his new driver to override the current sti and sto -(the "CON" device). This is accomplished by setting the -attributes to the desired characteristics, so he would set -Bits 0 and 1 to 1 (note that they are separate!!). Similarly -a new CLOCK device could be installed by setting that -attribute, see the section at the end on the CLOCK device. -NOTE: that although there is a NUL device attribute, the -NUL device cannot be re-assigned. This attribute exists -for the DOS so that it can tell if the NUL device is being -used. - - The NON IBM FORMAT bit applies only to block devices -and effects the operation of the get BPB device call (see -below). - - The other bit of interest is the IOCTL bit which has -meaning on character or block devices. This bit tells the -DOS whether this device can handle control strings (via the -IOCTL system call). - - If a driver cannot process control strings, it should -initially set this bit to 0. This tells the DOS to return -an error if an attempt is made (via IOCTL system call) to -send or receive control strings to this device. A device -which can process control strings should initialize it to -1. For drivers of this type, the DOS will make calls to -the IOCTL INPUT and OUTPUT device functions to send and -receive IOCTL strings (see IOCTL in the SYSTEM-CALLS -document). - - The IOCTL functions allow data to be sent and received -by the device itself for its own use (to set baud rate, stop -bits, form length etc., etc.), instead of passing data over -the device channel as a normal read or write does. The -interpretation of the passed information is up to the device, -but it MUST NOT simply be treated as a normal I/O. - - The SPECIAL bit applies only to character drivers and -more particularly to CON drivers. The new 2.0 interface -is a much more general and consistent interface than the -old 1.25 DOS interface. It allows for a number of additional -features of 2.0. It is also slower than 1.25 if old style -"single byte" system calls are made. To make most efficient -use of the interface all applications should block their -I/O as much as possible. This means make one XENIX style -system call to output X bytes rather than X system calls -to output one byte each. Also putting a device channel in -RAW mode (see IOCTL) provides a means of putting out -characters even FASTER than 1.25. To help alleviate the -CON output speed problem for older programs which use the -1 - 12 system calls to output large amounts of data the -SPECIAL bit has been implemented. If this bit is 1 it means -the device is the CON output device, and has implemented -an interrupt 29 Hex handler, where the 29 Hex handler is -defined as follows: - - Interrupt 29h handlers - - Input: - Character in AL - - Function: - output the character in al to the user - screen. - Output: - None - Registers: - all registers except bx must be preserved. - No registers except for al have a known or - consistent value. - - If a character device implements the SPECIAL bit, it -is the responsibility of the driver to install an address -at the correct location in the interrupt table for interrupt -29 Hex as part of its INIT code. IMPLICATION: There can -be only one device driver with the SPECIAL bit set in the -system. There is no check to insure this state. - -WARNING: THIS FEATURE WILL NOT BE SUPPORTED IN FUTURE VERSIONS - OF THE OPERATING SYSTEM. IMPLICATION: Any application - (not device driver) which uses INT 29H directly will - not work on future versions, YOU HAVE BEEN WARNED. - - In order to "make" a device driver that SYSINIT can -install, a memory image or .EXE (non-IBM only) format file -must be created with the above header at the start. The -link field should be initialized to -1 (SYSINIT fills it -in). The attribute field and entry points must be set -correctly, and if the device is a character device, the name -field must be filled in with the name (if a block device -SYSINIT will fill in the correct unit count). This name -can be any 8 character "legal" file name. In fact SYSINIT -always installs character devices at the start of the device -list, so if you want to install a new CON device all you -have to do is name it "CON". The new one is ahead of the -old one in the list and thus preempts the old one as the -search for devices stops on the first match. Be sure to -set the sti and sto bits on a new CON device! - -NOTE: Since SYSINIT may install the driver anywhere, you - must be very careful about FAR memory references. You - should NOT expect that your driver will go in the same - place every time (The default BIOS drivers are exempted - from this of course). - - -INSTALLATION OF DEVICE DRIVERS - - Unlike past versions MS-DOS 2.0 allows new device drivers -to be installed dynamically at boot time. This is -accomplished by the new SYSINIT module supplied by Microsoft, -which reads and processes the CONFIG.SYS file. This module -is linked together with the OEM default BIOS in a similar -manner to the way FORMAT is built. - - One of the functions defined for each device is INIT. -This routine is called once when the device is installed, -and never again. The only thing returned by the init routine -is a location (DS:DX) which is a pointer to the first free -byte of memory after the device driver, (like a terminate -and stay resident). This pointer method can be used to "throw -away" initialization code that is only needed once, saving -on space. - - Block devices are installed the same way and also return -a first free byte pointer as above, additional information -is also returned: - - o The number of units is returned, this determines - logical device names. If the current maximum logical - device letter is F at the time of the install call, - and the init routine returns 4 as the number of units, - then they will have logical names G, H, I and J. - This mapping is determined by by the position of - the driver in the device list and the number of units - on the device (stored in the first byte of the device - name field). - - o A pointer to a BPB (Bios Parameter Block) pointer - array is also returned. This will be similar to - the INIT table used in previous versions, but will - have more information in it. There is one table - for each unit defined. These blocks will be used - to build a DPB (Drive Parameter Block) for each of - the units. The pointer passed to the DOS from the - driver points to an array of n word pointers to BPBs - where n is the number of units defined. In this - way if all units are the same, all of the pointers - can point to the same BPB, saving space. NOTE: this - array must be protected (below the free pointer set - by the return) since the DPB will be built starting - at the byte pointed to by the free pointer. The - sector size defined must be less than or equal to - the maximum sector size defined at default BIOS init - time. If it isn't the install will fail. One new - piece of DPB info set from this table will be a "media - descriptor byte". This byte means nothing to the - DOS, but is passed to devices so that they know what - form of a DPB the DOS is currently using for a - particular Drive-Unit. - - Block devices may take several approaches; they may be -dumb or smart. A dumb device would define a unit (and -therefore a DPB) for each possible media drive combination. -Unit 0 = drive 0 single side, unit 1 = drive 0 double side, -etc. For this approach media descriptor bytes would mean -nothing. A smart device would allow multiple media per unit, -in this case the BPB table returned at init must define space -large enough to accommodate the largest possible media -supported. Smart drivers will use the "media byte" to pass -around info about what media is currently in a unit. NOTE: -If the DPB is a "hybrid" made to get the right sizes, it -should give an invalid "media byte" back to the DOS. - - The BOOT (default BIOS) drivers are installed pretty -much as above. The preset device list is scanned. If block -drivers are encountered they are installed as above (with -the exception that the break is not moved since the drivers -are already resident in the BIOS). Note that the logical -drive letters are assigned in list order, thus the driver -which is to have logical A must be the first unit of the -first block device in the list. The order of character -devices is also important. There must be at least 4 character -devices defined at boot which must be the first four devices -(of either type), the first will become standard input, -standard output, and standard error output. The second will -become standard auxiliary input and output, the third will -become standard list output, and the forth will become the -date/time (CLOCK) device. Thus the BIOS device list must -look like this: - -->CON->AUX->PRN->CLOCK->any other block or character devices - -THE DRIVER - - A device driver will define the following functions: - - Command Function - Code - - 0 INIT - 1 MEDIA CHECK (Block only, NOP for character) - 2 BUILD BPB " " " " " - 3 IOCTL INPUT (Only called if device has IOCTL) - 4 INPUT (read) - 5 NON-DESTRUCTIVE INPUT NO WAIT (Char devs only) - 6 INPUT STATUS " " " - 7 INPUT FLUSH " " " - 8 OUTPUT (write) - 9 OUTPUT (Write) with verify - 10 OUTPUT STATUS " " " - 11 OUTPUT FLUSH " " " - 12 IOCTL OUTPUT (Only called if device has IOCTL) - - As mentioned before, the first entry point is the strategy -routine which is called with a pointer to a data block. This -call does not perform the request, all it does is queue it -(save the data block pointer). The second interrupt entry -point is called immediately after the strategy call. The -"interrupt" routine is called with no parameters, its primary -function is to perform the operation based on the queued -data block and set up any returns. - - The "BUILD BPB" and "MEDIA CHECK" are the interesting -new ones, these are explained by examining the sequence of -events in the DOS which occurs when a drive access call (other -than read or write) is made: - - I. Turn drive letter into DPB pointer by looking - for DPB with correct driver-unit number. - - II. Call device driver and request media check for - Drive-Unit. DOS passes its current Media - descriptor byte (from DPB). Call returns: - - Media Not Changed - Media Changed - Not Sure - Error - - Error - If an error occurs the error code should - be set accordingly. - - Media Not changed - Current DPB and media byte - are OK, done. - - Media Changed - Current DPB and media are wrong, - invalidate any buffers for this unit, and - goto III. - - Not Sure - If there are dirty buffers for this - unit, assume DPB and media byte are OK and - done. If nothing dirty, assume media changed, - invalidate any buffers for unit, and goto - III. - - NOTE: If a hybrid DPB was built at init and - an invalid Media byte was set, the driver - should return media changed when this invalid - media byte is encountered. - - III. Call device driver to build BPB with media byte - and buffer. - - What the driver must do at step III is determine the -correct media that is currently in the unit, and return a -pointer to a BPB table (same as for the install call). This -table will be used as at init to build a correct DPB for -the unit If the determined media descriptor byte in the table -turns out to be the same as the one passed in, then the DOS -will not build a new table, but rather just use the old one. -Therefore in this case the driver doesn't have to correctly -fill in the other entries if desired. - - The build BPB call also gets a pointer to a one sector -buffer. What this buffer contains is determined by the NON -IBM FORMAT bit in the attribute field. If the bit is zero -(device is IBM format compatible) then the buffer contains -the first sector of the first FAT, in particular the FAT -ID byte is the first byte of this buffer. NOTE: It must -be true that the BPB is the same, as far as location of the -FAT is concerned, for all possible media. This is because -this first FAT sector must be read BEFORE the actual BPB -is returned. If the NON IBM FORMAT bit is set then the -pointer points to one sector of scratch space which may be -used for anything. - -CALL FORMAT - - When the DOS calls a device driver to perform a finction, -it passes a structure (Drive Request Structure) in ES:BX -to perform operations and does a long call to the driver's -strategy entry point. This structure is a fixed length header -(Static Request Header) followed by data pertinent to the -operation being performed. NOTE: It is the drivers -responsibility to preserve machine state. - -STATIC REQUEST HEADER -> - +-----------------------------+ - | BYTE length of record | - | Length in bytes of this | - | Drive Request Structure | - +-----------------------------+ - | BYTE unit code | - | The subunit the operation | - | is for (minor device) | - | (no meaning on character | - | devices) | - +-----------------------------+ - | BYTE command code | - +-----------------------------+ - | WORD Status | - +-----------------------------+ - | 8 bytes reserved here for | - | two DWORD links. One will | - | be a link for the DOS queue | - | The other for the device | - | queue | - +-----------------------------+ - -STATUS WORD - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+ - | E | | B | D | | - | R | RESERVED | U | O | ERROR CODE (bit 15 on)| - | R | | I | N | | - +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+ - - The status word is zero on entry and is set by the driver -interrupt routine on return. - - Bit 8 is the done bit, it means the operation is complete. -For the moment the Driver just sets it to one when it exits, -in the future this will be set by the interrupt routine to -tell the DOS the operation is complete. - - Bit 15 is the error bit, if it is set then the low 8 -bits indicate the error: - - 0 Write Protect violation - (NEW) 1 Unknown Unit - 2 Drive not ready - (NEW) 3 Unknown command - 4 CRC error - (NEW) 5 Bad Drive Request Structure length - 6 Seek error - (NEW) 7 Unknown media - 8 Sector not found - (NEW) 9 Printer out of paper - A Write Fault - (NEW) B Read Fault - C General Failure - -Bit 9 is the busy bit which is set only by status calls (see -STATUS CALL below). - - - Here is the data block format for each function: - -READ or WRITE - ES:BX (Including IOCTL) -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - | BYTE Media descriptor from DPB | - +------------------------------------+ - | DWORD transfer address | - +------------------------------------+ - | WORD byte/sector Count | - ---+------------------------------------+--- - | WORD starting sector number | - | (ignored on Char Devs) | - +------------------------------------+ - - In addition to setting the status word, the driver must -set the Sector count to the actual number of sectors (or -bytes) transferred. NOTE: No error check is performed on -an IOCTL I/O call, driver MUST correctly set the return sector -(byte) count to the actual number of bytes transferred, -however. - -NOTE: THE FOLLOWING APPLIES TO BLOCK DEVICE DRIVERS. - - Under certain circumstances the BIOS may be asked to -do a write operation of 64K bytes which seems to be a "wrap -around" of the transfer address in the BIOS I/O packet. This -arises due to an optimization added to the write code in -MS-DOS. It will only manifest on user WRITEs which are within -a sector size of 64K bytes on files which are "growing" past -the current EOF. IT IS ALLOWABLE FOR THE BIOS TO IGNORE -THE BALANCE OF THE WRITE WHICH "WRAPS AROUND" IF IT SO -CHOOSES. For instance a WRITE of 10000H bytes worth of -sectors with a transfer address of XXX:1 could ignore the -last two bytes (remember that a user program can never request -an I/O of more than FFFFH bytes and cannot wrap around (even -to 0) in his transfer segment, so in this case the last two -bytes can be ignored). - - -NON DESRUCTIVE READ NO WAIT - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - | BYTE read from device | - +------------------------------------+ - - This call is analogous to the console input status call -on MS-DOS 1.25. If the character device returns Busy bit -= 0 (characters in buffer), then the next character that -would be read is returned. This character is NOT removed -from the input buffer (hence the term Non Destructive Read). -In essence this call allows the DOS to look ahead one input -character. - - -MEDIA CHECK - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - | BYTE Media Descriptor from DPB | - +------------------------------------+ - | BYTE returned | - +------------------------------------+ - - In addition to setting status word, driver must set the -return byte. - - Return Byte : - -1 Media has been changed - 0 Don't know if media has been changed - 1 Media has not been changed - - If the driver can return -1 or 1 (by having a door-lock -or other interlock mechanism) the performance of MSDOS 2.0 -is enhanced as the DOS need not reread the FAT for each -directory access. - - -BUILD BPB - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - | BYTE Media Descriptor from DPB | - +------------------------------------+ - | DWORD Transfer Address | - | (points to one sectors worth of | - | scratch space or first sector | - | of FAT depending on the value | - | of the NON IBM FORMAT bit) | - +------------------------------------+ - | DWORD Pointer to BPB | - +------------------------------------+ - - If the NON IBM FORMAT bit of the device is set, then -the DWORD Transfer Address points to a one sector buffer -which can be used for any purpose. If the NON IBM FORMAT -bit is 0, then this buffer contains the first sector of the -FAT; in this case the driver must not alter this buffer (this -mode is useful if all that is desired is to read the FAT -ID byte). - - If IBM compatible format is used (NON IBM FORMAT BIT -= 0), then it must be true that the first sector of the first -FAT is located at the same sector on all possible media. -This is because the FAT sector will be read BEFORE the media -is actually determined. - - In addition to setting status word, driver must set the -Pointer to the BPB on return. - - - In order to allow for many different OEMs to read each -other's disks, the following standard is suggested: The -information relating to the BPB for a particular piece of -media is kept in the boot sector for the media. In -particular, the format of the boot sector is: - - +------------------------------------+ - | 3 BYTE near JUMP to boot code | - +------------------------------------+ - | 8 BYTES OEM name and version | - ---+------------------------------------+--- - B | WORD bytes per sector | - P +------------------------------------+ - B | BYTE sectors per allocation unit | - +------------------------------------+ - | | WORD reserved sectors | - V +------------------------------------+ - | BYTE number of FATs | - +------------------------------------+ - | WORD number of root dir entries | - +------------------------------------+ - | WORD number of sectors in logical | - ^ | image | - | +------------------------------------+ - B | BYTE media descriptor | - P +------------------------------------+ - B | WORD number of FAT sectors | - ---+------------------------------------+--- - | WORD sectors per track | - +------------------------------------+ - | WORD number of heads | - +------------------------------------+ - | WORD number of hidden sectors | - +------------------------------------+ - - The three words at the end are optional, the DOS doesn't -care about them (since they are not part of the BPB). They -are intended to help the BIOS understand the media. Sectors -per track may be redundant (could be figured out from total -size of the disk). Number of heads is useful for supporting -different multi-head drives which have the same storage -capacity, but a different number of surfaces. Number of -hidden sectors is useful for supporting drive partitioning -schemes. - - - Currently, the media descriptor byte has been defined -for a small range of media: - - 5 1/4" diskettes: - - Flag bits: - 01h - on -> 2 double sided - - All other bits must be on. - - 8" disks: - FEh - IBM 3740 format, singled-sided, single-density, - 128 bytes per sector, soft sectored, 4 sectors - per allocation unit, 1 reserved sector, 2 FATs, - 68 directory entries, 77*26 sectors - - FDh - 8" IBM 3740 format, singled-sided, - single-density, 128 bytes per sector, soft - sectored, 4 sectors per allocation unit, 4 - reserved sectors, 2 FATs, 68 directory entries, - 77*26 sectors - - FEh - 8" Double-sided, double-density, 1024 bytes - per sector, soft sectored, 1 sector per allocation - unit, 1 reserved sector, 2 FATs, 192 directory - entries, 77*8*2 sectors - - -STATUS Calls - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - - All driver must do is set status word accordingly and -set the busy bit as follows: - - o For output on character devices: If it is 1 on - return, a write request (if made) would wait for - completion of a current request. If it is 0, there - is no current request and a write request (if made) - would start immediately. - - o For input on character devices with a buffer a return - of 1 means, a read request (if made) would go to - the physical device. If it is 0 on return, then - there are characters in the devices buffer and a - read would return quickly, it also indicates that - the user has typed something. The DOS assumes all - character devices have an input type ahead buffer. - Devices which don't have them should always return - busy = 0 so that the DOS won't hang waiting for - something to get into a buffer which doesn't exist. - - -FLUSH Calls - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - - This call tells the driver to flush (terminate) all -pending requests that it has knowledge of. Its primary use -is to flush the input queue on character devices. - - -INIT - ES:BX -> - +------------------------------------+ - | 13-BYTE Static Request Header | - +------------------------------------+ - | BYTE # of units | - +------------------------------------+ - | DWORD Break Address | - ---+------------------------------------+--- - | DWORD Pointer to BPB array | - | (not set by Character devices) | - +------------------------------------+ - - The number of units, break address, and BPB pointer are -set by the driver. - - -FORMAT OF BPB (Bios Parameter Block) - - - +------------------------------------+ - | WORD Sector size in Bytes | - | Must be at least 32 | - +------------------------------------+ - | BYTE Sectors/Allocation unit | - | Must be a power of 2 | - +------------------------------------+ - | WORD Number of reserved sectors | - | May be zero | - +------------------------------------+ - | BYTE Number of FATS | - +------------------------------------+ - | WORD Number of directory entries | - +------------------------------------+ - | WORD Total number of sectors | - +------------------------------------+ - | BYTE Media descriptor | - +------------------------------------+ - | WORD Number of sectors occupied by | - | FAT | - +------------------------------------+ - - -THE CLOCK DEVICE - - One of the most popular add on boards seems to be "Real -Time CLOCK Boards". To allow these boards to be integrated -into the system for TIME and DATE, there is a special device -(determined by the attribute word) which is the CLOCK device. -In all respects this device defines and performs functions -like any other character device (most functions will be "set -done bit, reset error bit, return). When a read or write -to this device occurs, exactly 6 bytes are transferred. This -I/O can be thought of as transferring 3 words which correspond -exactly to the values of AX, CX and DX which were used in -the old 1.25 DOS date and time routines. Thus the first -two bytes are a word which is the count of days since 1-1-80. -The third byte is minutes, the fourth hours, the fifth -hundredths of seconds, and the sixth seconds. Reading the -CLOCK device gets the date and time, writing to it sets the -date and time. - \ No newline at end of file diff --git a/v2.0/bin/DISKCOPY.COM b/v2.0/bin/DISKCOPY.COM deleted file mode 100644 index ea4e0d2..0000000 Binary files a/v2.0/bin/DISKCOPY.COM and /dev/null differ diff --git a/v2.0/bin/DOSPATCH.TXT b/v2.0/bin/DOSPATCH.TXT deleted file mode 100644 index 20ebd95..0000000 --- a/v2.0/bin/DOSPATCH.TXT +++ /dev/null @@ -1,62 +0,0 @@ -There are three locations in the DOS where OEMs may want to -patch in information specific to their installation. - - -The first is the location of the default switch character. -This character is one byte at DEBUG location 1E5, and is -set to '/'. To change it to '-' (XENIX compatible) -do: - - DEBUG MSDOS.SYS - - >e1e5 - XXXX:01E5 2F. - >w - Writing YYYY Bytes - >q - -If the byte at 1E5 is not 2F, look around in the immediate -vacinity (do d1e0) for it. It is the only 2F in that area. - - -The second is the location of the 24 bit user number and the -8 bit OEM number. These values are returned by the GET_VERSION -system call. -The user number is 3 bytes starting at -debug location 683, The OEM number is one byte at debug location -686. The user number is initialized to 0, the OEM number to -1 -and they immediatly follow the Microsoft Copyright message. If these -bytes are not zero, look for the four bytes following the -Copyright message which should be in the vacinity of 683. -OEMs should request an OEM number from Microsoft if they -want one of their very own, this prevents selecting one someone -else already has. - - -The third is the location of the editing template definitions. -This is a table which defines the two byte edit function keys -for system call 10 and for EDLIN. This table is at debug location -33EA, and should start with a 1B. If the byte at 33EA is not -1B, look around in the immediate vacinity. Here is what the -default table looks like. It is a definition for the Zenith -Z-19 terminal: - -ESCCHAR DB 1BH ;The Escape character, Nul (0) on IBM -ESCTAB: - DB "Z" ;5AH Put a ^Z in the template, F6 on IBM - DB "S" ;53H Copy one char, --> on IBM - DB "V" ;56H Skip one char, DEL on IBM - DB "T" ;54H Copy to char, F2 on IBM - DB "W" ;57H Skip to char, F4 on IBM - DB "U" ;55H Copy line, F3 on IBM - DB "E" ;45H Kill line, Not used on IBM - DB "J" ;4AH Reedit line, F5 on IBM - DB "D" ;44H Backspace, <-- on IBM - DB "P" ;50H Toggle insert mode, INS on IBM - DB "Q" ;51H Toggle insert mode, INS on IBM - DB "R" ;52H Escape char, F7 on IBM - DB "R" ;52H End of table, must be same as previos character - - \ No newline at end of file diff --git a/v2.0/bin/EDLIN.COM b/v2.0/bin/EDLIN.COM deleted file mode 100644 index 81e097b..0000000 Binary files a/v2.0/bin/EDLIN.COM and /dev/null differ diff --git a/v2.0/bin/EXE2BIN.EXE b/v2.0/bin/EXE2BIN.EXE deleted file mode 100644 index f4b0dd7..0000000 Binary files a/v2.0/bin/EXE2BIN.EXE and /dev/null differ diff --git a/v2.0/bin/FC.EXE b/v2.0/bin/FC.EXE deleted file mode 100644 index aa06624..0000000 Binary files a/v2.0/bin/FC.EXE and /dev/null differ diff --git a/v2.0/bin/FILBP.PAS b/v2.0/bin/FILBP.PAS deleted file mode 100644 index 71decc8..0000000 Binary files a/v2.0/bin/FILBP.PAS and /dev/null differ diff --git a/v2.0/bin/FIND.EXE b/v2.0/bin/FIND.EXE deleted file mode 100644 index b5d07d0..0000000 Binary files a/v2.0/bin/FIND.EXE and /dev/null differ diff --git a/v2.0/bin/FORMAT.DOC b/v2.0/bin/FORMAT.DOC deleted file mode 100644 index ab47f54..0000000 --- a/v2.0/bin/FORMAT.DOC +++ /dev/null @@ -1,393 +0,0 @@ -FORMAT - formats a new disk, clears the FAT and DIRECTORY -and optionally copies the SYSTEM and COMMAND.COM to this -new disk. - -Command syntax: - - FORMAT [drive:][/switch1][/switch2]...[/switch16] - - Where "drive:" is a legal drive specification and if - omitted indicates that the default drive will be used. - There may be up to 16 legal switches included in the - command line. - - - The OEM must supply five (NEAR) routines to the program -along with 6 data items. The names of the routines are INIT, -DISKFORMAT, BADSECTOR, WRTFAT and DONE, and their flow of -control (by the Microsoft module) is like this: - - | - +---------+ - | INIT | - +---------+ - | - |<------------------------------+ -+------------+ | -| DISKFORMAT | | -+------------+ | - |<-------+ | -+-----------+ |-This loop is done |- This loop done -| BADSECTOR | | for each group of | once for each disk -+-----------+ | bad sectors | to be formatted. - |----->--+ | If variable HARDFLAG - | | is set then the loop -+----------+ | is only performed -| | | once. -| WRTFAT | | -+----------+ | - | | - +------+ | - | DONE | | - +------+ | - +---->--------------------------+ - - The INIT, DISKFORMAT, and BADSECTOR routines are free -to use any MS-DOS system calls, except for calls that cause -disk accesses on the disk being formatted. DONE may use -ANY calls, since by the time it is called the new disk has -been formatted. - -The following data must be declared PUBLIC in a module -provided by the OEM: - - SWITCHLIST - A string of bytes. The first byte is count - N, followed by N characters which are the switches to - be accepted by the command line scanner. Alphabetic - characters must be in upper case (the numeric - characters 0-9 are allowed). The last three switches, - normally "O", "V" and "S", have pre-defined meanings. - - The "S" switch is the switch which causes the - system files IO.SYS, MSDOS.SYS, and COMMAND.COM to be - transfered to the disk after it is formatted thus - making a "S"ystem disk. The switch can be some letter - other than "S", but the last switch in the list is - assumed to have the meaning "transfer system", - regardles of what the particular letter is. - - The second to the last switch, "V", causes FORMAT - to prompt the user for a volume label after the disk - is formatted. Again, as with "S", the particular - letter is not important but rather the position in the - list. - - The third to the last switch, "O", causes FORMAT to - produce an IBM Personal Computer DOS version 1.X - compatible disk. Normally FORMAT causes a 0 byte to - be placed in the first byte of each directory entry - instead of the 0E5 Hex free entry designator. This - results in a very marked directory search performance - increase due to an optimization in the DOS. Disks - made this way cause trouble on IBM PC DOS 1.X - versions, however, which did not have this - optimization. The 0 byte fools IBM 1.X versions into - thinking these entries are allocated instead of free, - NOTE that IBM Personnal Computer DOS version 2.00 and - MS-DOS version 1.25 will have no trouble with these - disks, since they have the same optimization. The "O" - switch causes FORMAT to re-do the directory with a 0E5 - Hex byte at the start of each entry so that the disk - may be used with 1.X versions of IBM PC DOS, as well - as MS-DOS 1.25/2.00 and IBM PC DOS 2.00. This switch - should only be given when needed because it takes a - fair amount of time for FORMAT to perform the - conversion, and it noticably decreases 1.25 and 2.00 - performance on disks with few directory entries. - - Up to 16 switches are permitted. Normally a "C" - switch is specified for "Clear". This switch should - cause the formatting operation to be bypassed (within - DISKFORMAT or BADSECTOR). This is provided as a - time-saving convenience to the user, who may wish - to "start fresh" on a previosly formatted and used - disk. - - HARDFLAG - BYTE location which specifies whether the - OEM routine is formatting a fixed disk or a a drive - with removable media. A zero indicates removable - media, any other value indicates a fixed disk. The - status of this byte only effect the messages printed - by the main format module. This value should be - set or reset by the OEM supplied INIT routine. - - FATID - BYTE location containing the value to be used - in the first byte of the FAT. Must be in the range - F8 hex to FF hex. - - STARTSECTOR - WORD location containing the sector number - of the first sector of the data area. - - FATSPACE - WORD location containing the address of the - start of the FAT area. A FAT built in this area - will be written to disk using the OEM supplied WRTFAT - subroutine. 6k is sufficient to store any FAT. This - area must not overlap the FREESPACE area. - - FREESPACE - WORD location which contains the address - of the start of free memory space. This is where - the system will be loaded, by the Microsoft module, - for transferring to the newly formatted disk. Memory - should be available from this address to the end - of memory, so it is typically the address of the - end of the OEM module. - -The following routines must be declared PUBLIC in the -OEM-supplied module: - - INIT - An initialization routine. This routine is called - once at the start of the FORMAT run after the switches - have been processed. This routine should perform - any functions that only need to be done once per - FORMAT run. An example of what this routine might - do is read the boot sector into a buffer so that - it can be transferred to the new disks by DISKFORMAT. - If this routine returns with the CARRY flag set it - indicates an error, and FORMAT will print "Format - failure" and quit. This feature can be used to detect - conflicting switches (like specifying both single - and double density) and cause FORMAT to quit without - doing anything. - - DISKFORMAT - Formats the disk according to the options - indicated by the switches and the value of FATID - must be defined when it returns (although INIT may - have already done it). This routine is called once - for EACH disk to be formatted. If neccessary it - must transfer the Bootstrap loader. If any error - conditions are detected, set the CARRY flag and return - to FORMAT. FORMAT will report a 'Format failure' - and prompt for another disk. (If you only require - a clear directory and FAT then simply setting the - appropriate FATID, if not done by INIT, will be all - that DISKFORMAT must do.) - - BADSECTOR - Reports the sector number of any bad sectors - that may have been found during the formatting of - the disk. This routine is called at least once for - EACH disk to be formatted, and is called repeatedly - until AX is zero or the carry flag is set. The carry - flag is used just as in DISKFORMAT to indicate an - error, and FORMAT handles it in the same way. The - first sector in the data area must be in STARTSECTOR - for the returns from this routine to be interpreted - correctly. If there are bad sectors, BADSECTOR must - return a sector number in in register BX, the number - of consecutive bad sectors in register AX, and carry - clear. FORMAT will then process the bad sectors - and call BADSECTOR again. When BADSECTOR returns - with AX = 0 this means there are no more bad sectors; - FORMAT clears the directory and goes on to DONE, - so for this last return BX need not contain anything - meaningful. - - FORMAT processes bad sectors by determining their - corresponding allocation unit and marking that unit - with an FF7 hex in the File Allocation Table. CHKDSK - understands the FF7 mark as a flag for bad sectors - and accordingly reports the number of bytes marked - in this way. - - NOTE: Actual formatting of the disk can be done in - BADSECTOR instead of DISKFORMAT on a "report as you - go" basis. Formatting goes until a group of bad - sectors is encountered, BADSECTOR then reports them - by returning with AX and BX set. FORMAT will then - call BADSECTOR again and formatting can continue. - - WRTFAT - This routine is called after the disk is - formatted and bad sectors have been reported. Its - purpose is to write all copies of the FAT from the - area of memory referenced by FATSPACE to the drive - just formatted. It may be possible to use INT 26H - to perform the write, or a direct BIOS call. Whether - this is possible depends on whether the FAT ID byte - is used by the BIOS to determine the media in the - drive. If it is, these methods will probably fail - because there is no FAT ID byte on the disk yet (in - this case WRTFATs primary job is to get the FAT ID - byte out on the disk and thus solve the chicken and - egg problem). - - DONE - This routine is called after the formatting is - complete, the disk directory has been initialized, - and the system has been transferred. It is called - once for EACH disk to be formatted. This gives the - chance for any finishing-up operations, if needed. - If the OEM desires certain extra files to be put - on the diskette by default, or according to a switch, - this could be done in DONE. Again, as in BADSECTOR - and DISKFORMAT, carry flag set on return means an - error has occurred: 'Format failure' will be printed - and FORMAT will prompt for another disk. - - -The following data is declared PUBLIC in Microsoft's FORMAT -module: - - SWITCHMAP - A word with a bit vector indicating what - switches have been included in the command line. The - correspondence of the bits to the switches is - determined by SWITCHLIST. The right-most - (highest-addressed) switch in SWITCHLIST (which must - be the system transfer switch, normally "S") - corresponds to bit 0, the second from the right, - normally "V" to bit 1, etc. For example, if - SWITCHLIST is the string "7,'AGI2OVS'", and the user - specifies "/G/S" on the command line, then bit 6 will - be 0 (A not specified), bit 5 will be 1 (G specified), - bits 4,3,2 and 1 will be 0 (neither I,2,O or V - specified), and bit 0 will be 1 (S specified). - - Bits 0,1 and 2 are the only switches used in - Microsoft's FORMAT module. These switches are used 1) - after INIT has been called, to determine if it is - necessary to load the system; 2) after the last - BADSECTOR call, to determine if the system is to be - written, E5 directory conversion is to be done, and/or - a volume label is to be asked for. INIT may force - these bits set or reset if desired (for example, some - drives may never be used as system disk, such as hard - disks). After INIT, the "S" bit may be turned off - (but not on, since the system was never read) if - something happens that means the system should not be - transferred. - - After INIT, a second copy of SWITCHMAP is made - internally which is used to restore SWITCHMAP for - each disk to be formatted. FORMAT itself will turn - off the system bit if bad sectors are reported in - the system area; DISKFORMAT and BADSECTOR are also - allowed to change the map. However, these changes - affect only the current disk being formatted, since - SWITCHMAP is restored after each disk. (Changes - made to SWITCHMAP by INIT do affect ALL disks.) - - DRIVE - A byte containing the drive specified in the - command line. 0=A, 1=B, etc. - -Once the OEM-supplied module has been prepared, it must linked -with Microsoft's FORMAT.OBJ module and the FORMES.OBJ module. -If the OEM-supplied module is called OEMFOR.OBJ, then the -following linker command will do: - - LINK FORMAT FORMES OEMFOR; - -This command will produce a file called FORMAT.EXE. FORMAT -has been designed to run under MS-DOS as a simple binary -.COM file. This conversion is performed by LOCATE (EXE2BIN) -with the command - - LOCATE FORMAT.EXE FORMAT.COM - -which will produce the file FORMAT.COM. - -;***************************************** -; -; A Sample OEM module -; -;***************************************** - -CODE SEGMENT BYTE PUBLIC 'CODE' -; This segment must be -; named CODE, it must be -; PUBLIC, and it's -; classname must be 'CODE' - - - ASSUME CS:CODE,DS:CODE,ES:CODE - -; Must declare data and routines PUBLIC - -PUBLIC FATID,STARTSECTOR,SWITCHLIST,FREESPACE -PUBLIC INIT,DISKFORMAT,BADSECTOR,DONE,WRTFAT -PUBLIC FATSPACE,HARDFLAG - -; This data defined in Microsoft-supplied module - - EXTRN SWITCHMAP:WORD,DRIVE:BYTE - -INIT: - -; Read the boot sector into memory - CALL READBOOT - ... -; Set FATID to double sided if "D" switch specified - TEST SWITCHMAP,10H - JNZ SETDBLSIDE - ... - RET - -DISKFORMAT: - ... - -; Use the bit map in SWITCHMAP to determine -; what switches are set - - TEST SWITCHMAP,8 ;Is there a "/C"? - JNZ CLEAR ; Yes -- clear operation - ; requested jump around the - ; format code - < format the disk > -CLEAR: - ... -; Transfer the boot from memory to the new disk - CALL TRANSBOOT - ... - RET - -; Error return - set carry - -ERRET: - STC - RET - -BADSECTOR: - ... - RET - - -WRTFAT: - ... - -WRTFATLOOP: - < Set up call to write out a fat to disk> - ... - MOV BX,[FATSPACE] - - < Write out one fat to disk> - JC ERRET - ... - < Decrement fat counter > - JNZ WRTFATLOOP - CLC ;Good return - RET - - -DONE: - ... - RET - -; Default Single sided -FATID DB 0FEH - -HARDFLAG DB 0 - -STARTSECTOR DW 9 - -SWITCHLIST DB 5,"DCOVS" ; "OVS" must be the last - ; switches in the list - -FATSPACE DW FATBUF - -FREESPACE DW ENDBOOT - -BOOT DB BOOTSIZE DUP(?) ; Buffer for the - ; boot sector - -FATBUF DB 6 * 1024 DUP(?) ; Fat buffer -ENDBOOT LABEL BYTE - -CODE ENDS - END - \ No newline at end of file diff --git a/v2.0/bin/FORMAT.OBJ b/v2.0/bin/FORMAT.OBJ deleted file mode 100644 index 61fe107..0000000 Binary files a/v2.0/bin/FORMAT.OBJ and /dev/null differ diff --git a/v2.0/bin/FORMES.OBJ b/v2.0/bin/FORMES.OBJ deleted file mode 100644 index 247f39e..0000000 Binary files a/v2.0/bin/FORMES.OBJ and /dev/null differ diff --git a/v2.0/bin/INCOMP.DOC b/v2.0/bin/INCOMP.DOC deleted file mode 100644 index 6c187b6..0000000 Binary files a/v2.0/bin/INCOMP.DOC and /dev/null differ diff --git a/v2.0/bin/INT24.DOC b/v2.0/bin/INT24.DOC deleted file mode 100644 index d38d6fa..0000000 Binary files a/v2.0/bin/INT24.DOC and /dev/null differ diff --git a/v2.0/bin/LINK.EXE b/v2.0/bin/LINK.EXE deleted file mode 100644 index aa58151..0000000 Binary files a/v2.0/bin/LINK.EXE and /dev/null differ diff --git a/v2.0/bin/MASM.EXE b/v2.0/bin/MASM.EXE deleted file mode 100644 index d43bfb7..0000000 Binary files a/v2.0/bin/MASM.EXE and /dev/null differ diff --git a/v2.0/bin/MORE.COM b/v2.0/bin/MORE.COM deleted file mode 100644 index b28f807..0000000 Binary files a/v2.0/bin/MORE.COM and /dev/null differ diff --git a/v2.0/bin/MSDOS.SYS b/v2.0/bin/MSDOS.SYS deleted file mode 100644 index 803eb70..0000000 Binary files a/v2.0/bin/MSDOS.SYS and /dev/null differ diff --git a/v2.0/bin/PRINT.COM b/v2.0/bin/PRINT.COM deleted file mode 100644 index b2788d3..0000000 Binary files a/v2.0/bin/PRINT.COM and /dev/null differ diff --git a/v2.0/bin/PROFIL.OBJ b/v2.0/bin/PROFIL.OBJ deleted file mode 100644 index 66946b3..0000000 Binary files a/v2.0/bin/PROFIL.OBJ and /dev/null differ diff --git a/v2.0/bin/PROFILE.DOC b/v2.0/bin/PROFILE.DOC deleted file mode 100644 index 2d50631..0000000 Binary files a/v2.0/bin/PROFILE.DOC and /dev/null differ diff --git a/v2.0/bin/PROHST.EXE b/v2.0/bin/PROHST.EXE deleted file mode 100644 index dfa8983..0000000 Binary files a/v2.0/bin/PROHST.EXE and /dev/null differ diff --git a/v2.0/bin/PROHST.PAS b/v2.0/bin/PROHST.PAS deleted file mode 100644 index 4ee13fc..0000000 --- a/v2.0/bin/PROHST.PAS +++ /dev/null @@ -1,403 +0,0 @@ -PROGRAM prohst(input,output); -{$debug- $line- $symtab+} - -{**********************************************************************} -{* *} -{* prohst *} -{* *} -{* This program produces a histogram from the profile file produced *} -{* by the MS-DOS profile utility. It optionally reads the map file *} -{* generated when the program being profiled was linked, and writes *} -{* either the module address or, if available, the line number as *} -{* a prefix to the line of the graph which describes a particular *} -{* bucket. *} -{* *} -{* After using filbm (derived from the Pascal and Fortran front end *} -{* command scanner) to parse its parameters, prohst opens the map *} -{* file if specified, searches for the heading line, and then reads *} -{* the lines giving the names and positions of the modules. It builds *} -{* a linked list of module names and start addresses. *} -{* *} -{* It then reads the bucket file header and and bucket array elements *} -{* into a variable created on the heap. It simultaneously calculates *} -{* a normalization factor. It writes the profile listing header and *} -{* starts to write the profile lines. For each bucket, the address *} -{* is calculated. The first entry in the address/name linked list *} -{* is the lowest addressed module. This is initially the 'current' *} -{* module. The bucket address is compared with the current module *} -{* address. When it becomes the greater, the module name is written *} -{* to the listing and the next entry in the address/name list becomes *} -{* the current module. If line numbers are available, the bucket *} -{* address is also compared to the current line/address. This is *} -{* read and calculated directly from the file. Since there may be *} -{* more than one line per bucket, several entries may be read until *} -{* the addresses compare within the span of addresses encompassed by *} -{* a bucket (its 'width'). Note that the idiosyncracies of Pascal i/o *} -{* make it necessary to continually check for the end of the map file *} -{* and the complexity of this code is mainly due to an attempt to *} -{* make it reasonably resilient to changes in the format of the map *} -{* file. *} -{* *} -{**********************************************************************} - - -CONST - max_file = 32; - - -TYPE - filenam = LSTRING (max_file); - sets = SET OF 0..31; - address_pointer = ^address_record; - address_record = RECORD - next: address_pointer; - name: STRING (15); - address: WORD; - END; - - - - - -VAR - - i: INTEGER; - bucket: FILE OF WORD; - hist: TEXT; - map: TEXT; - - first_address, - this_address: address_pointer; - current_base: WORD; - bucket_name, - hist_name, - map_name: filenam; - - switches: sets; - - line: LSTRING (100); - - map_avail: BOOLEAN; - line_nos_avail: BOOLEAN; - - norm: REAL; - per_cent: INTEGER; - real_bucket, - norm_bucket: REAL; - cum_per_cent, - real_per_cent: REAL; - - bucket_num, - clock_grain, - bucket_size, - prog_low_pa, - prog_high_pa, - dos_pa, - hit_io, - hit_dos, - hit_high: WORD; - - seg, - offset, - parcel: WORD; - - address: WORD; - new_line_no, - line_no: WORD; - - dummy : LSTRING (8); - name: LSTRING (20); - line_no_part: LSTRING (17); - start: LSTRING (6); - - buckets: ^SUPER ARRAY [1 .. *] OF REAL; - - this_bucket: WORD; - -LABEL 1; - - -PROCEDURE filbm (VAR prffil, hstfil, mapfil: filenam; - VAR switches: sets); EXTERN; - -FUNCTION realword (w: WORD): REAL; -BEGIN - IF ORD (w) < 0 THEN BEGIN - realword := FLOAT (maxint) + FLOAT (ORD (w - maxint)); - END - ELSE BEGIN - realword := FLOAT (ORD(w)); - END {IF}; -END {realword}; - - - -PROCEDURE skip_spaces; -BEGIN - WHILE NOT eof(map) AND THEN map^ = ' ' DO BEGIN - get (map); - END {WHILE}; -END {skip_spaces}; - - -FUNCTION hex_char (ch: CHAR): WORD; -BEGIN - IF ch >= '0' AND THEN ch <= '9' THEN BEGIN - hex_char := WRD (ch) - WRD ('0'); - END - ELSE IF ch >= 'A' AND THEN ch <= 'F' THEN BEGIN - hex_char := WRD (ch) - WRD ('A') + 10; - END - ELSE BEGIN - WRITELN ('Invalid hex character'); - hex_char := 0; - END {IF}; -END {hex_char}; - - -FUNCTION read_hex (i :WORD): WORD; -VAR - hex_val: WORD; -BEGIN - skip_spaces; - hex_val := 0; - WHILE NOT eof (map) AND THEN i <> 0 DO BEGIN - hex_val := hex_val * 16 + hex_char (map^); - GET (map); - i := i - 1; - END {WHILE}; - read_hex := hex_val; -END {read_hex}; - -FUNCTION read_h: WORD; -BEGIN - read_h := read_hex (4); - get (map); - get (map); -END; - -FUNCTION read_word: WORD; -VAR - int_value: WORD; -BEGIN - int_value := 0; - IF NOT EOF (map) THEN BEGIN - READ (map, int_value); - END {IF}; - read_word := int_value; -END {read_word}; - - -FUNCTION map_digit: BOOLEAN; -BEGIN - map_digit := (map^ >= '0') OR (map^ <= '9'); -END {map_digit}; - -BEGIN {prohst} - writeln (output, ' Profile Histogram Utility - Version 1.0'); - writeln (output); - writeln (output, ' Copyright - Microsoft, 1983'); - - start := ' '; - - filbm (bucket_name, hist_name, map_name, switches); - - IF 31 IN switches THEN BEGIN - ABORT ('Map file must not be terminal', 0, 0); - END {IF}; - - IF NOT (28 IN switches) THEN BEGIN - ABORT ('No histogram file specified', 0, 0); - END {IF}; - - ASSIGN (bucket, bucket_name); - reset (bucket); - ASSIGN (hist, hist_name); - rewrite (hist); - - map_avail := 29 IN switches; - line_nos_avail := FALSE; - - IF map_avail THEN BEGIN - ASSIGN (map, map_name); - RESET (map); - - WHILE NOT EOF (map) AND THEN start <> ' Start' DO BEGIN - READLN (map, start); - END {WHILE}; - - NEW (first_address); - this_address := NIL; - - WHILE NOT EOF(map) DO BEGIN - READLN (map, line); - IF line.len < 6 OR ELSE line [2] < '0' OR ELSE - line [2] > '9' THEN BEGIN - BREAK; - END {IF}; - - IF this_address <> NIL THEN BEGIN - NEW (this_address^.next); - this_address := this_address^.next; - END - ELSE BEGIN - this_address := first_address; - END {IF}; - this_address^.next := NIL; - - this_address^.address := (hex_char (line [2]) * 4096) + - (hex_char (line [3]) * 256) + - (hex_char (line [4]) * 16) + - hex_char (line [5]); - - FOR i := 1 TO 15 DO BEGIN - this_address^.name [i] := line [22 + i]; - END {FOR}; - - END {WHILE}; - - WHILE NOT EOF (map) DO BEGIN - READLN (map, line_no_part); - IF line_no_part = 'Line numbers for ' THEN BEGIN - line_nos_avail := TRUE; - BREAK; - END {IF}; - END {WHILE}; - - END {IF}; - - read (bucket, clock_grain, bucket_num, bucket_size, - prog_low_pa, prog_high_pa, dos_pa, hit_io, hit_dos, hit_high); - - NEW (buckets,ORD (bucket_num)); - - norm := 0.0; - norm_bucket := 0.0; - - FOR i := 1 TO ORD (bucket_num) DO BEGIN - read (bucket, this_bucket); - real_bucket := realword (this_bucket); - - IF real_bucket > norm_bucket THEN BEGIN - norm_bucket := real_bucket; - END {IF}; - - norm := norm + real_bucket; - buckets^[i] := real_bucket; - END {FOR}; - norm_bucket := 45.0/norm_bucket; - norm := 100.0/norm; - - WRITELN (hist, 'Microsoft Profiler Output Listing'); - - WRITELN (hist); - WRITELN (hist, ORD (bucket_num):6, bucket_size:4,'-byte buckets.'); - - WRITELN (hist); - WRITELN (hist, 'Profile taken between ', prog_low_pa*16::16, - ' and ', prog_high_pa*16::16, '.'); - - WRITELN (hist); - WRITELN (hist, 'DOS program address:', dos_pa::16); - - WRITELN (hist); - WRITELN (hist, 'Number of hits in DOS: ', hit_dos:5, - ' or ', realword (hit_dos) * norm:4:1, '%.'); - WRITELN (hist, 'Number of hits in I/O: ', hit_io:5, - ' or ', realword (hit_io) * norm:4:1, '%.'); - WRITELN (hist, 'Number of hits high : ', hit_high:5, - ' or ', realword (hit_high) * norm:4:1, '%.'); - WRITELN (hist); - WRITELN (hist, ' Hits Addr. Line/ Cumul. % 0.0 ', - ' ', - 1.0/norm:1:1); - - WRITELN (hist, ' Offset +----------------', - '----------------------------'); - WRITELN (hist, name); - i := 0; - parcel := 0; - current_base := 0; - line_no := 0; - new_line_no := 0; - cum_per_cent := 0.0; - - WHILE i < ORD (bucket_num) DO BEGIN - i := i + 1; - IF buckets^[i] < 0.9 THEN BEGIN - WRITELN (hist); - REPEAT - i := i + 1; - UNTIL (i = ORD (bucket_num)) OR ELSE buckets^[i] > 0.0; - END {IF}; - - address := bucket_size * (WRD (i) - 1); - - WHILE map_avail AND THEN - address >= first_address^.address DO BEGIN - WRITELN (hist, ' ', first_address^.name); - current_base := first_address^.address; - first_address := first_address^.next; - END {WHILE}; - - WHILE line_nos_avail AND THEN NOT eof (map) AND THEN - address >= parcel DO BEGIN - skip_spaces; - WHILE (map^ < '0') OR (map^ > '9') DO BEGIN - - IF EOF (map) THEN BEGIN - goto 1; - END {IF}; - READLN (map); - skip_spaces; - END {WHILE}; - - - line_no := new_line_no; - new_line_no := read_word; - seg := read_hex (4); - IF EOF (map) THEN BEGIN - GOTO 1; - END {IF}; - IF map^ <> ':' THEN BEGIN - WRITELN ('Invalid map file'); - END {IF}; - get (map); - IF EOF (map) THEN BEGIN - GOTO 1; - END {IF}; - offset := read_hex (3) + WRD (hex_char (map^) > 0); - get (map); - IF map^ <> 'H' THEN BEGIN - WRITELN ('Invalid map file'); - END {IF}; - IF EOF (map) THEN BEGIN - GOTO 1; - END {IF}; - get (map); - parcel := seg + offset; - END {WHILE}; -1: real_per_cent := buckets^[i] * norm; - cum_per_cent := cum_per_cent + real_per_cent; - per_cent := ROUND ( buckets^[i] * norm_bucket); - - WRITE (hist, buckets^ [i]:6:0, ' ', - address*16:6:16); - IF line_no <> 0 THEN BEGIN - WRITE (hist, line_no:6); - line_no := 0; - END - ELSE IF map_avail AND THEN first_address <> NIL THEN BEGIN - WRITE (hist, ' #', address - first_address^.address:4:16); - END - ELSE BEGIN - WRITE (hist, ' '); - END {IF}; - - WRITELN (hist, ' ', cum_per_cent:5:1, ' ', real_per_cent:4:1, ' |', - '*': per_cent); - END {WHILE}; - WRITELN (hist, ' +-----------------', - '------------------'); -END. - \ No newline at end of file diff --git a/v2.0/bin/QUICK.DOC b/v2.0/bin/QUICK.DOC deleted file mode 100644 index d443b8e..0000000 Binary files a/v2.0/bin/QUICK.DOC and /dev/null differ diff --git a/v2.0/bin/README.DOC b/v2.0/bin/README.DOC deleted file mode 100644 index c5bbf25..0000000 --- a/v2.0/bin/README.DOC +++ /dev/null @@ -1,177 +0,0 @@ - MSDOS 2.0 RELEASE - - -The 2.0 Release of MSDOS includes five 5 1/4 double density single sided -diskettes or three 8 iinch CP/M 80 format diskettes. - -The software/documentation on the five inch diskettes is arranged -as follows: - -1. DOS distribution diskette. This diskette contains files which - should be distriibuted to all users. This allows the DOS distri- - bution diskette to meet the requirements of users of high level - language compilers as well as users running only applications. - Many compilers marketed independently through the retail channel - (including those of Microsoft) assume LINK comes with the DOS, as - in the case of IBM. How you choose to distrubute BASIC (contracted - for separately) is up to you. - -2. Assembly Language Development System diskette. This diskette - contains files of interest to assembly language programmers. - High level language programmers do not need these programs unless - they are writing assembly language subroutines. IBM chose to - unbundle this package from the DOS distribution diskette (except - for DEBUG), but you do not have to do so. - -3. PRINT and FORMAT diskette. This diskette contains .ASM source - files which are necessary to assemble the print spooler, which you - may wish to customize for greater performance. .OBJ files are also - included for the FORMAT utility. - -4. Skeltal BIOS and documentation diskette. This diskette contains - the skeltal BIOS source code and the SYSINIT and SYSIMES object - modules which must be linked with your BIOS module. The proper - sequence for linking is BIOS - SYSINIT - SYSIMES. - A profiler utiliity is also included on the diskette, but this - is not intended for end-users. This is distributed for use by - your development staff only and is not supported by Microsoft - If you do decide to distribute it, it is at your own risk! - - -5. Documentation. Features of 2.0 are documented on this disk. - -The user manual contains some significant errors. Most of these are -due to last minute changes to achieve a greater degree of compatibility -with IBM's implementation of MS-DOS (PC DOS). This includes the use -of "\" instead of "/" as the path separator, and "/" instead of "-" -as the switch character. For transporting of batch files across -machines, Microsoft encourages the use of "\" and "/" respectively -in the U.S. market. (See DOSPATCH.TXT for how you can overide this. -The user guide explains how the end-user can override this in CONFIG.SYS). -Both the printer echo keys and insert mode keys have now been made to -toggle. The default prompt (this may also be changed by the user -with the PROMPT command) has been changed from "A:" to "A>". -We apologize for any inconveniences these changes may have caused -your technical publications staff. - - -Here is what you need to do to MSDOS 2.0 to create a shipable product: -(see "Making a Bootable Diskette" below) - -1. BIOS. If you have developed a BIOS for the Beta Test 2.0 version - You should link your BIOS module to SYSINIT.OBJ and SYSIMES.OBJ. - You must modify your BIOS to accomodate the call back to the BIOS - at the end of SYSINIT. If you have no need for this call, simply - find a far RET and label it RE_INIT and declare it public. - An example of this can be found in the skeletal BIOS. In addition - please add support for the new fast console output routine as - described in the device drivers document. We strongly recommend - that you adapt the standard boot sector format also described in - device drivers. Once again, please refer to the skeletal BIOS. - If you have not yet implemented version 2.0 please read the device - drivers document. Microsoft strongly recommends that machines - incorporating integrated display devices with memory mapped video - RAM implement some sort of terminal emulations through the use of - escape sequences. The skeletal BIOS includes a sample ANSI - terminal driver. - -2. Please refer to DOSPATCH.TXT for possible changes you might wish - to make. We strongly recommend that you not patch the switch - characters for the U.S. market. Your one byte serial number - will be issued upon signing the license agreement. Please patch - the DOS accordingly. If you wish to serialize the DOS, this is - described in DOSPATCH.TXT. Please patch the editing template - definitions. Please note the addition of the Control-Z entry - at the beginning of the table. Also note that the insert switches - have now both been made to toggle. - -3. Utilities. FORMAT must be configured for each specific system. - GENFOR is a generic example of a system independent format module, - but it is not recommended that this be distributed to your customers. - Link in the following order: FORMAT, FORMES, (your format module). - The print spooler is distributed as an executable file, which only - prints during wait for keyboard input. If you wish with your - implementation to steal some compute time when printing as well, - you will need to customize it and reassemble. Please note that - you can use a printer-ready or timer interrupt. The former is more - efficient, but ties the user to a specific device. Sample code - is conditionaled out for the IBM PC timer interrupt. - -The following problems are known to exist: - -1. Macro assembler does not support the initialization of 10-byte - floating point constants in 8087 emulation mode - the last two bytes - are zero filled. - -2. LIB has not been provided. The version which incorporates support - for 2.0 path names will be completed in a couple of weeks. The - 1.x version should work fine if you cannot wait. Because the library - manager acts as a counterpart to the linker, we recommend that it - be distributed with the DOS distribution diskette as opposed to the - assembly language development system. - -3. International (French, German, Japanese, and U.K.) versions will be - available in several months. - -4. COMMAND.ASM is currently too large to assemble on a micro. It is - being broken down into separate modules so it can be asembled on - a machine. Source licensees should realize that the resultant - binaries from the new version will not correspond exactly to the - old version. - -5. If you have any further questions regarding the MSDOS 2.0 distribution - please contact Don Immerwahr (OEM technical support (206) 828-8086). - - - Sincerely yours, - - - Chris Larson - MS-DOS Product Marketing Manager - (206) 828-8080 - - - - BUILDING A BOOTABLE (MSDOS FORMAT) DISKETTE - - -1. In implementing MSDOS on a new machine, it is highly recommended - that an MSDOS machine be available for the development. - Please note that utilities shipped with MSDOS 2.0 use MSDOS 2.0 - system calls and WILL NOT not run under MSDOS 1.25. - -2. Use your MSDOS development machine and EDLIN or a word processor - package to write BOOT.ASM, your bootstrap loader BIOS.ASM and - your Format module. - -3. Use MASM, the Microsoft Macro-86 Assembler, to assemble these - modules. LINK is then used to link together the .OBJ modules in - the order specified. - -4. Link creates .EXE format files which are not memory image files - and contain relocation information in their headers. Since your - BIOS and BOOT routines will not be loaded by the EXE loader in - MSDOS, they must first be turned into memory image files by - using the EXE2BIN utility. - -5. The easiest thing to do is to (using your development machine) - FORMAT a single sided diskette without the system. Use DEBUG - to load and write your BOOT.COM bootstrap loader to the BOOT - sector of that diskette. You may decide to have your bootstrap - load BIOS and let the BIOS load MSDOS or it may load both. Note that - the Bootstrap loader will have to know physically where to go on - the disk to get the BIOS and the DOS. COMMAND.COM is loaded - by the SYSINIT module. - -6. Use the COPY command to copy your IO.SYS file (what the - BIOS-SYSINIT-SYSIMES module is usually called) onto the disk - followed by MSDOS.SYS and COMMAND.COM. You may use DEBUG - to change the directory attribute bytes to make these files hidden. - -CAUTION: - -At all times, the BIOS writer should be careful to preserve the state -of the DOS - including the flags. You should be also be cautioned that -the MSDOS stack is not deep. You should not count on more than one or -two pushes of the registers. - \ No newline at end of file diff --git a/v2.0/bin/RECOVER.COM b/v2.0/bin/RECOVER.COM deleted file mode 100644 index fa51fae..0000000 Binary files a/v2.0/bin/RECOVER.COM and /dev/null differ diff --git a/v2.0/bin/SORT.EXE b/v2.0/bin/SORT.EXE deleted file mode 100644 index 9e2c19a..0000000 Binary files a/v2.0/bin/SORT.EXE and /dev/null differ diff --git a/v2.0/bin/SYS.COM b/v2.0/bin/SYS.COM deleted file mode 100644 index 2d315d7..0000000 Binary files a/v2.0/bin/SYS.COM and /dev/null differ diff --git a/v2.0/bin/SYSCALL.DOC b/v2.0/bin/SYSCALL.DOC deleted file mode 100644 index 26d4729..0000000 --- a/v2.0/bin/SYSCALL.DOC +++ /dev/null @@ -1,1657 +0,0 @@ - - - - - - - - - - - - - - - - - - - MS-DOS 2.0 - - System Calls Reference - - - - - - - - - - - - -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| | -| C A V E A T P R O G R A M M E R | -| | -| Certain structures, constants and system calls below | -| are private to the DOS and are extremely | -| version-dependent. They may change at any time at the | -| implementors' whim. As a result, they must not be | -| documented to the general public. If an extreme case | -| arises, they must be documented with this warning. | -| | -| Those structures and constants that are subject to the | -| above will be marked and bracketed with the flag: | -| | -| C A V E A T P R O G R A M M E R | -| | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - - - - - - - - - - - - - - - - - - Section 1 - - Extensions to existing call structure - - - Name: * Alloc - allocate memory - - Assembler usage: - MOV BX,size - MOV AH,Alloc - INT 21h - ; AX:0 is pointer to allocated memory - ; if alloc fails, BX is the largest block available - - Description: - Alloc returns a pointer to a free block of memory - that has the requested size in paragraphs. - - Error return: - AX = error_not_enough_memory - The largest available free block is smaller - than that requested or there is no free block. - = error_arena_trashed - The internal consistency of the memory arena - has been destroyed. This is due to a user - program changing memory that does not belong - to it. - - - Name: * CharOper - change incompatible configuration - parameters - - Assembler usage: - MOV AH, CharOper - MOV AL, func - MOV DL, data - INT 21h - ; on read functions, data is returned in DL - - Description: - CharOper allows a program to change system - parameters to allow for switch indicators and whether - devices are available at every level of the directory - tree. - - A function code is passed in AL: - - AL Function - -- -------- - 0 DL, on return, will contain the DOS switch - character. On most systems this will default to - '-'. - 1 Set the switch character to the character in DL. - 2 Read the device availability byte into DL. If - this byte is 0, then devices must be accessed in - file I/O calls by /dev/device. If this byte is - non-zero, then the devices are available at every - node of the directory tree (i.e. CON is the - console device not the file CON). This byte is - generally 0. - 3 Set the device availability byte to the value in - DL. - - Error returns: - AL = FF - The function code specified in AL is not in - the range 0:3 - - - Name: * CurrentDir - return text of current directory - - Assembler usage: - MOV AH,CurrentDir - LDS SI,area - MOV DL,drive - INT 21h - ; DS:SI is a pointer to 64 byte area that contains - ; drive current directory. - - Description: - CurrentDir returns the current directory for a - particular drive. The directory is root-relative and - does not contain the drive specifier. The drive code - passed in DL is 0=default, 1=A, 2=B, etc. - - Error returns: - AX = error_invalid_drive - The drive specified in DL was invalid. - - - Name: * Dealloc - free allocated memory - - Assembler usage: - MOV ES,block - MOV AH,dealloc - INT 21h - - Description: - Dealloc returns a piece of memory to the system - pool that was allocated by alloc. - - Error return: - AX = error_invalid_block - The block passed in ES is not one allocated - via Alloc. - = error_arena_trashed - The internal consistency of the memory arena - has been destroyed. This is due to a user - program changing memory that does not belong - to it. - - - Name: * FileTimes - get/set the write times of a - handle - - Assembler usage: - MOV AH, FileTimes - MOV AL, func - MOV BX, handle - ; if AL = 1 then then next two are mandatory - MOV CX, time - MOV DX, date - INT 21h - ; if AL = 0 then CX/DX has the last write time/date - ; for the handle. - - Description: - FileTimes returns or sets the last-write time for - a handle. These times are not recorded until the file - is closed. - - A function code is passed in AL: - - AL Function - -- -------- - 0 Return the time/date of the handle in CX/DX - 1 Set the time/date of the handle to CX/DX - - Error returns: - AX = error_invalid_function - The function passed in AL was not in the range - 0:1. - = error_invalid_handle - The handle passed in BX was not currently - open. - - - Name: * FindFirst - find matching file - - Assembler usage: - MOV AH, FindFirst - LDS DX, pathname - MOV CX, attr - INT 21h - ; DMA address has datablock - - Description: - FindFirst takes a pathname with wildcards in the - last component (passed in DS:DX), a set of attributes - (passed in CX) and attempts to find all files that - match the pathname and have a subset of the required - attributes. A datablock at the current DMA is written - that contains information in the following form: - - find_buf STRUC -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | - find_buf_sattr DB ? ; attribute of search - find_buf_drive DB ? ; drive of search - find_buf_name DB 11 DUP (?); search name - find_buf_LastEnt DW ? ; LastEnt - find_buf_ThisDPB DD ? ; This DPB - find_buf_DirStart DW ? ; DirStart -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - find_buf_attr DB ? ; attribute found - find_buf_time DW ? ; time - find_buf_date DW ? ; date - find_buf_size_l DW ? ; low(size) - find_buf_size_h DW ? ; high(size) - find_buf_pname DB 13 DUP (?) ; packed name - find_buf ENDS - - To obtain the subsequent matches of the pathname, - see the description of FindNext - - Error Returns: - AX = error_file_not_found - The path specified in DS:DX was an invalid - path. - = error_no_more_files - There were no files matching this - specification. - - - Name: * FindNext - step through a directory matching - files - - Assembler usage: - ; DMA points at area returned by find_first - MOV AH, findnext - INT 21h - ; next entry is at dma - - Description: - FindNext finds the next matching entry in a - directory. The current DMA address must point at a - block returned by FindFirst (see FindFirst). - - Error Returns: - AX = error_no_more_files - There are no more files matching this pattern. - - - Name: * GetDMA - get current DMA transfer address - - Assembler usage: - MOV AH,GetDMA - INT 21h - ; ES:BX has current DMA transfer address - - Description: - Return DMA transfer address. - - Error returns: - None. - -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | - - Name: * GetDSKPT(DL) - get pointer to drive parameter - block - - Assembler usage: - MOV AH,GetDSKPT - INT 21h - ; DS:BX has address of drive parameter block - - Description: - Return pointer to default drive parameter block. - - Error returns: - None. - - Assembler usage: - MOV DL,DrvNUM - MOV AH,GetDSKPTDL - INT 21h - ; DS:BX has address of drive parameter block - - Description: - Return pointer to drive parameter block for drive - designated in DL (0=Default, A=1, B=2 ...) - - Error returns: - AL = FF - The drive given in DL is invalid. -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - - Name: * GetFreespace - get Disk free space - - Assembler usage: - MOV AH,GetFreespace - MOV DL,Drive ;0 = default, A = 1 - INT 21h - ; BX = Number of free allocation units on drive - ; DX = Total number of allocation units on drive - ; CX = Bytes per sector - ; AX = Sectors per allocation unit - - Description: - Return Free space on disk along with additional - information about the disk. - - Error returns: - AX = FFFF - The drive number given in DL was invalid. - - NOTE: This call returns the same information in the same - registers (except for the FAT pointer) as the get FAT - pointer calls did in previous versions of the DOS. - - - Name: * GetInDOSF - get DOS critical-section flag - - Assembler usage: - MOV AH,GetInDOSF - INT 21h - ; ES:BX has location of the flag - MOV CritSEG, ES - MOV CritOFF, BX - ... - IntVec: - MOV AX, DWORD PTR Crit - CMP AX,0 - JZ DoFunc - IRET - DoFunc: ... - - Description: - Return location of indos flag. On return ES:BX is - the address of a byte memory cell inside the DOS. If - used in an interrupt service routine, it indicates - whether or not the DOS was interrupted in a critical - section. If the cell was zero, then the DOS was not - in a critical section and thus can be called by the - interrupt routine. If the cell was non-zero, the DOS - should be considered to be in an uninterruptable state - and for reliability, no DOS calls should be given. - - Error returns: - None. - - - Name: * GetVector - get interrupt vector - - Assembler usage: - MOV AH,GetVector - MOV AL,interrupt - INT 21h - ; ES:BX now has long pointer to interrupt routine - - Description: - Return interrupt vector associated with an - interrupt. - - Error returns: - None. - - - Name: * GetVerifyFlag - return current setting of the - verify after write flag. - - Assembler usage: - MOV AH,GetVerifyFlag - INT 21h - ; AL is the current verify flag value - - Description: - The current value of the verify flag is returned - in AL. - - Error returns: - None. - - - Name: * GetVersion - get DOS version number - - Assembler usage: - MOV AH,GetVersion - INT 21h - ; AL is the major version number - ; AH is the minor version number - ; BH is the OEM number - ; BL:CX is the (24 bit) user number - - Description: - Return MS-DOS version number. On return AL.AH - will be the two part version designation, ie. for - MS-DOS 1.28 AL would be 1 and AH would be 28. For pre - 1.28 DOS AL = 0. Note that version 1.1 is the same as - 1.10, not the same as 1.01. - - Error returns: - None. - - - Name: * International - return country dependent - information - - Assembler usage: - LDS DX, blk - MOV AH, International - MOV AL, func - INT 21h - - Description: - This call returns in the block of memory pointed - to by DS:DX, the following information pertinent to - international applications: - - +---------------------------+ - | WORD Date/time format | - +---------------------------+ - | BYTE ASCIZ string | - | currency symbol | - +---------------------------+ - | BYTE ASCIZ string | - | thousands separator | - +---------------------------+ - | BYTE ASCIZ string decimal | - | separator | - +---------------------------+ - - The date/time format has the following values and - meanings: - - 0 - USA standard h:m:s m/d/y - 1 - Europe standard h:m:s d/m/y - 2 - Japan standard y/m/d h:m:s - - The value passed in AL is either 0 (for current - country) or a country code (to be defined later. - Currently the country code must be zero). - - Error returns: - AX = error_invalid_function - The function passed in AL was not 0 - (currently). - - - Name: * KeepProcess - terminate process and remain - resident - - Assembler usage: - MOV AL, exitcode - MOV DX, parasize - MOV AH, KeepProcess - INT 21h - - Description: - This call terminates the current process and - attempts to set the initial allocation block to a - specific size in paragraphs. It will not free up any - other allocation blocks belonging to that process. - The exit code passed in AX is retrievable by the - parent via Wait. - - Error Returns: - None. - - - Name: * Rename - move a directory entry - - Assembler usage: - LDS DX, source - LES DI, dest - MOV AH, Rename - INT 21h - - Description: - Rename will attempt to rename a file into another - path. The paths must be on the same device. - - Error returns: - AX = error_file_not_found - The file name specifed by DS:DX was not found. - = error_not_same_device - The source and destination are on different - drives. - = error_access_denied - The path specified in DS:DX was a directory or - the file specified by ES:DI exists or the - destination directory entry could not be - created. - - - Name: * SetBlock - modify allocated blocks - - Assembler usage: - MOV ES,block - MOV BX,newsize - MOV AH,setblock - INT 21h - ; if setblock fails for growing, BX will have the - ; maximum size possible - - Description: - Setblock will attempt to grow/shrink an allocated - block of memory. - - Error return: - AX = error_invalid_block - The block passed in ES is not one allocated - via Alloc. - = error_arena_trashed - The internal consistency of the memory arena - has been destroyed. This is due to a user - program changing memory that does not belong - to it. - = error_not_enough_memory - There was not enough free memory after the - specified block to satisfy the grow request. - - - Name: * SetCtrlCTrapping - turn on/off broad ^C - checking - - Assembler usage: - MOV DL,val - MOV AH,SetCtrlCTrapping - MOV AL,func - INT 21h - ; If AL was 0, then DL has the current value of the - ; ^C check - - Description: - MSDOS ordinarily checks for a ^C on the - controlling device only when doing a function 1-12 - operation to that device. SetCtrlCTrapping allows the - user to expand this checking to include any system - call. For example, with the ^C trapping off, all disk - I/O will proceed without interruption while with ^C - trapping on, the ^C interrupt is given at the system - call that initiates the disk operation. - - Error return: - AL = FF - The function passed in AL was not in the range - 0:1. - -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | - - Name: * Set_OEM_Handler - set handler for OEM - specific INT 21H calls. - - Assembler usage: - LDS DX,handler_address - MOV AH,Set_OEM_Handler - INT 21H - - Description: - Set handler address for 0F9H-0FFH INT 21H system - calls to DS:DX. To return the 0F9H-0FFH calls to - the uninitialized state, give DS=DX=-1. - - Error returns: - None. - - Handler entry: - All registers as user set them when INT 21H - issued (including SS:SP). INT 21 return is on - stack, so the correct method for the OEM handler - to return to the user is to give an IRET. The - OEM handler is free to make any INT 21H system - call (including the 0F9H- 0FFH group if the OEM - handler is re-entrant). - - - The AH INT 21H function codes 0F8H through 0FFH are - reserved for OEM extensions to the INT 21H calling - convention. These calls have two states, initialized - and uninitialized. There will be one handler for all 7 - (0F9-0FFH) functions. When the DOS is first - initialized, these calls are uninitialized. The AH=0F8H - call is the call which will set the handler address for - the 0F9-0FFH calls. If the 0F9-0FFH calls are - uninitialized, an attempt to call them results in the - normal invalid system call number return. - OEMs should NOT document the 0F8 call. -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - - - - - - - - - - - - - - - - - - Section 2 - - XENIX-compatible system calls - - - - Previous to version 2.0, MSDOS had a simple single - directory structure that sufficed for small (160k to 320K) - diskettes. As the need for hard disk support grows, and - as MSDOS 2.0 will support a wide variety of hard disks, - the need for better disk organization also grows. Merely - expanding the directory is not an effective solution; - doing a 'DIR' on a directory with 1000 files is not a - user-friendly characteristic. - - People, by nature, think in hierarchical terms: - organization charts and family trees, for example. It - would be nice to allow users to organize their files on - disk in a similar manner. Consider the following: - - In a particular business, both sales and accounting - share a computer with a large disk and the individual - employees use it for preparation of reports and - maintaining accounting information. One would naturally - view the organization of files on the disk in this - fashion: - - +-disk-+ - / \ - / \ - / \ - sales accounting - / | | \ - / | | \ - / | | \ - John Mary Steve Sue - / | (A) | | | \ - / | | | | \ - / | | | | \ - report accts. report accts. report report - receiv. receiv - - In MSDOS 2.0 the user can arrange his files in such a - manner that files that are not part of his current task do - not interfere with that task. Pre-2.0 versions of MSDOS - has a single directory that contains files. MSDOS extends - this concept to allow a directory to contain both files - and directories and to introduce the notion of the - 'current' directory. - - To specify a filename, the user could use one of two - methods, either specify a path from the root node to the - file, or specify a path from the current node to the file. - A path is a series of directory names separated by '/' and - ending with a filename. A path that starts at the root - begins with a '/'. - - There is a special directory entry in each directory, - denoted by '..' that is the parent of the directory. The - root directory's parent is itself (who created God?). - - Using a directory structure like the hierarchy above, - and assuming that the current directory is at point (D), - to reference the report under John, the following are all - equivalent: - - report - /sales/John/report - ../John/report - - To refer to the report under Mary, the following are - all equivalent: - - ../Mary/report - /sales/Mary/report - - To refer to the report under Sue, the following are - all equivalent. - - ../../accounting/Sue/report - /accounting/Sue/report - - There is no restriction in MSDOS 2.0 on the depth of a - tree (the length of the longest path from root to leaf) - except in the number of allocation units available. The - root directory will have a fixed number of entries, 64 for - the single sided diskettes to XXX for a large hard disk. - For non-root directories, there is no limit to the number - of files per directory excepting in the number of - allocation units available. - - Old (pre-2.0) disks will appear to MSDOS 2.0 as having - only a root directory with files in it and no - subdirectories whatever. - - Implementation of the tree-structure is simple. The - root directory is the pre-2.0 directory. Subdirectories - of the root have a special attribute set indicating that - they are directories. The subdirectories themselves are - files, linked through the FAT as usual. Their contents - are identical in character to the contents of the root - directory. - - Pre-2.0 programs that use system calls not described - below will not be able to make use of files in other - directories. They will only be able to access files in - the current directory. This is no great loss of - functionality as users will aggregate their files into - sub-directories on basis of functionality; the files that - are being used will be found in the current directory. - Those that are not necessary for the current task will be - placed in other directories. Out of sight, out of mind. - - There are also new attributes in 2.0. These and the - old attributes apply to the tree structured directories in - the following manner: - - Attribute Meaning/Function Meaning/Function - for files for directories - - volume_id Present at the root. Meaningless. - Only one file may have - this set. - - directory Meaningless. Indicates that the - directory entry is a - directory. Cannot be - changed with ChMod. - - read_only Old fcb-create, new Meaningless. - Creat, new open (for - write or read/write) - will fail. - - archive Set when file is Meaningless. - written. Set/reset via - ChMod. - - hidden/ Prevents file from Prevents directory - system being found in search entry from being - first/search next. found. ChDir to - New open will fail. directory will still - work. - - - Name: * ChDir - Change the current directory - - Assembler usage: - LDS DX, name - MOV AH, ChDir - INT 21h - - Description: - ChDir is given the ASCIZ name of the directory - which is to become the current directory. If any - member of the specified pathname does not exist, then - the current directory is unchanged. Otherwise, the - current directory is set to the string. - - Error returns: - AX = error_path_not_found - The path specified in DS:DX either indicated a - file or the path was invalid. - - - Name: * ChMod - change write protection - - Assembler usage: - LDS DX, name - MOV CX, attribute - MOV AL, func - MOV AH, ChMod - INT 21h - - Description: - Given an ASCIZ name, ChMod will set/get the - attributes of the file to those given in CX. - - A function code is passed in AL: - - AL Function - -- -------- - 0 Return the attributes of the file in CX - 1 Set the attributes of the file to those in CX - - Error returns: - AX = error_path_not_found - The path specified was invalid. - = error_access_denied - The attributes specified in CX contained one - that could not be changed (directory, volume - ID). - = error_invalid_function - The function passed in AL was not in the range - 0:1. - - - Name: * Close - close a file handle - - Assembler usage: - MOV BX, handle - MOV AH, Close - INT 21h - - Description: - In BX is passed a file handle (like that returned - by Open, Creat or Dup); the Close call will close the - associated file. Internal buffers are flushed. - - Error return: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - - - Name: * Creat - create a file - - Assembler usage: - LDS DX, name - MOV AH, Creat - MOV CX, attribute - INT 21h - ; AX now has the handle - - Description: - Creat creates a new file or truncates an old file - to zero length in preparation for writing. If the - file did not exist, then the file is created in the - appropriate directory and the file is given the - read/write protection code of access. - - CX contains the default attributes to be set for - the file. Currently, the read-only bit must be off. - - Error returns: - AX = error_access_denied - The attributes specified in CX contained one - that could not be created (directory, volume - ID), a file already existed with a more - inclusive set of attributes, or a directory - existed with the same name. - = error_path_not_found - The path specified was invalid. - = error_too_many_open_files - The file was created with the specified - attributes, but there were no free handles - available for the process or that the internal - system tables were full. - - - Name: * Dup - duplicate a file handle - - Assembler usage: - MOV BX, fh - MOV AH, Dup - INT 21h - ; AX has the returned handle - - Description: - Dup takes an already opened file handle and - returns a new handle that refers to the same file at - the same position. - - Error returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - = error_too_many_open_files - There were no free handles available in the - current process or the internal system tables - were full. - - - Name: * Dup2 - force a duplicate of a handle - - Assembler usage: - MOV BX, fh - MOV CX, newfh - MOV AH, Dup2 - INT 21h - - Description: - Dup2 will cause newfh to refer to the same stream - as fh. If there was an open file on newfh, then it is - closed first. - - Error returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - - - Name: * Exec - load / execute a program - - Assembler usage: - LDS DX, name - LES BX, blk - MOV AH, Exec - MOV AL, func - INT 21h - - Description: - This call allows a program to load another program - into memory and (default) begin execution of it. - DS:DX points to the ASCIZ name of the file to be - loaded. ES:BX points to a parameter block for the - load. - - A function code is passed in AL: - - AL Function - -- -------- - 0 Load and execute the program. A program header is - established for the program and the terminate and - ^C addresses are set to the instruction after the - EXEC system call. - - NOTE: When control is returned, via a ^C or - terminate, from the program being EXECed ALL - registers are altered including the stack. - This is because control is returned from the - EXECed program, not the system. To regain - your stack, store an SS:SP value in a data - location reachable from your CS. - -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | - 1 Load, create the program header but do not begin - execution. The CS:IP/SS:SP of the program are - returned in the area provided by the user. -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - 3 Load, do not create the program header, and do not - begin execution. This is useful in loading - program overlays. - - For each value of AL, the block has the following - format: - - AL = 0 -> load/execute program - - +---------------------------+ - | WORD segment address of | - | environment. | - +---------------------------+ - | DWORD pointer to command | - | line at 80h | - +---------------------------+ - | DWORD pointer to default | - | FCB to be passed at 5Ch | - +---------------------------+ - | DWORD pointer to default | - | FCB to be passed at 6Ch | - +---------------------------+ - -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | - AL = 1 -> load program - - +---------------------------+ - | WORD segment address of | - | environment. | - +---------------------------+ - | DWORD pointer to command | - | line at 80h | - +---------------------------+ - | DWORD pointer to default | - | FCB to be passed at 5Ch | - +---------------------------+ - | DWORD pointer to default | - | FCB to be passed at 6Ch | - +---------------------------+ - | DWORD returned value of | - | SS:SP | - +---------------------------+ - | DWORD returned value of | - | CS:IP | - +---------------------------+ -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - - AL = 3 -> load overlay - - +---------------------------+ - | WORD segment address where| - | file will be loaded. | - +---------------------------+ - | WORD relocation factor to | - | be applied to the image. | - +---------------------------+ - - Note that all open files of a process are - duplicated in the child process after an Exec. This - is extremely powerful; the parent process has control - over the meanings of stdin, stdout, stderr, stdaux and - stdprn. The parent could, for example, write a series - of records to a file, open the file as standard input, - open a listing file as standard output and then Exec a - sort program that takes its input from stdin and - writes to stdout. - - Also inherited (or passed from the parent) is an - 'environment'. This is a block of text strings (less - than 32K bytes total) that convey various - configurations parameters. The format of the - environment is as follows: - - (paragraph boundary) - +---------------------------+ - | BYTE asciz string 1 | - +---------------------------+ - | BYTE asciz string 2 | - +---------------------------+ - | ... | - +---------------------------+ - | BYTE asciz string n | - +---------------------------+ - | BYTE of zero | - +---------------------------+ - - Typically the environment strings have the form: - - parameter=value - - for example, COMMAND.COM always passes its execution - search path as: - - PATH=A:/BIN;B:/BASIC/LIB - - A zero value of the environment address will cause the - child process to inherit the parent's environment - unchanged. - - Note that on a successful return from EXEC, all - registers, except for CS:IP, are changed. - - Error return: - AX = error_invalid_function - The function passed in AL was not 0, 1 or 3. - = error_bad_environment - The environment was larger than 32Kb. - = error_bad_format - The file pointed to by DS:DX was an EXE format - file and contained information that was - internally inconsistent. - = error_not_enough_memory - There was not enough memory for the process to - be created. - = error_file_not_found - The path specified was invalid or not found. - - - Name: * Exit - terminate a process - - Assembler usage: - MOV AL, code - MOV AH, Exit - INT 21h - - Description: - Exit will terminate the current process, - transferring control to the invoking process. In - addition, a return code may be sent. All files open - at the time are closed. - - Error returns: - None. - - - Name: * Ioctl - I/O control for devices - - Assembler usage: - MOV BX, Handle - - (or MOV BL, drive for calls AL=4,5 - 0=default,A=1...) - - MOV DX, Data - - (or LDS DX, buf and - MOV CX, count for calls AL=2,3,4,5) - - MOV AH, Ioctl - MOV AL, func - INT 21h - ; For calls AL=2,3,4,5 AX is the number of bytes - ; transferred (same as READ and WRITE). - ; For calls AL=6,7 AL is status returned, AL=0 if - ; status is not ready, AL=0FFH otherwise. - - Description: - Set or Get device information associated with open - Handle, or send/receive control string to device - Handle or device. - - The following values are allowed for func: - - Request Function - ------ -------- - 0 Get device information (returned in DX) - 1 Set device information (as determined by DX) - 2 Read CX number of bytes into DS:DX from device - control channel. - 3 Write CX number of bytes from DS:DX to device - control channel. - 4 Same as 2 only drive number in BL - 0=default,A=1,B=2,... - 5 Same as 3 only drive number in BL - 0=default,A=1,B=2,... - 6 Get input status - 7 Get output status - - Ioctl can be used to get information about device - channels. It is ok to make Ioctl calls on regular - files but only calls 0,6 and 7 are defined in that - case (AL=0,6,7), all other calls return an - error_invalid_function error. - - CALLS AL=0 and AL=1 - - The bits of DX are defined as follows for calls - AL=0 and AL=1. Note that the upper byte MUST be zero - on a set call. - - | - 15 14 13 12 11 10 9 8|7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+-+-+-+-+-+-+-+-+-+-+ - | R| C| |I|E|R|S|I|I|I|I| - | e| T| |S|O|A|P|S|S|S|S| - | s| R| Reserved |D|F|W|E|C|N|C|C| - | | L| |E| | |C|L|U|O|I| - | | | |V| | |L|K|L|T|N| - +--+--+--+--+--+--+-+-+-+-+-+-+-+-+-+-+ - | - - ISDEV = 1 if this channel is a device - = 0 if this channel is a disk file (Bits 8-15 = - 0 in this case) - - If ISDEV = 1 - - EOF = 0 if End Of File on input - RAW = 1 if this device is in Raw mode - = 0 if this device is cooked - ISCLK = 1 if this device is the clock device - ISNUL = 1 if this device is the null device - ISCOT = 1 if this device is the console output - ISCIN = 1 if this device is the console input - SPECL = 1 if this device is special - - CTRL = 0 if this device can NOT do control strings - via calls AL=2 and AL=3. - CTRL = 1 if this device can process control - strings via calls AL=2 and AL=3. - NOTE that this bit cannot be set. - - If ISDEV = 0 - EOF = 0 if channel has been written - Bits 0-5 are the block device number for the - channel (0 = A, 1 = B, ...) - - Bits 15,8-13,4 are reserved and should not be altered. - - Calls 2..5: - These four calls allow arbitrary control strings to be - sent or received from a device. The Call syntax is - the same as the READ and WRITE calls, except for 4 and - 5 which take a drive number in BL instead of a handle - in BX. - - An error_invalid_function error is returned if the - CTRL bit (see above) is 0. - - An error_access_denied is returned by calls AL=4,5 if - the drive number is invalid. - - Calls 6,7: - These two calls allow the user to check if a file - handle is ready for input or output. Status of - handles open to a device is the intended use of these - calls, but status of a handle open to a disk file is - OK and is defined as follows: - - Input: - Always ready (AL=FF) until EOF reached, then - always not ready (AL=0) unless current - position changed via LSEEK. - Output: - Always ready (even if disk full). - - IMPORTANT NOTE: - The status is defined at the time the system is - CALLED. On future versions, by the time control is - returned to the user from the system, the status - returned may NOT correctly reflect the true current - state of the device or file. - - Error returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - = error_invalid_function - The function passed in AL was not in the range - 0:7. - = error_invalid_data - = error_access_denied (calls AL=4..7) - - - Name: * LSeek - move file read/write pointer - - Assembler usage: - MOV DX, offsetlow - MOV CX, offsethigh - MOV AL, method - MOV BX, handle - MOV AH, LSeek - INT 21h - ; DX:AX has the new location of the pointer - - Description: - LSeek moves the read/write pointer according to - method: - - Method Function - ------ -------- - 0 The pointer is moved to offset bytes from the - beginning of the file. - 1 The pointer is moved to the current location - plus offset. - 2 The pointer is moved to the end of file plus - offset. - - Offset should be regarded as a 32-bit integer with - CX occupying the most significant 16 bits. - - Error returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - = error_invalid_function - The function passed in AL was not in the range - 0:2. - - - Name: * MkDir - Create a directory entry - - Assembler usage: - LDS DX, name - MOV AH, MkDir - INT 21h - - Description: - Given a pointer to an ASCIZ name, create a new - directory entry at the end. - - Error returns: - AX = error_path_not_found - The path specified was invalid or not found. - = error_access_denied - The directory could not be created (no room in - parent directory), the directory/file already - existed or a device name was specified. - - - Name: * Open - access a file - - Assembler usage: - LDS DX, name - MOV AH, Open - MOV AL, access - INT 21h - ; AX has error or file handle - ; If successful open - - Description: - Open associates a 16-bit file handle with a file. - - The following values are allowed for access: - - ACCESS Function - ------ -------- - 0 file is opened for reading - 1 file is opened for writing - 2 file is opened for both reading and writing. - - DS:DX point to an ASCIZ name of the file to be - opened. - - The read/write pointer is set at the first byte of - the file and the record size of the file is 1 byte. - The returned file handle must be used for subsequent - I/O to the file. - - The DOS, on initialization, will have a maximum - number of files. See the configuration file document - for information on changing this default. - - Error returns: - AX = error_invalid_access - The access specified in AL was not in the - range 0:2. - = error_file_not_found - The path specified was invalid or not found. - = error_access_denied - The user attempted to open a directory or - volume-id, or open a read-only file for - writing. - = error_too_many_open_files - There were no free handles available in the - current process or the internal system tables - were full. - - - Name: * Read - Do file/device I/O - - Assembler usage: - LDS DX, buf - MOV CX, count - MOV BX, handle - MOV AH, Read - INT 21h - ; AX has number of bytes read - - Description: - Read transfers count bytes from a file into a - buffer location. It is not guaranteed that all count - bytes will be read; for example, reading from the - keyboard will read at most one line of text. If the - returned value is zero, then the program has tried to - read from the end of file. - - All I/O is done using normalized pointers; no - segment wraparound will occur. - - Error returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - = error_access_denied - The handle passed in BX was opened in a mode - that did not allow reading. - - - Name: * RmDir - Remove a directory entry - - Assembler usage: - LDS DX, name - MOV AH, RmDir - INT 21h - - Description: - RmDir is given an asciz name of a directory. That - directory is removed from its parent - - Error returns: - AX = error_path_not_found - The path specified was invalid or not found. - = error_access_denied - The path specified was not empty, not a - directory, the root directory or contained - invalid information. - = error_current_directory - The path specified was the current directory - on a drive. - - - Name: * Unlink - delete a directory entry - - Assembler usage: - LDS DX, name - MOV AH, Unlink - INT 21h - - Description: - Unlink removes a directory entry associated with a - filename. If the file is currently open on another - handle, then no removal will take place. - - Error returns: - AX = error_file_not_found - The path specified was invalid or not found. - = error_access_denied - The path specified was a directory or - read-only. - - - Name: * Wait - retrieve the return code of a child - - Assembler usage: - MOV AH, Wait - INT 21h - ; AX has the exit code - - Description: - Wait will return the Exit code specified by a - child process. It will return this Exit code only - once. The low byte of this code is that sent by the - Exit routine. The high byte is one of the following: - - 0 - terminate/abort - 1 - ^C - 2 - Hard error - 3 - Terminate and stay resident - - Error returns: - None. - - - Name: * Write - write to a file - - Assembler usage: - LDS DX, buf - MOV CX, count - MOV BX, handle - MOV AH, Write - INT 21h - ; AX has number of bytes written - - Description: - Write transfers count bytes from a buffer into - a file. It should be regarded as an error if the - number of bytes written is not the same as the number - requested. - - It is important to note that the write system - call with a count of zero (CX = 0) will truncate - the file at the current position. - - All I/O is done using normalized pointers; no - segment wraparound will occur. - - Error Returns: - AX = error_invalid_handle - The handle passed in BX was not currently - open. - = error_access_denied - The handle was not opened in a mode that - allowed writing. - - -The following XENIX convention is followed for the new 2.0 -system calls: - - o If no error occurred, then the carry flag will be - reset and register AX will contain the appropriate - information. - - o If an error occurred, then the carry flag will be - set and register AX will contain the error code. - -The following code sample illustrates the recommended method -of detecting these errors: - - ... - MOV errno,0 - INT 21h - JNC continue - MOV errno,AX -continue: - ... - -The word variable errno will now have the correct error code -for that system call. - -The current equates for the error codes are: - -no_error_occurred EQU 0 - -error_invalid_function EQU 1 -error_file_not_found EQU 2 -error_path_not_found EQU 3 -error_too_many_open_files EQU 4 -error_access_denied EQU 5 -error_invalid_handle EQU 6 -error_arena_trashed EQU 7 -error_not_enough_memory EQU 8 -error_invalid_block EQU 9 -error_bad_environment EQU 10 -error_bad_format EQU 11 -error_invalid_access EQU 12 -error_invalid_data EQU 13 -error_invalid_drive EQU 15 -error_current_directory EQU 16 -error_not_same_device EQU 17 -error_no_more_files EQU 18 - - -System call assignments: - -ABORT EQU 0 ; 0 0 -STD_CON_INPUT EQU 1 ; 1 1 -STD_CON_OUTPUT EQU 2 ; 2 2 -STD_AUX_INPUT EQU 3 ; 3 3 -STD_AUX_OUTPUT EQU 4 ; 4 4 -STD_PRINTER_OUTPUT EQU 5 ; 5 5 -RAW_CON_IO EQU 6 ; 6 6 -RAW_CON_INPUT EQU 7 ; 7 7 -STD_CON_INPUT_NO_ECHO EQU 8 ; 8 8 -STD_CON_STRING_OUTPUT EQU 9 ; 9 9 -STD_CON_STRING_INPUT EQU 10 ; 10 A -STD_CON_INPUT_STATUS EQU 11 ; 11 B -STD_CON_INPUT_FLUSH EQU 12 ; 12 C -DISK_RESET EQU 13 ; 13 D -SET_DEFAULT_DRIVE EQU 14 ; 14 E -FCB_OPEN EQU 15 ; 15 F -FCB_CLOSE EQU 16 ; 16 10 -DIR_SEARCH_FIRST EQU 17 ; 17 11 -DIR_SEARCH_NEXT EQU 18 ; 18 12 -FCB_DELETE EQU 19 ; 19 13 -FCB_SEQ_READ EQU 20 ; 20 14 -FCB_SEQ_WRITE EQU 21 ; 21 15 -FCB_CREATE EQU 22 ; 22 16 -FCB_RENAME EQU 23 ; 23 17 -GET_DEFAULT_DRIVE EQU 25 ; 25 19 -SET_DMA EQU 26 ; 26 1A -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | -GET_DEFAULT_DPB EQU 31 ; 31 1F -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -FCB_RANDOM_READ EQU 33 ; 33 21 -FCB_RANDOM_WRITE EQU 34 ; 34 22 -GET_FCB_FILE_LENGTH EQU 35 ; 35 23 -GET_FCB_POSITION EQU 36 ; 36 24 -SET_INTERRUPT_VECTOR EQU 37 ; 37 25 -CREATE_PROCESS_DATA_BLOCK EQU 38 ; 38 26 -FCB_RANDOM_READ_BLOCK EQU 39 ; 39 27 -FCB_RANDOM_WRITE_BLOCK EQU 40 ; 40 28 -PARSE_FILE_DESCRIPTOR EQU 41 ; 41 29 -GET_DATE EQU 42 ; 42 2A -SET_DATE EQU 43 ; 43 2B -GET_TIME EQU 44 ; 44 2C -SET_TIME EQU 45 ; 45 2D -SET_VERIFY_ON_WRITE EQU 46 ; 46 2E -; Extended functionality group -GET_DMA EQU 47 ; 47 2F -GET_VERSION EQU 48 ; 48 30 -KEEP_PROCESS EQU 49 ; 49 31 -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | -GET_DPB EQU 50 ; 50 32 -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -SET_CTRL_C_TRAPPING EQU 51 ; 51 33 -GET_INDOS_FLAG EQU 52 ; 52 34 -GET_INTERRUPT_VECTOR EQU 53 ; 53 35 -GET_DRIVE_FREESPACE EQU 54 ; 54 36 -CHAR_OPER EQU 55 ; 55 37 -INTERNATIONAL EQU 56 ; 56 38 -; XENIX CALLS -; Directory Group -MKDIR EQU 57 ; 57 39 -RMDIR EQU 58 ; 58 3A -CHDIR EQU 59 ; 59 3B -; File Group -CREAT EQU 60 ; 60 3C -OPEN EQU 61 ; 61 3D -CLOSE EQU 62 ; 62 3E -READ EQU 63 ; 63 3F -WRITE EQU 64 ; 64 40 -UNLINK EQU 65 ; 65 41 -LSEEK EQU 66 ; 66 42 -CHMOD EQU 67 ; 67 43 -IOCTL EQU 68 ; 68 44 -XDUP EQU 69 ; 69 45 -XDUP2 EQU 70 ; 70 46 -CURRENT_DIR EQU 71 ; 71 47 -; Memory Group -ALLOC EQU 72 ; 72 48 -DEALLOC EQU 73 ; 73 49 -SETBLOCK EQU 74 ; 74 4A -; Process Group -EXEC EQU 75 ; 75 4B -EXIT EQU 76 ; 76 4C -WAIT EQU 77 ; 77 4D -FIND_FIRST EQU 78 ; 78 4E -; Special Group -FIND_NEXT EQU 79 ; 79 4F -; SPECIAL SYSTEM GROUP -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | -SET_CURRENT_PDB EQU 80 ; 80 50 -GET_CURRENT_PDB EQU 81 ; 81 51 -GET_IN_VARS EQU 82 ; 82 52 -SETDPB EQU 83 ; 83 53 -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -GET_VERIFY_ON_WRITE EQU 84 ; 84 54 -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -| C A V E A T P R O G R A M M E R | -| | -DUP_PDB EQU 85 ; 85 55 -| | -| C A V E A T P R O G R A M M E R | -+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -RENAME EQU 86 ; 86 56 -FILE_TIMES EQU 87 ; 87 57 - \ No newline at end of file diff --git a/v2.0/bin/SYSIMES.OBJ b/v2.0/bin/SYSIMES.OBJ deleted file mode 100644 index 3172652..0000000 Binary files a/v2.0/bin/SYSIMES.OBJ and /dev/null differ diff --git a/v2.0/bin/SYSINIT.DOC b/v2.0/bin/SYSINIT.DOC deleted file mode 100644 index fa20d08..0000000 Binary files a/v2.0/bin/SYSINIT.DOC and /dev/null differ diff --git a/v2.0/bin/SYSINIT.OBJ b/v2.0/bin/SYSINIT.OBJ deleted file mode 100644 index 3dc2c13..0000000 Binary files a/v2.0/bin/SYSINIT.OBJ and /dev/null differ diff --git a/v2.0/bin/UTILITY.DOC b/v2.0/bin/UTILITY.DOC deleted file mode 100644 index a63793c..0000000 --- a/v2.0/bin/UTILITY.DOC +++ /dev/null @@ -1,813 +0,0 @@ - - - - - - - - - - - - - - - - - - - MS-DOS 2.0 - - Utility Extensions - - - - - - - - - The following notation is used below: - - [item] item is optional. - item* item is repeated 0 or more times. - item+ item is repeated 1 or more times. - {item1 | item2} - item1 is present or item 2 is present but - not both. - indicates a syntactic variable. - - -COMMAND invokation - -COMMAND [[:]] [] [-D] [-P] [-C ] - - -P If present COMMAND will be permanent, otherwise - this is a transient command. - - -D If present COMMAND will not prompt for DATE and - TIME when it comes up. - - d: Specifies device where command will look for - COMMAND.COM current default drive if absent. - - Specifies a directory on device d: root - directory if absent. - - Name of the CTTY device. /DEV/CON if absent - and command is permanent. The /DEV/ may be left - off if AVAILDEV is TRUE (see sysinit doc). - - -C If present -C must be the last switch. - This causes COMMAND to try to execute the string - as if the user had typed it at the standard input. - COMMAND executes this single command string and - then exits. If the -P switch is present it is - ignored (can't have a single command, permanent - COMMAND). NOTE: ALL of the text on the command - line after the -C is just passed on. It is not - processed for more arguments, this is why -C must - be last. - -COMMAND extensions - -IF - - where is one of the following: - - ERRORLEVEL - true if and only if the previous program EXECed by - COMMAND had an exit code of or higher. - - == - true if and only if and are - identical after parameter substitution. Strings - may not have embedded delimiters. - - EXIST - true if and only if exists. - - NOT - true if and only if is false. - - The IF statement allows conditional execution of commands. - When the is true, then the is - executed otherwise, the is skipped. - - Examples: - - IF not exist /tmp/foo ECHO Can't find file /tmp/foo - - IF $1x == x ECHO Need at least one parameter - - IF NOT ERRORLEVEL 3 LINK $1,,; - - -FOR %% IN DO - - can be any character but 0,1,2,3,..,9 (so there is no - confusion with the %0 - %9 batch parameters). - - is ( * ) - - The %% variable is sequentially set to each member of - and then is evaluated. If a member of - is an expression involving * and/or ?, then the - variable is set to each matching pattern from disk. In - this case only one such may be in the set, any - s after the first are ignored. - - Example: - - FOR %%f IN ( *.ASM ) DO MASM %%f; - - for %%f in (FOO BAR BLECH) do REM %%f to you - - NOTE: The '%%' is needed so that after Batch parameter - (%0 - %9) processing is done, there is one '%' left. - If only '%f' were there, the batch parameter processor - would see the '%' then look at 'f', decide that '%f' - was an error (bad parameter reference) and throw out - the '%f' so that FOR would never see it. If the FOR - is NOT in a batch file, then only ONE '%' should be - used. - - -SHIFT - - Currently, command files are limited to handling 10 - parameters: %0 through %9. To allow access to more than - these, the command SHIFT will perform a 'pop' of the - command line parameters: - - if %0 = "foo" - %1 = "bar" - %2 = "blech" - %3...%9 are empty - - then a SHIFT will result in the following: - - %0 = "bar" - %1 = "blech" - %2...%9 are empty - - If there are more than 10 parameters given on a command - line, then the those that appear after the 10th (%9) will - be shifted one at a time into %9 by successive shifts. - -: