summaryrefslogtreecommitdiff
path: root/v1.25
diff options
context:
space:
mode:
authorGravatar Rich Turner1982-03-03 16:51:26 -0800
committerGravatar Rich Turner2018-09-21 17:51:26 -0700
commitfce0f75959b9806f4016beb7b19e19b37cc97b6c (patch)
tree758374b64f03e049ca9cfb8cae2674ec5b72cd2b /v1.25
parentInitial commit (diff)
downloadms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.tar.gz
ms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.tar.xz
ms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.zip
MS-DOS v1.25 Release
Diffstat (limited to 'v1.25')
-rw-r--r--v1.25/Tim_Paterson_16Dec2013_email.txt23
-rw-r--r--v1.25/bin/ART.BASbin0 -> 1920 bytes
-rw-r--r--v1.25/bin/BALL.BASbin0 -> 2048 bytes
-rw-r--r--v1.25/bin/BASIC.COMbin0 -> 11392 bytes
-rw-r--r--v1.25/bin/BASICA.COMbin0 -> 16768 bytes
-rw-r--r--v1.25/bin/CALENDAR.BASbin0 -> 3840 bytes
-rw-r--r--v1.25/bin/CHKDSK.COMbin0 -> 1720 bytes
-rw-r--r--v1.25/bin/CIRCLE.BASbin0 -> 1664 bytes
-rw-r--r--v1.25/bin/COLORBAR.BASbin0 -> 1536 bytes
-rw-r--r--v1.25/bin/COMM.BASbin0 -> 4352 bytes
-rw-r--r--v1.25/bin/COMMAND.COMbin0 -> 4959 bytes
-rw-r--r--v1.25/bin/COMP.COMbin0 -> 1649 bytes
-rw-r--r--v1.25/bin/DEBUG.COMbin0 -> 5999 bytes
-rw-r--r--v1.25/bin/DISKCOMP.COMbin0 -> 1640 bytes
-rw-r--r--v1.25/bin/DISKCOPY.COMbin0 -> 2008 bytes
-rw-r--r--v1.25/bin/DONKEY.BASbin0 -> 3584 bytes
-rw-r--r--v1.25/bin/EDLIN.COMbin0 -> 2392 bytes
-rw-r--r--v1.25/bin/EXE2BIN.EXEbin0 -> 1280 bytes
-rw-r--r--v1.25/bin/FORMAT.COMbin0 -> 3816 bytes
-rw-r--r--v1.25/bin/LINK.EXEbin0 -> 41856 bytes
-rw-r--r--v1.25/bin/MODE.COMbin0 -> 2509 bytes
-rw-r--r--v1.25/bin/MORTGAGE.BASbin0 -> 6272 bytes
-rw-r--r--v1.25/bin/MUSIC.BASbin0 -> 8704 bytes
-rw-r--r--v1.25/bin/PIECHART.BASbin0 -> 2304 bytes
-rw-r--r--v1.25/bin/SAMPLES.BASbin0 -> 2432 bytes
-rw-r--r--v1.25/bin/SETCLOCK.COMbin0 -> 853 bytes
-rw-r--r--v1.25/bin/SPACE.BASbin0 -> 1920 bytes
-rw-r--r--v1.25/bin/SYS.COMbin0 -> 605 bytes
-rw-r--r--v1.25/source/ASM.ASM4006
-rw-r--r--v1.25/source/COMMAND.ASM2166
-rw-r--r--v1.25/source/HEX2BIN.ASM214
-rw-r--r--v1.25/source/IO.ASM1934
-rw-r--r--v1.25/source/MSDOS.ASM4031
-rw-r--r--v1.25/source/STDDOS.ASM23
-rw-r--r--v1.25/source/TRANS.ASM1213
35 files changed, 13610 insertions, 0 deletions
diff --git a/v1.25/Tim_Paterson_16Dec2013_email.txt b/v1.25/Tim_Paterson_16Dec2013_email.txt
new file mode 100644
index 0000000..45c4055
--- /dev/null
+++ b/v1.25/Tim_Paterson_16Dec2013_email.txt
@@ -0,0 +1,23 @@
1From: Tim Paterson
2To: Len Shustek
3Date: Mon, 16 Dec 2013 10:34:17 -0800
4Subject: RE: Source code to MS-DOS 1.0
5
6
7I 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.
8
9IBM'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.
10
11Of 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:
12
13IO.ASM - I/O system unique to SCP (equivalent to ibmbio.sys).
14ASM.ASM & HEX2BIN.ASM - Old 8086 assembler developed by SCP (used to assemble older version of DOS).
15TRANS.ASM - Z80 to 8086 assembly source code translator developed by SCP.
16
17I also have a 6” stack of printouts of assembly listings for some of these and probably other related programs.
18
19Tim Paterson
20Paterson Technology
21http://www.patersontech.com/
22
23
diff --git a/v1.25/bin/ART.BAS b/v1.25/bin/ART.BAS
new file mode 100644
index 0000000..2de324a
--- /dev/null
+++ b/v1.25/bin/ART.BAS
Binary files differ
diff --git a/v1.25/bin/BALL.BAS b/v1.25/bin/BALL.BAS
new file mode 100644
index 0000000..132087a
--- /dev/null
+++ b/v1.25/bin/BALL.BAS
Binary files differ
diff --git a/v1.25/bin/BASIC.COM b/v1.25/bin/BASIC.COM
new file mode 100644
index 0000000..d6b32cf
--- /dev/null
+++ b/v1.25/bin/BASIC.COM
Binary files differ
diff --git a/v1.25/bin/BASICA.COM b/v1.25/bin/BASICA.COM
new file mode 100644
index 0000000..dc08578
--- /dev/null
+++ b/v1.25/bin/BASICA.COM
Binary files differ
diff --git a/v1.25/bin/CALENDAR.BAS b/v1.25/bin/CALENDAR.BAS
new file mode 100644
index 0000000..34860ec
--- /dev/null
+++ b/v1.25/bin/CALENDAR.BAS
Binary files differ
diff --git a/v1.25/bin/CHKDSK.COM b/v1.25/bin/CHKDSK.COM
new file mode 100644
index 0000000..bf88ed2
--- /dev/null
+++ b/v1.25/bin/CHKDSK.COM
Binary files differ
diff --git a/v1.25/bin/CIRCLE.BAS b/v1.25/bin/CIRCLE.BAS
new file mode 100644
index 0000000..611fc0d
--- /dev/null
+++ b/v1.25/bin/CIRCLE.BAS
Binary files differ
diff --git a/v1.25/bin/COLORBAR.BAS b/v1.25/bin/COLORBAR.BAS
new file mode 100644
index 0000000..067792c
--- /dev/null
+++ b/v1.25/bin/COLORBAR.BAS
Binary files differ
diff --git a/v1.25/bin/COMM.BAS b/v1.25/bin/COMM.BAS
new file mode 100644
index 0000000..ef3439a
--- /dev/null
+++ b/v1.25/bin/COMM.BAS
Binary files differ
diff --git a/v1.25/bin/COMMAND.COM b/v1.25/bin/COMMAND.COM
new file mode 100644
index 0000000..751326f
--- /dev/null
+++ b/v1.25/bin/COMMAND.COM
Binary files differ
diff --git a/v1.25/bin/COMP.COM b/v1.25/bin/COMP.COM
new file mode 100644
index 0000000..0d16119
--- /dev/null
+++ b/v1.25/bin/COMP.COM
Binary files differ
diff --git a/v1.25/bin/DEBUG.COM b/v1.25/bin/DEBUG.COM
new file mode 100644
index 0000000..b502552
--- /dev/null
+++ b/v1.25/bin/DEBUG.COM
Binary files differ
diff --git a/v1.25/bin/DISKCOMP.COM b/v1.25/bin/DISKCOMP.COM
new file mode 100644
index 0000000..08c595b
--- /dev/null
+++ b/v1.25/bin/DISKCOMP.COM
Binary files differ
diff --git a/v1.25/bin/DISKCOPY.COM b/v1.25/bin/DISKCOPY.COM
new file mode 100644
index 0000000..e2436d1
--- /dev/null
+++ b/v1.25/bin/DISKCOPY.COM
Binary files differ
diff --git a/v1.25/bin/DONKEY.BAS b/v1.25/bin/DONKEY.BAS
new file mode 100644
index 0000000..8b6ac8a
--- /dev/null
+++ b/v1.25/bin/DONKEY.BAS
Binary files differ
diff --git a/v1.25/bin/EDLIN.COM b/v1.25/bin/EDLIN.COM
new file mode 100644
index 0000000..5ed5148
--- /dev/null
+++ b/v1.25/bin/EDLIN.COM
Binary files differ
diff --git a/v1.25/bin/EXE2BIN.EXE b/v1.25/bin/EXE2BIN.EXE
new file mode 100644
index 0000000..d43a3f2
--- /dev/null
+++ b/v1.25/bin/EXE2BIN.EXE
Binary files differ
diff --git a/v1.25/bin/FORMAT.COM b/v1.25/bin/FORMAT.COM
new file mode 100644
index 0000000..c1cc45e
--- /dev/null
+++ b/v1.25/bin/FORMAT.COM
Binary files differ
diff --git a/v1.25/bin/LINK.EXE b/v1.25/bin/LINK.EXE
new file mode 100644
index 0000000..499b7b2
--- /dev/null
+++ b/v1.25/bin/LINK.EXE
Binary files differ
diff --git a/v1.25/bin/MODE.COM b/v1.25/bin/MODE.COM
new file mode 100644
index 0000000..b9f69e3
--- /dev/null
+++ b/v1.25/bin/MODE.COM
Binary files differ
diff --git a/v1.25/bin/MORTGAGE.BAS b/v1.25/bin/MORTGAGE.BAS
new file mode 100644
index 0000000..80c062e
--- /dev/null
+++ b/v1.25/bin/MORTGAGE.BAS
Binary files differ
diff --git a/v1.25/bin/MUSIC.BAS b/v1.25/bin/MUSIC.BAS
new file mode 100644
index 0000000..bd0ae0d
--- /dev/null
+++ b/v1.25/bin/MUSIC.BAS
Binary files differ
diff --git a/v1.25/bin/PIECHART.BAS b/v1.25/bin/PIECHART.BAS
new file mode 100644
index 0000000..943b398
--- /dev/null
+++ b/v1.25/bin/PIECHART.BAS
Binary files differ
diff --git a/v1.25/bin/SAMPLES.BAS b/v1.25/bin/SAMPLES.BAS
new file mode 100644
index 0000000..2d2b2aa
--- /dev/null
+++ b/v1.25/bin/SAMPLES.BAS
Binary files differ
diff --git a/v1.25/bin/SETCLOCK.COM b/v1.25/bin/SETCLOCK.COM
new file mode 100644
index 0000000..3bf8501
--- /dev/null
+++ b/v1.25/bin/SETCLOCK.COM
Binary files differ
diff --git a/v1.25/bin/SPACE.BAS b/v1.25/bin/SPACE.BAS
new file mode 100644
index 0000000..52ba147
--- /dev/null
+++ b/v1.25/bin/SPACE.BAS
Binary files differ
diff --git a/v1.25/bin/SYS.COM b/v1.25/bin/SYS.COM
new file mode 100644
index 0000000..7f478fa
--- /dev/null
+++ b/v1.25/bin/SYS.COM
Binary files differ
diff --git a/v1.25/source/ASM.ASM b/v1.25/source/ASM.ASM
new file mode 100644
index 0000000..d870d97
--- /dev/null
+++ b/v1.25/source/ASM.ASM
@@ -0,0 +1,4006 @@
1; Seattle Computer Products 8086 Assembler version 2.44
2; by Tim Paterson
3; Runs on the 8086 under MS-DOS
4
5;* * * * * * REVISION HISTORY * * * * * *
6;
7; 12/29/80 2.01 General release with 86-DOS version 0.34
8; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes
9; 03/18/81 2.11 General cleanup and more documentation
10; 03/24/81 2.20 Modify ESC handling for full 8087 operation
11; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling
12; 04/03/81 2.22 Fix 2.21 buffer handling
13; 04/13/81 2.23 Re-open source file for listing to allow assembling CON:
14; 04/28/81 2.24 Allow nested IFs
15; 07/30/81 2.25 Add Intel string mnemonics; clean up a little
16; 08/02/81 2.30 Re-write pass 2:
17; Always report errors to console
18; Exact byte lengths for HEX and PRN files
19; 11/08/81 2.40 Add 8087 mnemonics; print full error messages;
20; allow expressions with *, /, and ()
21; 07/04/82 2.41 Fix Intel's 8087 "reverse-bit" bug; don't copy date
22; 08/18/82 2.42 Increase stack from 80 to 256 (Damn! Overflowed again!)
23; 01/05/83 2.43 Correct over-zealous optimization in 2.42
24; 05/09/83 2.44 Add memory usage report
25;
26;* * * * * * * * * * * * * * * * * * * * *
27
28SYMWID: EQU 5 ;5 symbols per line in dump
29FCB: EQU 5CH
30BUFSIZ: EQU 1024 ;Source code buffer
31LSTBUFSIZ:EQU BUFSIZ ;List file buffer
32HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA)
33EOL: EQU 13 ;ASCII carriage return
34OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS
35
36;System call function codes
37PRINTMES: EQU 9
38OPEN: EQU 15
39CLOSE: EQU 16
40READ: EQU 20
41SETDMA: EQU 26
42MAKE: EQU 22
43BLKWRT: EQU 40
44
45;The following equates define some token values returned by GETSYM
46UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET)
47CONST: EQU 1 ;Constant (including $)
48REG: EQU 2 ;8-bit register
49XREG: EQU 3 ;16-bit register (except segment registers)
50SREG: EQU 4 ;Segment register
51FREG: EQU 6 ;8087 floating point register
52
53;Bits to build 8087 opcode table entries
54ONEREG: EQU 40H ;Single ST register OK as operand
55NEEDOP: EQU 80H ;Must have an operand
56INTEGER:EQU 20H ;For integer operations
57REAL: EQU 28H ;For real operations
58EXTENDED EQU 10H ;For Long integers or Temporary real
59MEMORY: EQU 18H ;For general memory operations
60STACKOP:EQU 10H ;Two register arithmetic with pop
61ARITH: EQU 8 ;Non-pop arithmetic operations
62
63 ORG 100H
64 PUT 100H
65
66 JMPS BEGIN
67
68HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.44'
69 DB 13,10,'Copyright 1979-1983 by Seattle Computer Products, Inc.'
70 DB 13,10,13,10,'$'
71
72BEGIN:
73 MOV SP,STACK
74 MOV DX,HEADER
75 MOV AH,PRINTMES
76 INT 33
77 MOV AL,[FCB+17]
78 MOV [SYMFLG],AL ;Save symbol table request flag
79 MOV SI,FCB+9 ;Point to file extension
80 LODB ;Get source drive letter
81 CALL CHKDSK ;Valid drive?
82 OR AL,AL
83 JZ DEFAULT ;If no extension, use existing drive spec
84 MOV [FCB],AL
85DEFAULT:
86 LODB ;Get HEX file drive letter
87 CMP AL,'Z' ;Suppress HEX file?
88 JZ L0000
89 CALL CHKDSK
90L0000:
91 MOV [HEXFCB],AL
92 LODB ;Get PRN file drive letter
93 MOV AH,0 ;Signal no PRN file
94 CMP AL,'Z' ;Suppress PRN file?
95 JZ NOPRN
96 CMP AL,'Y' ;Print errors only on console?
97 JZ NOPRN
98 MOV AH,2
99 CMP AL,'X' ;PRN file to console?
100 JZ NOPRN
101 MOV AH,4
102 CMP AL,'P' ;PRN file to printer?
103 JZ NOPRN
104 CALL CHKDSK
105 MOV AH,80H
106NOPRN:
107 MOV [LSTFCB],AL
108 MOV [LSTDEV],AH ;Flag device for list ouput
109 MOV SI,EXTEND
110 MOV DI,FCB+9
111 MOVW
112 MOVB ;Set extension to ASM
113 MOVW ;Zero extent field
114 MOV DX,FCB
115 MOV AH,OPEN
116 INT 33
117 MOV BX,NOFILE
118 OR AL,AL
119 JZ $+5
120 JMP PRERR
121 MOV DX,HEXFCB
122 CALL MAKFIL
123 MOV DX,LSTFCB
124 CALL MAKFIL
125 XOR AX,AX
126 MOV [FCB+12],AX ;Zero CURRENT BLOCK field
127 MOV [FCB+32],AL ;Zero Next Record field
128 MOV [FCB+14],BUFSIZ ;Set record size
129 MOV [BUFPT],SRCBUF ;Initialize buffer pointer
130 MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE
131 MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE
132 XOR AX,AX
133 MOV [PC],AX ;DEFAULT PROGRAM COUNTER
134 MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL
135 MOV [RETPT],AX ;Pointer to last RET record
136 MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF
137 MOV [CHKLAB],AL ;LOOKUP ALL LABELS
138 DEC AX
139 MOV [LSTRET],AX ;Location of last RET
140 MOV AX,[6] ;HL=END OF MEMORY
141 MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE
142 MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE
143
144;Assemble each line of code
145
146LOOP:
147 CALL NEXTCHR ;Get first character on line
148 CMP AL,1AH
149 JZ ENDJ
150 MOV AL,-1 ;Flag that no tokens have been read yet
151 MOV [SYM],AL
152 CALL ASMLIN ;Assemble the line
153 MOV AL,[SYM]
154 CMP AL,-1 ;Any tokens found on line?
155 JNZ L0002
156 CALL GETSYM ;If no tokens read yet, read first one
157L0002:
158 CMP AL,';'
159 JZ ENDLN
160 CMP AL,EOL
161 JZ ENDLN
162 MOV AL,14H ;Garbage at end of line error
163 JP ENDLIN
164ENDJ: JMP END
165
166ENDLN:
167 XOR AL,AL ;Flag no errors on line
168ENDLIN:
169;AL = error code for line. Stack depth unknown
170 MOV SP,STACK
171 CALL NEXLIN
172 JP LOOP
173
174NEXLIN:
175 MOV CH,0C0H ;Put end of line marker and error code (AL)
176 CALL PUTCD
177 CALL GEN1
178 MOV AL,[CHR]
179GETEOL:
180 CMP AL,10
181 JZ RET
182 CMP AL,1AH
183 JZ ENDJ
184 CALL NEXTCHR ;Scan over comments for linefeed
185 JP GETEOL
186
187ABORT:
188 MOV BX,NOMEM
189PRERR:
190 MOV DX,BX
191 MOV AH,PRINTMES
192 INT 33
193 INT 32
194
195MAKFIL:
196 MOV SI,DX
197 LODB ;Get drive select byte
198 CMP AL,20H ;If not valid, don't make file
199 JNC RET
200 MOV CX,4
201 MOV DI,SI
202 MOV SI,FCB+1
203 REP
204 MOVW ;Copy source file name
205 MOV AH,MAKE
206 INT 33
207 MOV [DI-9+14],1 ;Set record length to 1 byte
208 MOV BX,NOSPAC
209 OR AL,AL ;Success?
210 JNZ PRERR
211 RET
212
213CHKDSK:
214 SUB AL,' ' ;If not present, set zero flag
215 JZ RET
216 SUB AL,20H
217 JZ DSKERR ;Must be in range A-O
218 CMP AL,'P'-'@'
219 JC RET
220DSKERR:
221 MOV BX,BADDSK
222 JP PRERR
223
224ERROR:
225 MOV AL,CL
226 JMP ENDLIN
227
228NEXTCHR:
229 MOV SI,[BUFPT]
230 CMP SI,SRCBUF
231 JNZ GETCH
232;Buffer empty so refill it
233 PUSH DX
234 PUSH AX ;AH must be saved
235 MOV DX,SI
236 MOV AH,SETDMA
237 INT 33
238 MOV DX,FCB
239 MOV AH,READ
240 INT 33
241 XCHG AX,DX ;Put error code in DL
242 POP AX ;Restore AH
243 MOV AL,DL ;Error code back in AL
244 POP DX
245 CMP AL,1
246 MOV AL,1AH ;Possibly signal End of File
247 JZ NOMOD ;If nothing read
248GETCH:
249 LODB
250 CMP SI,SRCBUF+BUFSIZ
251 JNZ NOMOD
252 MOV SI,SRCBUF
253NOMOD:
254 MOV [BUFPT],SI
255 MOV [CHR],AL
256 RET
257
258
259MROPS:
260
261; Get two operands and check for certain types, according to flag byte
262; in CL. OP code in CH. Returns only if immediate operation.
263
264 PUSH CX ;Save type flags
265 CALL GETOP
266 PUSH DX ;Save first operand
267 CALL GETOP2
268 POP BX ;First op in BX, second op in DX
269 MOV AL,SREG ;Check for a segment register
270 CMP AL,BH
271 JZ SEGCHK
272 CMP AL,DH
273 JZ SEGCHK
274 MOV AL,CONST ;Check if the first operand is immediate
275 MOV CL,26
276 CMP AL,BH
277 JZ ERROR ;Error if so
278 POP CX ;Restore type flags
279 CMP AL,DH ;If second operand is immediate, then done
280 JZ RET
281 MOV AL,UNDEFID ;Check for memory reference
282 CMP AL,BH
283 JZ STORE ;Is destination memory?
284 CMP AL,DH
285 JZ LOAD ;Is source memory?
286 TEST CL,1 ;Check if register-to-register operation OK
287 MOV CL,27
288 JZ ERROR
289 MOV AL,DH
290 CMP AL,BH ;Registers must be of same length
291RR:
292 MOV CL,22
293 JNZ ERROR
294RR1:
295 AND AL,1 ;Get register length (1=16 bits)
296 OR AL,CH ;Or in to OP code
297 CALL PUT ;And write it
298 POP CX ;Dump return address
299 MOV AL,BL
300 ADD AL,AL ;Rotate register number into middle position
301 ADD AL,AL
302 ADD AL,AL
303 OR AL,0C0H ;Set register-to-register mode
304 OR AL,DL ;Combine with other register number
305 JMP PUT
306
307SEGCHK:
308;Come here if at least one operand is a segment register
309 POP CX ;Restore flags
310 TEST CL,8 ;Check if segment register OK
311 MOV CL,22
312 JZ ERR1
313 MOV CX,8E03H ;Segment register move OP code
314 MOV AL,UNDEFID
315 CMP AL,DH ;Check if source is memory
316 JZ LOAD
317 CMP AL,BH ;Check if destination is memory
318 JZ STORE
319 MOV AL,XREG
320 SUB AL,DH ;Check if source is 16-bit register
321 JZ RR ;If so, AL must be zero
322 MOV CH,8CH ;Change direction
323 XCHG DX,BX ;Flip which operand is first and second
324 MOV AL,XREG
325 SUB AL,DH ;Let RR perform finish the test
326 JP RR
327
328STORE:
329 TEST CL,004H ;Check if storing is OK
330 JNZ STERR
331 XCHG DX,BX ;If so, flip operands
332 AND CH,0FDH ; and zero direction bit
333LOAD:
334 MOV DH,25
335 CMP AL,BH ;Check if memory-to-memory
336 JZ MRERR
337 MOV AL,BH
338 CMP AL,REG ;Check if 8-bit operation
339 JNZ XRG
340 MOV DH,22
341 TEST CL,1 ;See if 8-bit operation is OK
342 JZ MRERR
343XRG:
344 MOV AL,DL
345 SUB AL,6 ;Check for R/M mode 6 and register 0
346 OR AL,BL ; meaning direct load/store of accumulator
347 JNZ NOTAC
348 TEST CL,8 ;See if direct load/store of accumulator
349 JZ NOTAC ; means anything in this case
350; Process direct load/store of accumulator
351 MOV AL,CH
352 AND AL,2 ;Preserve direction bit only
353 XOR AL,2 ; but flip it
354 OR AL,0A0H ;Combine with OP code
355 MOV CH,AL
356 MOV AL,BH ;Check byte/word operation
357 AND AL,1
358 OR AL,CH
359 POP CX ;Dump return address
360 JMP PUTADD ;Write the address
361
362NOTAC:
363 MOV AL,BH
364 AND AL,1 ;Get byte/word bit
365 AND AL,CL ;But don't use it in word-only operations
366 OR AL,CH ;Combine with OP code
367 CALL PUT
368 MOV AL,BL
369 ADD AL,AL ;Rotate to middle position
370 ADD AL,AL
371 ADD AL,AL
372 OR AL,DL ;Combine register field
373 POP CX ;Dump return address
374 JMP PUTADD ;Write the address
375
376STERR:
377 MOV DH,29
378MRERR:
379 MOV CL,DH
380
381ERR1: JMP ERROR
382
383GETOP2:
384;Get the second operand: look for a comma and drop into GETOP
385 MOV AL,[SYM]
386 CMP AL,','
387 MOV CL,21
388 JNZ ERR1
389
390
391GETOP:
392
393; Get one operand. Operand may be a memory reference in brackets, a register,
394; or a constant. If a flag (such as "B" for byte operation) is encountered,
395; it is noted and processing continues to find the operand.
396;
397; On exit, AL (=DH) has the type of operand. Other information depends
398; on the actual operand:
399;
400; AL=DH=0 Memory Reference. DL has the address mode properly prepared in
401; the 8086 R/M format (middle bits zero). The constant part of the address
402; is in ADDR. If an undefined label needs to be added to this, a pointer to
403; its information fields is in ALABEL, otherwise ALABEL is zero.
404;
405; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs
406; to be added to this, a pointer to its information fields is in DLABEL,
407; otherwise DLABEL is zero. "$" and "RET" are in this class.
408;
409; AL=DH=2 8-bit Register. DL has the register number.
410;
411; AL=DH=3 16-bit Register. DL has the register number.
412;
413; AL=DH=4 Segment Register. DL has the register number.
414
415 CALL GETSYM
416GETOP1:
417;Enter here if we don't need a GETSYM first
418 CMP AL,'[' ;Memory reference?
419 JZ MEM
420 CMP AL,5 ;Flag ("B", "W", etc.)?
421 JZ FLG
422 CMP AL,REG ;8-Bit register?
423 JZ NREG
424 CMP AL,XREG ;16-Bit register?
425 JZ NREG
426 CMP AL,SREG ;Segment register?
427 JZ NREG
428VAL: ;Must be immediate
429 XOR AL,AL ;No addressing modes allowed
430VAL1:
431 CALL GETVAL
432 MOV AX,[CON] ;Defined part
433 MOV [DATA],AX
434 MOV AX,[UNDEF] ;Undefined part
435 MOV [DLABEL],AX
436 MOV DL,CH
437 MOV DH,CONST
438 MOV AL,DH
439 RET
440NREG:
441 PUSH DX
442 CALL GETSYM
443 POP DX
444 MOV AL,DH
445 RET
446MEM:
447 CALL GETSYM
448 MOV AL,1
449 CALL GETVAL
450 MOV AL,[SYM]
451 CMP AL,']'
452 MOV CL,24
453 JNZ ERR1
454 CALL GETSYM
455 MOV BX,[CON]
456 MOV [ADDR],BX
457 MOV BX,[UNDEF]
458 MOV [ALABEL],BX
459 MOV DL,CH
460 MOV DH,UNDEFID
461 MOV AL,DH
462 RET
463FLG:
464 CMP DL,[MAXFLG] ;Invalid flag for this operation?
465 MOV CL,27H
466 JG ERR1
467 CALL GETSYM
468 CMP AL,','
469 JZ GETOP
470 JP GETOP1
471
472
473GETVAL:
474
475; Expression analyzer. On entry, if AL=0 then do not allow base or index
476; registers. If AL=1, we are analyzing a memory reference, so allow base
477; and index registers, and compute addressing mode when done. The constant
478; part of the expression will be found in CON. If an undefined label is to
479; be added to this, a pointer to its information fields will be found in
480; UNDEF.
481
482 MOV AH,AL ;Flag is kept in AH
483 MOV [UNDEF],0
484 MOV AL,[SYM]
485 CALL EXPRESSION
486 MOV [CON],DX
487 MOV AL,AH
488 MOV CH,0 ;Initial mode
489 TEST AL,10H ;Test INDEX bit
490 RCL AL ;BASE bit (zero flag not affected)
491 JZ NOIND ;Jump if not indexed, with BASE bit in carry
492 CMC
493 RCL CH ;Rotate in BASE bit
494 RCL AL ;BP bit
495 RCL CH
496 RCL AL ;DI bit
497 RCL CH ;The low 3 bits now have indexing mode
498MODE:
499 OR CH,080H ;If undefined label, force 16-bit displacement
500 TEST [UNDEF],-1
501 JNZ RET
502 MOV BX,[CON]
503 MOV AL,BL
504 CBW ;Extend sign
505 CMP AX,BX ;Is it a signed 8-bit number?
506 JNZ RET ;If not, use 16-bit displacement
507 AND CH,07FH ;Reset 16-bit displacement
508 OR CH,040H ;Set 8-bit displacement
509 OR BX,BX
510 JNZ RET ;Use it if not zero displacement
511 AND CH,7 ;Specify no displacement
512 CMP CH,6 ;Check for BP+0 addressing mode
513 JNZ RET
514 OR CH,040H ;If BP+0, use 8-bit displacement
515 RET
516
517NOIND:
518 MOV CH,6 ;Try direct address mode
519 JNC RET ;If no base register, that's right
520 RCL AL ;Check BP bit
521 JC MODE
522 INC CH ;If not, must be BX
523 JP MODE
524
525EXPRESSION:
526;Analyze arbitrary expression. Flag byte in AH.
527;On exit, AL has type byte: 0=register or undefined label
528 MOV CH,-1 ;Initial type
529 MOV DI,DX
530 XOR DX,DX ;Initial value
531 CMP AL,'+'
532 JZ PLSMNS
533 CMP AL,'-'
534 JZ PLSMNS
535 MOV CL,'+'
536 PUSH DX
537 PUSH CX
538 MOV DX,DI
539 JP OPERATE
540PLSMNS:
541 MOV CL,AL
542 PUSH DX
543 PUSH CX
544 OR AH,4 ;Flag that a sign was found
545 CALL GETSYM
546OPERATE:
547 CALL TERM
548 POP CX ;Recover operator
549 POP BX ;Recover current value
550 XCHG DX,BX
551 AND CH,AL
552 OR AL,AL ;Is it register or undefined label?
553 JZ NOCON ;If so, then no constant part
554 CMP CL,"-" ;Subtract it?
555 JNZ ADD
556 NEG BX
557ADD:
558 ADD DX,BX
559NEXTERM:
560 MOV AL,[SYM]
561 CMP AL,'+'
562 JZ PLSMNS
563 CMP AL,'-'
564 JZ PLSMNS
565 MOV AL,CH
566 RET
567NOCON:
568 CMP CL,"-"
569 JNZ NEXTERM
570BADOP:
571 MOV CL,5
572 JMP ERROR
573
574TERM:
575 CALL FACTOR
576MULOP:
577 PUSH DX ;Save value
578 PUSH AX ;Save type
579 CALL GETSYM
580 POP CX
581 CMP AL,"*"
582 JZ GETFACT
583 CMP AL,"/"
584 JNZ ENDTERM
585GETFACT:
586 OR CL,CL ;Can we operate on this type?
587 JZ BADOP
588 PUSH AX ;Save operator
589 CALL GETSYM ;Get past operator
590 CALL FACTOR
591 OR AL,AL
592 JZ BADOP
593 POP CX ;Recover operator
594 POP BP ;And current value
595 XCHG AX,BP ;Save AH in BP
596 CMP CL,"/" ;Do we divide?
597 JNZ DOMUL
598 OR DX,DX ;Dividing by zero?
599 MOV CL,29H
600 JZ ERR2
601 MOV BX,DX
602 XOR DX,DX ;Make 32-bit dividend
603 DIV AX,BX
604 JMPS NEXFACT
605DOMUL:
606 MUL AX,DX
607NEXFACT:
608 MOV DX,AX ;Result in DX
609 XCHG AX,BP ;Restore flags to AH
610 MOV AL,-1 ;Indicate a number
611 JMPS MULOP
612ENDTERM:
613 POP DX
614 MOV AL,CL
615 RET
616
617FACTOR:
618 MOV AL,[SYM]
619 CMP AL,CONST
620 JZ RET
621 CMP AL,UNDEFID
622 JZ UVAL
623 CMP AL,"("
624 JZ PAREN
625 CMP AL,'"'
626 JZ STRING
627 CMP AL,"'"
628 JZ STRING
629 CMP AL,XREG ;Only 16-bit register may index
630 MOV CL,20
631 JNZ ERR2
632 TEST AH,1 ;Check to see if indexing is OK
633 MOV CL,1
634 JZ ERR2
635 MOV AL,DL
636 MOV CL,3
637 SUB AL,3 ;Check for BX
638 JZ BXJ
639 SUB AL,2 ;Check for BP
640 JZ BPJ
641 DEC AL ;Check for SI
642 MOV CL,4
643 JZ SIJ
644 DEC AL ;Check for DI
645 JZ DIJ
646 MOV CL,2 ;Invalid base/index register
647ERR2: JMP ERROR
648
649DIJ:
650 OR AH,20H ;Flag seeing index register DI
651SIJ:
652 TEST AH,10H ;Check if already seen index register
653 JNZ ERR2
654 OR AH,10H ;Flag seeing index register
655 RET
656
657BPJ:
658 OR AH,40H ;Flag seeing base register BP
659BXJ:
660 TEST AH,80H ;Check if already seen base register
661 JNZ ERR2
662 OR AH,80H ;Flag seeing base register
663 RET
664
665PAREN:
666 CALL GETSYM ;Eat the "("
667 CALL EXPRESSION
668 CMP B,[SYM],")" ;Better have closing paren
669 MOV CL,20
670 JNZ ERR30
671 RET
672
673UVAL:
674 MOV CL,6
675 TEST AH,8 ;Check if undefined label has been seen
676 JNZ ERR30
677 OR AH,8 ;Flag seeing undefined label
678 MOV [UNDEF],BX
679 RET
680
681ERR30: JMP ERROR
682
683STRING:
684 MOV CH,AL
685 MOV AL,[CHR]
686 CMP AL,CH
687 MOV CL,35
688 MOV DL,AL
689 MOV DH,0
690 JNZ L0003
691 CALL ZERLEN
692L0003:
693 CALL GETCHR
694 MOV CL,37
695 TEST AH,2
696 JZ ERR30
697 TEST AH,4
698 MOV CL,38
699 JNZ ERR30
700STRGDAT:
701 MOV AL,DL
702 CMP AL,EOL
703 MOV CL,39
704 JZ ERR30
705 CALL PUT
706 MOV AL,[DATSIZ]
707 OR AL,AL
708 JNZ BYTSIZ
709 MOV AL,DH
710 CALL PUT
711BYTSIZ:
712 MOV AL,[CHR]
713 MOV DL,AL
714 CALL GETCHR
715 JP STRGDAT
716
717ZERLEN:
718 CALL NEXTCHR
719 CMP AL,CH
720 JNZ ERR30
721 RET
722
723GETCHR:
724 CALL NEXTCHR
725 CMP AL,CH
726 JNZ RET
727 CALL NEXTCHR
728 CMP AL,CH
729 JZ RET
730 POP BX ;Kill return address to STRGDAT loop
731 MOV AL,-1 ;Flag type as constant
732 RET
733
734
735GETSYM:
736
737; The lexical scanner. Used only in the operand field. Returns with the token
738; in SYM and AL, sometimes with additional info in BX or DX.
739;
740; AL=SYM=0 Undefined label. BX has pointer to information fields.
741;
742; AL=SYM=1 Constant (or defined label). DX has value.
743;
744; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register,
745; respectively. DL has register number.
746;
747; AL=SYM=5 A mode flag (such as "B" for byte operation). Type of flag in DL
748; and also stored in FLAG: -1=no flags, 0=B, 1=W, 2=S, 3=L, 4=T.
749;
750; AL=SYM=6 8087 floating point register, ST(n) or ST. DL has register number.
751;
752; All other values are the ASCII code of the character. Note that this may
753; never be a letter or number.
754
755 PUSH AX ;Save AH
756 CALL GETSY
757 POP AX
758 MOV AL,[SYM]
759 RET
760
761SCANB:
762 MOV AL,[CHR]
763SCANT:
764 CMP AL,' '
765 JZ NEXB
766 CMP AL,9
767 JNZ RET
768NEXB:
769 CALL NEXTCHR
770 JP SCANT
771
772DOLLAR:
773 MOV DX,[OLDPC]
774 MOV AL,CONST
775 MOV [SYM],AL
776NEXTCHJ:
777 JMP NEXTCHR
778
779GETSY:
780 CALL SCANB
781 CMP AL,'$'
782 JZ DOLLAR
783 MOV [SYM],AL
784 OR AL,20H
785 CMP AL,'z'+1
786 JNC NEXTCHJ
787 CMP AL,'a'
788 JC $+5
789 JMP LETTER
790 CMP AL,'9'+1
791 JNC NEXTCHJ
792 CMP AL,'0'
793 JC NEXTCHJ
794 MOV BX,SYM
795 MOV B,[BX],CONST
796 CALL READID
797 DEC BX
798 MOV AL,[BX]
799 MOV CL,7
800 MOV BX,0
801 CMP AL,'h'
802 JNZ $+5
803 JMP HEX
804 INC CL
805 MOV [IX],ID
806DEC:
807 MOV SI,[IX]
808 MOV AL,[SI]
809 INC [IX]
810 CMP AL,'9'+1
811 JC $+5
812 JMP ERROR
813 SUB AL,'0'
814 MOV DX,BX
815 SHL BX
816 SHL BX
817 ADD BX,DX
818 SHL BX
819 MOV DL,AL
820 MOV DH,0
821 ADD BX,DX
822 DEC CH
823 JNZ DEC
824 XCHG DX,BX
825 RET
826
827HEX:
828 MOV DX,ID
829 DEC CH
830HEX1:
831 MOV SI,DX
832 LODB
833 INC DX
834 SUB AL,'0'
835 CMP AL,10
836 JC GOTIT
837 CMP AL,'g'-'0'
838 JNC ERR4
839 SUB AL,'a'-10-'0'
840GOTIT:
841 SHL BX
842 SHL BX
843 SHL BX
844 SHL BX
845 ADD BL,AL
846 DEC CH
847 JNZ HEX1
848 XCHG DX,BX
849 RET
850
851ERR4: JMP ERROR
852
853GETLET:
854 CALL SCANB
855 CMP AL,EOL
856 STC
857 JZ RET
858 CMP AL,';'
859 STC
860 JZ RET
861 MOV CL,10
862 OR AL,20H
863 CMP AL,'a'
864 JC ERR4
865 CMP AL,'z'+1
866 JNC ERR4
867READID:
868 MOV BX,ID
869 MOV CH,0
870MOREID:
871 MOV [BX],AL
872 INC CH
873 INC BX
874 CALL NEXTCHR
875 CMP AL,'0'
876 JC NOMORE
877 OR AL,20H
878 CMP AL,'z'+1
879 JNC NOMORE
880 CMP AL,'9'+1
881 JC MOREID
882 CMP AL,'a'
883 JNC MOREID
884NOMORE:
885 MOV CL,AL
886 MOV AL,CH
887 MOV [LENID],AL
888 OR AL,AL
889 MOV AL,CL
890 RET
891
892LETTER:
893 CALL READID
894 MOV AL,CH
895 DEC AL
896 JNZ NOFLG
897 MOV AL,[ID]
898 MOV CX,5
899 MOV DI,FLGTAB
900 UP
901 REPNE
902 SCAB ;See if one of B,W,S,L,T
903 JZ SAVFLG ;Go save flag
904 XOR AL,AL
905 MOV CH,[LENID]
906NOFLG:
907 DEC AL
908 PUSH BX
909 JNZ L0004
910 CALL REGCHK
911L0004:
912 POP BX
913 MOV AL,DH
914 JZ SYMSAV
915 CALL LOOKRET
916SYMSAV:
917 MOV [SYM],AL
918 RET
919
920SAVFLG:
921 MOV DL,CL ;Need flag type in DL
922 XCHG [FLAG],CL
923 CMP CL,-1
924 MOV CL,32
925 MOV AL,5
926 JZ SYMSAV
927ERRJ3: JMP ERROR
928
929FLGTAB: DB "tlswb"
930
931FPREG:
932;Have detected "ST" for 8087 floating point stack register
933 MOV DL,0 ;Default is ST(0)
934 CALL SCANB ;Get next character
935 CMP AL,"(" ;Specifying register number?
936 JNZ HAVREG
937;Get register number
938 CALL NEXTCHR ;Skip over the "("
939 CALL GETOP ;A little recursion never hurt anybody
940 CMP AL,CONST ;Better have found a constant
941 MOV CL,20 ;Operand error if not
942 JNZ ERRJ3
943 CMP [DLABEL],0 ;Constant must be defined
944 MOV CL,30
945 JNZ ERRJ3
946 MOV DX,[DATA] ;Get constant
947 CMP DX,7 ;Constant must be in range 0-7
948 MOV CL,31
949 JA ERRJ3
950 MOV AL,[SYM]
951 CMP AL,")"
952 MOV CL,24
953 JNZ ERRJ3
954HAVREG:
955 MOV DH,FREG
956 XOR AL,AL ;Zero set means register found
957 RET
958
959REGCHK:
960 MOV BX,ID
961 CMP [BX],"s"+7400H ;"st"
962 JZ FPREG
963 MOV CL,[BX]
964 INC BX
965 MOV AL,[BX]
966 MOV BX,REGTAB
967 MOV DH,XREG
968 MOV DL,0
969 CMP AL,'x'
970 JZ SCANREG
971 MOV DH,REG
972 CMP AL,'l'
973 JZ SCANREG
974 MOV DL,4
975 CMP AL,'h'
976 JZ SCANREG
977 MOV DH,SREG
978 MOV DL,0
979 MOV BX,SEGTAB
980 CMP AL,'s'
981 JZ SCANREG
982 MOV DH,XREG
983 CMP AL,'p'
984 JZ PREG
985 CMP AL,'i'
986 JNZ RET
987 MOV DL,6
988 MOV AL,CL
989 CMP AL,'s'
990 JZ RET
991 INC DL
992 CMP AL,'d'
993 RET
994PREG:
995 MOV DL,4
996 MOV AL,CL
997 CMP AL,'s'
998 JZ RET
999 INC DL
1000 CMP AL,'b'
1001 RET
1002SCANREG:
1003 MOV AL,CL
1004 MOV CX,4
1005 UP
1006 MOV DI,BX
1007 REPNZ
1008 SCAB
1009 MOV BX,DI
1010 JNZ RET
1011 MOV AL,CL
1012 ADD AL,DL
1013 MOV DL,AL
1014 XOR AL,AL
1015 RET
1016
1017REGTAB: DB 'bdca'
1018
1019SEGTAB: DB 'dsce'
1020
1021LOOK:
1022 MOV CH,[BX]
1023 INC BX
1024 MOV DX,ID
1025 CALL CPSLP
1026 JZ RET
1027 XOR AL,80H
1028 ROL AL ;Make end-of-symbol bit least significant
1029 MOV CL,AL
1030 DEC BX
1031 MOV AL,[BX]
1032 XOR AL,80H
1033 ROL AL
1034 CMP AL,CL
1035 JNC SMALL
1036 INC CH
1037 INC CH
1038SMALL:
1039 MOV DL,CH
1040 MOV DH,0
1041 ADD BX,DX
1042 MOV DX,[BX]
1043 INC BX
1044 MOV AL,DL
1045 OR AL,DH
1046 STC
1047 JZ RET
1048 XCHG DX,BX
1049 JP LOOK
1050
1051LOOKRET:
1052 MOV AL,CH
1053 CMP AL,3 ;RET has 3 letters
1054 JNZ LOOKUP
1055 DEC BX
1056 OR B,[BX],080H
1057 MOV DX,RETSTR+2
1058CHKRET:
1059 MOV SI,DX
1060 LODB
1061 CMP AL,[BX]
1062 JNZ LOOKIT
1063 DEC BX
1064 DEC DX
1065 DEC CH
1066 JNZ CHKRET
1067 MOV DX,[LSTRET]
1068 MOV AL,DL
1069 AND AL,DH
1070 INC AL
1071 JZ ALLRET
1072 MOV BX,[PC]
1073 SUB BX,DX
1074 MOV AL,BL
1075 CBW
1076 CMP AX,BX ;Signed 8-bit number?
1077 MOV AL,1
1078 JZ RET
1079ALLRET:
1080 MOV BX,[RETPT]
1081 MOV AL,BH
1082 OR AL,BL
1083 MOV AL,0
1084 JNZ RET
1085 MOV BX,[HEAP]
1086 DEC BX
1087 DEC BX
1088 DEC BX
1089 MOV [HEAP],BX
1090 XOR AL,AL
1091 MOV [BX],AL
1092 MOV [RETPT],BX
1093 RET
1094
1095LOOKUP:
1096 DEC BX
1097 OR B,[BX],080H
1098LOOKIT:
1099 MOV BX,[BASE]
1100 MOV AL,BH
1101 OR AL,BL
1102 JZ EMPTY
1103 CALL LOOK
1104 JC ENTER
1105 MOV DX,4
1106 ADD BX,DX
1107 MOV AL,[BX]
1108 OR AL,AL
1109 JZ RET
1110 INC BX
1111 MOV DX,[BX]
1112 INC BX
1113 RET
1114
1115ENTER:
1116 PUSH BX ;Save pointer to link field
1117 CALL CREATE ;Add the node
1118 POP SI
1119 MOV [SI-1],DX ;Link new node
1120 RET ;Zero was set by CREATE
1121
1122EMPTY:
1123 CALL CREATE
1124 MOV [BASE],DX
1125 RET
1126
1127
1128CREATE:
1129
1130; Add a new node to the identifier tree. The identifier is at ID with
1131; bit 7 of the last character set to one. The length of the identifier is
1132; in LENID, which is ID-1.
1133;
1134; Node format:
1135; 1. Length of identifier (1 byte)
1136; 2. Identifier (1-80 bytes)
1137; 3. Left link (2-byte pointer to alphabetically smaller identifiers)
1138; 4. Right link (0 if none larger)
1139; 5. Data field:
1140; a. Defined flag (0=undefined, 1=defined)
1141; b. Value (2 bytes)
1142;
1143; This routine returns with AL=zero and zero flag set (which indicates
1144; on return from LOOKUP that it has not yet been defined), DX points
1145; to start of new node, and BX points to data field of new node.
1146
1147 MOV AL,[LENID]
1148 ADD AL,8 ;Storage needed for the node
1149 MOV BX,[HEAP]
1150 MOV DL,AL
1151 MOV DH,0
1152 SUB BX,DX ;Heap grows downward
1153 MOV [HEAP],BX
1154 XCHG DX,BX
1155 MOV BX,[CODE] ;Check to make sure there's enough
1156 CMP BX,DX
1157 JB $+5
1158 JMP ABORT
1159 PUSH DX
1160 MOV BX,LENID
1161 MOV CL,[BX]
1162 INC CL
1163 MOV CH,0
1164 UP
1165 MOV SI,BX
1166 MOV DI,DX
1167 REP
1168 MOVB ;Move identifier and length into node
1169 MOV DX,DI
1170 MOV BX,SI
1171 MOV CH,4
1172 XCHG DX,BX
1173NILIFY:
1174 MOV [BX],CL ;Zero left and right links
1175 INC BX
1176 DEC CH
1177 JNZ NILIFY
1178 XOR AL,AL ;Set zero flag
1179 MOV [BX],AL ;Zero defined flag
1180 POP DX ;Restore pointer to node
1181 RET
1182
1183CPSLP:
1184 MOV SI,DX
1185 LODB
1186 CMP AL,[BX]
1187 LAHF
1188 INC DX
1189 INC BX
1190 SAHF
1191 JNZ RET
1192 DEC CH
1193 JNZ CPSLP
1194 RET
1195
1196GETLAB:
1197 MOV BX,0
1198 MOV [LABPT],BX
1199 MOV B,[FLAG],-1
1200 MOV DH,0
1201 MOV AL,[CHR]
1202 CMP AL,' '+1
1203 JC NOT1
1204 OR DH,001H
1205NOT1:
1206 CALL GETLET
1207 JC RET
1208 CMP AL,':'
1209 JNZ LABCHK
1210 CALL NEXTCHR
1211 JP LABEL
1212LABCHK:
1213 OR AL,AL
1214 TEST DH,001H
1215 JZ RET
1216LABEL:
1217 MOV AL,[CHKLAB]
1218 OR AL,AL
1219 JZ $+5
1220 JMP GETLET
1221 CALL LOOKUP
1222 MOV CL,11
1223 JNZ ERR5
1224 MOV DX,[PC]
1225 MOV B,[BX],1
1226 INC BX
1227 MOV [BX],DX
1228 MOV [LABPT],BX
1229 JMP GETLET
1230
1231ERR5: JMP ERROR
1232
1233ASMLIN:
1234 MOV B,[MAXFLG],1 ;Allow only B and W flags normally
1235 MOV BX,[PC]
1236 MOV [OLDPC],BX
1237 CALL GETLAB
1238 JNC $+5
1239 JMP ENDLN
1240 MOV BX,LENID
1241 MOV AL,[BX]
1242 MOV CL,12
1243 SUB AL,2
1244 MOV CH,AL
1245 JC ERR5
1246 INC BX
1247 CMP B,[BX],"f" ;See if an 8087 mnemonic
1248 JZ NDPOP
1249 CMP AL,5
1250 JNC ERR5
1251 MOV AL,[BX]
1252 SUB AL,'a'
1253 MOV CL,AL
1254 ADD AL,AL
1255 ADD AL,AL
1256 ADD AL,CL
1257 ADD AL,CH
1258 ADD AL,AL
1259 MOV BX,OPTAB
1260 MOV DL,AL
1261 MOV DH,0
1262 ADD BX,DX
1263 MOV BX,[BX]
1264 INC CH
1265 MOV CL,CH
1266 MOV AH,[BX]
1267 INC BX
1268 OR AH,AH
1269 JZ OPERR
1270FINDOP:
1271 MOV CH,CL
1272 MOV DX,ID+1
1273 XCHG AX,BP ;Save count of opcodes in BP
1274 CALL CPSLP
1275 JZ HAVOP
1276 XCHG AX,BP
1277 MOV DH,0
1278 MOV DL,CH
1279 INC DX
1280 INC DX
1281 ADD BX,DX
1282 DEC AH
1283 JNZ FINDOP
1284OPERR:
1285 MOV CL,12
1286 JMP ERROR
1287
1288HAVOP:
1289 MOV AL,[BX+2] ;Get opcode
1290 JMP [BX]
1291
1292NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor")
1293 MOV B,[MAXFLG],4 ;Allow all type flags
1294 INC BX
1295 CMP B,[BX],"n" ;"No-wait" form?
1296 MOV AH,0
1297 JNZ SAVNFLG
1298 MOV AH,1
1299 DEC AL
1300 INC BX ;Skip over the "N"
1301SAVNFLG:
1302 MOV [NOWAIT],AH ;0 for wait, 1 for no wait
1303 CMP AL,1
1304 JB OPERR ;Not enough char left for valid opcode?
1305 CMP AL,5
1306 JA OPERR ;Too many?
1307 CBW
1308 XCHG AX,DX ;Save length in DX
1309 MOV SI,DX
1310 OR B,[SI+BX],80H ;Set high bit of last character
1311 MOV AL,[BX] ;Get first char of opcode
1312 INC BX
1313 SUB AL,"a"
1314 JB TRY2XM1 ;Go see if opcode starts with "2"
1315 CMP AL,"z"-"a"
1316 JA OPERR
1317 CBW
1318 SHL AX ;Double to index into address table
1319 XCHG AX,SI ;Put in index register
1320 MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter
1321LOOKNDP:
1322 MOV AH,[DI] ;Number of opcodes starting with this letter
1323 OR AH,AH
1324 JZ OPERR ;Any start with this letter?
1325FNDNDP:
1326 INC DI
1327 MOV SI,BX ;Pointer to start of opcode
1328 MOV CX,DX ;Get length of opcode
1329 REPE
1330 CMPB ;Compare opcode to table entry
1331 JZ HAVNDP
1332 DEC DI ;Back up in case that was last letter
1333 MOV AL,80H ;Look for char with high bit set
1334ENDOP:
1335 SCASB
1336 JA ENDOP
1337 INC DI ;Skip over info about opcode
1338 DEC AH
1339 JNZ FNDNDP
1340OPERRJ: JP OPERR
1341
1342TRY2XM1:
1343 CMP AL,"2"-"a"
1344 JNZ OPERR
1345 MOV DI,XM1
1346 JP LOOKNDP
1347
1348SPECIALOP:
1349 AND AL,7 ;Mask to special op number
1350 JZ FWAIT ;If zero, go handle FWAIT
1351;Handle FNOP
1352 CMP B,[NOWAIT],0 ;Was "N" present (If not opcode was "FOP")
1353 JZ OPERR
1354 MOV AL,9BH ;Need Wait opcode after all
1355 CALL PUT
1356 MOV AL,0D9H
1357 CALL PUT
1358 MOV AL,0D0H
1359 JMP PUT
1360
1361FWAIT:
1362 CMP B,[NOWAIT],0 ;"FNWAIT" not legal
1363 JNZ OPERRJ
1364 RET ;Nothing to do - "WAIT" already sent
1365
1366HAVNDP:
1367 MOV SI,DI
1368 CMP B,[NOWAIT],0
1369 JNZ NWAIT
1370 MOV AL,9BH ;Wait opcode
1371 CALL PUT
1372NWAIT:
1373 LODW ;Get opcode info
1374 TEST AL,0F8H ;Any operand bits set?
1375 JZ NOOPS ;If no operands, output code
1376 TEST AL,78H ;Special case?
1377 JZ SPECIALOP
1378 PUSH AX
1379 CALL GETSYM ;See if any operands
1380 POP CX
1381 CMP AL,";"
1382 JZ NOOPCHK
1383 CMP AL,EOL
1384 JZ NOOPCHK
1385 CMP AL,FREG ;Is it 8087 register?
1386 JNZ MEMOP
1387 XCHG AX,CX
1388 TEST AL,ONEREG ;One register OK as operand?
1389 JNZ PUTREG ;Yes - save it
1390 TEST AL,20H ;Memory-only operation?
1391 MOV CL,20
1392 JNZ ERRJ4
1393 TEST AL,18H ;Two-register operation?
1394 JPE ERRJ4 ;Must be exactly one bit set
1395 PUSH DX ;Save register number
1396 PUSH AX ;Save opcode
1397 CALL GETSYM
1398 CMP AL,","
1399 MOV CL,15H
1400 JNZ ERRJ4
1401 CALL GETSYM
1402 MOV CL,20
1403 CMP AL,FREG
1404 JNZ ERRJ4
1405 POP AX
1406 POP BX
1407 XOR AL,2 ;Flip "POP" bit
1408 AND AL,0FBH ;Reset direction bit to ST(0)
1409 OR BL,BL ;Is first register ST(0)?
1410 JZ ST0DEST
1411 XCHG DX,BX
1412 OR BL,BL ;One of these must be ST(0)
1413 JNZ ERRJ4
1414 XOR AL,4 ;Flip direction
1415 JMPS PUTREG
1416ST0DEST:
1417 TEST AL,2 ;Is POP bit set?
1418 JNZ ERRJ4 ;Don't allow destination ST(0) then pop
1419PUTREG:
1420 AND AH,0F8H ;Zero out register field
1421 OR AH,DL
1422 OR AH,0C0H
1423 PUSH AX
1424 CALL GETSYM ;Get to next symbol
1425 POP AX
1426 JMPS NOOPS
1427
1428NOOPCHK:
1429 XCHG AX,CX
1430 TEST AL,80H ;Is no operands OK?
1431 MOV CL,20
1432 JNZ ERRJ4
1433NOOPS:
1434;First test for FDIV or FSUB and reverse "R" bit if "D" bit is set
1435 PUSH AX
1436 AND AX,0E005H
1437 CMP AX,0E004H
1438 POP AX
1439 JNZ NOREV
1440 XOR AH,8 ;Reverse "R" bit
1441NOREV:
1442 AND AL,7
1443 OR AL,0D8H ;ESC hook
1444 CALL PUT
1445 MOV AL,AH
1446 JMP PUT
1447
1448BADFLAG:
1449 MOV CL,20H
1450ERRJ4: JMP ERROR
1451
1452MEMOP:
1453 PUSH CX ;Save opcode
1454 CALL GETOP1 ;Get memory operand
1455 CMP AL,UNDEFID ;Is it?
1456 MOV CL,20
1457 JNZ ERRJ4
1458 POP AX
1459 TEST AL,20H ;Does it have memory format field?
1460 JNZ GETFORMAT
1461 TEST AL,8 ;Check if any memory operand legal
1462 JZ ERRJ4
1463 TEST AL,10H ;Check for 2-op arithmetic
1464 JNZ PUTMEM ;If not, just use as plain memory op
1465GETFORMAT:
1466 AND AL,0F9H ;Zero memory format bits
1467 MOV CL,[FLAG]
1468 DEC CL ;Must now be in range 0-3
1469 JL BADFLAG
1470 MOV CH,AL ;Save opcode byte
1471 SHR AL ;Put format bits in bits 2 & 3
1472 AND AL,0CH
1473 OR AL,CL ;Combine format bits with flag
1474 MOV BX,FORMATTAB
1475 XLAT
1476 OR AL,AL ;Valid combination?
1477 JS BADFLAG
1478 OR AH,AL ;Possibly set new bits in second byte
1479 OR AL,CH ;Set memory format bits
1480PUTMEM:
1481 AND AL,7
1482 OR AL,0D8H
1483 CALL PUT
1484 MOV AL,AH
1485 AND AL,38H
1486 OR AL,DL ;Combine addressing mode
1487 JMP PUTADD
1488
1489FORMATTAB:
1490;There are 16 entries in this table. The 4-bit index is built like this:
1491; Bit 3 0 for normal memory ops, 1 if extended is OK
1492; Bit 2 0 for integer, 1 for real
1493; Bit 0 & 1 Flag: 00=W, 01=S, 10=L, 11=T
1494;
1495;The entries in the table are used as two 3-bit fields. Bits 0-2 are ORed
1496;into the first byte of the opcode for the Memory Format field. Bits 3-6
1497;are ORed into the second byte to modify the opcode for extended operands.
1498;If bit 7 is set, then that combination is illegal.
1499
1500 DB 6,2,80H,80H ;Normal integers
1501 DB 80H,0,4,80H ;Normal reals
1502 DB 6,2,2EH,80H ;Extended integers
1503 DB 80H,0,4,2BH ;Extended reals
1504
1505GRP1:
1506 MOV CX,8A09H
1507 CALL MROPS
1508 MOV CX,0C6H
1509 MOV AL,BH
1510 CMP AL,UNDEFID
1511 JNZ L0006
1512 CALL STIMM
1513L0006:
1514 AND AL,1
1515 JZ BYTIMM
1516 MOV AL,0B8H
1517 OR AL,BL
1518 CALL PUT
1519 JMP PUTWOR
1520
1521BYTIMM:
1522 MOV AL,0B0H
1523 OR AL,BL
1524 CALL PUT
1525PUTBJ: JMP PUTBYT
1526
1527IMMED:
1528 MOV AL,BH
1529 CMP AL,UNDEFID
1530 JZ STIMM
1531 MOV AL,BL
1532 OR AL,AL
1533 JZ RET
1534 MOV AL,BH
1535 CALL IMM
1536 OR AL,0C0H
1537 CALL PUT
1538FINIMM:
1539 MOV AL,CL
1540 POP CX
1541 TEST AL,1
1542 JZ PUTBJ
1543 CMP AL,83H
1544 JZ PUTBJ
1545 JMP PUTWOR
1546
1547STIMM:
1548 MOV AL,[FLAG]
1549 CALL IMM
1550 CALL PUTADD
1551 JP FINIMM
1552
1553IMM:
1554 AND AL,1
1555 OR AL,CL
1556 MOV CL,AL
1557 CALL PUT
1558 MOV AL,CH
1559 AND AL,38H
1560 OR AL,BL
1561 RET
1562
1563PUT:
1564;Save byte in AL as pure code, with intermediate code bits 00. AL and
1565;DI destroyed, no other registers affected.
1566 PUSH BX
1567 PUSH CX
1568 MOV CH,0 ;Flag as pure code
1569 CALL GEN
1570 POP CX
1571 POP BX
1572 RET
1573
1574GEN:
1575;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH.
1576 CALL PUTINC ;Save it and bump code pointer
1577GEN1:
1578 MOV AL,[RELOC]
1579 RCL CH
1580 RCL AL
1581 RCL CH
1582 RCL AL
1583 MOV [RELOC],AL
1584 MOV BX,BCOUNT
1585 DEC B,[BX]
1586 JNZ RET
1587 MOV B,[BX],4
1588 MOV BX,RELOC
1589 MOV AL,[BX]
1590 MOV B,[BX],0
1591 MOV DI,[IY]
1592 MOV [DI],AL
1593 MOV BX,[CODE]
1594 MOV [IY],BX
1595 INC BX
1596 MOV [CODE],BX
1597 RET
1598
1599PUTINC:
1600 INC [PC]
1601PUTCD:
1602 MOV DI,[CODE]
1603 STOB
1604 MOV [CODE],DI
1605 RET
1606
1607PUTWOR:
1608;Save the word value described by [DLABEL] and [DATA] as code. If defined,
1609;two bytes of pure code will be produced. Otherwise, appropriate intermediate
1610;code will be generated.
1611 PUSH CX
1612 MOV CH,80H
1613 PUSH DX
1614 PUSH BX
1615 JP PUTBW
1616
1617PUTBYT:
1618;Same as PUTWOR, above, but for byte value.
1619 PUSH CX
1620 MOV CH,40H
1621 PUSH DX
1622 PUSH BX
1623 MOV BX,[DLABEL]
1624 MOV AL,BH
1625 OR AL,BL
1626 JNZ PUTBW
1627 MOV BX,[DATA]
1628 OR AL,BH
1629 JZ PUTBW
1630 INC BH
1631 JZ PUTBW
1632 MOV CL,31
1633 JMP ERROR
1634PUTBW:
1635 MOV DX,[DLABEL]
1636 MOV BX,[DATA]
1637PUTCHK:
1638 OR DX,DX
1639 JZ NOUNDEF
1640 MOV AL,DL
1641 CALL PUTCD
1642 MOV AL,DH
1643 CALL PUTCD
1644 MOV AL,BL
1645 CALL PUTINC
1646 MOV AL,BH
1647 TEST CH,080H
1648 JZ SMPUT
1649 CALL GEN
1650 JP PRET
1651SMPUT:
1652 CALL PUTCD
1653 CALL GEN1
1654PRET:
1655 POP BX
1656 POP DX
1657 POP CX
1658 RET
1659
1660NOUNDEF:
1661 MOV AL,BL
1662 MOV CL,BH
1663 PUSH CX
1664 MOV CH,0
1665 CALL GEN
1666 POP CX
1667 MOV AL,CL
1668 TEST CH,080H
1669 MOV CH,0
1670 JZ PRET
1671 CALL GEN
1672 JP PRET
1673
1674PUTADD:
1675;Save complete addressing mode. Addressing mode is in AL; if this is a register
1676;operation (>=C0), then the one byte will be saved as pure code. Otherwise,
1677;the details of the addressing mode will be investigated and the optional one-
1678;or two-byte displacement will be added, as described by [ADDR] and [ALABEL].
1679 PUSH CX
1680 PUSH DX
1681 PUSH BX
1682 MOV CH,0
1683 MOV CL,AL
1684 CALL GEN ;Save the addressing mode as pure code
1685 MOV AL,CL
1686 MOV CH,80H
1687 AND AL,0C7H
1688 CMP AL,6
1689 JZ TWOBT ;Direct address?
1690 AND AL,0C0H
1691 JZ PRET ;Indirect through reg, no displacement?
1692 CMP AL,0C0H
1693 JZ PRET ;Register to register operation?
1694 MOV CH,AL ;Save whether one- or two-byte displacement
1695TWOBT:
1696 MOV BX,[ADDR]
1697 MOV DX,[ALABEL]
1698 JP PUTCHK
1699
1700GRP2:
1701 CALL GETOP
1702 MOV CX,0FF30H
1703 CMP AL,UNDEFID
1704 JZ PMEM
1705 MOV CH,50H
1706 CMP AL,XREG
1707 JZ PXREG
1708 MOV CH,6
1709 CMP AL,SREG
1710 JNZ $+5
1711 JMP PACKREG
1712 MOV CL,20
1713 JMP ERROR
1714
1715PMEM:
1716 MOV AL,CH
1717 CALL PUT
1718 MOV AL,CL
1719 OR AL,DL
1720 JMP PUTADD
1721
1722PXREG:
1723 MOV AL,CH
1724 OR AL,DL
1725 JMP PUT
1726
1727GRP3:
1728 CALL GETOP
1729 PUSH DX
1730 CALL GETOP2
1731 POP BX
1732 MOV CX,8614H
1733 MOV AL,SREG
1734 CMP AL,BH
1735 JZ ERR6
1736 CMP AL,DH
1737 JZ ERR6
1738 MOV AL,CONST
1739 CMP AL,BH
1740 JZ ERR6
1741 CMP AL,DH
1742 JZ ERR6
1743 MOV AL,UNDEFID
1744 CMP AL,BH
1745 JZ EXMEM
1746 CMP AL,DH
1747 JZ EXMEM1
1748 MOV AL,BH
1749 CMP AL,DH
1750 MOV CL,22
1751 JNZ ERR6
1752 CMP AL,XREG
1753 JZ L0008
1754 CALL RR1
1755L0008: ;RR1 never returns
1756 MOV AL,BL
1757 OR AL,AL
1758 JZ EXACC
1759 XCHG DX,BX
1760 MOV AL,BL
1761 OR AL,AL
1762 MOV AL,BH
1763 JZ EXACC
1764 CALL RR1
1765EXACC:
1766 MOV AL,90H
1767 OR AL,DL
1768 JMP PUT
1769
1770EXMEM:
1771 XCHG DX,BX
1772EXMEM1:
1773 CMP AL,BH
1774 JZ ERR6
1775 MOV CL,1 ;Flag word as OK
1776 CALL NOTAC ;NOTAC never returns
1777ERR6: JMP ERROR
1778
1779GRP4:
1780 PUSH AX
1781 CALL GETOP
1782 POP CX
1783 XCHG CL,CH
1784 CMP AL,CONST
1785 JZ FIXED
1786 SUB AL,XREG
1787 DEC DL
1788 DEC DL
1789 OR AL,DL
1790 MOV CL,20
1791 JNZ ERR6
1792 MOV AL,CH
1793 OR AL,8
1794 JMP PUT
1795FIXED:
1796 MOV AL,CH
1797 CALL PUT
1798 JMP PUTBYT
1799
1800GRP5:
1801 PUSH AX
1802 CALL GETOP
1803 MOV CL,20
1804 CMP AL,CONST
1805 JNZ ERR6
1806 MOV BX,[DLABEL]
1807 MOV AL,BH
1808 OR AL,BL
1809 MOV CL,30
1810 JNZ ERR6
1811 MOV BX,[DATA]
1812 POP AX
1813 OR AL,AL
1814 JZ ORG
1815 DEC AL
1816 JZ DSJ
1817 DEC AL
1818 JZ EQU
1819 DEC AL
1820 JZ $+5
1821 JMP IF
1822PUTOP:
1823 MOV AL,-3
1824 JP NEWLOC
1825ALIGN:
1826 MOV AL,[PC]
1827 AND AL,1
1828 JZ RET
1829 MOV BX,1
1830DSJ:
1831 XCHG DX,BX
1832 MOV BX,[PC]
1833 ADD BX,DX
1834 MOV [PC],BX
1835 XCHG DX,BX
1836 MOV AL,-4
1837 JP NEWLOC
1838EQU:
1839 XCHG DX,BX
1840 MOV BX,[LABPT]
1841 MOV AL,BH
1842 OR AL,BL
1843 MOV CL,34
1844 JZ ERR7
1845 MOV [BX],DL
1846 INC BX
1847 MOV [BX],DH
1848 RET
1849ORG:
1850 MOV [PC],BX
1851 MOV AL,-2
1852NEWLOC:
1853 CALL PUTCD
1854 MOV AL,BL
1855 CALL PUTCD
1856 MOV AL,BH
1857 CALL PUTCD
1858 MOV CH,0C0H
1859 JMP GEN1
1860GRP6:
1861 MOV CH,AL
1862 MOV CL,4
1863 CALL MROPS
1864 MOV CL,23
1865ERR7: JMP ERROR
1866GRP7:
1867 MOV CH,AL
1868 MOV CL,1
1869 CALL MROPS
1870 MOV CL,80H
1871 MOV DX,[DLABEL]
1872 MOV AL,DH
1873 OR AL,DL
1874 JNZ ACCJ
1875 XCHG DX,BX
1876 MOV BX,[DATA]
1877 MOV AL,BL
1878 CBW
1879 CMP AX,BX
1880 XCHG DX,BX
1881 JNZ ACCJ
1882 OR CL,002H
1883ACCJ: JMP ACCIMM
1884GRP8:
1885 MOV CL,AL
1886 MOV CH,0FEH
1887 JP ONEOP
1888GRP9:
1889 MOV CL,AL
1890 MOV CH,0F6H
1891ONEOP:
1892 PUSH CX
1893 CALL GETOP
1894ONE:
1895 MOV CL,26
1896 CMP AL,CONST
1897 JZ ERR7
1898 CMP AL,SREG
1899 MOV CL,22
1900 JZ ERR7
1901 POP CX
1902 CMP AL,UNDEFID
1903 JZ MOP
1904 AND AL,1
1905 JZ ROP
1906 TEST CL,001H
1907 JZ ROP
1908 MOV AL,CL
1909 AND AL,0F8H
1910 OR AL,DL
1911 JMP PUT
1912MOP:
1913 MOV AL,[FLAG]
1914 AND AL,1
1915 OR AL,CH
1916 CALL PUT
1917 MOV AL,CL
1918 AND AL,38H
1919 OR AL,DL
1920 JMP PUTADD
1921ROP:
1922 OR AL,CH
1923 CALL PUT
1924 MOV AL,CL
1925 AND AL,38H
1926 OR AL,0C0H
1927 OR AL,DL
1928 JMP PUT
1929GRP10:
1930 MOV CL,AL
1931 MOV CH,0F6H
1932 PUSH CX
1933 CALL GETOP
1934 MOV CL,20
1935 MOV AL,DL
1936 OR AL,AL
1937 JNZ ERRJ1
1938 MOV AL,DH
1939 CMP AL,XREG
1940 JZ G10
1941 CMP AL,REG
1942ERRJ1: JNZ ERR8
1943G10:
1944 PUSH AX
1945 CALL GETOP
1946 POP AX
1947 AND AL,1
1948 MOV [FLAG],AL
1949 MOV AL,DH
1950ONEJ: JP ONE
1951GRP11:
1952 CALL PUT
1953 MOV AL,0AH
1954 JMP PUT
1955GRP12:
1956 MOV CL,AL
1957 MOV CH,0D0H
1958 PUSH CX
1959 CALL GETOP
1960 MOV AL,[SYM]
1961 CMP AL,','
1962 MOV AL,DH
1963 JNZ ONEJ
1964 PUSH DX
1965 CALL GETOP
1966 SUB AL,REG
1967 MOV CL,20
1968 DEC DL
1969 OR AL,DL
1970 JNZ ERR8
1971 POP DX
1972 MOV AL,DH
1973 POP CX
1974 OR CH,002H
1975 PUSH CX
1976 JMP ONE
1977GRP13:
1978 MOV CH,AL
1979 MOV CL,1
1980 CALL MROPS
1981 MOV CL,80H
1982ACCIMM:
1983 CALL IMMED
1984 OR CH,004H
1985 AND CH,0FDH
1986AIMM:
1987 MOV AL,BH
1988 AND AL,1
1989 LAHF
1990 PUSH AX
1991 OR AL,CH
1992 CALL PUT
1993 POP AX
1994 SAHF
1995 JNZ $+5
1996 JMP PUTBYT
1997 JMP PUTWOR
1998
1999ERR8: JMP ERROR
2000
2001GRP14:
2002;JMP and CALL mnemonics
2003 LAHF
2004 XCHG AH,AL
2005 PUSH AX
2006 XCHG AH,AL
2007 MOV B,[MAXFLG],3 ;Allow "L" flag
2008 CALL GETOP
2009 CMP AL,CONST
2010 JZ DIRECT
2011 MOV CL,20
2012 CMP AL,REG
2013 JZ ERR8
2014 CMP AL,SREG
2015 JZ ERR8
2016 CMP AL,XREG
2017 JNZ NOTRG
2018 OR DL,0C0H
2019NOTRG:
2020;Indirect jump. DL has addressing mode.
2021 MOV AL,0FFH
2022 CALL PUT
2023 POP AX
2024 XCHG AH,AL
2025 SAHF
2026 AND AL,38H
2027 OR AL,DL
2028 MOV CH,[FLAG]
2029 CMP CH,3 ;Flag "L" present?
2030 JZ PUTADDJ ;If so, do inter-segment
2031 MOV CL,27H
2032 CMP CH,-1 ;Better not be a flag
2033 JNZ ERR8
2034 AND AL,0F7H ;Convert to intra-segment
2035PUTADDJ:
2036 JMP PUTADD
2037DIRECT:
2038 MOV AL,[SYM]
2039 CMP AL,','
2040 JZ LONGJ
2041 POP AX
2042 XCHG AH,AL
2043 SAHF
2044 DEC AL
2045 CMP AL,0E9H
2046 JZ GOTOP
2047 MOV AL,0E8H
2048GOTOP:
2049 CALL PUT
2050 MOV DX,[PC]
2051 INC DX
2052 INC DX
2053 SUB [DATA],DX
2054 JMP PUTWOR
2055LONGJ:
2056 POP AX
2057 XCHG AH,AL
2058 SAHF
2059 CALL PUT
2060 CALL PUTWOR
2061 CALL GETOP
2062 MOV CL,20
2063 CMP AL,CONST
2064 JNZ ERR8
2065 JMP PUTWOR
2066
2067GRP16:
2068;RET mnemonic
2069 LAHF
2070 XCHG AH,AL
2071 PUSH AX
2072 XCHG AH,AL
2073 CALL GETSYM
2074 CMP AL,5
2075 JZ LONGR
2076 CMP AL,EOL
2077 JZ NODEC
2078 CMP AL,';'
2079 JZ NODEC
2080GETSP:
2081 CALL GETOP1
2082 POP CX
2083 CMP AL,CONST
2084 MOV CL,20
2085 JNZ ERR9
2086 MOV AL,CH
2087 AND AL,0FEH
2088 CALL PUT
2089 JMP PUTWOR
2090LONGR:
2091 CMP DL,3 ;Is flag "L"?
2092 MOV CL,27H
2093 JNZ ERR10 ;If not, bad flag
2094 POP AX
2095 XCHG AH,AL
2096 SAHF
2097 OR AL,8
2098 LAHF
2099 XCHG AH,AL
2100 PUSH AX
2101 XCHG AH,AL
2102NOTLON:
2103 CALL GETSYM
2104 CMP AL,EOL
2105 JZ DORET
2106 CMP AL,';'
2107 JZ DORET
2108 CMP AL,','
2109 JNZ L0011
2110 CALL GETSYM
2111L0011:
2112 JP GETSP
2113NODEC:
2114;Return is intra-segment (short) without add to SP.
2115;Record position for RET symbol.
2116 MOV BX,[PC]
2117 MOV [LSTRET],BX
2118 XCHG DX,BX
2119 MOV BX,[RETPT]
2120 MOV AL,BH
2121 OR AL,BL
2122 JZ DORET
2123 MOV B,[BX],1
2124 INC BX
2125 MOV [BX],DX
2126 MOV BX,0
2127 MOV [RETPT],BX
2128DORET:
2129 POP AX
2130 XCHG AH,AL
2131 SAHF
2132 JMP PUT
2133
2134GRP17:
2135 CALL PUT
2136 CALL GETOP
2137 CMP AL,CONST
2138 MOV CL,20
2139ERR9: JNZ ERR10
2140 MOV BX,[DATA]
2141 MOV DX,[PC]
2142 INC DX
2143 SUB BX,DX
2144 MOV [DATA],BX
2145 CALL PUTBYT
2146 MOV BX,[DLABEL]
2147 MOV AL,BH
2148 OR AL,BL
2149 JNZ RET
2150 MOV BX,[DATA]
2151 MOV AL,BL
2152 CBW
2153 CMP AX,BX ;Signed 8-bit number?
2154 JZ RET
2155 MOV CL,31
2156ERR10: JMP ERROR
2157 RET
2158GRP18:
2159 CALL GETOP
2160 CMP AL,CONST
2161 MOV CL,20
2162 JNZ ERR10
2163 MOV BX,[DLABEL]
2164 MOV AL,BH
2165 OR AL,BL
2166 JNZ GENINT
2167 MOV BX,[DATA]
2168 MOV DX,3
2169 SBB BX,DX
2170 JNZ GENINT
2171 MOV AL,0CCH
2172 JMP PUT
2173GENINT:
2174 MOV AL,0CDH
2175 CALL PUT
2176 JMP PUTBYT
2177
2178GRP19: ;ESC opcode
2179 CALL GETOP
2180 MOV CL,20
2181 CMP AL,CONST
2182 JNZ ERRJ ;First operand must be immediate
2183 MOV CL,1EH
2184 TEST [DLABEL],-1 ;See if all labels have been defined
2185 JNZ ERRJ
2186 MOV AX,[DATA]
2187 CMP AX,64 ;Must only be 6 bits
2188 MOV CL,1FH
2189 JNB ERRJ
2190 MOV BL,AL ;Save for second byte
2191 SHR AL
2192 SHR AL
2193 SHR AL
2194 OR AL,0D8H ;ESC opcode
2195 CALL PUT
2196 PUSH BX
2197 CALL GETOP2
2198 POP BX
2199 AND BL,7 ;Low 3 bits of first operand
2200 SHL BL
2201 SHL BL
2202 SHL BL
2203 CMP AL,UNDEFID ;Check for memory operand
2204 JZ ESCMEM
2205 CMP AL,CONST ;Check for another immediate
2206 JZ ESCIMM
2207 MOV CL,20
2208ERRJ: JMP ERROR
2209
2210ESCMEM:
2211 OR BL,DL ;Combine mode with first operand
2212 MOV AL,BL
2213 JMP PUTADD
2214
2215ESCIMM:
2216 MOV CL,1EH
2217 TEST [DLABEL],-1 ;See if second operand is fully defined
2218 JNZ ERRJ
2219 MOV AX,[DATA]
2220 MOV CL,1FH
2221 CMP AX,8 ;Must only be 3 bit value
2222 JNB ERRJ
2223 OR AL,BL ;Combine first and second operands
2224 OR AL,0C0H ;Force "register" mode
2225 JMP PUT
2226
2227GRP20:
2228 MOV CH,AL
2229 MOV CL,1
2230 CALL MROPS
2231 MOV CL,0F6H
2232 CALL IMMED
2233 MOV CH,0A8H
2234 JMP AIMM
2235GRP21:
2236 CALL GETOP
2237 CMP AL,SREG
2238 MOV CL,28
2239 JNZ ERRJ
2240 MOV CH,26H
2241PACKREG:
2242 MOV AL,DL
2243 ADD AL,AL
2244 ADD AL,AL
2245 ADD AL,AL
2246 OR AL,CH
2247 JMP PUT
2248GRP22:
2249 CALL GETOP
2250 MOV CX,8F00H
2251 CMP AL,UNDEFID
2252 JNZ $+5
2253 JMP PMEM
2254 MOV CH,58H
2255 CMP AL,XREG
2256 JNZ $+5
2257 JMP PXREG
2258 MOV CH,7
2259 CMP AL,SREG
2260 JZ PACKREG
2261 MOV CL,20
2262ERR11: JMP ERROR
2263GRP23:
2264 MOV [DATSIZ],AL
2265GETDAT:
2266 CALL GETSYM
2267 MOV AL,2
2268 CALL VAL1
2269 MOV AL,[SYM]
2270 CMP AL,','
2271 MOV AL,[DATSIZ]
2272 JNZ ENDDAT
2273 CALL SAVDAT
2274 JP GETDAT
2275ENDDAT:
2276 CMP AL,2
2277 JNZ SAVDAT
2278 MOV BX,[DATA]
2279 LAHF
2280 OR BL,080H
2281 SAHF
2282 MOV [DATA],BX
2283SAVDAT:
2284 OR AL,AL
2285 JZ $+5
2286 JMP PUTBYT
2287 JMP PUTWOR
2288IF:
2289 OR BX,BX
2290 JZ SKIPCD
2291 INC B,[IFFLG]
2292 RET
2293
2294SKIPCD:
2295 INC B,[CHKLAB]
2296SKIPLP:
2297 XOR AL,AL
2298 CALL NEXLIN
2299 CALL NEXTCHR
2300 CMP AL,1AH
2301 JZ END
2302 CALL GETLAB
2303 JC SKIPLP
2304 MOV DI,LENID
2305 MOV SI,IFEND
2306 MOV CH,0
2307 MOV CL,[DI]
2308 INC CL
2309 REPE
2310 CMPB
2311 JZ ENDCOND
2312 MOV DI,LENID
2313 MOV SI,IFNEST
2314 MOV CL,[DI]
2315 INC CL
2316 REPE
2317 CMPB
2318 JNZ SKIPLP
2319 INC B,[CHKLAB]
2320 JP SKIPLP
2321
2322ENDCOND:
2323 DEC B,[CHKLAB]
2324 JNZ SKIPLP
2325 RET
2326
2327ENDIF:
2328 MOV AL,[IFFLG]
2329 MOV CL,36
2330 DEC AL
2331 JS ERRJMP
2332 MOV [IFFLG],AL
2333 RET
2334
2335ERRJMP: JMP ERROR
2336
2337;*********************************************************************
2338;
2339; PASS 2
2340;
2341;*********************************************************************
2342
2343END:
2344 MOV DL,4
2345WREND:
2346 MOV CH,0FFH
2347 MOV AL,CH
2348 CALL GEN
2349 DEC DL
2350 JNZ WREND
2351 MOV [BUFPT],SRCBUF
2352 MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY
2353 MOV [LSTPNT],LSTBUF
2354 MOV [HEXPNT],HEXBUF
2355 XOR AX,AX
2356 MOV [ERRCNT],AX
2357 MOV [PC],AX
2358 MOV [LINE],AX ;Current line number
2359 MOV [HEXADD],OBJECT
2360 MOV DX,FCB
2361 MOV AH,OPEN
2362 INT 33 ;Re-open source file
2363 XOR AX,AX
2364 MOV [FCB+12],AX ;Set CURRENT BLOCK to zero
2365 MOV [FCB+20H],AL ;Set NEXT RECORD field to zero
2366 MOV [FCB+14],BUFSIZ
2367 MOV [COUNT],AL
2368 MOV CH,1
2369 MOV SI,START
2370FIXLINE:
2371 MOV DI,START ;Store code over used up intermediate code
2372 XOR AL,AL
2373 MOV [SPC],AL ;No "special" yet (ORG, PUT, DS)
2374 MOV [ERR],AL ;No second pass errors yet
2375NEXBT:
2376 SHL CL ;Shift out last bit of previous code
2377 DEC CH ;Still have codes left?
2378 JNZ TESTTYP
2379 LODB ;Get next flag byte
2380 MOV CL,AL
2381 MOV CH,4
2382TESTTYP:
2383 SHL CL ;Set flags based on two bits
2384 JO FIXUP
2385 LODB
2386 JC EMARK
2387OBJBT:
2388 STOB
2389 JP NEXBT
2390
2391FIXUP:
2392;Either a word or byte fixup is needed from a forward reference
2393 LODW ;Get pointer to symbol
2394 XCHG AX,BX
2395 LODW ;Get constant part
2396 ADD AX,[BX+1] ;Add symbol value to constant part
2397 CMP B,[BX],0 ;See if symbol got defined
2398 JNZ HAVDEF
2399 MOV B,[ERR],100 ;Undefined - flag error
2400 XOR AX,AX
2401HAVDEF:
2402 OR CL,CL ;See if word or byte fixup
2403 JS DEFBYT
2404 STOW
2405 JP NEXBT
2406
2407DEFBYT:
2408 MOV DX,AX
2409 CBW ;Extend sign
2410 CMP AX,DX ;See if in range +127 to -128
2411 JZ OBJBT ;If so, it's always OK
2412 NOT AH ;Check for range +255 to -256
2413 CMP AH,DH
2414 JNZ RNGERR ;Must always be in this range
2415;Check for short jump. If so, we're out of range; otherwise we're OK
2416 CMP DI,START+1 ;Only one other byte on line?
2417 JNZ OBJBT ;Can't be short jump if not
2418 MOV AL,[START] ;Get the first byte of this line
2419 CMP AL,0EBH ;Direct short jump?
2420 JZ RNGERR
2421 AND AL,0FCH
2422 CMP AL,0E0H ;LOOP or JCXZ instruction?
2423 JZ RNGERR
2424 AND AL,0F0H
2425 CMP AL,70H ;Conditional jump?
2426 MOV AL,DL ;Get code byte in AL
2427 JNZ OBJBT ;If not, we're OK
2428RNGERR:
2429 MOV B,[ERR],101 ;Value out of range
2430 JP OBJBT
2431
2432FINIJ: JMP FINI
2433
2434EMARK:
2435 CMP AL,-1 ;End of file?
2436 JZ FINIJ
2437 CMP AL,-10 ;Special item?
2438 JA SPEND
2439 PUSH CX
2440 PUSH SI
2441 PUSH AX ;Save error code
2442 MOV AH,[LSTDEV]
2443 AND AH,0FEH ;Reset error indicator
2444 OR AL,[ERR] ;See if any errors on this line
2445 JZ NOERR
2446 OR AH,1 ;Send line to console if error occured
2447NOERR:
2448 MOV [LSTDEV],AH
2449 MOV CX,DI
2450 CALL STRTLIN ;Print address of line
2451 MOV SI,START
2452 SUB CX,SI ;Get count of bytes of code
2453 JZ SHOLIN
2454CODLP:
2455 LODB
2456 CALL SAVCD ;Ouput code to HEX and PRN files
2457 LOOP CODLP
2458SHOLIN:
2459 MOV AL,0
2460 XCHG AL,[COUNT]
2461 MOV CX,7 ;Allow 7 bytes of code per line
2462 SUB CL,AL
2463 MOV AL,' '
2464 JZ NOFIL
2465BLNK: ;Put in 3 blanks for each byte not present
2466 CALL LIST
2467 CALL LIST
2468 CALL LIST
2469 LOOP BLNK
2470NOFIL:
2471 CALL OUTLIN
2472 POP AX ;Restore error code
2473 CALL REPERR
2474 MOV AL,[ERR]
2475 CALL REPERR
2476 POP SI
2477 POP CX
2478 MOV AL,[SPC] ;Any special funtion?
2479 OR AL,AL
2480 JNZ SPCFUN
2481 JMP FIXLINE
2482
2483SPEND:
2484 MOV [SPC],AL ;Record special function
2485 LODW ;Get it's data
2486 MOV [DATA],AX
2487 JMP NEXBT
2488
2489SPCFUN:
2490 MOV DX,[DATA]
2491 CMP AL,-2
2492 JZ DORG
2493 CMP AL,-3
2494 JZ DPUT
2495DDS:
2496;Handle DS pseudo-op
2497 ADD [PC],DX
2498 ADD [HEXADD],DX
2499 JMP FIXLINE
2500
2501DORG:
2502;Handle ORG pseudo-op
2503 MOV [PC],DX
2504 JMP FIXLINE
2505
2506DPUT:
2507;Handle PUT pseudo-op
2508 MOV [HEXADD],DX
2509 JMP FIXLINE
2510
2511OUTLIN:
2512;Copy the source line to the ouput device. Line will be preceded by
2513;assembler-generated line number. This routine may be called several times
2514;on one line (once for each line of object code bytes), so it sets a flag
2515;so the line will only be output on the first call.
2516 MOV AL,-1
2517 XCHG AL,[LINFLG]
2518 OR AL,AL
2519 JNZ CRLF ;Output line only if first time
2520 MOV AX,[LINE]
2521 INC AX
2522 MOV [LINE],AX
2523 MOV BH,0 ;No leading zero suppression
2524 CALL OUT10
2525 MOV AL," "
2526 CALL LIST
2527 MOV AL,[LSTFCB]
2528 CMP AL,'Z'
2529 JZ CRLF ;Don't call NEXTCHR if listing suppressed
2530 PUSH SI ;Save the only register destroyed by NEXTCHR
2531OUTLN:
2532 CALL NEXTCHR
2533 CALL LIST
2534 CMP AL,10 ;Output until linefeed found
2535 JNZ OUTLN
2536 POP SI
2537 RET
2538
2539PRTCNT:
2540 MOV AX,[ERRCNT]
2541 MOV BX,ERCNTM
2542PRNT10:
2543 PUSH AX
2544 CALL PRINT
2545 POP AX
2546 MOV BH,"0"-" " ;Enable leading zero suppression
2547 CALL OUT10
2548CRLF:
2549 MOV AL,13
2550 CALL LIST
2551 MOV AL,10
2552 JP LIST
2553
2554OUT10:
2555 XOR DX,DX
2556 MOV DI,10000
2557 DIV AX,DI
2558 OR AL,AL ;>10,000?
2559 JNZ LEAD
2560 SUB AL,"0"-" " ;Convert leading zero to blank
2561LEAD:
2562 ADD AL,"0"
2563 CALL LIST
2564 XCHG AX,DX
2565 MOV BL,100
2566 DIV AL,BL
2567 MOV BL,AH
2568 CALL HIDIG ;Convert to decimal and print 1000s digit
2569 CALL DIGIT ;Print 100s digit
2570 MOV AL,BL
2571 CALL HIDIG ;Convert to decimal and print 10s digit
2572 MOV BH,0 ;Ensure leading zero suppression is off
2573 JP DIGIT
2574
2575HIDIG:
2576 AAM ;Convert binary to unpacked BCD
2577 OR AX,3030H ;Add "0" bias
2578DIGIT:
2579 XCHG AL,AH
2580 CMP AL,"0"
2581 JZ SUPZ
2582 MOV BH,0 ;Turn off zero suppression if not zero
2583SUPZ:
2584 SUB AL,BH ;Convert leading zeros to blanks
2585 JP LIST
2586
2587STRTLIN:
2588 MOV B,[LINFLG],0
2589 MOV BX,[PC]
2590 MOV AL,BH
2591 CALL PHEX
2592 MOV AL,BL
2593PHEXB:
2594 CALL PHEX
2595 MOV AL,' '
2596LIST:
2597 PUSH AX
2598 PUSH DX
2599 AND AL,7FH
2600 MOV DL,AL
2601 TEST B,[LSTDEV],3 ;See if output goes to console
2602 JZ PRNCHK
2603 MOV AH,2
2604 INT 33 ;Output to console
2605PRNCHK:
2606 TEST B,[LSTDEV],4 ;See if output goes to printer
2607 JZ FILCHK
2608 MOV AH,5
2609 INT 33 ;Output to printer
2610FILCHK:
2611 MOV AL,DL
2612 POP DX
2613 TEST B,[LSTDEV],80H ;See if output goes to a file
2614 JZ LISTRET
2615 CALL WRTBUF
2616LISTRET:
2617 POP AX
2618 RET
2619
2620WRTBUF:
2621 PUSH DI
2622 MOV DI,[LSTPNT]
2623 STOB
2624 CMP DI,LSTBUF+LSTBUFSIZ
2625 JNZ SAVPT
2626 PUSH AX
2627 PUSH CX
2628 PUSH DX
2629 CALL FLUSHBUF
2630 POP DX
2631 POP CX
2632 POP AX
2633SAVPT:
2634 MOV [LSTPNT],DI
2635 POP DI
2636 RET
2637
2638PHEX:
2639 PUSH AX
2640 CALL UHALF
2641 CALL LIST
2642 POP AX
2643 CALL LHALF
2644 JP LIST
2645
2646FINI:
2647 OR B,[LSTDEV],1
2648 CALL PRTCNT
2649 MOV BX,SYMSIZE
2650 MOV AX,[6]
2651 SUB AX,[HEAP] ;Size of symbol table
2652 CALL PRNT10
2653 MOV BX,FRESIZE
2654 MOV AX,[HEAP]
2655 SUB AX,[CODE] ;Free space remaining
2656 CALL PRNT10
2657 AND B,[LSTDEV],0FEH
2658 MOV AL,[HEXFCB]
2659 CMP AL,'Z'
2660 JZ SYMDMP
2661 MOV AL,[HEXCNT]
2662 CMP AL,-5
2663 JZ L0012
2664 CALL ENHEXL
2665L0012:
2666 MOV AL,':'
2667 CALL PUTCHR
2668 MOV CH,10
2669HEXEND:
2670 PUSH CX
2671 MOV AL,'0'
2672 CALL PUTCHR
2673 POP CX
2674 DEC CH
2675 JNZ HEXEND
2676 MOV AL,13
2677 CALL PUTCHR
2678 MOV AL,10
2679 CALL PUTCHR
2680 MOV AL,1AH
2681 CALL PUTCHR
2682 CALL WRTHEX ;Flush HEX file buffer
2683 MOV DX,HEXFCB
2684 MOV AH,CLOSE
2685 INT 33
2686SYMDMP:
2687 MOV AL,[SYMFLG]
2688 CMP AL,'S'
2689 JNZ ENDSYM
2690 MOV AL,[LSTDEV]
2691 OR AL,AL ;Any output device for symbol table dump?
2692 JNZ DOSYMTAB
2693 OR AL,1 ;If not, send it to console
2694 MOV [LSTDEV],AL
2695DOSYMTAB:
2696 MOV BX,SYMMES
2697 CALL PRINT
2698 MOV DX,[BASE]
2699 MOV AL,DH
2700 OR AL,DL
2701 JZ ENDSYM
2702 MOV B,[SYMLIN],SYMWID ;No symbols on this line yet
2703 MOV BX,[HEAP]
2704 MOV SP,BX ;Need maximum stack for recursive tree walk
2705 CALL NODE
2706ENDSYM:
2707 TEST B,[LSTDEV],80H ;Print listing to file?
2708 JZ EXIT
2709 MOV AL,1AH
2710 CALL WRTBUF ;Write end-of-file mark
2711 MOV DI,[LSTPNT]
2712 CALL FLUSHBUF
2713 MOV AH,CLOSE
2714 INT 33
2715EXIT: JMP 0
2716
2717NODE:
2718 XCHG DX,BX
2719 PUSH BX
2720 MOV DL,[BX]
2721 MOV DH,0
2722 INC BX
2723 ADD BX,DX
2724 MOV DX,[BX]
2725 OR DX,DX
2726 JZ L0014
2727 CALL NODE
2728L0014:
2729 POP BX
2730 MOV AL,[BX]
2731 INC BX
2732 MOV CH,AL
2733 ADD AL,24
2734 SHR AL
2735 SHR AL
2736 SHR AL
2737 MOV CL,AL
2738 INC CL ;Invert last bit
2739 AND CL,1 ;Number of extra tabs needed (0 or 1)
2740 SHR AL ;Number of positions wide this symbol needs
2741 SUB [SYMLIN],AL
2742 JNC WRTSYM ;Will it fit?
2743 SUB AL,SYMWID
2744 NEG AL
2745 MOV [SYMLIN],AL
2746 CALL CRLF ;Start new line if not
2747WRTSYM:
2748 MOV AL,[BX]
2749 INC BX
2750 CALL LIST
2751 DEC CH
2752 JNZ WRTSYM
2753 INC CL
2754TABVAL:
2755 MOV AL,9
2756 CALL LIST
2757 LOOP TABVAL
2758 INC BX
2759 INC BX
2760 PUSH BX
2761 MOV AL,[BX+4]
2762 CALL PHEX
2763 MOV AL,[BX+3]
2764 CALL PHEX
2765 CMP B,[SYMLIN],0 ;Will any more fit on line?
2766 JZ NEXSYMLIN
2767 MOV AL,9
2768 CALL LIST
2769 JP RIGHTSON
2770NEXSYMLIN:
2771 CALL CRLF
2772 MOV B,[SYMLIN],SYMWID
2773RIGHTSON:
2774 POP BX
2775 MOV DX,[BX]
2776 OR DX,DX
2777 JNZ NODE
2778 RET
2779
2780SAVCD:
2781 MOV [PREV],AL
2782 PUSH BX
2783 PUSH CX
2784 PUSH AX
2785 PUSH DX
2786 CALL CODBYT
2787 POP DX
2788 MOV BX,COUNT
2789 INC B,[BX]
2790 MOV AL,[BX]
2791 CMP AL,8
2792 JNZ NOEXT
2793 MOV B,[BX],1
2794 CALL OUTLIN
2795 MOV AL,' '
2796 MOV CH,5
2797TAB:
2798 CALL LIST
2799 DEC CH
2800 JNZ TAB
2801NOEXT:
2802 POP AX
2803 CALL PHEXB
2804 POP CX
2805 INC [PC]
2806 INC [HEXADD]
2807 POP BX
2808 RET
2809
2810REPERR:
2811 OR AL,AL ;Did an error occur?
2812 JZ RET
2813 INC [ERRCNT]
2814 PUSH AX
2815 MOV BX,ERRMES ;Print "ERROR"
2816 CALL PRINT
2817 POP AX
2818;We have error number in AL. See if there's an error message for it
2819 MOV DI,ERRTAB
2820 MOV BL,80H
2821ERRLOOK:
2822 SCASB ;Do we have the error message
2823 JBE HAVMES ;Quit looking if we have it or passed it
2824 XCHG AX,BX ;Put 80H in AL to look for end of this message
2825NEXTMES:
2826 SCASB ;Look for high bit set in message
2827 JA NEXTMES ; which means we've reached the end
2828 XCHG AX,BX ;Restore error number to AL
2829 JMPS ERRLOOK ;Keep looking
2830
2831HAVMES:
2832 MOV BX,DI ;Put address of message in BX
2833 JZ PRNERR ;Do we have a message for this error?
2834 CALL PHEX ;If not, just print error number
2835 JMP CRLF
2836
2837PRNERR:
2838 CALL PRINT
2839 JMP CRLF
2840
2841PRINT:
2842 MOV AL,[BX]
2843 CALL LIST
2844 OR AL,AL
2845 JS RET
2846 INC BX
2847 JP PRINT
2848
2849OUTA:
2850 MOV DL,AL
2851OUT:
2852 AND DL,7FH
2853 MOV CL,2
2854SYSTEM:
2855 CALL 5
2856 RET
2857
2858CODBYT:
2859 CMP B,[HEXFCB],"Z"
2860 JZ RET
2861 PUSH AX
2862 MOV DX,[LASTAD]
2863 MOV BX,[HEXADD]
2864 MOV [LASTAD],BX
2865 INC DX
2866 MOV AL,[HEXCNT]
2867 CMP AL,-5
2868 JZ NEWLIN
2869 CMP BX,DX
2870 JZ AFHEX
2871 CALL ENHEXL
2872NEWLIN:
2873 MOV AL,':'
2874 CALL PUTCHR
2875 MOV AL,-4
2876 MOV [HEXCNT],AL
2877 XOR AL,AL
2878 MOV [CHKSUM],AL
2879 MOV BX,[HEXPNT]
2880 MOV [HEXLEN],BX
2881 CALL HEXBYT
2882 MOV AL,[HEXADD+1]
2883 CALL HEXBYT
2884 MOV AL,[HEXADD]
2885 CALL HEXBYT
2886 XOR AL,AL
2887 CALL HEXBYT
2888AFHEX:
2889 POP AX
2890HEXBYT:
2891 MOV CH,AL
2892 MOV BX,CHKSUM
2893 ADD AL,[BX]
2894 MOV [BX],AL
2895 MOV AL,CH
2896 CALL UHALF
2897 CALL PUTCHR
2898 MOV AL,CH
2899 CALL LHALF
2900 CALL PUTCHR
2901 MOV BX,HEXCNT
2902 INC B,[BX]
2903 MOV AL,[BX]
2904 CMP AL,26
2905 JNZ RET
2906ENHEXL:
2907 MOV DI,[HEXLEN]
2908 MOV CH,AL
2909 CALL UHALF
2910 STOB
2911 MOV AL,CH
2912 CALL LHALF
2913 STOB
2914 MOV AL,-6
2915 MOV [HEXCNT],AL
2916 MOV AL,[CHKSUM]
2917 ADD AL,CH
2918 NEG AL
2919 CALL HEXBYT
2920 MOV AL,13
2921 CALL PUTCHR
2922 MOV AL,10
2923 CALL PUTCHR
2924WRTHEX:
2925;Write out the line
2926 MOV DX,HEXBUF
2927 MOV [HEXPNT],DX
2928 MOV AH,SETDMA
2929 INT 33
2930 SUB DI,DX ;Length of buffer
2931 MOV CX,DI
2932 MOV DX,HEXFCB
2933 MOV AH,BLKWRT
2934 INT 33
2935 OR AL,AL
2936 JNZ DSKFUL
2937 RET
2938
2939PUTCHR:
2940 MOV DI,[HEXPNT]
2941 STOB
2942 MOV [HEXPNT],DI
2943 RET
2944
2945FLUSHBUF:
2946 MOV CX,DI
2947 MOV DX,LSTBUF
2948 MOV DI,DX
2949 SUB CX,DX
2950 JZ RET ;Buffer empty?
2951 MOV AH,SETDMA
2952 INT 33
2953 MOV DX,LSTFCB
2954 MOV AH,BLKWRT
2955 INT 33
2956 OR AL,AL
2957 JZ RET
2958DSKFUL:
2959 MOV BX,WRTERR
2960 JMP PRERR
2961
2962UHALF:
2963 RCR AL
2964 RCR AL
2965 RCR AL
2966 RCR AL
2967LHALF:
2968 AND AL,0FH
2969 OR AL,30H
2970 CMP AL,'9'+1
2971 JC RET
2972 ADD AL,7
2973 RET
2974
2975NONE: DB 0
2976
2977; 8086 MNEMONIC TABLE
2978
2979; This table is actually a sequence of subtables, each starting with a label.
2980; The label signifies which mnemonics the subtable applies to--A3, for example,
2981; means all 3-letter mnemonics beginning with A.
2982
2983A3:
2984 DB 7
2985 DB 'dd'
2986 DW GRP7
2987 DB 2
2988 DB 'nd'
2989 DW GRP13
2990 DB 22H
2991 DB 'dc'
2992 DW GRP7
2993 DB 12H
2994 DB 'aa'
2995 DW PUT
2996 DB 37H
2997 DB 'as'
2998 DW PUT
2999 DB 3FH
3000 DB 'am'
3001 DW GRP11
3002 DB 0D4H
3003 DB 'ad'
3004 DW GRP11
3005 DB 0D5H
3006A5:
3007 DB 1
3008 DB 'lign'
3009 DW ALIGN
3010 DB 0
3011C3:
3012 DB 7
3013 DB 'mp'
3014 DW GRP7
3015 DB 3AH
3016 DB 'lc'
3017 DW PUT
3018 DB 0F8H
3019 DB 'ld'
3020 DW PUT
3021 DB 0FCH
3022 DB 'li'
3023 DW PUT
3024 DB 0FAH
3025 DB 'mc'
3026 DW PUT
3027 DB 0F5H
3028 DB 'bw'
3029 DW PUT
3030 DB 98H
3031 DB 'wd'
3032 DW PUT
3033 DB 99H
3034C4:
3035 DB 3
3036 DB 'all'
3037 DW GRP14
3038 DB 9AH
3039 DB 'mpb'
3040 DW PUT
3041 DB 0A6H
3042 DB 'mpw'
3043 DW PUT
3044 DB 0A7H
3045C5:
3046 DB 2
3047 DB 'mpsb'
3048 DW PUT
3049 DB 0A6H
3050 DB 'mpsw'
3051 DW PUT
3052 DB 0A7H
3053D2:
3054 DB 5
3055 DB 'b'
3056 DW GRP23
3057 DB 1
3058 DB 'w'
3059 DW GRP23
3060 DB 0
3061 DB 'm'
3062 DW GRP23
3063 DB 2
3064 DB 's'
3065 DW GRP5
3066 DB 1
3067 DB 'i'
3068 DW PUT
3069 DB 0FAH
3070D3:
3071 DB 4
3072 DB 'ec'
3073 DW GRP8
3074 DB 49H
3075 DB 'iv'
3076 DW GRP10
3077 DB 30H
3078 DB 'aa'
3079 DW PUT
3080 DB 27H
3081 DB 'as'
3082 DW PUT
3083 DB 2FH
3084D4:
3085 DB 1
3086 DB 'own'
3087 DW PUT
3088 DB 0FDH
3089E2:
3090 DB 1
3091 DB 'i'
3092 DW PUT
3093 DB 0FBH
3094E3:
3095 DB 3
3096 DB 'qu'
3097 DW GRP5
3098 DB 2
3099 DB 'sc'
3100 DW GRP19
3101 DB 0D8H
3102 DB 'nd'
3103 DW END
3104 DB 0
3105E5:
3106 DB 1
3107 DB 'ndif'
3108 DW ENDIF
3109 DB 0
3110H3:
3111 DB 1
3112 DB 'lt'
3113 DW PUT
3114 DB 0F4H
3115H4:
3116 DB 1
3117 DB 'alt'
3118 DW PUT
3119 DB 0F4H
3120I2:
3121 DB 2
3122 DB 'n'
3123 DW GRP4
3124 DB 0E4H
3125 DB 'f'
3126 DW GRP5
3127 DB 4
3128I3:
3129 DB 4
3130 DB 'nc'
3131 DW GRP8
3132 DB 41H
3133 DB 'nb'
3134 DW GRP4
3135 DB 0E4H
3136 DB 'nw'
3137 DW GRP4
3138 DB 0E5H
3139 DB 'nt'
3140 DW GRP18
3141 DB 0CCH
3142I4:
3143 DB 4
3144 DB 'mul'
3145 DW GRP10
3146 DB 28H
3147 DB 'div'
3148 DW GRP10
3149 DB 38H
3150 DB 'ret'
3151 DW PUT
3152 DB 0CFH
3153 DB 'nto'
3154 DW PUT
3155 DB 0CEH
3156J2:
3157 DB 10
3158 DB 'p'
3159 DW GRP17
3160 DB 0EBH
3161 DB 'z'
3162 DW GRP17
3163 DB 74H
3164 DB 'e'
3165 DW GRP17
3166 DB 74H
3167 DB 'l'
3168 DW GRP17
3169 DB 7CH
3170 DB 'b'
3171 DW GRP17
3172 DB 72H
3173 DB 'a'
3174 DW GRP17
3175 DB 77H
3176 DB 'g'
3177 DW GRP17
3178 DB 7FH
3179 DB 'o'
3180 DW GRP17
3181 DB 70H
3182 DB 's'
3183 DW GRP17
3184 DB 78H
3185 DB 'c'
3186 DW GRP17
3187 DB 72H
3188J3:
3189 DB 17
3190 DB 'mp'
3191 DW GRP14
3192 DB 0EAH
3193 DB 'nz'
3194 DW GRP17
3195 DB 75H
3196 DB 'ne'
3197 DW GRP17
3198 DB 75H
3199 DB 'nl'
3200 DW GRP17
3201 DB 7DH
3202 DB 'ge'
3203 DW GRP17
3204 DB 7DH
3205 DB 'nb'
3206 DW GRP17
3207 DB 73H
3208 DB 'ae'
3209 DW GRP17
3210 DB 73H
3211 DB 'nc'
3212 DW GRP17
3213 DB 73H
3214 DB 'ng'
3215 DW GRP17
3216 DB 7EH
3217 DB 'le'
3218 DW GRP17
3219 DB 7EH
3220 DB 'na'
3221 DW GRP17
3222 DB 76H
3223 DB 'be'
3224 DW GRP17
3225 DB 76H
3226 DB 'pe'
3227 DW GRP17
3228 DB 7AH
3229 DB 'np'
3230 DW GRP17
3231 DB 7BH
3232 DB 'po'
3233 DW GRP17
3234 DB 7BH
3235 DB 'no'
3236 DW GRP17
3237 DB 71H
3238 DB 'ns'
3239 DW GRP17
3240 DB 79H
3241J4:
3242 DB 6
3243 DB 'mps'
3244 DW GRP17
3245 DB 0EBH
3246 DB 'cxz'
3247 DW GRP17
3248 DB 0E3H
3249 DB 'nge'
3250 DW GRP17
3251 DB 7CH
3252 DB 'nae'
3253 DW GRP17
3254 DB 72H
3255 DB 'nbe'
3256 DW GRP17
3257 DB 77H
3258 DB 'nle'
3259 DW GRP17
3260 DB 7FH
3261L3:
3262 DB 3
3263 DB 'ea'
3264 DW GRP6
3265 DB 8DH
3266 DB 'ds'
3267 DW GRP6
3268 DB 0C5H
3269 DB 'es'
3270 DW GRP6
3271 DB 0C4H
3272L4:
3273 DB 5
3274 DB 'oop'
3275 DW GRP17
3276 DB 0E2H
3277 DB 'odb'
3278 DW PUT
3279 DB 0ACH
3280 DB 'odw'
3281 DW PUT
3282 DB 0ADH
3283 DB 'ahf'
3284 DW PUT
3285 DB 9FH
3286 DB 'ock'
3287 DW PUT
3288 DB 0F0H
3289L5:
3290 DB 4
3291 DB 'oope'
3292 DW GRP17
3293 DB 0E1H
3294 DB 'oopz'
3295 DW GRP17
3296 DB 0E1H
3297 DB 'odsb'
3298 DW PUT
3299 DB 0ACH
3300 DB 'odsw'
3301 DW PUT
3302 DB 0ADH
3303L6:
3304 DB 2
3305 DB 'oopne'
3306 DW GRP17
3307 DB 0E0H
3308 DB 'oopnz'
3309 DW GRP17
3310 DB 0E0H
3311M3:
3312 DB 2
3313 DB 'ov'
3314 DW GRP1
3315 DB 88H
3316 DB 'ul'
3317 DW GRP10
3318 DB 20H
3319M4:
3320 DB 2
3321 DB 'ovb'
3322 DW PUT
3323 DB 0A4H
3324 DB 'ovw'
3325 DW PUT
3326 DB 0A5H
3327M5:
3328 DB 2
3329 DB 'ovsb'
3330 DW PUT
3331 DB 0A4H
3332 DB 'ovsw'
3333 DW PUT
3334 DB 0A5H
3335N3:
3336 DB 3
3337 DB 'ot'
3338 DW GRP9
3339 DB 10H
3340 DB 'eg'
3341 DW GRP9
3342 DB 18H
3343 DB 'op'
3344 DW PUT
3345 DB 90H
3346O2:
3347 DB 1
3348 DB 'r'
3349 DW GRP13
3350 DB 0AH
3351O3:
3352 DB 2
3353 DB 'ut'
3354 DW GRP4
3355 DB 0E6H
3356 DB 'rg'
3357 DW GRP5
3358 DB 0
3359O4:
3360 DB 2
3361 DB 'utb'
3362 DW GRP4
3363 DB 0E6H
3364 DB 'utw'
3365 DW GRP4
3366 DB 0E7H
3367P3:
3368 DB 2
3369 DB 'op'
3370 DW GRP22
3371 DB 8FH
3372 DB 'ut'
3373 DW GRP5
3374 DB 3
3375P4:
3376 DB 2
3377 DB 'ush'
3378 DW GRP2
3379 DB 0FFH
3380 DB 'opf'
3381 DW PUT
3382 DB 9DH
3383P5:
3384 DB 1
3385 DB 'ushf'
3386 DW PUT
3387 DB 9CH
3388R3:
3389 DB 6
3390 DB 'et'
3391 DW GRP16
3392 DB 0C3H
3393 DB 'ep'
3394 DW PUT
3395 DB 0F3H
3396 DB 'ol'
3397 DW GRP12
3398 DB 0
3399 DB 'or'
3400 DW GRP12
3401 DB 8
3402 DB 'cl'
3403 DW GRP12
3404 DB 10H
3405 DB 'cr'
3406 DW GRP12
3407 DB 18H
3408R4:
3409 DB 2
3410 DB 'epz'
3411 DW PUT
3412 DB 0F3H
3413 DB 'epe'
3414 DW PUT
3415 DB 0F3H
3416R5:
3417 DB 2
3418 DB 'epnz'
3419 DW PUT
3420 DB 0F2H
3421 DB 'epne'
3422 DW PUT
3423 DB 0F2H
3424S3:
3425 DB 11
3426 DB 'ub'
3427 DW GRP7
3428 DB 2AH
3429 DB 'bb'
3430 DW GRP7
3431 DB 1AH
3432 DB 'bc'
3433 DW GRP7
3434 DB 1AH
3435 DB 'tc'
3436 DW PUT
3437 DB 0F9H
3438 DB 'td'
3439 DW PUT
3440 DB 0FDH
3441 DB 'ti'
3442 DW PUT
3443 DB 0FBH
3444 DB 'hl'
3445 DW GRP12
3446 DB 20H
3447 DB 'hr'
3448 DW GRP12
3449 DB 28H
3450 DB 'al'
3451 DW GRP12
3452 DB 20H
3453 DB 'ar'
3454 DW GRP12
3455 DB 38H
3456 DB 'eg'
3457 DW GRP21
3458 DB 26H
3459S4:
3460 DB 5
3461 DB 'cab'
3462 DW PUT
3463 DB 0AEH
3464 DB 'caw'
3465 DW PUT
3466 DB 0AFH
3467 DB 'tob'
3468 DW PUT
3469 DB 0AAH
3470 DB 'tow'
3471 DW PUT
3472 DB 0ABH
3473 DB 'ahf'
3474 DW PUT
3475 DB 9EH
3476S5:
3477 DB 4
3478 DB 'casb'
3479 DW PUT
3480 DB 0AEH
3481 DB 'casw'
3482 DW PUT
3483 DB 0AFH
3484 DB 'tosb'
3485 DW PUT
3486 DB 0AAH
3487 DB 'tosw'
3488 DW PUT
3489 DB 0ABH
3490T4:
3491 DB 1
3492 DB 'est'
3493 DW GRP20
3494 DB 84H
3495U2:
3496 DB 1
3497 DB 'p'
3498 DW PUT
3499 DB 0FCH
3500W4:
3501 DB 1
3502 DB 'ait'
3503 DW PUT
3504 DB 9BH
3505X3:
3506 DB 1
3507 DB 'or'
3508 DW GRP13
3509 DB 32H
3510X4:
3511 DB 2
3512 DB 'chg'
3513 DW GRP3
3514 DB 86H
3515 DB 'lat'
3516 DW PUT
3517 DB 0D7H
3518
3519
3520; 8087 MNEMONIC TABLE
3521; Similar to 8086 table above, except NOT distinguished by opcode length
3522
3523XM1: ;F2XM1
3524 DB 1 ;One opcode
3525 DM "xm1"
3526 DB 1,0F0H
3527
3528NDPA:
3529 DB 3
3530 DM "dd"
3531 DB 6+ARITH,0C1H
3532 DM "ddp"
3533 DB NEEDOP+STACKOP,0
3534 DM "bs"
3535 DB 1,0E1H
3536
3537NDPB:
3538 DB 2
3539 DM "ld"
3540 DB 7+NEEDOP+MEMORY,20H
3541 DM "stp"
3542 DB 7+NEEDOP+MEMORY,30H
3543
3544NDPC:
3545 DB 5
3546 DM "om"
3547 DB 0+ONEREG+REAL,0D1H
3548 DM "omp"
3549 DB 0+ONEREG+REAL,0D9H
3550 DM "hs"
3551 DB 1,0E0H
3552 DM "ompp"
3553 DB 6,0D9H
3554 DM "lex"
3555 DB 3,0E2H
3556
3557NDPD:
3558 DB 6
3559 DM "iv"
3560 DB 6+ARITH,0F1H
3561 DM "ivp"
3562 DB NEEDOP+STACKOP,30H
3563 DM "ivr"
3564 DB 6+ARITH,0F9H
3565 DM "ivrp"
3566 DB NEEDOP+STACKOP,38H
3567 DM "ecstp"
3568 DB 1,0F6H
3569 DM "isi"
3570 DB 3,0E1H
3571
3572NDPE:
3573 DB 1
3574 DM "ni"
3575 DB 3,0E0H
3576
3577NDPF:
3578 DB 1
3579 DM "ree"
3580 DB 5+NEEDOP+ONEREG,0
3581
3582NDPI:
3583 DB 13
3584 DM "add"
3585 DB 2+NEEDOP+INTEGER,0
3586 DM "ld"
3587 DB 3+NEEDOP+INTEGER+EXTENDED,0
3588 DM "sub"
3589 DB 2+NEEDOP+INTEGER,20H
3590 DM "stp"
3591 DB 3+NEEDOP+INTEGER+EXTENDED,18H
3592 DM "st"
3593 DB 3+NEEDOP+INTEGER,10H
3594 DM "mul"
3595 DB 2+NEEDOP+INTEGER,8
3596 DM "div"
3597 DB 2+NEEDOP+INTEGER,30H
3598 DM "subr"
3599 DB 2+NEEDOP+INTEGER,28H
3600 DM "divr"
3601 DB 2+NEEDOP+INTEGER,38H
3602 DM "com"
3603 DB 2+NEEDOP+INTEGER,10H
3604 DM "comp"
3605 DB 2+NEEDOP+INTEGER,18H
3606 DM "ncstp"
3607 DB 1,0F7H
3608 DM "nit"
3609 DB 3,0E3H
3610
3611NDPL:
3612 DB 10
3613 DM "d"
3614 DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0
3615 DM "dz"
3616 DB 1,0EEH
3617 DM "d1"
3618 DB 1,0E8H
3619 DM "dpi"
3620 DB 1,0EBH
3621 DM "dl2t"
3622 DB 1,0E9H
3623 DM "dl2e"
3624 DB 1,0EAH
3625 DM "dlg2"
3626 DB 1,0ECH
3627 DM "dln2"
3628 DB 1,0EDH
3629 DM "dcw"
3630 DB 1+NEEDOP+MEMORY,28H
3631 DM "denv"
3632 DB 1+NEEDOP+MEMORY,20H
3633
3634NDPM:
3635 DB 2
3636 DM "ul"
3637 DB 6+ARITH,0C9H
3638 DM "ulp"
3639 DB NEEDOP+STACKOP,8
3640
3641NDPO:
3642 DB 1
3643 DM "p"
3644 DB NEEDOP+1,0 ;Flag special handling
3645
3646NDPN:
3647 DB 1
3648 DM "op"
3649 DB 1,0D0H
3650
3651NDPP:
3652 DB 3
3653 DM "rem"
3654 DB 1,0F8H
3655 DM "tan"
3656 DB 1,0F2H
3657 DM "atan"
3658 DB 1,0F3H
3659
3660NDPR:
3661 DB 2
3662 DM "ndint"
3663 DB 1,0FCH
3664 DM "stor"
3665 DB 5+NEEDOP+MEMORY,20H
3666
3667NDPS:
3668 DB 12
3669 DM "t"
3670 DB 5+NEEDOP+ONEREG+REAL,0D0H
3671 DM "tp"
3672 DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H
3673 DM "ub"
3674 DB 6+ARITH,0E1H
3675 DM "ubp"
3676 DB NEEDOP+STACKOP,0E0H
3677 DM "ubr"
3678 DB 6+ARITH,0E9H
3679 DM "ubrp"
3680 DB NEEDOP+STACKOP,0E8H
3681 DM "qrt"
3682 DB 1,0FAH
3683 DM "cale"
3684 DB 1,0FDH
3685 DM "ave"
3686 DB 5+NEEDOP+MEMORY,30H
3687 DM "tcw"
3688 DB 1+NEEDOP+MEMORY,38H
3689 DM "tenv"
3690 DB 1+NEEDOP+MEMORY,30H
3691 DM "tsw"
3692 DB 5+NEEDOP+MEMORY,38H
3693
3694NDPT:
3695 DB 1
3696 DM "st"
3697 DB 1,0E4H
3698
3699NDPW:
3700 DB 1
3701 DM "ait"
3702 DB NEEDOP,0 ;Flag special handling
3703
3704NDPX:
3705 DB 3
3706 DM "ch"
3707 DB 1+ONEREG,0C9H
3708 DM "am"
3709 DB 1,0E5H
3710 DM "tract"
3711 DB 1,0F4H
3712
3713NDPY:
3714 DB 2
3715 DM "l2x"
3716 DB 1,0F1H
3717 DM "l2xp1"
3718 DB 1,0F9H
3719
3720
3721OPTAB:
3722; Table of pointers to mnemonics. For each letter of the alphabet (the
3723; starting letter of the mnemonic), there are 5 entries. Each entry
3724; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters
3725; long, respectively. If there are no mnemonics for a given combination
3726; of first letter and length (such as A-2), then the corresponding entry
3727; points to NONE. Otherwise, it points to a place in the mnemonic table
3728; for that type.
3729
3730; This table only needs to be modified if a mnemonic is added to a group
3731; previously marked NONE. Change the NONE to a label made up of the first
3732; letter of the mnemonic and its length, then add a new subsection to
3733; the mnemonic table in alphabetical order.
3734
3735 DW NONE
3736 DW A3
3737 DW NONE
3738 DW A5
3739 DW NONE
3740 DW NONE ;B
3741 DW NONE
3742 DW NONE
3743 DW NONE
3744 DW NONE
3745 DW NONE ;C
3746 DW C3
3747 DW C4
3748 DW C5
3749 DW NONE
3750 DW D2 ;D
3751 DW D3
3752 DW D4
3753 DW NONE
3754 DW NONE
3755 DW E2 ;E
3756 DW E3
3757 DW NONE
3758 DW E5
3759 DW NONE
3760 DW NONE ;F
3761 DW NONE
3762 DW NONE
3763 DW NONE
3764 DW NONE
3765 DW NONE ;G
3766 DW NONE
3767 DW NONE
3768 DW NONE
3769 DW NONE
3770 DW NONE ;H
3771 DW H3
3772 DW H4
3773 DW NONE
3774 DW NONE
3775 DW I2 ;I
3776 DW I3
3777 DW I4
3778 DW NONE
3779 DW NONE
3780 DW J2 ;J
3781 DW J3
3782 DW J4
3783 DW NONE
3784 DW NONE
3785 DW NONE ;K
3786 DW NONE
3787 DW NONE
3788 DW NONE
3789 DW NONE
3790 DW NONE ;L
3791 DW L3
3792 DW L4
3793 DW L5
3794 DW L6
3795 DW NONE ;M
3796 DW M3
3797 DW M4
3798 DW M5
3799 DW NONE
3800 DW NONE ;N
3801 DW N3
3802 DW NONE
3803 DW NONE
3804 DW NONE
3805 DW O2 ;O
3806 DW O3
3807 DW O4
3808 DW NONE
3809 DW NONE
3810 DW NONE ;P
3811 DW P3
3812 DW P4
3813 DW P5
3814 DW NONE
3815 DW NONE ;Q
3816 DW NONE
3817 DW NONE
3818 DW NONE
3819 DW NONE
3820 DW NONE ;R
3821 DW R3
3822 DW R4
3823 DW R5
3824 DW NONE
3825 DW NONE ;S
3826 DW S3
3827 DW S4
3828 DW S5
3829 DW NONE
3830 DW NONE ;T
3831 DW NONE
3832 DW T4
3833 DW NONE
3834 DW NONE
3835 DW U2 ;U
3836 DW NONE
3837 DW NONE
3838 DW NONE
3839 DW NONE
3840 DW NONE ;V
3841 DW NONE
3842 DW NONE
3843 DW NONE
3844 DW NONE
3845 DW NONE ;W
3846 DW NONE
3847 DW W4
3848 DW NONE
3849 DW NONE
3850 DW NONE ;X
3851 DW X3
3852 DW X4
3853 DW NONE
3854 DW NONE
3855 DW NONE ;Y
3856 DW NONE
3857 DW NONE
3858 DW NONE
3859 DW NONE
3860 DW NONE ;Z
3861 DW NONE
3862 DW NONE
3863 DW NONE
3864 DW NONE
3865
3866NDPTAB:
3867;Lookup table for 8087 mnemonics. There is one entry for each letter of the
3868;alphabet
3869 DW NDPA
3870 DW NDPB
3871 DW NDPC
3872 DW NDPD
3873 DW NDPE
3874 DW NDPF
3875 DW NONE ;G
3876 DW NONE ;H
3877 DW NDPI
3878 DW NONE ;J
3879 DW NONE ;K
3880 DW NDPL
3881 DW NDPM
3882 DW NDPN
3883 DW NDPO
3884 DW NDPP
3885 DW NONE ;Q
3886 DW NDPR
3887 DW NDPS
3888 DW NDPT
3889 DW NONE ;U
3890 DW NONE ;V
3891 DW NDPW
3892 DW NDPX
3893 DW NDPY
3894 DW NONE ;Z
3895
3896;Error message table
3897
3898ERRTAB:
3899 DM 1,"Register not allowed in immediate value"
3900 DM 2,"Index or base register must be BP, BX, SI, or DI"
3901 DM 3,"Only one base register (BX, BP) allowed"
3902 DM 4,"Only one index register (SI or DI) allowed"
3903 DM 5,"Only addition allowed on register or undefined label"
3904 DM 6,"Only one undefined label per expression allowed"
3905 DM 7,"Illegal digit in hexadecimal number"
3906 DM 8,"Illegal digit in decimal number"
3907 DM 10,"Illegal character in label or opcode"
3908 DM 11,"Label defined twice"
3909 DM 12,"Opcode not recognized"
3910 DM 20,"Invalid operand"
3911 DM 21,'"," and second operand expected'
3912 DM 22,"Register mismatch"
3913 DM 23,"Immediate operand not allowed"
3914 DM 24,'"]" expected'
3915 DM 25,"Two memory operands not allowed"
3916 DM 26,"Destination must not be immediate value"
3917 DM 27,"Both operands must not be registers"
3918 DM 28,"Operand must be segment register"
3919 DM 29,"First operand must be register"
3920 DM 30,"Undefined label not allowed"
3921 DM 31,"Value out of range"
3922 DM 32,"Missing or illegal operand size flag"
3923 DM 33,"Must have label on same line"
3924 DM 35,"Zero-length string illegal"
3925 DM 36,"ENDIF without IF"
3926 DM 37,"One-character strings only"
3927 DM 38,"Illegal expression"
3928 DM 39,"End of string not found"
3929 DM 100,"Undefined label"
3930 DM 101,"Value out of range (forward)"
3931 DB 255
3932
3933ERRMES: DM '***** ERROR: '
3934NOSPAC: DB 13,10,'File creation error',13,10,"$"
3935NOMEM: DB 13,10,'Insufficient memory',13,10,'$'
3936NOFILE: DB 13,10,'File not found',13,10,'$'
3937WRTERR: DB 13,10,'Disk full',13,10,'$'
3938BADDSK: DB 13,10,'Bad disk specifier',13,10,'$'
3939ERCNTM: DM 13,10,13,10,'Error Count ='
3940SYMSIZE DM 13,10,'Symbol Table size = '
3941FRESIZE DM 'Free space = '
3942SYMMES: DM 13,10,'Symbol Table',13,10,13,10
3943EXTEND: DB 'ASM',0,0
3944IFEND: DB 5,'endif'
3945IFNEST: DB 2,'if'
3946RETSTR: DM 'ret'
3947HEXFCB: DB 0,' HEX',0,0,0,0
3948 DS 16
3949 DB 0,0,0,0,0
3950LSTFCB: DB 0,' PRN',0,0,0,0
3951 DS 16
3952 DB 0,0,0,0,0
3953PC: DS 2
3954OLDPC: DS 2
3955LABPT: DS 2
3956FLAG: DS 1
3957MAXFLG: DS 1
3958ADDR: DS 2
3959ALABEL: DS 2
3960DATA: DS 2
3961DLABEL: DS 2
3962CON: DS 2
3963UNDEF: DS 2
3964LENID: DS 1
3965ID: DS 80
3966CHR: DS 1
3967SYM: DS 1
3968BASE: DS 2
3969HEAP: DS 2
3970SYMFLG: DS 1
3971SYMLIN: DS 1
3972CODE: DS 2
3973DATSIZ: DS 1
3974RELOC: DS 1
3975BCOUNT: DS 1
3976COUNT: DS 1
3977ERR: DS 1
3978LINE: DS 2
3979HEXLEN: DS 2
3980HEXADD: DS 2
3981LASTAD: DS 2
3982HEXCNT: DS 1
3983CHKSUM: DS 1
3984LINFLG: DS 1
3985PREV: DS 1
3986IFFLG: DS 1
3987CHKLAB: DS 1
3988ERRCNT: DS 2
3989LSTRET: DS 2
3990RETPT: DS 2
3991LSTDEV: DS 2
3992SPC: DS 1
3993NOWAIT: DS 1
3994IX: DS 2
3995IY: DS 2
3996HEXPNT: DS 2
3997LSTPNT: DS 2
3998HEXBUF: DS HEXBUFSIZ
3999LSTBUF: DS LSTBUFSIZ
4000BUFPT: DS 2
4001SRCBUF: DS BUFSIZ
4002 DS 100H
4003 ALIGN
4004STACK: EQU $
4005START: EQU $
4006 \ No newline at end of file
diff --git a/v1.25/source/COMMAND.ASM b/v1.25/source/COMMAND.ASM
new file mode 100644
index 0000000..830bf73
--- /dev/null
+++ b/v1.25/source/COMMAND.ASM
@@ -0,0 +1,2166 @@
1; COMMAND version 1.17
2;
3; This version of COMMAND is divided into three distinct parts. First
4; is the resident portion, which includes handlers for interrupts
5; 22H (terminate), 23H (Cntrl-C), 24H (fatal error), and 27H (stay
6; resident); it also has code to test and, if necessary, reload the
7; transient portion. Following the resident is the init code, which is
8; overwritten after use. Then comes the transient portion, which
9; includes all command processing (whether internal or external).
10; The transient portion loads at the end of physical memory, and it may
11; be overlayed by programs that need as much memory as possible. When
12; the resident portion of command regains control from a user program,
13; a checksum is performed on the transient portion to see if it must be
14; reloaded. Thus programs which do not need maximum memory will save
15; the time required to reload COMMAND when they terminate.
16
17;Use the following booleans to set assembly flags
18FALSE EQU 0
19TRUE EQU NOT FALSE
20
21IBMVER EQU FALSE ;Switch to build IBM version of Command
22MSVER EQU TRUE ;Switch to build MS-DOS version of Command
23
24HIGHMEM EQU TRUE ;Run resident part above transient (high memory)
25
26LINPERPAG EQU 23
27NORMPERLIN EQU 1
28WIDEPERLIN EQU 5
29
30 IF IBMVER
31SYM EQU ">"
32COMDRV EQU 1
33 ENDIF
34
35 IF MSVER
36SYM EQU ":"
37COMDRV EQU 0
38 ENDIF
39
40FCB EQU 5CH
41DSKRESET EQU 13
42SETBASE EQU 38
43SRCHFRST EQU 17
44SRCHNXT EQU 18
45RENAM EQU 23
46INCHAR EQU 1
47GETFAT EQU 27
48OPEN EQU 15
49CLOSE EQU 16
50MAKE EQU 22
51DELETE EQU 19
52RDBLK EQU 39
53WRBLK EQU 40
54SETDMA EQU 26
55SELDRV EQU 14
56GETDRV EQU 25
57PRINTBUF EQU 9
58OUTCH EQU 2
59INBUF EQU 10
60GETDATE EQU 2AH
61SETDATE EQU 2BH
62GETTIME EQU 2CH
63SETTIME EQU 2DH
64RR EQU 33
65RECLEN EQU 14
66FILLEN EQU 16
67OFFDATE EQU 20
68
69
70;The following are all of the segments used in the load order
71
72CODERES SEGMENT
73CODERES ENDS
74
75DATARES SEGMENT BYTE
76DATARES ENDS
77
78INIT SEGMENT BYTE
79INIT ENDS
80
81TAIL SEGMENT PARA
82TAIL ENDS
83
84TRANCODE SEGMENT PARA
85TRANCODE ENDS
86
87TRANDATA SEGMENT BYTE
88TRANDATA ENDS
89
90TRANSPACE SEGMENT BYTE
91TRANSPACE ENDS
92
93RESGROUP GROUP CODERES,DATARES,INIT,TAIL
94TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE
95
96;Data for resident portion
97
98DATARES SEGMENT BYTE
99 ORG 0
100ZERO = $
101MESBAS DW OFFSET RESGROUP:ERR0
102 DW OFFSET RESGROUP:ERR2
103 DW OFFSET RESGROUP:ERR4
104 DW OFFSET RESGROUP:ERR6
105 DW OFFSET RESGROUP:ERR8
106 DW OFFSET RESGROUP:ERR10
107 DW OFFSET RESGROUP:ERR12
108ERR0 DB "Write protect$"
109ERR2 DB "Not ready$"
110ERR4 DB "Data$"
111ERR6 DB "Seek$"
112ERR8 DB "Sector not found$"
113ERR10 DB "Write fault$"
114ERR12 DB "Disk$"
115READ DB "read$"
116WRITE DB "writ$"
117ERRMES DB " error "
118IOTYP DB "writing"
119DRVNUM DB " drive "
120DRVLET DB "A"
121NEWLIN DB 13,10,"$"
122REQUEST DB "Abort, Retry, Ignore? $"
123BADFAT DB 13,10,"File allocation table bad,$"
124COMBAD DB 13,10,"Invalid COMMAND.COM"
125NEEDCOM DB 13,10,"Insert DOS disk in "
126 IF IBMVER
127 DB "drive A"
128 ELSE
129 DB "default drive"
130 ENDIF
131PROMPT DB 13,10,"and strike any key when ready",13,10,"$"
132NEEDBAT DB 13,10,"Insert disk with batch file$"
133ENDBATMES DB 13,10,"Terminate batch job (Y/N)? $"
134LOADING DB 0
135BATFCB DB 1,"AUTOEXECBAT"
136 DB 21 DUP(?)
137 DW 0
138 DW 0 ;Initialize RR field to zero
139PARMTAB DW 10 DUP(-1) ;No parameters initially
140BATCH DB 1 ;Assume batch mode initially
141COMFCB DB COMDRV,"COMMAND COM"
142 DB 25 DUP(?)
143TRANS DW OFFSET TRANGROUP:COMMAND
144TRNSEG DW ?
145BATBYT DB ?
146MEMSIZ DW ?
147SUM DW ?
148INITADD DB 4 DUP(?)
149RESDATASIZE EQU $-ZERO
150DATARES ENDS
151
152;Data for transient portion
153
154TRANDATA SEGMENT BYTE
155 ORG 0
156ZERO EQU $
157BADNAM DB "Bad command or file name",13,10,"$"
158MISNAM DB "Missing file name$"
159RENERR DB "Duplicate file name or "
160NOTFND DB "File not found$"
161EXEBAD DB "Error in EXE file$"
162NOSPACE DB "Insufficient disk space",13,10,"$"
163FULDIR DB "File creation error",13,10,"$"
164OVERWR DB "File cannot be copied onto itself",13,10,"$"
165LOSTERR DB "Content of destination lost before copy",13,10,"$"
166COPIED DB " File(s) copied$"
167DIRMES DB " File(s)$"
168TOOBIG DB "Program too big to fit in memory$"
169BADDRV DB "Invalid drive specification$"
170PAUSMES DB "Strike a key when ready . . . $"
171BADSWT DB "Illegal switch",13,10,"$"
172WEEKTAB DB "SunMonTueWedThuFriSat"
173BADDAT DB 13,10,"Invalid date$"
174CURDAT DB "Current date is $"
175NEWDAT DB 13,10,"Enter new date: $"
176BADTIM DB 13,10,"Invalid time$"
177CURTIM DB "Current time is $"
178NEWTIM DB 13,10,"Enter new time: $"
179SUREMES DB "Are you sure (Y/N)? $"
180
181COMTAB DB 4,"DIR",1
182 DW OFFSET TRANGROUP:CATALOG
183 DB 7,"RENAME",1
184 DW OFFSET TRANGROUP:RENAME
185 DB 4,"REN",1
186 DW OFFSET TRANGROUP:RENAME
187 DB 6,"ERASE",1
188 DW OFFSET TRANGROUP:ERASE
189 DB 4,"DEL",1
190 DW OFFSET TRANGROUP:ERASE
191 DB 5,"TYPE",1
192 DW OFFSET TRANGROUP:TYPEFIL
193 DB 4,"REM",1
194 DW OFFSET TRANGROUP:COMMAND
195 DB 5,"COPY",1
196 DW OFFSET TRANGROUP:COPY
197 DB 6,"PAUSE",1
198 DW OFFSET TRANGROUP:PAUSE
199 DB 5,"DATE",0
200 DW OFFSET TRANGROUP:DATE
201 DB 5,"TIME",0
202 DW OFFSET TRANGROUP:TIME
203 DB 0 ;Terminate command table
204
205COMBUF DB 128,1,13
206
207TRANDATASIZE EQU $-ZERO
208TRANDATA ENDS
209
210;Uninitialized transient data
211TRANSPACE SEGMENT BYTE
212 ORG 0
213ZERO = $
214 DB 128 DUP(?)
215TPA DW 1 DUP(?)
216RESSEG DW 1 DUP(?)
217CHKDRV DB 1 DUP(?)
218FILTYP DB 1 DUP(?)
219CURDRV DB 1 DUP(?)
220PARM1 DB 1 DUP(?)
221PARM2 DB 1 DUP(?)
222COMSW DW 1 DUP(?)
223ARG1S DW 1 DUP(?)
224ARG2S DW 1 DUP(?)
225FLAGER DB 1 DUP(?)
226CFLAG DB 1 DUP(?)
227SPECDRV DB 1 DUP(?)
228BYTCNT DW 1 DUP(?)
229NXTADD DW 1 DUP(?)
230LINCNT DB 1 DUP(?)
231LINLEN DB 1 DUP(?)
232FILECNT DW 1 DUP(?)
233EXEFCB LABEL WORD
234IDLEN DB 1 DUP(?)
235ID DB 8 DUP(?)
236COM DB 3 DUP(?)
237DEST DB 37 DUP(?)
238DESTNAME DB 11 DUP(?)
239DIRBUF DB 37 DUP(?)
240BITS DW 1 DUP(?)
241FULLSCR DW 1 DUP(?)
242EXEEND DW 1 DUP(?)
243;Header variables for EXE file load
244;These are overlapped with COPY variables, below
245RUNVAR LABEL WORD
246RELPT DW 1 DUP(?)
247RELSEG DW 1 DUP(?)
248PSIZE LABEL WORD
249PAGES DW 1 DUP(?)
250RELCNT DW 1 DUP(?)
251HEADSIZ DW 1 DUP(?)
252 DW 1 DUP(?)
253LOADLOW DW 1 DUP(?)
254INITSS DW 1 DUP(?)
255INITSP DW 1 DUP(?)
256 DW 1 DUP(?)
257INITIP DW 1 DUP(?)
258INITCS DW 1 DUP(?)
259RELTAB DW 1 DUP(?)
260RUNVARSIZ EQU $-RUNVAR
261
262 DB 80H DUP(?)
263STACK LABEL WORD
264
265PRETRLEN EQU $-ZERO ;Used later to compute TRNLEN
266
267 ORG RUNVAR-ZERO ;Overlaps EXE variables
268
269SRCPT DW 1 DUP(?)
270INEXACT DB 1 DUP(?)
271APPEND DB 1 DUP(?)
272NOWRITE DB 1 DUP(?)
273ASCII DB 1 DUP(?)
274PLUS DB 1 DUP(?)
275SOURCE DB 11 DUP(?)
276TRANSPACESIZE EQU $-ZERO
277TRANSPACE ENDS
278
279
280;START OF RESIDENT PORTION
281
282CODERES SEGMENT
283ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP
284 ORG 0
285ZERO = $
286PARMBUF LABEL WORD
287
288 ORG 100H
289
290RSTACK LABEL WORD
291
292PROGSTART:
293 JMP CONPROC
294
295LTPA DW 0 ;WILL STORE TPA SEGMENT HERE
296MYSEG DW 0 ;Put our own segment here
297
298CONTC:
299 MOV AX,CS
300 MOV DS,AX
301 MOV SS,AX
302 MOV SP,OFFSET RESGROUP:RSTACK
303 STI
304 CALL SETVECT
305 MOV AH,DSKRESET
306 INT 33 ;Reset disks in case files were open
307 TEST [BATCH],-1
308 JZ LODCOM
309ASKEND:
310 MOV DX,OFFSET RESGROUP:ENDBATMES
311 MOV AH,PRINTBUF
312 INT 33
313 MOV AX,0C00H+INCHAR
314 INT 33
315 AND AL,5FH
316 CMP AL,"N"
317 JZ LODCOM
318 CMP AL,"Y"
319 JNZ ASKEND
320 MOV [BATCH],0
321LODCOM:
322 MOV AX,CS
323 MOV SS,AX
324 MOV SP,OFFSET RESGROUP:RSTACK
325 MOV DS,AX
326 CALL SETVECT
327 CALL CHKSUM
328 CMP DX,[SUM]
329 JZ HAVCOM
330 MOV [LOADING],1
331 CALL LOADCOM
332CHKSAME:
333 CALL CHKSUM
334 CMP DX,[SUM]
335 JZ HAVCOM
336 CALL WRONGCOM
337 JMP SHORT CHKSAME
338HAVCOM:
339 MOV [LOADING],0
340 MOV SI,OFFSET RESGROUP:LTPA
341 MOV DI,OFFSET TRANGROUP:TPA
342 MOV ES,[TRNSEG]
343 CLD
344 MOVSW ;Move TPA segment to transient storage
345 MOVSW ;Move resident segment too
346 MOV AX,[MEMSIZ]
347 MOV WORD PTR ES:[2],AX
348 JMP DWORD PTR [TRANS]
349
350RESIDENT:
351 ADD DX,15
352 MOV CL,4
353 SHR DX,CL ;Number of paragraphs of new addition
354 ADD CS:[LTPA],DX
355 XOR AX,AX
356 MOV DS,AX
357 JMP DWORD PTR DS:[80H] ;Pretend user executed INT 20H
358
359DSKERR:
360 ;******************************************************
361 ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE
362 ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO
363 ; INTERCEPT INTERRUPT 24H.
364 ;******************************************************
365 STI
366 PUSH DS
367 PUSH CS
368 POP DS ;Set up local data segment
369 PUSH DX
370 CALL CRLF
371 POP DX
372 ADD AL,"A" ;Compute drive letter
373 MOV [DRVLET],AL
374 TEST AH,80H ;Check if hard disk error
375 JNZ FATERR
376 MOV SI,OFFSET RESGROUP:READ
377 TEST AH,1
378 JZ SAVMES
379 MOV SI,OFFSET RESGROUP:WRITE
380SAVMES:
381 LODSW
382 MOV WORD PTR [IOTYP],AX
383 LODSW
384 MOV WORD PTR [IOTYP+2],AX
385 AND DI,0FFH
386 CMP DI,12
387 JBE HAVCOD
388 MOV DI,12
389HAVCOD:
390 MOV DI,WORD PTR [DI+MESBAS] ;Get pointer to error message
391 XCHG DI,DX ;May need DX later
392 MOV AH,PRINTBUF
393 INT 33 ;Print error type
394 MOV DX,OFFSET RESGROUP:ERRMES
395 INT 33
396 CMP [LOADING],0
397 JNZ GETCOMDSK
398ASK:
399 MOV DX,OFFSET RESGROUP:REQUEST
400 MOV AH,PRINTBUF
401 INT 33
402 MOV AX,0C00H+INCHAR
403 INT 33 ;Get response
404 CALL CRLF
405 OR AL,20H ;Convert to lower case
406 MOV AH,0 ;Return code for ignore
407 CMP AL,"i" ;Ignore?
408 JZ EXIT
409 INC AH
410 CMP AL,"r" ;Retry?
411 JZ EXIT
412 INC AH
413 CMP AL,"a" ;Abort?
414 JNZ ASK
415EXIT:
416 MOV AL,AH
417 MOV DX,DI
418 POP DS
419 IRET
420
421FATERR:
422 MOV DX,OFFSET RESGROUP:BADFAT
423 MOV AH,PRINTBUF
424 INT 33
425 MOV DX,OFFSET RESGROUP:DRVNUM
426 INT 33
427 MOV AL,2 ;Abort
428 POP DS
429 IRET
430
431GETCOMDSK:
432 MOV DX,OFFSET RESGROUP:NEEDCOM
433 MOV AH,PRINTBUF
434 INT 33
435 MOV AX,0C07H ;Get char without testing or echo
436 INT 33
437 JMP LODCOM
438
439CRLF:
440 MOV DX,OFFSET RESGROUP:NEWLIN
441 PUSH AX
442 MOV AH,PRINTBUF
443 INT 33
444 POP AX
445RET10: RET
446
447LOADCOM:
448 PUSH DS
449 MOV DS,[TRNSEG]
450 MOV DX,100H
451 MOV AH,SETDMA
452 INT 33
453 POP DS
454 MOV DX,OFFSET RESGROUP:COMFCB
455 MOV AH,OPEN
456 INT 33 ;Open COMMAND.COM
457 OR AL,AL
458 JZ READCOM
459 MOV DX,OFFSET RESGROUP:NEEDCOM
460PROMPTCOM:
461 MOV AH,PRINTBUF
462 INT 33
463 MOV AX,0C07H ;Get char without testing or echo
464 INT 33
465 JMP SHORT LOADCOM
466READCOM:
467 MOV WORD PTR[COMFCB+RR],OFFSET RESGROUP:TRANSTART
468 XOR AX,AX
469 MOV WORD PTR[COMFCB+RR+2],AX
470 MOV [COMFCB],AL ;Use default drive
471 INC AX
472 MOV WORD PTR[COMFCB+RECLEN],AX
473 MOV CX,COMLEN
474 MOV DX,OFFSET RESGROUP:COMFCB
475 MOV AH,RDBLK
476 INT 33
477 OR AL,AL
478 JZ RET10
479WRONGCOM:
480 MOV DX,OFFSET RESGROUP:COMBAD
481 JMP SHORT PROMPTCOM
482
483CHKSUM:
484 CLD
485 PUSH DS
486 MOV DS,[TRNSEG]
487 MOV SI,100H
488 MOV CX,COMLEN
489 SHR CX,1
490 XOR DX,DX
491CHK:
492 LODSW
493 ADD DX,AX
494 LOOP CHK
495 POP DS
496 RET
497
498SETVECT:
499 MOV DX,OFFSET RESGROUP:LODCOM
500 MOV AX,2522H ;Set Terminate address
501 INT 21H
502 MOV DX,OFFSET RESGROUP:CONTC
503 MOV AX,2523H ;Set Ctrl-C address
504 INT 21H
505 MOV DX,OFFSET RESGROUP:DSKERR
506 MOV AX,2524H ;Set Hard Disk Error address
507 INT 33
508 MOV DX,OFFSET RESGROUP:RESIDENT
509 MOV AX,2527H ;Set Terminate and Stay Resident address
510 INT 33
511 RET
512RESCODESIZE EQU $-ZERO
513CODERES ENDS
514
515;*******************************************************************
516;START OF INIT PORTION
517;This code is overlayed the first time the TPA is used.
518
519INIT SEGMENT BYTE
520
521 ORG 0
522ZERO = $
523CONPROC:
524 MOV SP,OFFSET RESGROUP:RSTACK
525
526 IF HIGHMEM
527 MOV AX,WORD PTR DS:[2]
528 SUB AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Subtract size of resident
529 MOV WORD PTR DS:[2],AX
530 MOV ES,AX
531 MOV SI,100H
532 MOV DI,SI
533 MOV CX,((RESCODESIZE+RESDATASIZE)-100H+1)/2 ;Length of resident in words
534 REP MOVSW ;Move to end of memory
535 MOV DS,AX
536 MOV [LTPA],CS
537 ENDIF
538
539 IF NOT HIGHMEM
540 MOV AX,CS
541 ADD AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Compute segment of TPA
542 MOV [LTPA],AX
543 MOV AX,WORD PTR DS:[2]
544 ENDIF
545
546 MOV [MYSEG],DS
547 MOV [MEMSIZ],AX
548 SUB AX,TRNLEN ;Subtract size of transient
549 MOV [TRNSEG],AX
550 CALL SETVECT
551 CALL LOADCOM
552 CALL CHKSUM
553 MOV [SUM],DX
554
555 IF MSVER
556 IF HIGHMEM
557 PUSH DS
558 PUSH CS
559 POP DS
560 ENDIF
561 MOV DX,OFFSET RESGROUP:HEADER
562 MOV AH,PRINTBUF
563 INT 33
564 IF HIGHMEM
565 POP DS
566 ENDIF
567 ENDIF
568
569 MOV DX,OFFSET RESGROUP:BATFCB
570 MOV AH,OPEN
571 INT 33 ;See if AUTOEXEC.BAT exists
572 MOV WORD PTR[BATFCB+RECLEN],1 ;Set record length to 1
573 OR AL,AL ;Zero means file found
574 JZ DRV0
575 MOV [BATCH],0 ;Not found--turn off batch job
576 MOV AX,OFFSET TRANGROUP:DATINIT
577 MOV WORD PTR[INITADD],AX
578 MOV AX,[TRNSEG]
579 MOV WORD PTR[INITADD+2],AX
580 CALL DWORD PTR DS:[INITADD]
581
582 IF IBMVER
583 MOV DX,OFFSET RESGROUP:HEADER
584 MOV AH,PRINTBUF
585 INT 33
586 ENDIF
587
588DRV0:
589 JMP HAVCOM
590
591
592 IF MSVER
593HEADER DB 13,10,"Command v. 1.17"
594 IF HIGHMEM
595 DB "H"
596 ENDIF
597 DB 13,10,"$"
598 ENDIF
599
600 IF IBMVER
601HEADER DB 13,10,13,10,"The IBM Personal Computer DOS",13,10
602 DB "Version 1.10 (C)Copyright IBM Corp 1981, 1982",13,10,"$"
603 DB "Licensed Material - Program Property of IBM"
604 ENDIF
605
606INITSIZE EQU $-ZERO
607INIT ENDS
608
609;This TAIL segment is used to produce a PARA aligned label in the resident
610; group which is the location where the transient segments will be loaded
611; initialy.
612
613TAIL SEGMENT PARA
614 ORG 0
615TRANSTART LABEL WORD
616TAIL ENDS
617
618;********************************************************************
619;START OF TRANSIENT PORTION
620;This code is loaded at the end of memory and may be overwritten by
621;memory-intensive user programs.
622
623TRANCODE SEGMENT PARA
624ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:TRANGROUP
625
626WSWITCH EQU 1 ;Wide display during DIR
627PSWITCH EQU 2 ;Pause (or Page) mode during DIR
628VSWITCH EQU 4 ;Verify during COPY
629ASWITCH EQU 8 ;ASCII mode during COPY
630BSWITCH EQU 10H ;Binary mode during COPY
631
632 ORG 0
633ZERO = $
634
635 ORG 100H ;Allow for 100H parameter area
636
637SETDRV:
638 MOV AH,SELDRV
639 INT 21H
640COMMAND:
641 CLD
642 MOV AX,CS
643 MOV SS,AX
644 MOV SP,OFFSET TRANGROUP:STACK
645 MOV ES,AX
646 MOV DS,AX
647 STI
648 MOV AX,46*100H
649 MOV DL,0
650 INT 33 ;Turn off verify after write
651 MOV AX,CS ;Get segment we're in
652 SUB AX,[TPA] ;AX=size ot TPA in paragraphs
653 MOV DX,16
654 MUL DX ;DX:AX=size of TPA in bytes
655 OR DX,DX ;See if over 64K
656 JZ SAVSIZ ;OK if not
657 MOV AX,-1 ;If so, limit to 65535 bytes
658SAVSIZ:
659 MOV [BYTCNT],AX ;Max no. of bytes that can be buffered
660 CALL CRLF2
661GETCOM:
662 MOV AH,GETDRV
663 INT 21H
664 MOV [CURDRV],AL
665 ADD AL,"A"
666 CALL OUT ;Print letter for default drive
667 MOV AL,SYM
668 CALL OUT
669 MOV DS,[RESSEG] ;All batch work must use resident seg.
670ASSUME DS:RESGROUP
671 TEST [BATCH],-1
672 JNZ READBAT
673 PUSH CS
674 POP DS ;Need local segment to point to buffer
675ASSUME DS:TRANGROUP
676 MOV DX,OFFSET TRANGROUP:COMBUF
677 MOV AH,INBUF
678 INT 21H ;Get a command
679 JMP DOCOM
680
681;All batch proccessing has DS set to segment of resident portion
682ASSUME DS:RESGROUP
683NEEDPARM:
684 CALL GETBATBYT
685 CMP AL,"%" ;Check for two consecutive %
686 JZ SAVBATBYT
687 CMP AL,13 ;Check for end-of-line
688 JZ SAVBATBYT
689 SUB AL,"0"
690 JB RDBAT ;Ignore parameter reference if invalid
691 CMP AL,9
692 JA RDBAT
693 CBW
694 MOV SI,AX
695 SHL SI,1 ;Two bytes per entry
696 MOV SI,[SI+OFFSET RESGROUP:PARMTAB] ;Get pointer to corresponding parameter
697 CMP SI,-1 ;Check if parameter exists
698 JZ RDBAT ;Ignore if it doesn't
699 MOV AH,OUTCH
700RDPARM:
701 LODSB ;From resident segment
702 CMP AL,0DH ;Check for end of parameter
703 JZ RDBAT
704 STOSB ;To transient segment
705 MOV DL,AL
706 INT 33 ;Display paramters too
707 JMP SHORT RDPARM
708
709PROMPTBAT:
710 MOV AH,PRINTBUF
711 MOV DX,OFFSET RESGROUP:NEEDBAT
712 INT 33 ;Prompt for batch file
713 MOV AH,PRINTBUF
714 MOV DX,OFFSET RESGROUP:PROMPT
715 INT 33
716 MOV AX,0C00H+INCHAR
717 INT 33
718 JMP COMMAND
719
720BADCOMJ1:JMP BADCOM
721
722READBAT:
723 MOV DX,OFFSET RESGROUP:BATFCB
724 MOV AH,OPEN
725 INT 33 ;Make sure batch file still exists
726 OR AL,AL
727 JNZ PROMPTBAT ;If OPEN fails, prompt for disk
728 MOV WORD PTR [BATFCB+RECLEN],1
729 MOV DX,OFFSET RESGROUP:BATBYT
730 MOV AH,SETDMA
731 INT 33
732 MOV DI,OFFSET TRANGROUP:COMBUF+2
733RDBAT:
734 CALL GETBATBYT
735 CMP AL,"%" ;Check for parameter
736 JZ NEEDPARM
737SAVBATBYT:
738 STOSB
739 CALL OUT ;Display batched command line
740 CMP AL,0DH
741 JNZ RDBAT
742 SUB DI,OFFSET TRANGROUP:COMBUF+3
743 MOV AX,DI
744 MOV ES:[COMBUF+1],AL ;Set length of line
745 CALL GETBATBYT ;Eat linefeed
746 PUSH CS
747 POP DS ;Go back to local segment
748ASSUME DS:TRANGROUP
749DOCOM:
750;All segments are local for command line processing
751 MOV AL,10
752 CALL OUT
753 MOV SI,OFFSET TRANGROUP:COMBUF+2
754 MOV DI,OFFSET TRANGROUP:IDLEN
755 MOV AX,2901H ;Make FCB with blank scan-off
756 INT 21H
757 CMP AL,1 ;Check for ambiguous command name
758 JZ BADCOMJ1 ;Ambiguous commands not allowed
759 CMP AL,-1
760 JNZ DRVGD
761 JMP DRVBAD
762DRVGD:
763 MOV AL,[DI]
764 MOV [SPECDRV],AL
765 MOV AL," "
766 MOV CX,9
767 INC DI
768 REPNE SCASB ;Count no. of letters in command name
769 MOV AL,9
770 SUB AL,CL
771 MOV [IDLEN],AL
772 MOV DI,81H
773 MOV CX,0
774 PUSH SI
775COMTAIL:
776 LODSB
777 STOSB ;Move command tail to 80H
778 CMP AL,13
779 LOOPNZ COMTAIL
780 NOT CL
781 MOV BYTE PTR DS:[80H],CL
782 POP SI
783;If the command has 0 parameters must check here for
784;any switches that might be present.
785;SI -> first character after the command.
786 MOV [FLAGER],0 ;Set error flag before any calls to switch
787 CALL SWITCH ;Is the next character a "/"
788 MOV [COMSW],AX
789 MOV DI,FCB
790 MOV AX,2901H
791 INT 21H
792 MOV [PARM1],AL ;Save result of parse
793 CALL SWITCH
794 MOV [ARG1S],AX
795 MOV DI,FCB+10H
796 MOV AX,2901H
797 INT 21H ;Parse file name
798 MOV [PARM2],AL ;Save result
799 CALL SWITCH
800 MOV [ARG2S],AX
801 MOV AL,[IDLEN]
802 MOV DL,[SPECDRV]
803 OR DL,DL ;Check if drive was specified
804 JZ OK
805 JMP DRVCHK
806OK: DEC AL ;Check for null command
807 JNZ FNDCOM
808 JMP GETCOM
809
810RETSW:
811 XCHG AX,BX ;Put switches in AX
812 RET
813
814SWITCH:
815 XOR BX,BX ;Initialize - no switches set
816SWLOOP:
817 CALL SCANOFF ;Skip any delimiters
818 CMP AL,"/" ;Is it a switch specifier?
819 JNZ RETSW ;No -- we're finished
820 INC SI ;Skip over "/"
821 CALL SCANOFF
822 INC SI
823;Convert lower case input to upper case
824 CMP AL,"a"
825 JB SAVCHR
826 CMP AL,"z"
827 JA SAVCHR
828 SUB AL,20H ;Lower-case changed to upper-case
829SAVCHR:
830 MOV DI,OFFSET TRANGROUP:SWLIST
831 MOV CX,SWCOUNT
832 REPNE SCASB ;Look for matching switch
833 JNZ BADSW
834 MOV AX,1
835 SHL AX,CL ;Set a bit for the switch
836 OR BX,AX
837 JMP SHORT SWLOOP
838
839BADSW:
840 MOV [FLAGER],1 ;Record error in switch
841 JMP SHORT SWLOOP
842
843SWLIST DB "BAVPW"
844SWCOUNT EQU $-SWLIST
845
846DRVBAD:
847 MOV DX,OFFSET TRANGROUP:BADDRV
848 JMP ERROR
849
850FNDCOM:
851 MOV SI,OFFSET TRANGROUP:COMTAB ;Prepare to search command table
852 MOV CH,0
853FINDCOM:
854 MOV DI,OFFSET TRANGROUP:IDLEN
855 MOV CL,[SI]
856 JCXZ EXTERNAL
857 REPE CMPSB
858 LAHF
859 ADD SI,CX ;Bump to next position without affecting flags
860 SAHF
861 LODSB ;Get flag for drive check
862 MOV [CHKDRV],AL
863 LODSW ;Get address of command
864 JNZ FINDCOM
865 MOV DX,AX
866 CMP [CHKDRV],0
867 JZ NOCHECK
868 MOV AL,[PARM1]
869 OR AL,[PARM2] ;Check if either parm. had invalid drive
870 CMP AL,-1
871 JZ DRVBAD
872NOCHECK:CALL DX
873COMJMP: JMP COMMAND
874
875BADCOMJ:JMP BADCOM
876
877SETDRV1:
878 JMP SETDRV
879
880DRVCHK:
881 DEC DL ;Adjust for correct drive number
882 DEC AL ;Check if anything else is on line
883 JZ SETDRV1
884EXTERNAL:
885 MOV AL,[SPECDRV]
886 MOV [IDLEN],AL
887 MOV WORD PTR[COM],4F00H+"C" ;"CO"
888 MOV BYTE PTR[COM+2],"M"
889 MOV DX,OFFSET TRANGROUP:IDLEN
890 MOV AH,OPEN
891 INT 33 ;Check if command to be executed
892 MOV [FILTYP],AL ;0 for COM files, -1 for EXE files
893 OR AL,AL
894 JZ EXECUTE
895 MOV WORD PTR[COM],5800H+"E" ;"EX"
896 MOV BYTE PTR[COM+2],"E"
897 INT 33 ;Check for EXE file
898 OR AL,AL
899 JZ EXECUTE
900 MOV WORD PTR[COM],4100H+"B" ;"BA"
901 MOV BYTE PTR[COM+2],"T"
902 INT 33 ;Check if batch file to be executed
903 OR AL,AL
904 JNZ BADCOMJ
905BATCOM:
906;Batch parameters are read with ES set to segment of resident part
907 MOV ES,[RESSEG]
908ASSUME ES:RESGROUP
909 MOV DI,OFFSET RESGROUP:PARMTAB
910 MOV AX,-1
911 MOV CX,10
912 REP STOSW ;Zero parameter pointer table
913 MOV SI,OFFSET TRANGROUP:COMBUF+2
914 MOV DI,OFFSET RESGROUP:PARMBUF
915 MOV BX,OFFSET RESGROUP:PARMTAB
916EACHPARM:
917 CALL SCANOFF
918 CMP AL,0DH
919 JZ HAVPARM
920 MOV ES:[BX],DI ;Set pointer table to point to actual parameter
921 INC BX
922 INC BX
923MOVPARM:
924 LODSB
925 CALL DELIM
926 JZ ENDPARM ;Check for end of parameter
927 STOSB
928 CMP AL,0DH
929 JZ HAVPARM
930 JMP SHORT MOVPARM
931ENDPARM:
932 MOV AL,0DH
933 STOSB ;End-of-parameter marker
934 CMP BX,OFFSET RESGROUP:PARMTAB+20 ;Maximum number of parameters?
935 JB EACHPARM
936HAVPARM:
937 MOV SI,OFFSET TRANGROUP:IDLEN
938 MOV DI,OFFSET RESGROUP:BATFCB
939 MOV CX,16
940 REP MOVSW ;Move into private batch FCB
941 XOR AX,AX
942 PUSH ES
943 POP DS ;Simply batch FCB setup
944ASSUME DS:RESGROUP
945 MOV WORD PTR[BATFCB+RR],AX
946 MOV WORD PTR[BATFCB+RR+2],AX ;Zero RR field
947 INC AX
948 MOV WORD PTR[BATFCB+RECLEN],AX ;Set record length to 1 byte
949 MOV [BATCH],AL ;Flag batch job in progress
950 JMP COMMAND
951ASSUME DS:TRANGROUP,ES:TRANGROUP
952
953EXECUTE:
954 MOV AX,WORD PTR[IDLEN+16]
955 OR AX,WORD PTR[IDLEN+18] ;See if zero length
956 JZ BADCOM ;If so, error
957 XOR AX,AX
958 MOV WORD PTR[IDLEN+RR],AX
959 MOV WORD PTR[IDLEN+RR+2],AX ;Set RR field to zero
960 INC AX
961 MOV WORD PTR[IDLEN+RECLEN],AX ;Set record length field to 1
962 MOV DX,[TPA]
963 MOV BX,DX
964 MOV AH,SETBASE
965 INT 21H
966 TEST [FILTYP],-1 ;Check if file is COM or EXE
967 JZ COMLOAD
968 JMP EXELOAD
969COMLOAD:PUSH DS
970 MOV DS,DX
971 MOV DX,100H
972 MOV AH,SETDMA
973 INT 21H
974 POP DS
975 MOV CX,[BYTCNT]
976 SUB CX,100H
977 MOV DX,OFFSET TRANGROUP:IDLEN
978 MOV AH,RDBLK
979 INT 21H
980 DEC AL
981 MOV DX,OFFSET TRANGROUP:TOOBIG
982 JNZ ERROR
983;Set up exit conditions
984 MOV CX,[BYTCNT]
985 MOV DS,BX
986 MOV ES,BX
987 CLI
988 MOV SS,BX
989 MOV SP,CX
990 STI
991 SUB CX,100H ;Allow some stack space
992 XOR AX,AX
993 PUSH AX
994 MOV AX,100H
995 PUSH BX
996 PUSH AX
997 CALL SETUP
998XXX PROC FAR
999 RET
1000XXX ENDP
1001BADCOM:
1002 MOV DX,OFFSET TRANGROUP:BADNAM
1003ERROR:
1004 MOV AH,PRINTBUF
1005 INT 21H
1006 JMP COMMAND
1007
1008CHKCNT:
1009 TEST [FILECNT],-1
1010 JNZ ENDDIR
1011 MOV DX,OFFSET TRANGROUP:NOTFND
1012 JMP ERROR
1013
1014ENDDIR:
1015;Make sure last line ends with CR/LF
1016 MOV AL,[LINLEN]
1017 CMP AL,[LINCNT] ;Will be equal if just had CR/LF
1018 JZ MESSAGE
1019 CALL CRLF2
1020MESSAGE:
1021 MOV SI,[FILECNT]
1022 XOR DI,DI
1023 CALL DISP32BITS
1024 MOV DX,OFFSET TRANGROUP:DIRMES
1025 MOV AH,PRINTBUF
1026 INT 21H
1027 RET
1028
1029CATALOG:
1030 MOV AL,"?" ;*.* is default file spec.
1031 MOV DI,5DH
1032 MOV CX,11
1033 REP STOSB
1034 MOV SI,81H
1035 CALL SWITCH
1036 MOV DI,5CH
1037 MOV AX,41*100H+0DH ;Parse with default name and extension
1038 INT 33
1039
1040;Begin by processing any switches that may have been specified.
1041;BITS will contain any information about switches that was
1042;found when the command line was parsed.
1043
1044SETSWT:
1045 MOV AX,[COMSW] ;Get switches from command
1046 OR AX,[ARG1S] ;OR in switches from first parameter
1047 MOV [BITS],AX
1048 MOV BYTE PTR[FULLSCR],LINPERPAG
1049 TEST AL,1 ;Look for /W
1050 MOV AL,NORMPERLIN
1051 JZ DIR
1052 MOV AL,WIDEPERLIN
1053DIR:
1054 MOV [LINLEN],AL ;Set number of entries per line
1055 MOV [LINCNT],AL
1056 MOV [FILECNT],0 ;Keep track of how many files found
1057 MOV DX,OFFSET TRANGROUP:DIRBUF ;Set Disk transfer address
1058 MOV AH,SETDMA
1059 INT 21H
1060 MOV AH,SRCHFRST
1061SHOWDIR:
1062 MOV DX,5CH ;DX -> Unopened FCB
1063 INT 21H ;Search for a file to match FCB
1064 INC AL ;FF = file not found
1065 JNZ AGAIN ;Either an error or we are finished
1066 JMP CHKCNT
1067AGAIN:
1068 INC [FILECNT] ;Keep track of how many we find
1069 MOV SI,OFFSET TRANGROUP:DIRBUF+1 ;SI -> information returned by sys call
1070 CALL SHONAME
1071 TEST BYTE PTR[BITS],1 ;/W set?
1072 JNZ NEXENT ;If so, no size, date, or time
1073 CALL DISPSIZE ;Print size of file
1074 CALL TWOSPC
1075 MOV AX,WORD PTR[DIRBUF+25] ;Get date
1076 OR AX,AX
1077 JZ NEXENT ;Skip if no date
1078 MOV DX,AX
1079 MOV CL,5
1080 SHR AX,CL ;Align month
1081 AND AL,0FH
1082 MOV BH,"0"-" " ;Enable zero suppression
1083 CALL OUT2
1084 MOV AL,"-"
1085 CALL OUT
1086 MOV AL,DL
1087 AND AL,1FH ;Mask to day
1088 CALL OUT2
1089 MOV AL,"-"
1090 CALL OUT
1091 MOV AL,DH
1092 SHR AL,1 ;Align year
1093 ADD AX,80 ;Relative 1980
1094 CMP AL,100
1095 JB MILLENIUM
1096 SUB AL,100
1097MILLENIUM:
1098 CALL OUT2
1099 MOV BX,WORD PTR[DIRBUF+23] ;Get time
1100 OR BX,BX ;Time field present?
1101 JZ NEXENT
1102 CALL TWOSPC
1103 SHR BX,1
1104 SHR BX,1
1105 SHR BX,1
1106 SHR BL,1
1107 SHR BL,1 ;Hours in BH, minutes in BL
1108 MOV AL,BH
1109 MOV DH,"a" ;Assume A.M.
1110 CMP AL,12 ;In the afternoon?
1111 JB MORN
1112 MOV DH,"p"
1113 JE MORN
1114 SUB AL,12 ;Keep it to 12 hours or less
1115MORN:
1116 OR AL,AL ;Before 1 am?
1117 JNZ SHOHOURS
1118 MOV AL,12
1119SHOHOURS:
1120 MOV BH,"0"-" " ;Enable zero suppression
1121 CALL OUT2
1122 MOV AL,":"
1123 CALL OUT
1124 MOV AL,BL ;Output minutes
1125 CALL OUT2
1126 MOV AL,DH ;Get "a" or "p"
1127 CALL OUT
1128NEXENT:
1129 DEC [LINCNT]
1130 JNZ SAMLIN
1131NEXLIN:
1132 MOV AL,[LINLEN]
1133 MOV [LINCNT],AL
1134 CALL CRLF2
1135 TEST BYTE PTR[BITS],2 ;/P switch present?
1136 JZ SCROLL ;If not, just continue
1137 DEC BYTE PTR[FULLSCR]
1138 JNZ SCROLL
1139 MOV BYTE PTR[FULLSCR],LINPERPAG
1140 MOV AH,PRINTBUF
1141 MOV DX,OFFSET TRANGROUP:PAUSMES
1142 INT 33
1143 MOV AX,0C08H ;Wait for any character to be typed
1144 INT 21H
1145 CALL CRLF2
1146SCROLL:
1147 MOV AH,SRCHNXT
1148 JMP SHOWDIR
1149
1150SAMLIN:
1151 MOV AL,9 ;Output a tab
1152 CALL OUT
1153 JMP SHORT SCROLL
1154
1155SHONAME:
1156 MOV CX,8
1157 CALL OUTCNT
1158 CALL ONESPC
1159 MOV CX,3
1160OUTCNT:
1161 LODSB
1162 CALL OUT
1163 LOOP OUTCNT
1164 RET
1165
1166TWOSPC:
1167 CALL ONESPC
1168ONESPC:
1169 MOV AL," "
1170 JMP OUT
1171
1172CRLF2:
1173 MOV AL,13
1174 CALL OUT
1175 MOV AL,10
1176 JMP OUT
1177
1178DISPSIZE:
1179 MOV SI,WORD PTR[DIRBUF+29]
1180 MOV DI,WORD PTR[DIRBUF+31]
1181DISP32BITS:
1182;Prints the 32-bit number DI:SI on the console in decimal. Uses a total
1183;of 9 digit positions with leading blanks.
1184 XOR AX,AX
1185 MOV BX,AX
1186 MOV BP,AX
1187 MOV CX,32
1188CONVLP:
1189 SHL SI,1
1190 RCL DI,1
1191 XCHG AX,BP
1192 CALL CONVWRD
1193 XCHG AX,BP
1194 XCHG AX,BX
1195 CALL CONVWRD
1196 XCHG AX,BX
1197 ADC AL,0
1198 LOOP CONVLP
1199; Conversion complete. Print 9-digit number.
1200 MOV CX,1810H ;Allow leading zero blanking for 8 digits
1201 XCHG DX,AX
1202 CALL DIGIT
1203 XCHG AX,BX
1204 CALL OUTWORD
1205 XCHG AX,BP
1206OUTWORD:
1207 PUSH AX
1208 MOV DL,AH
1209 CALL OUTBYTE
1210 POP DX
1211OUTBYTE:
1212 MOV DH,DL
1213 SHR DL,1
1214 SHR DL,1
1215 SHR DL,1
1216 SHR DL,1
1217 CALL DIGIT
1218 MOV DL,DH
1219DIGIT:
1220 AND DL,0FH
1221 JZ BLANKZER
1222 MOV CL,0
1223BLANKZER:
1224 DEC CH
1225 AND CL,CH
1226 OR DL,30H
1227 SUB DL,CL
1228 MOV AH,OUTCH
1229 INT 21H
1230 RET
1231
1232CONVWRD:
1233 ADC AL,AL
1234 DAA
1235 XCHG AL,AH
1236 ADC AL,AL
1237 DAA
1238 XCHG AL,AH
1239RET20: RET
1240
1241ERASE:
1242 MOV CX,11
1243 MOV SI,FCB+1
1244AMBSPEC:
1245 LODSB
1246 CMP AL,"?"
1247 JNZ ALLFIL
1248 LOOP AMBSPEC
1249ALLFIL:
1250 CMP CX,0
1251 JNZ NOPRMPT
1252ASKAGN:
1253 MOV DX,OFFSET TRANGROUP:SUREMES ;"Are you sure (Y/N)?"
1254 MOV AH,PRINTBUF
1255 INT 21H
1256 MOV AX,0C00H+INCHAR
1257 INT 21H
1258 AND AL,5FH
1259 CMP AL,"N"
1260 JZ RET20
1261 CMP AL,"Y"
1262 CALL CRLF2
1263 JZ NOPRMPT
1264 JMP SHORT ASKAGN
1265NOPRMPT:
1266 MOV AH,DELETE
1267 MOV BX,OFFSET TRANGROUP:NOTFND
1268 CMP BYTE PTR DS:[FCB+1]," " ;Check if parameter exists
1269 JMP SHORT OPFILE
1270RENAME:
1271 MOV AH,RENAM
1272 MOV BX,OFFSET TRANGROUP:RENERR
1273 CMP BYTE PTR DS:[FCB+16+1]," " ;Check if parameter exists
1274OPFILE:
1275 MOV DX,OFFSET TRANGROUP:MISNAM
1276 JZ ERRJ ;Error if missing parameter
1277 MOV DX,FCB
1278 INT 21H
1279 INC AL
1280 JNZ RET20
1281 MOV DX,BX
1282ERRJ: JMP ERROR
1283
1284TYPEFIL:
1285 MOV DS,[TPA]
1286 XOR DX,DX
1287 MOV AH,SETDMA
1288 INT 21H
1289 PUSH CS
1290 POP DS
1291 MOV DX,FCB
1292 MOV AH,OPEN
1293 INT 21H
1294 OR AL,AL
1295 MOV DX,OFFSET TRANGROUP:NOTFND
1296 JNZ ERRJ
1297 XOR AX,AX
1298 MOV WORD PTR DS:[FCB+RR],AX ;Set RR field
1299 MOV WORD PTR DS:[FCB+RR+2],AX
1300 INC AX
1301 MOV WORD PTR DS:[FCB+RECLEN],AX ;Set record length
1302 MOV ES,[TPA]
1303TYPELP:
1304 MOV DX,FCB
1305 MOV CX,[BYTCNT]
1306 MOV AH,RDBLK
1307 INT 21H
1308 JCXZ RET30
1309 XOR SI,SI ;Start at 0 in TPA
1310OUTLP:
1311 LODS BYTE PTR ES:[SI] ;In TPA segment
1312 CMP AL,1AH
1313 JZ RET30
1314 MOV AH,OUTCH
1315 MOV DL,AL
1316 INT 21H
1317 LOOP OUTLP
1318 JMP SHORT TYPELP
1319
1320RET30: RET ;Need a nearby RET
1321
1322COPY:
1323 XOR AX,AX
1324 MOV [PLUS],AL ;Will keep track of "+"s
1325 MOV [FILECNT],AX
1326 MOV SI,81H ;Point to input line
1327 CALL SWITCH ;Skip over switches on command
1328 MOV BP,AX
1329 MOV DI,FCB
1330 CALL PARSNAM ;Scan first source
1331 MOV [PARM1],DL ;Save ambiguous flag
1332 MOV [SRCPT],SI ;Save pointer to command line
1333;Parse each name to find destination and check for /V switch
1334SCANNAM:
1335 CALL PARSE
1336 JNZ SCANNAM
1337GETDEST:
1338 MOV DI,OFFSET TRANGROUP:DEST
1339 MOV BX,BP ;Remeber switches so far
1340 XOR BP,BP ;Must have dest. swtiches alone
1341 CALL PARSNAM
1342 MOV [ARG2S],BP ;Remember switches on destination
1343 JNZ HAVDESTNAM ;File name present?
1344 INC DI ;Point to file name spot
1345 MOV AL,"?" ;Substitute *.*
1346 MOV CX,11
1347 REP STOSB
1348HAVDESTNAM:
1349 OR BX,BP ;BX = all switches combined
1350 AND BL,VSWITCH ;Verify requested?
1351 JZ NOVER
1352 MOV AX,46*100H+1 ;Set verify
1353 MOV DL,0
1354 INT 33
1355NOVER:
1356 MOV DI,OFFSET TRANGROUP:DESTNAME
1357 MOV SI,OFFSET TRANGROUP:DEST+1
1358 MOV BX,FCB+1
1359 CALL BUILDNAME ;See if we can make it unambiguous
1360 MOV DI,OFFSET TRANGROUP:DESTNAME
1361 MOV AL,"?"
1362 MOV CX,11
1363 REPNE SCASB ;Scan for "?" to see if ambiguous
1364 MOV AL,1 ;Flag if ambig.
1365 JZ AMBIG
1366 DEC AX ;AL=0 if unambig.
1367AMBIG:
1368 MOV DL,AL
1369 MOV AH,[PLUS] ;1=found "+"
1370 XOR AL,1 ;0=ambig, 1=unambig destination
1371 AND AL,[PARM1] ;Source ambig. AND dest unambig.
1372 OR AL,AH ;OR found "+" means concatenation
1373 MOV [ASCII],AL ;Concatenation implies ASCII mode
1374 MOV [INEXACT],AL ;ASCII implies inexact copy
1375 SHL AL,1
1376 OR AL,DL ;Combine multiple and concat flags
1377 MOV [PARM2],AL
1378 MOV AL,BYTE PTR[COMSW]
1379 CALL SETASC ;Check /A,/B on command
1380 MOV AL,BYTE PTR[ARG1S]
1381 CALL SETASC ;Check for ASCII on first filename
1382 MOV BYTE PTR[COMSW],AL ;Save starting switch values
1383 MOV AH,SRCHFRST
1384 CALL SEARCH ;Search for first source name
1385MULTDEST:
1386 JZ FIRSTSRC ;Find a first source name?
1387 TEST [PARM2],1 ;If multiple, we're done
1388 JNZ ENDCOPY
1389 XOR AX,AX
1390 MOV [NXTADD],AX
1391 MOV [CFLAG],AL ;Flag nothing read yet
1392NEXTSNG:
1393 MOV DI,FCB
1394 MOV SI,[SRCPT]
1395 CALL PARSESRC ;Parse next file name into FCB
1396 MOV [PARM1],DL ;Remember if it's ambiguous
1397 MOV [SRCPT],SI
1398 JZ SNGCLOS
1399 MOV AH,SRCHFRST
1400 CALL SEARCH ;Search for new file name
1401 JNZ NEXTSNG ;If none, skip it and move to next name
1402READSNG:
1403 CALL CHECKREAD
1404SNGLOOP:
1405 CALL SEARCHNEXT ;See if any more of this name
1406 JZ READSNG
1407 JMP SHORT NEXTSNG
1408
1409SNGCLOS:
1410 CALL CLOSEFIL
1411ENDCOPY:
1412 MOV SI,[FILECNT]
1413 XOR DI,DI
1414 CALL DISP32BITS
1415 MOV DX,OFFSET TRANGROUP:COPIED
1416 MOV AH,PRINTBUF
1417 INT 21H
1418 JMP COMMAND ;Stack could be messed up
1419
1420FIRSTSRC:
1421 MOV SI,OFFSET TRANGROUP:DIRBUF+1
1422 MOV DI,OFFSET TRANGROUP:SOURCE
1423 MOV CX,11
1424 REP MOVSB ;Copy first source name to SOURCE
1425 MOV SI,OFFSET TRANGROUP:DESTNAME
1426 MOV DI,OFFSET TRANGROUP:DEST+1
1427 MOV BX,OFFSET TRANGROUP:SOURCE
1428 CALL BUILDNAME ;Build destination name
1429 XOR AX,AX
1430 MOV [NXTADD],AX
1431 MOV [CFLAG],AL
1432 MOV [APPEND],AL
1433 MOV [NOWRITE],AL
1434 TEST [PARM2],1 ;Multiple destinations?
1435 JZ NOPRT
1436 MOV SI,OFFSET TRANGROUP:DIRBUF+1
1437 CALL SHONAME ;If so, show first source
1438 CALL CRLF2
1439NOPRT:
1440 CALL COMPNAME ;Source and dest. the same?
1441 JNZ DOREAD ;If not, read source in
1442 TEST [PARM2],2 ;Concatenation?
1443 MOV DX,OFFSET TRANGROUP:OVERWR
1444 JZ COPERRJ ;If not, overwrite error
1445 MOV [APPEND],1 ;Set physical append
1446 MOV AH,OPEN
1447 MOV DX,OFFSET TRANGROUP:DEST
1448 INT 33 ;Open (existing) destination
1449 CMP [ASCII],0 ;ASCII flag set?
1450 JZ BINARYAPP
1451;ASCII append. Must find logical EOF, then seek there with dest. FCB
1452 MOV [NOWRITE],1
1453 CALL READIN ;Find EOF
1454 CALL FLSHFIL ;Seek there
1455 MOV [NOWRITE],0
1456 CALL FLSHFIL ;Truncate file
1457 JMP SHORT SNGLCHK
1458
1459SNGLOOPJ:JMP SNGLOOP
1460
1461COPERRJ:JMP COPERR
1462
1463BINARYAPP:
1464 MOV WORD PTR[DEST+RECLEN],1 ;Set record length to 1
1465 MOV SI,OFFSET TRANGROUP:DEST+16 ;Point to file size
1466 MOV DI,OFFSET TRANGROUP:DEST+RR
1467 MOVSW
1468 MOVSW ;Seek to end of file
1469 MOV [CFLAG],1
1470 JMP SHORT SNGLCHK
1471DOREAD:
1472 CALL READIN
1473SNGLCHK:
1474 TEST [PARM2],1 ;Single or multiple destinations?
1475 JZ SNGLOOPJ
1476 MOV SI,[SRCPT]
1477MULTAPP:
1478 CALL PARSE
1479 JZ MULTCLOS
1480 PUSH SI
1481 MOV SI,OFFSET TRANGROUP:DIRBUF+1
1482 MOV DI,SI
1483 MOV BX,OFFSET TRANGROUP:SOURCE
1484 CALL BUILDNAME
1485 CALL CHECKREAD
1486 POP SI
1487 JMP SHORT MULTAPP
1488MULTCLOS:
1489 CALL CLOSEFIL
1490 MOV AL,BYTE PTR[COMSW]
1491 MOV [ASCII],AL ;Restore ASCII flag
1492 CALL SEARCHNEXT
1493 JMP MULTDEST
1494
1495PARSE:
1496 MOV DI,OFFSET TRANGROUP:DIRBUF
1497PARSESRC:
1498 CALL SCANOFF
1499 CMP AL,"+"
1500 JNZ RETZF
1501 MOV [PLUS],1 ;Keep track of "+" signs
1502 INC SI ;Skip over it
1503PARSNAM:
1504 MOV AX,2901H
1505 INT 33 ;Parse file name
1506 CMP AL,-1 ;Illegal?
1507 MOV DX,OFFSET TRANGROUP:BADDRV
1508 JZ COPERRJ
1509 XCHG AX,DX ;Save parse flag in DL
1510 MOV AL,BYTE PTR[DI] ;Get drive number
1511 OR AL,AL ;Is it default?
1512 JNZ PARSW
1513 MOV AL,[CURDRV] ;Substitute actual drive
1514 INC AX
1515 MOV BYTE PTR[DI],AL
1516PARSW:
1517 PUSH BX
1518 PUSH DI
1519 CALL SWITCH ;Process switches
1520 OR BP,AX ;Combine all switches
1521 CALL SETASC ;Check for /A or /B
1522 POP DI
1523 POP BX
1524 CMP BYTE PTR[DI+1]," " ;Did we even get a file name?
1525 RET
1526
1527RETZF:
1528 XOR AX,AX
1529RET35: RET
1530
1531SEARCHNEXT:
1532 MOV AL,[PARM1] ;Is name ambiguous?
1533 DEC AL
1534 JNZ RET35 ;Don't perform search if not
1535 MOV AH,SRCHNXT
1536SEARCH:
1537 PUSH AX
1538 MOV AH,SETDMA
1539 MOV DX,OFFSET TRANGROUP:DIRBUF
1540 INT 33 ;Put result of search in DIRBUF
1541 POP AX ;Restore search first/next command
1542 MOV DX,FCB
1543 INT 33 ;Do the search
1544 OR AL,AL
1545 RET
1546
1547SETASC:
1548;Given switch vector in AX,
1549; Set ASCII switch if /A is set
1550; Clear ASCII switch if /B is set
1551; Leave ASCII unchanged if neither or both are set
1552; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
1553 AND AL,ASWITCH+BSWITCH
1554 JPE LOADSW ;PE means both or neither are set
1555 AND AL,ASWITCH
1556 MOV [ASCII],AL
1557 OR [INEXACT],AL
1558LOADSW:
1559 MOV AL,[ASCII]
1560 OR AL,AL
1561 RET
1562
1563BUILDNAME:
1564; [SI] = Ambiguous input file name
1565; [BX] = Source of replacement characters
1566; [DI] = Destination
1567; File name is copied from [SI] to [DI]. If "?"s are encountered,
1568; they are replaced with the character in the same position at [BX].
1569 MOV CX,11
1570BUILDNAM:
1571 LODSB
1572 CMP AL,"?"
1573 JNZ NOTAMBIG
1574 MOV AL,BYTE PTR[BX]
1575NOTAMBIG:
1576 STOSB
1577 INC BX
1578 LOOP BUILDNAM
1579 RET
1580
1581COMPNAME:
1582 MOV SI,OFFSET TRANGROUP:DEST
1583 MOV DI,OFFSET TRANGROUP:DIRBUF
1584 MOV CX,6
1585 REPE CMPSW
1586 RET
1587
1588CHECKREAD:
1589;Read file in (with READIN) if not identical to destination
1590 CALL COMPNAME ;See if source and destination the same
1591 JNZ READIN
1592 CMP [APPEND],0 ;If physical append, it's OK
1593 JNZ RET40
1594 MOV DX,OFFSET TRANGROUP:LOSTERR ;Tell him he's not going to get it
1595 MOV AH,PRINTBUF
1596 INT 33
1597RET40: RET
1598
1599READIN:
1600;Open source file and read it in. If memory fills up, flush it out to
1601;destination and keep reading. If /A switch set, chop file at first ^Z.
1602; Inputs/Outputs:
1603; [NXTADD] has current pointer in buffer
1604; [CFLAG] <>0 if destination has been created
1605
1606 MOV DX,OFFSET TRANGROUP:DIRBUF
1607 MOV AH,OPEN
1608 INT 21H
1609 OR AL,AL ;Successful open?
1610 JNZ RET40 ;If not, just ignore it
1611 XOR AX,AX
1612 MOV WORD PTR[DIRBUF+RR],AX
1613 MOV WORD PTR[DIRBUF+RR+2],AX
1614 INC AX
1615 MOV WORD PTR[DIRBUF+RECLEN],AX
1616COPYLP:
1617 MOV DX,[NXTADD]
1618 MOV AH,SETDMA
1619 PUSH DS
1620 MOV DS,[TPA]
1621 INT 33
1622 POP DS
1623 MOV CX,[BYTCNT]
1624 SUB CX,DX ;Compute available space
1625 MOV DX,OFFSET TRANGROUP:DIRBUF
1626 MOV AH,RDBLK ;Read in source file
1627 INT 21H
1628 JCXZ RET40
1629 CMP [ASCII],0
1630 JZ BINREAD
1631 MOV DX,CX
1632 MOV DI,[NXTADD]
1633 MOV AL,1AH
1634 PUSH ES
1635 MOV ES,[TPA]
1636 REPNE SCASB ;Scan for EOF
1637 POP ES
1638 JNZ USEALL
1639 INC CX
1640USEALL:
1641 SUB DX,CX
1642 MOV CX,DX
1643BINREAD:
1644 ADD CX,[NXTADD]
1645 MOV [NXTADD],CX
1646 CMP CX,[BYTCNT] ;Is buffer full?
1647 JB RET40 ;If not, we must have found EOF
1648 CALL FLSHFIL
1649 JMP SHORT COPYLP
1650
1651CLOSEFIL:
1652 MOV AX,[NXTADD]
1653 MOV BX,AX
1654 OR AL,AH ;See if any data is loaded
1655 OR AL,[CFLAG] ; or file was created
1656 JZ RET50 ;Don't close or count if not created
1657 MOV AL,BYTE PTR[ARG2S]
1658 CALL SETASC ;Check for /B or /A on destination
1659 JZ BINCLOS
1660 CMP BX,[BYTCNT] ;Is memory full?
1661 JNZ PUTZ
1662 CALL FLSHFIL ;Empty it to make room for 1 lousy byte
1663 XOR BX,BX
1664PUTZ:
1665 PUSH DS
1666 MOV DS,[TPA]
1667 MOV WORD PTR[BX],1AH ;Add End-of-file mark (Ctrl-Z)
1668 POP DS
1669 INC [NXTADD]
1670BINCLOS:
1671 CALL FLSHFIL
1672 CMP [INEXACT],0 ;Copy not exact?
1673 JNZ NODATE ;If so, don't copy date & time
1674 MOV SI,OFFSET TRANGROUP:DIRBUF+OFFDATE
1675 MOV DI,OFFSET TRANGROUP:DEST+OFFDATE ;Make date & time same as original
1676 MOVSW ;Copy date
1677 MOVSW ;Copy time
1678NODATE:
1679 MOV DX,OFFSET TRANGROUP:DEST
1680 MOV AH,CLOSE
1681 INT 21H
1682 INC [FILECNT]
1683RET50: RET
1684
1685FLSHFIL:
1686;Write out any data remaining in memory.
1687; Inputs:
1688; [NXTADD] = No. of bytes to write
1689; [CFLAG] <>0 if file has been created
1690; Outputs:
1691; [NXTADD] = 0
1692
1693 MOV AL,1
1694 XCHG [CFLAG],AL
1695 OR AL,AL
1696 JNZ EXISTS
1697 CMP [NOWRITE],0
1698 JNZ SKPMAK ;Don't actually create if NOWRITE set
1699 MOV DX,OFFSET TRANGROUP:DEST
1700 MOV AH,MAKE
1701 INT 21H
1702 MOV DX,OFFSET TRANGROUP:FULDIR
1703 OR AL,AL
1704 JNZ COPERR
1705SKPMAK:
1706 XOR AX,AX
1707 MOV WORD PTR[DEST+RR],AX
1708 MOV WORD PTR[DEST+RR+2],AX
1709 INC AX
1710 MOV WORD PTR[DEST+RECLEN],AX
1711EXISTS:
1712 XOR CX,CX
1713 XCHG CX,[NXTADD]
1714 CMP [NOWRITE],0 ;If NOWRITE set, just seek CX bytes
1715 JNZ SEEKEND
1716 XOR DX,DX
1717 PUSH DS
1718 MOV DS,[TPA]
1719 MOV AH,SETDMA
1720 INT 33
1721 POP DS
1722 MOV DX,OFFSET TRANGROUP:DEST
1723 MOV AH,WRBLK
1724 INT 21H
1725 OR AL,AL
1726 JZ RET60
1727 MOV DX,OFFSET TRANGROUP:DEST
1728 MOV AH,CLOSE
1729 INT 21H
1730 MOV AH,DELETE
1731 INT 33
1732 MOV DX,OFFSET TRANGROUP:NOSPACE
1733COPERR:
1734 MOV AH,9
1735 INT 21H
1736 JMP ENDCOPY
1737
1738SEEKEND:
1739 ADD WORD PTR[DEST+RR],CX
1740 ADC WORD PTR[DEST+RR+2],0 ;Propagate carry
1741RET60: RET
1742
1743GETBATBYT:
1744;Get one byte from the batch file and return it in AL. End-of-file
1745;returns <CR> and ends batch mode. DS must be set to resident segment.
1746;AH, CX, DX destroyed.
1747ASSUME DS:RESGROUP
1748 MOV DX,OFFSET RESGROUP:BATFCB
1749 MOV AH,RDBLK
1750 MOV CX,1
1751 INT 33 ;Get one more byte from batch file
1752 JCXZ BATEOF
1753 MOV AL,[BATBYT]
1754 CMP AL,1AH
1755 JNZ RET70
1756BATEOF:
1757 MOV AL,0DH ;If end-of-file, then end of line
1758 MOV [BATCH],0 ;And turn off batch mode
1759RET70: RET
1760ASSUME DS:TRANGROUP
1761
1762SCANOFF:
1763 LODSB
1764 CALL DELIM
1765 JZ SCANOFF
1766 DEC SI ;Point to first non-delimiter
1767 RET
1768
1769DELIM:
1770 CMP AL," "
1771 JZ RET80
1772 CMP AL,"="
1773 JZ RET80
1774 CMP AL,","
1775 JZ RET80
1776 CMP AL,9 ;Check for TAB character
1777RET80: RET
1778
1779PAUSE:
1780 MOV DX,OFFSET TRANGROUP:PAUSMES
1781 MOV AH,PRINTBUF
1782 INT 33
1783 MOV AX,0C00H+INCHAR ;Get character with KB buffer flush
1784 INT 33
1785RET90: RET
1786
1787;Date and time are set during initialization and use
1788;this routines since they need to do a long return
1789
1790DATINIT:
1791 PUSH ES
1792 PUSH DS ;Going to use the previous stack
1793 MOV AX,CS ;Set up the appropriate segment registers
1794 MOV ES,AX
1795 MOV DS,AX
1796 MOV WORD PTR DS:[81H],13 ;Want to prompt for date during initialization
1797 CALL DATE
1798 CALL TIME
1799 POP DS
1800 POP ES
1801YYY PROC FAR
1802 RET
1803YYY ENDP
1804
1805; DATE - Gets and sets the time
1806
1807DATE:
1808 MOV SI,81H ;Accepting argument for date inline
1809 CALL SCANOFF
1810 CMP AL,13
1811 JZ PRMTDAT
1812 MOV BX,2F00H+"-" ;"/-"
1813 CALL INLINE
1814 JMP COMDAT
1815
1816PRMTDAT:
1817 MOV DX,OFFSET TRANGROUP:CURDAT
1818 MOV AH,PRINTBUF
1819 INT 33 ;Print "Current date is "
1820 MOV AH,GETDATE
1821 INT 33 ;Get date in CX:DX
1822 CBW
1823 MOV SI,AX
1824 SHL SI,1
1825 ADD SI,AX ;SI=AX*3
1826 ADD SI,OFFSET TRANGROUP:WEEKTAB
1827 MOV BX,CX
1828 MOV CX,3
1829 CALL OUTCNT
1830 MOV AL," "
1831 CALL OUT
1832 MOV AX,BX
1833 MOV CX,DX
1834 MOV DL,100
1835 DIV DL
1836 XCHG AL,AH
1837 XCHG AX,DX
1838 MOV BL,"-"
1839 CALL SHOW
1840GETDAT:
1841 MOV DX,OFFSET TRANGROUP:NEWDAT
1842 MOV BX,2F00H+"-" ;"/-" in BX
1843 CALL GETBUF
1844COMDAT: JZ RET90
1845 JC DATERR
1846 LODSB
1847 CMP AL,BL
1848 JZ SEPGD
1849 CMP AL,BH
1850 JNZ DATERR
1851SEPGD: CALL GETNUM
1852 JC DATERR
1853 MOV CX,1900
1854 CMP BYTE PTR[SI],13
1855 JZ BIAS
1856 MOV AL,100
1857 MUL AH
1858 MOV CX,AX
1859 CALL GETNUM
1860 JC DATERR
1861BIAS:
1862 MOV AL,AH
1863 MOV AH,0
1864 ADD CX,AX
1865 LODSB
1866 CMP AL,13
1867 JNZ DATERR
1868 MOV AH,SETDATE
1869 INT 33
1870 OR AL,AL
1871 JNZ DATERR
1872 JMP RET90
1873DATERR:
1874 MOV DX,OFFSET TRANGROUP:BADDAT
1875 MOV AH,PRINTBUF
1876 INT 33
1877 JMP GETDAT
1878
1879; TIME gets and sets the time
1880
1881TIME:
1882 MOV SI,81H ;Accepting argument for time inline
1883 CALL SCANOFF
1884 CMP AL,13
1885 JZ PRMTTIM
1886 MOV BX,3A00H+":"
1887 CALL INLINE
1888 JMP COMTIM
1889
1890PRMTTIM:
1891 MOV DX,OFFSET TRANGROUP:CURTIM
1892 MOV AH,PRINTBUF
1893 INT 33 ;Print "Current time is "
1894 MOV AH,GETTIME
1895 INT 33 ;Get time in CX:DX
1896 MOV BL,":"
1897 CALL SHOW
1898GETTIM:
1899 XOR CX,CX ;Initialize hours and minutes to zero
1900 MOV DX,OFFSET TRANGROUP:NEWTIM
1901 MOV BX,3A00H+":"
1902 CALL GETBUF
1903COMTIM: JZ RET100 ;If no time present, don't change it
1904 JC TIMERR
1905 MOV CX,DX
1906 XOR DX,DX
1907 LODSB
1908 CMP AL,13
1909 JZ SAVTIM
1910 CMP AL,BL
1911 JNZ TIMERR
1912 MOV BL,"."
1913 CALL GETNUM
1914 JC TIMERR
1915 MOV DH,AH ;Position seconds
1916 LODSB
1917 CMP AL,13
1918 JZ SAVTIM
1919 CMP AL,BL
1920 JNZ TIMERR
1921 CALL GETNUM
1922 JC TIMERR
1923 MOV DL,AH
1924 LODSB
1925 CMP AL,13
1926 JNZ TIMERR
1927SAVTIM:
1928 MOV AH,SETTIME
1929 INT 33
1930 OR AL,AL
1931 JZ RET100 ;Error in time?
1932TIMERR:
1933 MOV DX,OFFSET TRANGROUP:BADTIM
1934 MOV AH,PRINTBUF
1935 INT 33 ;Print error message
1936 JMP GETTIM ;Try again
1937
1938GETBUF:
1939 MOV AH,PRINTBUF
1940 INT 33 ;Print "Enter new date: "
1941 MOV AH,INBUF
1942 MOV DX,OFFSET TRANGROUP:COMBUF
1943 INT 33 ;Get input line
1944 CALL CRLF2
1945 MOV SI,OFFSET TRANGROUP:COMBUF+2
1946 CMP BYTE PTR[SI],13 ;Check if new date entered
1947 JZ RET100
1948INLINE:
1949 CALL GETNUM ;Get one or two digit number
1950 JC RET100
1951 MOV DH,AH ;Put in position
1952 LODSB
1953 CMP AL,BL
1954 JZ NEXT
1955 CMP BL,":" ;Is it a date seperator?
1956 JNZ DATESEP
1957 DEC SI
1958 MOV DL,0
1959RET100: RET ;Time may have only an hour specified
1960DATESEP:
1961 CMP AL,BH
1962 STC
1963 JNZ RET100
1964NEXT: CALL GETNUM
1965 MOV DL,AH ;Put in position
1966 RET
1967
1968GETNUM:
1969 CALL INDIG
1970 JC RET100
1971 MOV AH,AL ;Save first digit
1972 CALL INDIG ;Another digit?
1973 JC OKRET
1974 AAD ;Convert unpacked BCD to decimal
1975 MOV AH,AL
1976OKRET:
1977 OR AL,1
1978RET110: RET
1979
1980INDIG:
1981 MOV AL,BYTE PTR[SI]
1982 SUB AL,"0"
1983 JC RET110
1984 CMP AL,10
1985 CMC
1986 JC RET110
1987 INC SI
1988 RET
1989
1990SHOW:
1991 MOV AL,CH
1992 MOV BH,"0"-" " ;Enable leading zero suppression
1993 CALL OUT2
1994 MOV AL,BL
1995 CALL OUT
1996 MOV AL,CL
1997 CALL OUT2
1998 MOV AL,BL
1999 CALL OUT
2000 MOV AL,DH
2001 CALL OUT2
2002 CMP BL,":" ;Are we outputting time?
2003 JNZ SKIPIT
2004 MOV AL,"."
2005 CALL OUT
2006SKIPIT: MOV AL,DL
2007OUT2: ;Output binary number as two ASCII digits
2008 AAM ;Convert binary to unpacked BCD
2009 XCHG AL,AH
2010 OR AX,3030H ;Add "0" bias to both digits
2011 CMP AL,"0" ;Is MSD zero?
2012 JNZ NOSUP
2013 SUB AL,BH ;Suppress leading zero if enabled
2014NOSUP:
2015 MOV BH,0 ;Disable zero suppression
2016 CALL OUT
2017 MOV AL,AH
2018OUT:
2019;Print char in AL without affecting registers
2020 XCHG AX,DX
2021 PUSH AX
2022 MOV AH,OUTCH
2023 INT 33
2024 POP AX
2025 XCHG AX,DX
2026 RET
2027
2028EXELOAD:
2029 MOV AX,CS
2030 ADD AX,LOADSEG
2031 MOV [EXEEND],AX ;Store in EXEEND
2032 MOV DX,OFFSET TRANGROUP:RUNVAR ;Read header in here
2033 MOV AH,SETDMA
2034 INT 33
2035 MOV CX,RUNVARSIZ ;Amount of header info we need
2036 MOV DX,OFFSET TRANGROUP:EXEFCB
2037 MOV AH,RDBLK
2038 INT 33 ;Read in header
2039 OR AL,AL
2040 JNZ BADEXE ;Must not reach EOF
2041 MOV AX,[HEADSIZ] ;Size of header in paragraphs
2042;Convert header size to 512-byte pages by multiplying by 32 & rounding up
2043 ADD AX,31 ;Round up first
2044 MOV CL,5
2045 SHR AX,CL ;Multiply by 32
2046 MOV [EXEFCB+RR],AX ;Position in file of program
2047 MOV WORD PTR[EXEFCB+RECLEN],512 ;Set record size
2048 ADD BX,10H ;First paragraph above parameter area
2049 MOV DX,[PAGES] ;Total size of file in 512-byte pages
2050 SUB DX,AX ;Size of program in pages
2051 MOV [PSIZE],DX
2052 SHL DX,CL ;Convert pages back to paragraphs
2053 MOV AX,DX
2054 ADD DX,BX ;Size + start = minimum memory (paragr.)
2055 MOV CX,[EXEEND] ;Get memory size in paragraphs
2056 CMP DX,CX ;Enough memory?
2057 JA SHRTERR
2058 MOV DX,[INITSP]
2059 ADD DX,15
2060 SHR DX,1
2061 SHR DX,1
2062 SHR DX,1
2063 SHR DX,1
2064 ADD DX,[INITSS]
2065 ADD DX,BX ;Adjusted value of SP
2066 CMP DX,CX ;Is it valid?
2067 JA SHRTERR
2068 CMP [LOADLOW],-1 ;Load low or high?
2069 JZ LOAD ;If low, load at segment BX
2070 SUB CX,AX ;Memory size - program size = load addr.
2071 MOV BX,CX
2072LOAD:
2073 MOV BP,BX ;Save load segment
2074LOAD1:
2075LOADSEG EQU (LOAD1-ZERO)/16
2076 PUSH DS
2077 MOV DS,BX
2078 XOR DX,DX ;Address 0 in segment
2079 MOV AH,SETDMA
2080 INT 33 ;Set load address
2081 POP DS
2082 MOV CX,[PSIZE] ;Number of records to read
2083 MOV DX,OFFSET TRANGROUP:EXEFCB
2084 MOV AH,RDBLK
2085 INT 33 ;Read in up to 64K
2086 SUB [PSIZE],CX ;Decrement count by amount read
2087 JZ HAVEXE ;Did we get it all?
2088 TEST AL,1 ;Check return code if not
2089 JNZ BADEXE ;Must be zero if more to come
2090 ADD BX,1000H-20H ;Bump data segment 64K minus one record
2091 JMP SHORT LOAD1 ;Get next 64K block
2092
2093BADEXE:
2094 MOV DX,OFFSET TRANGROUP:EXEBAD
2095 JMP ERROR
2096
2097SHRTERR:
2098 MOV DX,OFFSET TRANGROUP:TOOBIG
2099 JMP ERROR
2100
2101HAVEXE:
2102 MOV AX,[RELTAB] ;Get position of table
2103 MOV [EXEFCB+RR],AX ;Set in random record field
2104 MOV WORD PTR[EXEFCB+RECLEN],1 ;Set one-byte record
2105 MOV DX,OFFSET TRANGROUP:RELPT ;4-byte buffer for relocation address
2106 MOV AH,SETDMA
2107 INT 33
2108 CMP [RELCNT],0
2109 JZ NOREL
2110RELOC:
2111 MOV AH,RDBLK
2112 MOV DX,OFFSET TRANGROUP:EXEFCB
2113 MOV CX,4
2114 INT 33 ;Read in one relocation pointer
2115 OR AL,AL ;Check return code
2116 JNZ BADEXE
2117 MOV DI,[RELPT] ;Get offset of relocation pointer
2118 MOV AX,[RELSEG] ;Get segment
2119 ADD AX,BP ;Bias segment with actual load segment
2120 MOV ES,AX
2121 ADD WORD PTR ES:[DI],BP ;Relocate
2122 DEC [RELCNT] ;Count off
2123 JNZ RELOC
2124;Set up exit conditions
2125NOREL:
2126 MOV AX,[INITSS]
2127 ADD AX,BP
2128 CLI
2129 MOV SS,AX ;Initialize SS
2130 MOV SP,[INITSP]
2131 STI
2132 ADD [INITCS],BP
2133 MOV AX,[TPA] ;Get pointer to parameter area
2134 MOV CX,[BYTCNT] ;Size of TPA segment
2135 MOV ES,AX
2136 MOV DS,AX ;Set segment registers to point to it
2137 CALL SETUP
2138 JMP DWORD PTR CS:[INITIP] ;Long jump to program
2139
2140SETUP:
2141 AND CL,0F0H ;Adjust to even paragraph boundary
2142 MOV AX,WORD PTR DS:[6] ;Get current memory size
2143 SUB AX,CX ;Find out how much we're changing it
2144 MOV WORD PTR DS:[6],CX
2145 MOV CL,4
2146 SAR AX,CL ;Convert to a segment address
2147 ADD WORD PTR DS:[8],AX ;Adjust long jump to go to same place
2148 MOV DX,80H
2149 MOV AH,SETDMA
2150 INT 33 ;Set default disk transfer address
2151 MOV AX,WORD PTR CS:[PARM1] ;Pass on info about FCBs
2152 XOR CX,CX
2153 MOV DX,CX ;Assume no batch file
2154ASSUME CS:RESGROUP
2155 TEST CS:[BATCH],-1 ;Batch file in progress?
2156ASSUME CS:TRANGROUP
2157 JZ RET120 ;If not, all set up
2158 MOV CX,CS:[RESSEG]
2159 MOV DX,OFFSET RESGROUP:BATFCB ;CX:DX points to batch FCB
2160RET120: RET
2161TRANCODESIZE EQU $-ZERO
2162TRANCODE ENDS
2163COMLEN EQU TRANDATASIZE+TRANCODESIZE-102H ;End of COMMAND load. ZERO Needed to make COMLEN absolute
2164TRNLEN EQU (PRETRLEN+TRANCODESIZE+TRANDATASIZE+15)/16 ;Length of transient in paragraphs
2165 END PROGSTART
2166 \ No newline at end of file
diff --git a/v1.25/source/HEX2BIN.ASM b/v1.25/source/HEX2BIN.ASM
new file mode 100644
index 0000000..d7ba742
--- /dev/null
+++ b/v1.25/source/HEX2BIN.ASM
@@ -0,0 +1,214 @@
1; HEX2BIN version 1.02
2; Converts Intel hex format files to straight binary
3
4FCB: EQU 5CH
5READ: EQU 20
6SETDMA: EQU 26
7OPEN: EQU 15
8CLOSE: EQU 16
9CREATE: EQU 22
10DELETE: EQU 19
11BLKWRT: EQU 40
12GETSEG: EQU 38
13BUFSIZ: EQU 1024
14
15 ORG 100H
16 PUT 100H
17
18HEX2BIN:
19 MOV DI,FCB+9
20 CMP B,[DI]," "
21 JNZ HAVEXT
22 MOV SI,HEX
23 MOVB
24 MOVW
25HAVEXT:
26;Get load offset (default is -100H)
27 MOV CL,4 ;Needed for shifts
28 MOV [OFFSET],-100H
29 MOV SI,FCB+11H ;Scan second FCB for offset
30 LODB
31 CMP AL," " ;Check if offset present
32 JZ HAVOFF
33 MOV B,[SIGN],0 ;Assume positive sign for now
34 CMP AL,"+"
35 JZ GETOFF ;Get a positive offset
36 CMP AL,"-"
37 JNZ GETOFF1 ;If not + or -, then not signed
38 MOV B,[SIGN],1 ;Flag as negative offset
39GETOFF:
40 LODB ;Eat sign
41GETOFF1:
42 CALL HEXCHK ;Check for valid hex character
43 JC HAVOFF ;No offset if not valid
44 XOR BX,BX ;Intialize offset sum to 0
45CONVOFF:
46 SHL BX,CL ;Multiply current sum by 16
47 OR BL,AL ;Add in current hex digit
48 LODB ;Get next digit
49 CALL HEXCHK ;And convert it to binary
50 JNC CONVOFF ;Loop until all hex digits read
51 TEST B,[SIGN],-1 ;Check if offset was to be negative
52 JZ SAVOFF
53 NEG BX
54SAVOFF:
55 MOV [OFFSET],BX
56HAVOFF:
57 MOV DX,STARTSEG
58 MOV AX,DS
59 ADD DX,AX ;Compute load segment
60 MOV AH,GETSEG
61 INT 33
62 MOV ES,DX
63 SEG ES
64 MOV CX,[6] ;Get size of segment
65 MOV [SEGSIZ],CX
66 XOR AX,AX
67 MOV DI,AX
68 MOV BP,AX
69 SHR CX
70 REP
71 STOW ;Fill entire segment with zeros
72 MOV AH,OPEN
73 MOV DX,FCB
74 INT 21H
75 OR AL,AL
76 JNZ NOFIL
77 MOV B,[FCB+32],0
78 MOV [FCB+14],BUFSIZ ;Set record size to buffer size
79 MOV DX,BUFFER
80 MOV AH,SETDMA
81 INT 33
82 MOV AH,READ
83 MOV DX,FCB ;All set up for sequential reads
84 MOV SI,BUFFER+BUFSIZ ;Flag input buffer as empty
85READHEX:
86 CALL GETCH
87 CMP AL,":" ;Search for : to start line
88 JNZ READHEX
89 CALL GETBYT ;Get byte count
90 MOV CL,AL
91 MOV CH,0
92 JCXZ DONE
93 CALL GETBYT ;Get high byte of load address
94 MOV BH,AL
95 CALL GETBYT ;Get low byte of load address
96 MOV BL,AL
97 ADD BX,[OFFSET] ;Add in offset
98 MOV DI,BX
99 CALL GETBYT ;Throw away type byte
100READLN:
101 CMP DI,[SEGSIZ]
102 JAE ADERR
103 CALL GETBYT ;Get data byte
104 STOB
105 CMP DI,BP ;Check if this is the largest address so far
106 JBE HAVBIG
107 MOV BP,DI ;Save new largest
108HAVBIG:
109 LOOP READLN
110 JP READHEX
111
112NOFIL:
113 MOV DX,NOFILE
114QUIT:
115 MOV AH,9
116 INT 21H
117 INT 20H
118
119ADERR:
120 MOV DX,ADDR
121 JMP SHOWERR
122
123GETCH:
124 CMP SI,BUFFER+BUFSIZ
125 JNZ NOREAD
126 INT 21H
127 CMP AL,1
128 JZ ERROR
129 MOV SI,BUFFER
130NOREAD:
131 LODB
132 CMP AL,1AH
133 JZ DONE
134 RET
135
136GETBYT:
137 CALL HEXDIG
138 MOV BL,AL
139 CALL HEXDIG
140 SHL BL
141 SHL BL
142 SHL BL
143 SHL BL
144 OR AL,BL
145 RET
146
147HEXCHK:
148 SUB AL,"0"
149 JC RET
150 CMP AL,10
151 JC CMCRET
152 SUB AL,"A"-"0"-10
153 JC RET
154 CMP AL,16
155CMCRET:
156 CMC
157 RET
158
159HEXDIG:
160 CALL GETCH
161 CALL HEXCHK
162 JNC RET
163ERROR:
164 MOV DX,ERRMES
165SHOWERR:
166 MOV AH,9
167 INT 21H
168DONE:
169 MOV [FCB+9],4F00H+"C" ;"CO"
170 MOV B,[FCB+11],"M"
171 MOV DX,FCB
172 MOV AH,CREATE
173 INT 21H
174 OR AL,AL
175 JNZ NOROOM
176 XOR AX,AX
177 MOV [FCB+33],AX
178 MOV [FCB+35],AX ;Set RR field
179 INC AX
180 MOV [FCB+14],AX ;Set record size
181 XOR DX,DX
182 PUSH DS
183 PUSH ES
184 POP DS ;Get load segment
185 MOV AH,SETDMA
186 INT 21H
187 POP DS
188 MOV CX,BP
189 MOV AH,BLKWRT
190 MOV DX,FCB
191 INT 21H
192 MOV AH,CLOSE
193 INT 21H
194EXIT:
195 INT 20H
196
197NOROOM:
198 MOV DX,DIRFUL
199 JMP QUIT
200
201HEX: DB "HEX"
202ERRMES: DB "Error in HEX file--conversion aborted$"
203NOFILE: DB "File not found$"
204ADDR: DB "Address out of range--conversion aborted$"
205DIRFUL: DB "Disk directory full$"
206
207OFFSET: DS 2
208SEGSIZ: DS 2
209SIGN: DS 1
210BUFFER: DS BUFSIZ
211
212START:
213STARTSEG EQU (START+15)/16
214 \ No newline at end of file
diff --git a/v1.25/source/IO.ASM b/v1.25/source/IO.ASM
new file mode 100644
index 0000000..3b9f181
--- /dev/null
+++ b/v1.25/source/IO.ASM
@@ -0,0 +1,1934 @@
1; I/O System for 86-DOS version 1.20 and later. Revised 8-02-82.
2;
3; Assumes a CPU Support card at F0 hex for character I/O,
4; with disk drivers for SCP, Tarbell, or Cromemco controllers.
5;
6; Select whether console input is interrupt-driven or polled.
7INTINP: EQU 1
8;
9; Select whether the auxiliary port is the Support Card parallel port
10; or on channel 1 of a Multiport Serial card addressed at 10H.
11PARALLELAUX: EQU 1
12SERIALAUX: EQU 0
13;
14; Select whether the printer is connected to the Support card parallel
15; output port (standard) or channel 0 of a Multiport Serial card
16; addressed at 10H.
17PARALLELPRN: EQU 1
18SERIALPRN: EQU 0
19;
20; If the Multiport Serial was chosen for either the auxiliary or the
21; printer, select the baud rate here. Refer to Multiport Serial manual
22; page 11 to pick the correct value for a given baud rate.
23PRNBAUD:EQU 7 ; 1200 baud
24AUXBAUD:EQU 0FH ; 19200 baud
25;
26; Select disk controller here.
27SCP: EQU 1
28TARBELLSD: EQU 0
29TARBELLDD: EQU 0
30CROMEMCO4FDC: EQU 0
31CROMEMCO16FDC: EQU 0
32;
33; Select if you want a special conversion version which can read/write
34; both the new Microsoft format and the old SCP format.
35; For a two drive system, drives A and B are the new Microsoft format,
36; and drives C and D are the old SCP format (where C is the same physical
37; drive as A, and D is the same drive as B). CONVERT has no effect
38; on 5.25-inch drives.
39CONVERT:EQU 1
40;
41; Select disk configuration:
42LARGE: EQU 1 ; Large drives.
43COMBIN: EQU 0 ; Two 8-inch and one 5.25-inch.
44SMALL: EQU 0 ; Three 5.25-inch drives.
45CUSTOM: EQU 0 ; User defined.
46;
47; If 8-inch drives are PerSci, select FASTSEEK here:
48; (Fastseek with Tarbell controllers doesn't work yet).
49FASTSEEK: EQU 1
50;
51; For double-density controllers, select double-sided operation of
52; 8-inch disks in double-density mode.
53LARGEDS: EQU 0
54;
55; For double-density controllers, select double-sided operation of
56; 5.25-inch disks in double-density mode.
57SMALLDS: EQU 0
58;
59; Use table below to select head step speed. Step times for 5" drives
60; are double that shown in the table. Times for Fast Seek mode (using
61; PerSci drives) is very small - 200-400 microseconds.
62;
63; Step value 1771 1793
64;
65; 0 6ms 3ms
66; 1 6ms 6ms
67; 2 10ms 10ms
68; 3 20ms 15ms
69;
70STPSPD: EQU 0
71;
72; ****** End of selections ********************************************
73;
74BIOSSEG:EQU 40H ; I/O system segment.
75BIOSLEN:EQU 2048 ; Maximum length of I/O system.
76DOSLEN: EQU 8192 ; Maximum length of MS-DOS.
77QSIZE: EQU 80 ; Input queue size.
78PBUFSIZ:EQU 128 ; Size of print buffer
79BASE: EQU 0F0H ; CPU Support card base port number.
80SIOBASE:EQU 10H ; Base port number of Multiport Serial card.
81STAT: EQU BASE+7 ; Serial I/O status port.
82DATA: EQU BASE+6 ; Serial I/O data port.
83DAV: EQU 2 ; Data available bit.
84TBMT: EQU 1 ; Transmitter buffer empty bit.
85SERIAL: EQU SERIALPRN+SERIALAUX
86STCDATA:EQU BASE+4 ; Ports for 9513 Timer chip.
87STCCOM: EQU BASE+5
88
89 IF SERIALAUX
90AUXSTAT:EQU SIOBASE+3
91AUXDATA:EQU SIOBASE+2
92 ENDIF
93
94 IF PARALLELAUX
95AUXSTAT:EQU BASE+13
96AUXDATA:EQU BASE+12
97 ENDIF
98
99 IF SERIALPRN
100PRNSTAT:EQU SIOBASE+1
101PRNDATA:EQU SIOBASE+0
102 ENDIF
103
104 IF PARALLELPRN
105PRNSTAT:EQU BASE+13
106PRNDATA:EQU BASE+12
107 ENDIF
108
109 ORG 0
110 PUT 100H
111
112 JMP INIT
113 JMP STATUS
114 JMP INP
115 JMP OUTP
116 JMP PRINT
117 JMP AUXIN
118 JMP AUXOUT
119 JMP READ
120 JMP WRITE
121 JMP DSKCHG
122 JMP SETDATE
123 JMP SETTIME
124 JMP GETTIME
125 JMP FLUSH
126 JMP MAPDEV
127MAPDEV:
128 RET L
129
130INIT:
131 XOR BP,BP ; Set up stack just below I/O system.
132 MOV SS,BP
133 MOV SP,BIOSSEG*16
134
135 IF INTINP-1
136 MOV AL,0FFH ; Mask all interrupts.
137 OUTB BASE+3
138 ENDIF
139
140 IF INTINP
141 DI ; Set up keyboard interrupt vector.
142 MOV [BP+64H],KBINT
143 MOV [BP+66H],CS
144 EI
145 ENDIF
146
147 MOV [BP+4*38H],PRNFCB
148 MOV [BP+4*38H+2],CS
149 PUSH CS
150 POP DS
151;
152; Initialize time-of-day clock.
153;
154 MOV SI,STCTAB
155 MOV CX,4 ;Initialize 4 registers
156 UP
157INITSTC:
158 LODB
159 OUT STCCOM ;Select register to initialize
160 LODB
161 OUT STCDATA
162 LODB
163 OUT STCDATA
164 LOOP INITSTC
165
166 IF SERIAL
167 MOV CX,4
168SERINIT:
169 LODB
170 OUT SIOBASE+1
171 OUT SIOBASE+3
172 LOOP SERINIT
173 LODB ;Baud rate for channel 0
174 OUT SIOBASE+8
175 LODB ;Baud rate for channel 1
176 OUT SIOBASE+9
177 ENDIF
178;
179; Move MS-DOS down to the first segment just above the I/O system.
180;
181 MOV SI,BIOSLEN ; Source points to where MS-DOS currently is.
182 MOV AX,DOSSEG ; Destination is beginning of DOSSEG.
183 MOV ES,AX
184 SUB DI,DI
185 MOV CX,DOSLEN/2 ; CX is number of words to move.
186 REP
187 MOVSW
188
189 MOV SI,INITTAB
190 MOV DX,1 ; Do auto memory scan.
191 CALL 0,DOSSEG
192;
193; Change disk read and write vectors (INT 37 and INT 38) to go to
194; DIRECTREAD and DIRECTWRITE rather than READ and WRITE.
195;
196 SUB BP,BP
197 MOV W,[BP+37*4],DIRECTREAD
198 MOV W,[BP+38*4],DIRECTWRITE
199
200 MOV DX,100H
201 MOV AH,26 ;Set DMA address
202 INT 33
203 MOV CX,[6] ;Get size of segment
204 MOV BX,DS ;Save segment for later
205;
206; DS must be set to CS so we can point to the FCB.
207;
208 MOV AX,CS
209 MOV DS,AX
210 MOV DX,FCB ;File Control Block for COMMAND.COM
211 MOV AH,15
212 INT 33 ;Open COMMAND.COM
213 OR AL,AL
214 JNZ COMERR ;Error if file not found
215 XOR AX,AX
216 MOV [FCB+33],AX ; Set 4-byte Random Record field to
217 MOV [FCB+35],AX ; beginning of file.
218 INC AX
219 MOV [FCB+14],AX ;Set record length field
220 MOV AH,39 ;Block read (CX already set)
221 INT 33
222 JCXZ COMERR ;Error if no records read
223 TEST AL,1
224 JZ COMERR ;Error if not end-of-file
225;
226; Make all segment registers the same.
227;
228 MOV DS,BX
229 MOV ES,BX
230 MOV SS,BX
231 MOV SP,5CH ;Set stack to standard value
232 XOR AX,AX
233 PUSH AX ;Put zero on top of stack for return
234 MOV DX,80H
235 MOV AH,26
236 INT 33 ;Set default transfer address (DS:0080)
237 PUSH BX ;Put segment on stack
238 MOV AX,100H
239 PUSH AX ;Put address to execute within segment on stack
240 RET L ;Jump to COMMAND
241
242COMERR:
243 MOV DX,BADCOM
244 MOV AH,9 ;Print string
245 INT 33
246 EI
247STALL: JP STALL
248
249STCTAB: DB 17H ;Select master mode register
250 DW 84F3H ;Enable time-of-day
251 DB 1 ;Counter 1 mode register
252 DW 0138H
253 DB 2
254 DW 0038H
255 DB 3
256 DW 0008H ;Set counter 3 to count days
257
258 IF SERIAL
259 DB 0B7H, 77H, 4EH, 37H, PRNBAUD, AUXBAUD
260 ENDIF
261
262BADCOM: DB 13,10,"Error in loading Command Interpreter",13,10,"$"
263FCB: DB 1,"COMMAND COM"
264 DS 25
265;
266; ************ Time and Date ************
267;
268GETTIME:
269 MOV AL,0A7H ;Save counters 1,2,3
270 OUT STCCOM
271 MOV AL,0E0H ;Enable data pointer sequencing
272 OUT STCCOM
273 MOV AL,19H ;Select hold 1 / hold cycle
274 OUT STCCOM
275 CALL STCTIME ;Get seconds & 1/100's
276 XCHG AX,DX
277 CALL STCTIME ;Get hours & minutes
278 XCHG AX,CX
279 IN STCDATA
280 MOV AH,AL
281 IN STCDATA
282 XCHG AL,AH ;Count of days
283 JP POINTSTAT
284
285STCTIME:
286 CALL STCBYTE
287 MOV CL,AH
288STCBYTE:
289 IN STCDATA
290 MOV AH,AL
291 SHR AH
292 SHR AH
293 SHR AH
294 SHR AH
295 AND AL,0FH ;Unpack BCD digits
296 AAD ;Convert to binary
297 MOV AH,AL
298 MOV AL,CL
299 RET
300
301SETTIME:
302 PUSH CX
303 PUSH DX
304 CALL LOAD0 ;Put 0 into load registers to condition timer
305 MOV AL,43H ;Load counters 1 & 2
306 OUT STCCOM
307 POP DX
308 POP CX
309 CALL LOAD
310 MOV AL,43H
311 OUT STCCOM ;Load counters 1&2
312 CALL LOAD0
313 MOV AL,27H ;Arm counters 1,2,3
314 OUT STCCOM
315 JP POINTSTAT
316
317LOAD0:
318 XOR CX,CX
319 MOV DX,CX
320LOAD:
321 MOV AL,09 ;Counter 1 load register
322 CALL OUTDX
323 MOV AL,0AH ;Counter 2 load register
324 MOV DX,CX
325OUTDX:
326 OUT STCCOM ;Select a load register
327 MOV AL,DL
328 CALL OUTBCD
329 MOV AL,DH
330OUTBCD:
331 AAM ;Convert binary to unpacked BCD
332 SHL AH
333 SHL AH
334 SHL AH
335 SHL AH
336 OR AL,AH ;Packed BCD
337 OUT STCDATA
338 RET
339
340SETDATE:
341 XCHG AX,DX ;Put date in DX
342 MOV AL,0BH ;Select Counter 3 load register
343 OUT STCCOM
344 XCHG AX,DX
345 OUT STCDATA
346 MOV AL,AH
347 OUT STCDATA
348 MOV AL,44H ;Load counter 3
349 OUT STCCOM
350POINTSTAT:
351 PUSH AX
352 MOV AL,1FH ;Point to status register
353 OUT STCCOM ; so power-off glitches won't hurt
354 POP AX
355 RET L
356;
357; ************ CONSOLE INPUT ************
358;
359
360 IF INTINP-1 ; Non-interrupt driven input.
361STATUS:
362 IN STAT
363 AND AL,DAV
364 JZ NOTHING ; Jump if nothing there.
365 PUSHF ; Save Z flag.
366 INB DATA
367 AND AL,7FH
368 SEG CS
369 MOV [QUEUE],AL ; Put new character in buffer.
370 POPF ; Return with Z flag clear.
371 RET L
372NOTHING:
373 SEG CS
374 MOV AL,[QUEUE] ; See if there's anything in the buffer.
375 NOT AL ; Set up the Z flag.
376 TEST AL,80H
377 PUSHF
378 NOT AL
379 POPF
380 RET L
381
382INP:
383 MOV AL,-1
384 SEG CS
385 XCHG AL,[QUEUE] ; Remove the character from the buffer.
386 AND AL,AL
387 JNS INRET ; Return if we have a character.
388INLOOP:
389 IN STAT ; Wait till a character is available.
390 AND AL,DAV
391 JZ INLOOP
392 IN DATA
393 AND AL,7FH
394INRET:
395FLUSH:
396 RET L
397
398QUEUE: DB -1 ; For storing characters from STATUS to INP.
399 ENDIF
400
401 IF INTINP ; Interrupt-driven input.
402;
403; Console keyboard interrupt handler.
404;
405KBINT:
406 PUSH AX
407 PUSH SI
408 MOV AL,20H ;End of Interrupt command
409 OUT BASE+2 ;Send to slave
410 IN DATA ;Get the character
411 AND AL,7FH
412 CMP AL,"C"-"@"
413 JZ FLSH
414 CMP AL,"S"-"@"
415 JZ FLSH
416 CMP AL,"F"-"@"
417 JNZ SAVKY
418FLSH:
419 CALL 13*3,BIOSSEG ; Call I/O system keyboard buffer flush.
420SAVKY:
421 SEG CS
422 MOV SI,[REAR] ;Pointer to rear of queue
423 CALL INCQ
424 SEG CS
425 CMP SI,[FRONT] ;Any room in queue?
426 JZ QFULL
427 SEG CS
428 MOV [SI],AL ;Put character in queue
429 SEG CS
430 MOV [REAR],SI ;Save pointer
431LEAVINT:
432 POP SI
433 POP AX
434 IRET
435QFULL:
436 MOV AL,7 ; BELL character.
437 CALL 3*3,BIOSSEG ; Call I/O system console output function.
438 JMPS LEAVINT
439
440STATUS:
441 PUSH SI
442;See if printer ready
443 IN PRNSTAT
444 AND AL,TBMT
445 JZ NOPRN
446 SEG CS
447 MOV SI,[PFRONT]
448 SEG CS
449 CMP SI,[PREAR] ;Anything in print queue?
450 JNZ SENDPRN
451 SEG CS
452 CMP B,[PRNFCB],-1 ;Print spooling in progress?
453 JZ NOPRN ;If not, nothing to print
454;Print spooling in progress. Get next buffer
455 PUSH DS
456 PUSH CS
457 POP DS
458 PUSH AX
459 PUSH CX
460 PUSH DX
461 PUSH [STKSAV]
462 PUSH [STKSAV+2]
463 PUSH [DMAADD]
464 PUSH [DMAADD+2]
465 MOV DX,PQUEUE
466 MOV AH,26 ;Set DMA address
467 INT 33
468 MOV DX,PRNFCB
469 MOV CX,PBUFSIZ
470 MOV AH,39 ;Read buffer
471 INT 33
472 OR AL,AL
473 JZ NOTEOF
474 MOV B,[PRNFCB],-1 ;Turn off print spooling at EOF
475NOTEOF:
476 POP [DMAADD+2]
477 POP [DMAADD]
478 POP [STKSAV+2]
479 POP [STKSAV]
480 MOV SI,CX
481 POP DX
482 POP CX
483 POP AX
484 POP DS
485 OR SI,SI
486 JZ NOPRN
487 ADD SI,PQUEUE-1
488 SEG CS
489 MOV [PREAR],SI
490 MOV SI,ENDPQ-1
491SENDPRN:
492 CALL INCPQ
493 SEG CS
494 MOV [PFRONT],SI
495 SEG CS
496 LODSB ;Get character to print
497 OUT PRNDATA
498NOPRN:
499 DI ; Disable interrupts while checking queue.
500 SEG CS
501 MOV SI,[FRONT]
502 SEG CS
503 CMP SI,[REAR] ; Anything in queue?
504 JZ NOCHR ; Jump if nothing in queue.
505 CALL INCQ
506 SEG CS
507 LODSB ;Get character (if there is one)
508 OR SI,SI ;Reset zero flag
509NOCHR:
510 EI
511 POP SI
512 RET L ;Zero clear if we have a character
513
514INP:
515 CALL STATUS,BIOSSEG ; Get I/O system console input status.
516 JZ INP
517 PUSH SI
518 DI ; Disable interrupts while changing queue pointers.
519 SEG CS
520 MOV SI,[FRONT]
521 CALL INCQ ; Permanently remove char from queue
522 SEG CS
523 MOV [FRONT],SI
524 EI
525 POP SI
526 RET L
527
528FLUSH:
529 DI
530 SEG CS
531 MOV [REAR],QUEUE
532 SEG CS
533 MOV [FRONT],QUEUE
534 EI
535 RET L
536
537INCQ:
538 INC SI
539 CMP SI,ENDQ ;Exceeded length of queue?
540 JB RET
541 MOV SI,QUEUE
542 RET
543
544INCPQ:
545 INC SI
546 CMP SI,ENDPQ ;Exceeded length of queue?
547 JB RET
548 MOV SI,PQUEUE
549 RET
550
551FRONT: DW QUEUE
552REAR: DW QUEUE
553QUEUE: DS QSIZE
554ENDQ: EQU $
555PFRONT: DW PQUEUE
556PREAR: DW PQUEUE
557PQUEUE: DS PBUFSIZ
558ENDPQ: EQU $
559PRNFCB: DB -1
560 DS 36
561 ENDIF
562
563;
564; ************ Console and Printer Output ************
565;
566OUTP:
567 PUSH AX
568OUTLP:
569 IN STAT
570 AND AL,TBMT
571 JZ OUTLP
572 POP AX
573 OUT DATA
574 RET L
575
576PRINT:
577 PUSH SI
578 SEG CS
579 MOV SI,[PREAR]
580 CALL INCPQ
581PRINLP:
582 SEG CS
583 CMP SI,[PFRONT]
584 JNZ PRNCHR
585;Print queue is full
586 PUSH AX
587 CALL STATUS,BIOSSEG ;Poll and maybe print something
588 POP AX
589 JMPS PRINLP
590PRNCHR:
591 SEG CS
592 MOV [PREAR],SI
593 SEG CS
594 MOV [SI],AL
595 POP SI
596 RET L
597;
598; ************ Auxiliary I/O ************
599;
600AUXIN:
601 IN AUXSTAT
602 AND AL,DAV
603 JZ AUXIN
604 IN AUXDATA
605 RET L
606
607AUXOUT:
608 PUSH AX
609AUXLP:
610 IN AUXSTAT
611 AND AL,TBMT
612 JZ AUXLP
613 POP AX
614 OUT AUXDATA
615 RET L
616;
617; ************ 1771/1793-type controller disk I/O ************
618;
619TARBELL:EQU TARBELLSD+TARBELLDD
620CROMEMCO:EQU CROMEMCO4FDC+CROMEMCO16FDC
621
622WD1791: EQU SCP+TARBELLDD+CROMEMCO16FDC
623WD1771: EQU TARBELLSD+CROMEMCO4FDC
624
625 IF WD1791
626READCOM:EQU 80H
627WRITECOM:EQU 0A0H
628 ENDIF
629
630 IF WD1771
631READCOM:EQU 88H
632WRITECOM:EQU 0A8H
633 ENDIF
634
635 IF SCP
636SMALLBIT:EQU 10H
637BACKBIT:EQU 04H
638DDENBIT:EQU 08H
639DONEBIT:EQU 01H
640DISK: EQU 0E0H
641 ENDIF
642
643 IF TARBELL
644BACKBIT:EQU 40H
645DDENBIT:EQU 08H
646DONEBIT:EQU 80H
647DISK: EQU 78H
648 ENDIF
649
650 IF CROMEMCO
651SMALLBIT:EQU 10H
652BACKBIT:EQU 0FDH ; Send this to port 4 to select back.
653DDENBIT:EQU 40H
654DONEBIT:EQU 01H
655DISK: EQU 30H
656 ENDIF
657
658 IF SMALLDS-1
659SMALLDDSECT: EQU 8
660 ENDIF
661
662 IF SMALLDS
663SMALLDDSECT: EQU 16
664 ENDIF
665
666 IF LARGEDS-1
667LARGEDDSECT: EQU 8
668 ENDIF
669
670 IF LARGEDS
671LARGEDDSECT: EQU 16
672 ENDIF
673;
674; Disk change function.
675; On entry:
676; AL = disk drive number.
677; On exit:
678; AH = -1 (FF hex) if disk is changed.
679; AH = 0 if don't know.
680; AH = 1 if not changed.
681;
682; CF clear if no disk error.
683; AL = disk I/O driver number.
684;
685; CF set if disk error.
686; AL = disk error code (see disk read below).
687;
688 IF WD1771
689DSKCHG:
690 MOV AH,0 ; AH = 0 in case we don't know.
691 SEG CS
692 CMP AL,[CURDRV]
693 JNZ RETL
694 PUSH AX ; Save drive number.
695
696 IF CROMEMCO
697 INB DISK+4
698 ENDIF
699
700 IF TARBELL
701 INB DISK
702 ENDIF
703
704 AND AL,20H ; Look at head load bit
705 POP AX
706 JZ RETL
707 MOV AH,1 ; AH = 1, disk not changed.
708RETL:
709 CLC ; No disk error.
710 RET L
711 ENDIF ; End of 1771 DSKCHG.
712
713 IF WD1791
714DSKCHG:
715 MOV AH,0 ; AH = 0 in case we don't know.
716 SEG CS
717 CMP AL,[CURDRV]
718 JNZ DENSCHK ; Check density if not same drive.
719 PUSH AX
720
721 IF SCP+CROMEMCO
722 INB DISK+4
723 ENDIF
724
725 IF TARBELL
726 INB DISK
727 ENDIF
728
729 AND AL,20H ; Look at head load bit
730 POP AX
731 JZ DENSCHK ; Check density if head not loaded.
732 MOV AH,1 ; AH = 1, disk not changed.
733 MOV BX,PREVDENS
734 SEG CS
735 XLAT ; Get previous density
736 CLC ; No disk error.
737 RET L
738DENSCHK:
739 CALL CHKNEW ; Unload head if selecting new drive.
740 CBW
741 XCHG AX,SI
742 ADD SI,PREVDENS
743 MOV CX,4 ; Try each density twice
744 MOV AH,0 ; Disk may not have been changed.
745CHKDENS:
746 SEG CS
747 MOV AL,[SI] ; Get previous disk I/O driver number.
748 MOV BX,DRVTAB
749 SEG CS
750 XLAT ; Get drive select byte for previous density
751
752 IF CROMEMCO16FDC
753 CALL MOTOR ; Wait for motor to come up to speed.
754 ENDIF
755
756 OUT DISK+4 ; Select disk
757 MOV AL,0C4H ; READ ADDRESS command
758 CALL DCOM
759 AND AL,98H
760 IN DISK+3 ; Eat last byte to reset DRQ
761 JZ HAVDENS ; Jump if no error in reading address.
762 NOT AH ; AH = -1 (disk changed) if new density works.
763 SEG CS
764 XOR B,[SI],1 ; Try other density
765 LOOP CHKDENS
766 MOV AX,2 ; Couldn't read disk at all, AH = 0 for don't
767 STC ; know if disk changed, AL = error code 2 -
768 RET L ; disk not ready, carry set to indicate error.
769
770HAVDENS:
771 SEG CS
772 LODSB ; AL = disk I/O driver number.
773 CLC ; No disk error.
774 RET L
775
776PREVDENS:DB 1,3,5,7,9,11,13 ; Table of previous disk I/O driver numbers.
777 ENDIF ; End of 1793 DSKCHG function.
778
779CHKNEW:
780 MOV AH,AL ; Save disk drive number in AH.
781 SEG CS ; AL = previous disk drive number,
782 XCHG AL,[CURDRV] ; make new drive current.
783 CMP AL,AH ; Changing drives?
784 JZ RET
785;
786; If changing drives, unload head so the head load delay one-shot will
787; fire again. Do it by seeking to the same track with the H bit reset.
788;
789 IN DISK+1 ; Get current track number
790 OUT DISK+3 ; Make it the track to seek to
791 MOV AL,10H ; Seek and unload head
792 CALL DCOM
793 MOV AL,AH ; Restore current drive number
794 RET
795
796 IF CROMEMCO16FDC
797MOTOR:
798 PUSH AX
799 MOV AH,AL
800 IN DISK+4 ; See if the motor is on.
801 TEST AL,08H
802 MOV AL,AH
803 OUTB DISK+4 ; Select drive & start motor.
804 JNZ MOTORSON ; No delay if motors already on.
805 PUSH CX
806 MOV CX,43716 ; Loop count for 1 second.
807MOTORDELAY: ; (8 MHz, 16-bit memory).
808 AAM ; 83 clocks.
809 AAM ; 83 clocks.
810 LOOP MOTORDELAY ; 17 clocks.
811 POP CX
812MOTORSON:
813 POP AX
814 RET
815 ENDIF
816;
817; Disk read function.
818;
819; On entry:
820; AL = Disk I/O driver number
821; BX = Disk transfer address in DS
822; CX = Number of sectors to transfer
823; DX = Logical record number of transfer
824; On exit:
825; CF clear if transfer complete
826;
827; CF set if hard disk error.
828; CX = number of sectors left to transfer.
829; AL = disk error code
830; 0 = write protect error
831; 2 = not ready error
832; 4 = "data" (CRC) error
833; 6 = seek error
834; 8 = sector not found
835; 10 = write fault
836; 12 = "disk" (none of the above) error
837;
838READ:
839 CALL SEEK ;Position head
840 JC ERROR
841 PUSH ES ; Make ES same as DS.
842 MOV BX,DS
843 MOV ES,BX
844RDLP:
845 CALL READSECT ;Perform sector read
846 JC POPESERROR
847 INC DH ;Next sector number
848 LOOP RDLP ;Read each sector requested
849 CLC ; No errors.
850 POP ES ; Restore ES register.
851 RET L
852;
853; Disk write function.
854; Registers same on entry and exit as read above.
855;
856WRITE:
857 CALL SEEK ;Position head
858 JC ERROR
859WRTLP:
860 CALL WRITESECT ;Perform sector write
861 JC ERROR
862 INC DH ;Bump sector counter
863 LOOP WRTLP ;Write CX sectors
864 CLC ; No errors.
865WRITERET:
866 RET L
867
868POPESERROR:
869 POP ES ; Restore ES register.
870ERROR:
871 MOV BL,-1
872 SEG CS
873 MOV [DI],BL ; Indicate we don't know where head is.
874 MOV SI,ERRTAB
875GETCOD:
876 INC BL ; Increment to next error code.
877 SEG CS
878 LODB
879 TEST AH,AL ; See if error code matches disk status.
880 JZ GETCOD ; Try another if not.
881 MOV AL,BL ; Now we've got the code.
882 SHL AL ; Multiply by two.
883 STC
884 RET L
885
886ERRTAB:
887 DB 40H ;Write protect error
888 DB 80H ;Not ready error
889 DB 8 ;CRC error
890 DB 2 ;Seek error
891 DB 10H ;Sector not found
892 DB 20H ;Write fault
893 DB 7 ;"Disk" error
894;
895; Direct disk read and write from INT 37 and INT 38. Subroutine GETIODRIVER
896; calls DSKCHG to convert disk drive number to I/O driver number.
897;
898; Setting CURDRV to -1 before calling DSKCHG forces DSKCHG to check the disk's
899; density before returning the I/O driver number. This is necessary because
900; programs such as FORMAT could change the density of a disk and leave the
901; head loaded. If the head is loaded DSKCHG assumes the disk hasn't been
902; changed and returns the old I/O driver number which could be wrong.
903;
904; CURDRV is set to -1 before returning so when DSKCHG is called by the
905; operating system, it will tell the operating system the disk may have
906; been changed (because it may have been).
907;
908DIRECTREAD:
909
910 IF WD1791
911 CALL GETIODRIVER ; Convert drive number to I/O driver number.
912 JC DIRECTRET ; Return if DSKCHG returned error.
913 ENDIF
914
915 CALL 7*3,BIOSSEG ; Call READ.
916 JMPS DIRECTRET
917
918DIRECTWRITE:
919
920 IF WD1791
921 CALL GETIODRIVER ; Convert drive number to I/O driver number.
922 JC DIRECTRET ; Return if DSKCHG returned error.
923 ENDIF
924
925 CALL 8*3,BIOSSEG ; Call WRITE.
926DIRECTRET:
927 SEG CS
928 MOV B,[CURDRV],-1 ; Force DSKCHG to do density check.
929 RET L
930
931 IF WD1791
932GETIODRIVER:
933 SEG CS
934 MOV B,[CURDRV],-1 ; Force DSKCHG to do density check.
935 PUSH BX
936 PUSH CX
937 CALL 9*3,BIOSSEG ; Call DSKCHG.
938 POP CX
939 POP BX
940 RET
941 ENDIF
942;
943; Function:
944; Seeks to proper track.
945; On entry:
946; Same as for disk read or write above.
947; On exit:
948; AH = Drive select byte
949; DL = Track number
950; DH = Sector number
951; SI = Disk transfer address in DS
952; DI = pointer to drive's track counter in CS
953; CX unchanged (number of sectors)
954;
955SEEK:
956 MOV SI,BX ; Save transfer address
957 CBW
958 MOV BX,AX ; Prepare to index on drive number
959
960 IF WD1791 ; If two disk formats per drive.
961 SHR AL ; Convert to physical disk drive number.
962 ENDIF
963
964 CALL CHKNEW ; Unload head if changing drives.
965 SEG CS
966 MOV AL,[BX+DRVTAB] ; Get drive-select byte.
967
968 IF CROMEMCO16FDC
969 CALL MOTOR ; Wait for the motors to come up to speed.
970 ENDIF
971
972 OUTB DISK+4 ; Select drive.
973
974 IF CROMEMCO
975 OR AL,80H ; Set auto-wait bit.
976 ENDIF
977
978 MOV AH,AL ; Save drive-select byte in AH.
979 XCHG AX,DX ; AX = logical sector number.
980 MOV DL,26 ; 26 sectors/track unless changed below
981
982 IF SCP
983 TEST DH,SMALLBIT ; Check if small disk.
984 JZ BIGONE ; Jump if big disk.
985 MOV DL,18 ; Assume 18 sectors on small track.
986 TEST DH,DDENBIT ; Check if double-density.
987 JZ HAVSECT ; Jump if not.
988 MOV DL,SMALLDDSECT ; Number of sectors on small DD track.
989 JP HAVSECT
990BIGONE:
991 TEST DH,DDENBIT ; Check if double-density.
992 JZ HAVSECT ; Jump if not.
993 MOV DL,LARGEDDSECT ; Number of sectors on big DD track.
994 ENDIF
995
996 IF TARBELLDD ; Tarbell DD controller.
997 TEST DH,DDENBIT ; Check for double-density.
998 JZ HAVSECT
999 MOV DL,LARGEDDSECT ; Number of sectors on DD track.
1000 ENDIF
1001
1002 IF CROMEMCO4FDC
1003 TEST DH,SMALLBIT ; Check if small disk.
1004 JNZ HAVSECT ; Jump if not.
1005 MOV DL,18 ; 18 sectors on small disk track.
1006 ENDIF
1007
1008 IF CROMEMCO16FDC
1009 TEST DH,SMALLBIT ; Check if small disk.
1010 JNZ BIGONE ; Jump if big disk.
1011 MOV DL,18 ; Assume 18 sectors on small track.
1012 TEST DH,DDENBIT ; Check if double-density.
1013 JZ HAVSECT ; Jump if not.
1014 MOV DL,SMALLDDSECT ; Number of sectors on small DD track.
1015 JP HAVSECT
1016BIGONE:
1017 TEST DH,DDENBIT ; Check if double-density.
1018 JZ HAVSECT ; Jump if not.
1019 MOV DL,LARGEDDSECT ; Number of sectors on big DD track.
1020 ENDIF
1021
1022HAVSECT:
1023 DIV AL,DL ; AL = track, AH = sector.
1024 XCHG AX,DX ; AH has drive-select byte, DX = track & sector.
1025 INC DH ; Sectors start at one, not zero.
1026 SEG CS
1027 MOV BL,[BX+TRKPT] ; Get this drive's displacement into track table.
1028 ADD BX,TRKTAB ; BX now points to track counter for this drive.
1029 MOV DI,BX
1030 MOV AL,DL ; Move new track number into AL.
1031 SEG CS
1032 XCHG AL,[DI] ; Xchange current track with desired track
1033 OUT DISK+1 ; Inform controller chip of current track
1034 CMP AL,DL ; See if we're at the right track.
1035 JZ RET
1036 MOV BH,2 ; Seek retry count
1037 CMP AL,-1 ; Head position known?
1038 JNZ NOHOME ; If not, home head
1039TRYSK:
1040 CALL HOME
1041 JC SEEKERR
1042NOHOME:
1043 MOV AL,DL ; AL = new track number.
1044 OUT DISK+3
1045 MOV AL,1CH+STPSPD ; Seek command.
1046 CALL MOVHEAD
1047 AND AL,98H ; Accept not ready, seek, & CRC error bits.
1048 JZ RET
1049 JS SEEKERR ; No retries if not ready
1050 DEC BH
1051 JNZ TRYSK
1052SEEKERR:
1053 MOV AH,AL ; Put status in AH.
1054 TEST AL,80H ; See if it was a Not Ready error.
1055 STC
1056 JNZ RET ; Status is OK for Not Ready error.
1057 MOV AH,2 ; Everything else is seek error.
1058 RET
1059
1060SETUP:
1061 MOV BL,DH ; Move sector number to BL to play with
1062
1063 IF SCP+CROMEMCO16FDC
1064 TEST AH,DDENBIT ; Check for double density.
1065 JZ CHECKSMALL ; Not DD, check size for SD.
1066 ENDIF
1067
1068 IF TARBELLDD
1069 TEST AH,DDENBIT ; Check for double density.
1070 JZ CHECK26 ; Not DD.
1071 ENDIF
1072
1073 IF WD1791
1074
1075 IF (SCP+TARBELL)*LARGEDS+SCP*SMALLDS
1076 MOV AL,AH ; Select front side of disk.
1077 OUT DISK+4
1078 ENDIF
1079
1080 IF CROMEMCO*(LARGEDS+SMALLDS)
1081 MOV AL,0FFH ; Select front side of disk.
1082 OUT 04H
1083 ENDIF
1084
1085 CMP BL,8 ; See if legal DD sector number.
1086 JBE PUTSEC ; Jump if ok.
1087
1088 IF (LARGEDS-1)*((SMALLDS*(SCP+CROMEMCO))-1)
1089 JP STEP ; If only SS drives, we gotta step.
1090 ENDIF
1091
1092 IF SCP*LARGEDS*(SMALLDS-1)
1093 TEST AH,SMALLBIT ; Check for 5.25 inch disk.
1094 JNZ STEP ; Jump if small because SMALLDS is off.
1095 ENDIF
1096
1097 IF SCP*SMALLDS*(LARGEDS-1)
1098 TEST AH,SMALLBIT ; Check for 8 inch disk.
1099 JZ STEP ; Jump if large because LARGEDS is off.
1100 ENDIF
1101
1102 IF CROMEMCO16FDC*LARGEDS*(SMALLDS-1)
1103 TEST AH,SMALLBIT ; Check for 5.25 inch disk.
1104 JZ STEP ; Jump if small because SMALLDS is off.
1105 ENDIF
1106
1107 IF CROMEMCO16FDC*SMALLDS*(LARGEDS-1)
1108 TEST AH,SMALLBIT ; Check for 8 inch disk.
1109 JNZ STEP ; Jump if large because LARGEDS is off.
1110 ENDIF
1111
1112 IF LARGEDS+SMALLDS*(SCP+CROMEMCO)
1113 SUB BL,8 ; Find true sector for back side.
1114 CMP BL,8 ; See if ok now.
1115 JA STEP ; Have to step if still too big.
1116
1117 IF SCP+TARBELLDD
1118 MOV AL,AH ; Move drive select byte into AL.
1119 OR AL,BACKBIT ; Select back side.
1120 OUT DISK+4
1121 ENDIF
1122
1123 IF CROMEMCO16FDC
1124 MOV AL,BACKBIT ; Select back side.
1125 OUT 04H
1126 ENDIF
1127
1128 JP PUTSEC
1129 ENDIF
1130
1131 ENDIF
1132
1133 IF SCP
1134CHECKSMALL:
1135 TEST AH,SMALLBIT ; See if big disk.
1136 JZ CHECK26 ; Jump if big.
1137 ENDIF
1138
1139 IF CROMEMCO
1140CHECKSMALL:
1141 TEST AH,SMALLBIT ; See if big disk.
1142 JNZ CHECK26 ; Jump if big.
1143 ENDIF
1144
1145 IF SCP+CROMEMCO
1146 CMP BL,18 ; See if legal small SD/SS sector.
1147 JA STEP ; Jump if not.
1148 ENDIF
1149
1150CHECK26:
1151 CMP BL,26 ; See if legal large SD/SS sector.
1152 JBE PUTSEC ; Jump if ok.
1153STEP:
1154 INC DL ; Increment track number.
1155 MOV AL,58H ; Step in with update.
1156 CALL DCOM
1157 SEG CS
1158 INC B,[DI] ; Increment the track pointer.
1159 MOV DH,1 ; After step, do first sector.
1160 MOV BL,DH ; Fix temporary sector number also.
1161PUTSEC:
1162 MOV AL,BL ; Output sector number to controller.
1163 OUT DISK+2
1164 DI ; Interrupts not allowed until I/O done
1165
1166 IF SCP+CROMEMCO
1167 INB DISK+4 ; Get head-load bit.
1168 ENDIF
1169
1170 IF TARBELL
1171 INB DISK
1172 ENDIF
1173
1174 NOT AL
1175 AND AL,20H ; Check head load status
1176 JZ RET
1177 MOV AL,4
1178 RET
1179
1180READSECT:
1181 CALL SETUP
1182 MOV BL,10 ; Retry count for hard error.
1183 XCHG DI,SI ; Transfer address to DI.
1184 PUSH DX ; Save track & sector number.
1185 MOV DL,DISK+3 ; Disk controller data port.
1186RDAGN:
1187 OR AL,READCOM
1188 OUT DISK
1189
1190 IF CROMEMCO
1191 MOV AL,AH ; Turn on auto-wait.
1192 OUT DISK+4
1193 ENDIF
1194
1195 MOV BP,DI ; Save address for retry.
1196 JMPS RLOOPENTRY
1197RLOOP:
1198 STOB ; Write into memory.
1199RLOOPENTRY:
1200
1201 IF SCP
1202 IN DISK+5 ; Wait for DRQ or INTRQ.
1203 ENDIF
1204
1205 IF TARBELL+CROMEMCO
1206 IN DISK+4
1207 ENDIF
1208
1209 IF TARBELL
1210 SHL AL
1211 INB DX ; Read data from disk controller chip.
1212 JC RLOOP
1213 ENDIF
1214
1215 IF SCP+CROMEMCO
1216 SHR AL
1217 INB DX ; Read data from disk controller chip.
1218 JNC RLOOP
1219 ENDIF
1220
1221 EI ; Interrupts OK now
1222 CALL GETSTAT
1223 AND AL,9CH
1224 JZ RDPOP
1225 MOV DI,BP ; Get origainal address back for retry.
1226 MOV BH,AL ; Save error status for report
1227 MOV AL,0
1228 DEC BL
1229 JNZ RDAGN
1230 MOV AH,BH ; Put error status in AH.
1231 STC
1232RDPOP:
1233 POP DX ; Get back track & sector number.
1234 XCHG SI,DI ; Address back to SI.
1235
1236 IF TARBELL
1237FORCINT:
1238 MOV AL,0D0H ; Tarbell controllers need this Force Interrupt
1239 OUT DISK ; so that Type I status is always available
1240 MOV AL,10 ; at the 1771/1793 status port so we can find
1241INTDLY: ; out if the head is loaded. SCP and Cromemco
1242 DEC AL ; controllers have head-load status available
1243 JNZ INTDLY ; at the DISK+4 status port.
1244 ENDIF
1245
1246 RET
1247
1248WRITESECT:
1249 CALL SETUP
1250 MOV BL,10
1251 PUSH DX ; Save track & sector number.
1252 MOV DL,DISK+3 ; Disk controller data port.
1253WRTAGN:
1254 OR AL,WRITECOM
1255 OUT DISK
1256
1257 IF CROMEMCO
1258 MOV AL,AH ; Turn on auto-wait.
1259 OUT DISK+4
1260 ENDIF
1261
1262 MOV BP,SI
1263WRLOOP:
1264
1265 IF SCP
1266 INB DISK+5
1267 ENDIF
1268
1269 IF TARBELL+CROMEMCO
1270 INB DISK+4
1271 ENDIF
1272
1273 IF SCP+CROMEMCO
1274 SHR AL
1275 LODB ; Get data from memory.
1276 OUTB DX ; Write to disk.
1277 JNC WRLOOP
1278 ENDIF
1279
1280 IF TARBELL
1281 SHL AL
1282 LODB ; Get data from memory.
1283 OUTB DX ; Write to disk.
1284 JC WRLOOP
1285 ENDIF
1286
1287 EI ; Interrupts OK now.
1288 DEC SI
1289 CALL GETSTAT
1290 AND AL,0FCH
1291 JZ WRPOP
1292 MOV SI,BP
1293 MOV BH,AL
1294 MOV AL,0
1295 DEC BL
1296 JNZ WRTAGN
1297 MOV AH,BH ; Error status to AH.
1298 STC
1299WRPOP:
1300 POP DX ; Get back track & sector number.
1301
1302 IF TARBELL
1303 JMPS FORCINT
1304 ENDIF
1305
1306 IF SCP+CROMEMCO
1307 RET
1308 ENDIF
1309;
1310; Subroutine to restore the read/write head to track 0.
1311;
1312 IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1)
1313HOME:
1314 ENDIF
1315
1316 IF FASTSEEK*CROMEMCO
1317 TEST AH,SMALLBIT ; Check for large disk.
1318 JNZ RESTORE ; Big disks are fast seek PerSci.
1319 ENDIF
1320
1321 MOV BL,3
1322TRYHOM:
1323
1324 IF SCP*FASTSEEK
1325 MOV AL,AH ; Turn on Restore to PerSci.
1326 OR AL,80H
1327 OUTB DISK+4
1328 ENDIF
1329
1330 MOV AL,0CH+STPSPD ; Restore with verify command.
1331 CALL DCOM
1332 AND AL,98H
1333
1334 IF SCP*FASTSEEK
1335 MOV AL,AH ; Restore off.
1336 OUTB DISK+4
1337 ENDIF
1338
1339 JZ RET
1340 JS HOMERR ; No retries if not ready
1341 MOV AL,58H+STPSPD ; Step in with update
1342 CALL DCOM
1343 DEC BL
1344 JNZ TRYHOM
1345HOMERR:
1346 STC
1347 RET
1348;
1349; RESTORE for PerSci drives.
1350; Doesn't exist yet for Tarbell controllers.
1351;
1352 IF FASTSEEK*TARBELL
1353HOME:
1354RESTORE:
1355 RET
1356 ENDIF
1357
1358 IF FASTSEEK*CROMEMCO4FDC
1359RESTORE:
1360 MOV AL,0C4H ;READ ADDRESS command to keep head loaded
1361 OUT DISK
1362 MOV AL,77H
1363 OUT 4
1364CHKRES:
1365 IN 4
1366 AND AL,40H
1367 JZ RESDONE
1368 IN DISK+4
1369 TEST AL,DONEBIT
1370 JZ CHKRES
1371 IN DISK
1372 JP RESTORE ;Reload head
1373RESDONE:
1374 MOV AL,7FH
1375 OUT 4
1376 CALL GETSTAT
1377 MOV AL,0
1378 OUT DISK+1 ;Tell 1771 we're now on track 0
1379 RET
1380 ENDIF
1381
1382 IF FASTSEEK*CROMEMCO16FDC
1383RESTORE:
1384 MOV AL,0D7H ; Turn on Drive-Select and Restore.
1385 OUTB 4
1386 PUSH AX
1387 AAM ; 10 uS delay.
1388 POP AX
1389RESWAIT:
1390 INB 4 ; Wait till Seek Complete is active.
1391 TEST AL,40H
1392 JNZ RESWAIT
1393 MOV AL,0FFH ; Turn off Drive-Select and Restore.
1394 OUTB 4
1395 SUB AL,AL ; Tell 1793 we're on track 0.
1396 OUTB DISK+1
1397 RET
1398 ENDIF
1399;
1400; Subroutine to move the read/write head to the desired track.
1401; Usually falls through to DCOM unless special handling for
1402; PerSci drives is required in which case go to FASTSK.
1403;
1404 IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1)
1405MOVHEAD:
1406 ENDIF
1407
1408 IF CROMEMCO*FASTSEEK
1409 TEST AH,SMALLBIT ; Check for PerSci.
1410 JNZ FASTSK
1411 ENDIF
1412
1413DCOM:
1414 OUT DISK
1415 PUSH AX
1416 AAM ;Delay 10 microseconds
1417 POP AX
1418GETSTAT:
1419 IN DISK+4
1420 TEST AL,DONEBIT
1421
1422 IF TARBELL
1423 JNZ GETSTAT
1424 ENDIF
1425
1426 IF SCP+CROMEMCO
1427 JZ GETSTAT
1428 ENDIF
1429
1430 IN DISK
1431 RET
1432;
1433; Fast seek code for PerSci drives.
1434; Tarbell not installed yet.
1435;
1436 IF FASTSEEK*TARBELL
1437MOVHEAD:
1438FASTSK:
1439 RET
1440 ENDIF
1441
1442 IF FASTSEEK*CROMEMCO
1443FASTSK:
1444 MOV AL,6FH
1445 OUT 4
1446 MOV AL,18H
1447 CALL DCOM
1448SKWAIT:
1449 IN 4
1450 TEST AL,40H
1451 JNZ SKWAIT
1452 MOV AL,7FH
1453 OUT 4
1454 MOV AL,0
1455 RET
1456 ENDIF
1457
1458CURDRV: DB -1
1459;
1460; Explanation of tables below.
1461;
1462; DRVTAB is a table of bytes which are sent to the disk controller as drive-
1463; select bytes to choose which physical drive is selected for each disk I/O
1464; driver. It also selects whether the disk is 5.25-inch or 8-inch, single-
1465; density or double-density. Always select side 0 in the drive-select byte if
1466; a side-select bit is available. There should be one entry in the DRVTAB
1467; table for each disk I/O driver. Exactly which bits in the drive-select byte
1468; do what depends on which disk controller is used.
1469;
1470; TRKTAB is a table of bytes used to store which track the read/write
1471; head of each drive is on. Each physical drive should have its own
1472; entry in TRKTAB.
1473;
1474; TRKPT is a table of bytes which indicates which TRKTAB entry each
1475; disk I/O driver should use. Since each physical drive may be used for
1476; more than one disk I/O driver, more than one entry in TRKPT may point
1477; to the same entry in TRKTAB. Drives such as PerSci 277s which use
1478; the same head positioner for more than one drive should share entrys
1479; in TRKTAB.
1480;
1481; INITTAB is the initialization table for 86-DOS as described in the
1482; 86-DOS Programer's Manual under "Customizing the I/O System."
1483;
1484 IF SCP*COMBIN*FASTSEEK
1485;
1486; A PerSci 277 or 299 and one 5.25-inch drive.
1487;
1488DRVTAB: DB 00H,08H,01H,09H,10H,18H,00H,08H,01H,09H
1489TRKPT: DB 0,0,0,0,1,1,0,0,0,0
1490TRKTAB: DB -1,-1
1491INITTAB:
1492 IF CONVERT-1
1493 DB 6 ; Number of disk I/O drivers.
1494 ENDIF
1495
1496 IF CONVERT
1497 DB 10
1498 ENDIF
1499
1500 DB 0 ; Disk I/O driver 0 uses disk drive 0.
1501 DW LSDRIVE ; Disk I/O driver 0 is 8-inch single-density.
1502 DB 0 ; Disk I/O driver 1 uses disk drive 0.
1503 DW LDDRIVE ; Disk I/O driver 1 is 8-inch double-density.
1504 DB 1 ; Etc.
1505 DW LSDRIVE
1506 DB 1
1507 DW LDDRIVE
1508 DB 2
1509 DW SSDRIVE
1510 DB 2
1511 DW SDDRIVE
1512
1513 IF CONVERT
1514 DB 3
1515 DW OLDLSDRIVE
1516 DB 3
1517 DW OLDLDDRIVE
1518 DB 4
1519 DW OLDLSDRIVE
1520 DB 4
1521 DW OLDLDDRIVE
1522 ENDIF
1523 ENDIF
1524
1525 IF SCP*LARGE*FASTSEEK
1526;
1527; PerSci 277 or 299.
1528;
1529DRVTAB: DB 00H,08H,01H,09H,00H,08H,01H,09H
1530TRKPT: DB 0,0,0,0,0,0,0,0
1531TRKTAB: DB -1
1532INITTAB:
1533 IF CONVERT-1
1534 DB 4
1535 ENDIF
1536
1537 IF CONVERT
1538 DB 8
1539 ENDIF
1540
1541 DB 0
1542 DW LSDRIVE
1543 DB 0
1544 DW LDDRIVE
1545 DB 1
1546 DW LSDRIVE
1547 DB 1
1548 DW LDDRIVE
1549
1550 IF CONVERT
1551 DB 2
1552 DW OLDLSDRIVE
1553 DB 2
1554 DW OLDLDDRIVE
1555 DB 3
1556 DW OLDLSDRIVE
1557 DB 3
1558 DW OLDLDDRIVE
1559 ENDIF
1560 ENDIF
1561
1562 IF TARBELLDD
1563;
1564; Two 8-inch Shugart-type drives.
1565;
1566DRVTAB: DB 0,8,10H,18H,0,8,10H,18H
1567TRKPT: DB 0,0,1,1,0,0,1,1
1568TRKTAB: DB -1,-1
1569INITTAB:
1570
1571 IF CONVERT-1
1572 DB 4
1573 ENDIF
1574
1575 IF CONVERT
1576 DB 8
1577 ENDIF
1578
1579 DB 0
1580 DW LSDRIVE
1581 DB 0
1582 DW LDDRIVE
1583 DB 1
1584 DW LSDRIVE
1585 DB 1
1586 DW LDDRIVE
1587
1588 IF CONVERT
1589 DB 2
1590 DW OLDLSDRIVE
1591 DB 2
1592 DW OLDLDDRIVE
1593 DB 3
1594 DW OLDLSDRIVE
1595 DB 3
1596 DW OLDLDDRIVE
1597 ENDIF
1598 ENDIF
1599
1600 IF TARBELLSD
1601;
1602; Four 8-inch Shugart-type drives.
1603;
1604DRVTAB: DB 0F2H,0E2H,0F2H,0E2H
1605TRKPT: DB 0,1,0,1
1606TRKTAB: DB -1,-1
1607INITTAB:
1608
1609 IF CONVERT-1
1610 DB 2
1611 ENDIF
1612
1613 IF CONVERT
1614 DB 4
1615 ENDIF
1616
1617 DB 0
1618 DW LSDRIVE
1619 DB 1
1620 DW LSDRIVE
1621
1622 IF CONVERT
1623 DB 2
1624 DW OLDLSDRIVE
1625 DB 3
1626 DW OLDLSDRIVE
1627 ENDIF
1628 ENDIF
1629;
1630; Cromemco drive select byte is derived as follows:
1631; Bit 7 = 0
1632; Bit 6 = 1 if double density (if 16FDC)
1633; Bit 5 = 1 (motor on)
1634; Bit 4 = 0 for 5", 1 for 8" drives
1635; Bit 3 = 1 for drive 3
1636; Bit 2 = 1 for drive 2
1637; Bit 1 = 1 for drive 1
1638; Bit 0 = 1 for drive 0
1639;
1640 IF CROMEMCO4FDC*LARGE
1641;
1642; PerSci 277 drive.
1643;
1644DRVTAB: DB 31H,32H,31H,32H
1645TRKPT: DB 0,0,0,0
1646TRKTAB: DB -1
1647INITTAB:
1648
1649 IF CONVERT-1
1650 DB 2
1651 ENDIF
1652
1653 IF CONVERT
1654 DB 4
1655 ENDIF
1656
1657 DB 0
1658 DW LSDRIVE
1659 DB 1
1660 DW LSDRIVE
1661
1662 IF CONVERT
1663 DB 2
1664 DW OLDLSDRIVE
1665 DB 3
1666 DW OLDLSDRIVE
1667 ENDIF
1668 ENDIF
1669
1670 IF CROMEMCO4FDC*COMBIN
1671;
1672; A PerSci 277 and one 5.25-inch drive.
1673;
1674DRVTAB: DB 31H,32H,24H,31H,32H
1675TRKPT: DB 0,0,1,0,0
1676TRKTAB: DB -1,-1
1677INITTAB:
1678
1679 IF CONVERT-1
1680 DB 3
1681 ENDIF
1682
1683 IF CONVERT
1684 DB 5
1685 ENDIF
1686
1687 DB 0
1688 DW LSDRIVE
1689 DB 1
1690 DW LSDRIVE
1691 DB 2
1692 DW SSDRIVE
1693
1694 IF CONVERT
1695 DB 3
1696 DW OLDLSDRIVE
1697 DB 4
1698 DW OLDLSDRIVE
1699 ENDIF
1700 ENDIF
1701
1702 IF CROMEMCO4FDC*SMALL
1703;
1704; Three 5.25-inch drives.
1705;
1706DRVTAB: DB 21H,22H,24H
1707TRKPT: DB 0,1,2
1708TRKTAB: DB -1,-1,-1
1709INITTAB:DB 3
1710 DB 0
1711 DW SSDRIVE
1712 DB 1
1713 DW SSDRIVE
1714 DB 2
1715 DW SSDRIVE
1716 ENDIF
1717
1718 IF CUSTOM
1719;
1720; Cromemco 4FDC with two 8-inch Shugart-type drives.
1721;
1722DRVTAB: DB 31H,32H,31H,32H
1723TRKPT: DB 0,1,0,1
1724TRKTAB: DB -1,-1
1725INITTAB:
1726 IF CONVERT-1
1727 DB 2
1728 ENDIF
1729
1730 IF CONVERT
1731 DB 4
1732 ENDIF
1733
1734 DB 0
1735 DW LSDRIVE
1736 DB 1
1737 DW LSDRIVE
1738
1739 IF CONVERT
1740 DB 2
1741 DW OLDLSDRIVE
1742 DB 3
1743 DW OLDLSDRIVE
1744 ENDIF
1745 ENDIF
1746
1747 IF CROMEMCO16FDC*SMALL
1748;
1749; Three 5.25-inch drives.
1750;
1751DRVTAB: DB 21H,61H,22H,62H,24H,64H
1752TRKPT: DB 0,0,1,1,2,2
1753TRKTAB: DB -1,-1,-1
1754INITTAB:DB 6
1755 DB 0
1756 DW SSDRIVE
1757 DB 0
1758 DW SDDRIVE
1759 DB 1
1760 DW SSDRIVE
1761 DB 1
1762 DW SDDRIVE
1763 DB 2
1764 DW SSDRIVE
1765 DB 2
1766 DW SDDRIVE
1767 ENDIF
1768
1769 IF CROMEMCO16FDC*COMBIN
1770;
1771; A PerSci 277 or 299 and one 5.25-inch drive.
1772;
1773DRVTAB: DB 31H,71H,32H,72H,24H,64H,31H,71H,32H,72H
1774TRKPT: DB 0,0,0,0,1,1,0,0,0,0
1775TRKTAB: DB -1,-1
1776INITTAB:
1777 IF CONVERT-1
1778 DB 6
1779 ENDIF
1780
1781 IF CONVERT
1782 DB 10
1783 ENDIF
1784
1785 DB 0
1786 DW LSDRIVE
1787 DB 0
1788 DW LDDRIVE
1789 DB 1
1790 DW LSDRIVE
1791 DB 1
1792 DW LDDRIVE
1793 DB 2
1794 DW SSDRIVE
1795 DB 2
1796 DW SDDRIVE
1797
1798 IF CONVERT
1799 DB 3
1800 DW OLDLSDRIVE
1801 DB 3
1802 DW OLDLDDRIVE
1803 DB 4
1804 DW OLDLSDRIVE
1805 DB 4
1806 DW OLDLDDRIVE
1807 ENDIF
1808 ENDIF
1809
1810 IF CROMEMCO16FDC*LARGE
1811;
1812; A PerSci 277 or 299.
1813;
1814DRVTAB: DB 31H,71H,32H,72H,31H,71H,32H,72H
1815TRKPT: DB 0,0,0,0,0,0,0,0
1816TRKTAB: DB -1
1817INITTAB:
1818 IF CONVERT-1
1819 DB 4
1820 ENDIF
1821
1822 IF CONVERT
1823 DB 8
1824 ENDIF
1825
1826 DB 0
1827 DW LSDRIVE
1828 DB 0
1829 DW LDDRIVE
1830 DB 1
1831 DW LSDRIVE
1832 DB 1
1833 DW LDDRIVE
1834
1835 IF CONVERT
1836 DB 2
1837 DW OLDLSDRIVE
1838 DB 2
1839 DW OLDLDDRIVE
1840 DB 3
1841 DW OLDLSDRIVE
1842 DB 3
1843 DW OLDLDDRIVE
1844 ENDIF
1845 ENDIF
1846
1847 IF SMALL+COMBIN
1848SSDRIVE:
1849 DW 128 ; Sector size in bytes.
1850 DB 2 ; Sector per allocation unit.
1851 DW 54 ; Reserved sectors.
1852 DB 2 ; Number of allocation tables.
1853 DW 64 ; Number of directory entrys.
1854 DW 720 ; Number of sectors on the disk.
1855
1856 IF SMALLDS-1
1857SDDRIVE: ; This is the IBM Personal Computer
1858 DW 512 ; disk format.
1859 DB 1
1860 DW 1
1861 DB 2
1862 DW 64
1863 DW 320
1864 ENDIF
1865
1866 IF SMALLDS
1867SDDRIVE:
1868 DW 512
1869 DB 2
1870 DW 1
1871 DB 2
1872 DW 112
1873 DW 640
1874 ENDIF
1875 ENDIF ; End of small drive DPTs.
1876
1877 IF COMBIN+LARGE
1878LSDRIVE:
1879 DW 128 ; Size of sector in bytes.
1880 DB 4 ; Sectors per allocation unit.
1881 DW 1 ; Number of reserved sectors.
1882 DB 2 ; Number of File Allocation Tables.
1883 DW 68 ; Number of directory entrys.
1884 DW 77*26 ; Number of sectors on the disk.
1885
1886 IF CONVERT
1887OLDLSDRIVE:
1888 DW 128
1889 DB 4
1890 DW 52 ; Old format had two tracks reserved.
1891 DB 2
1892 DW 64 ; 64 directory entrys.
1893 DW 77*26
1894 ENDIF
1895
1896 IF LARGEDS-1
1897OLDLDDRIVE:
1898LDDRIVE:
1899 DW 1024
1900 DB 1
1901 DW 1
1902 DB 2
1903 DW 96
1904 DW 77*8
1905 ENDIF
1906
1907 IF LARGEDS
1908LDDRIVE:
1909 DW 1024
1910 DB 1
1911 DW 1
1912 DB 2
1913 DW 192 ; 192 directory entrys in new 8-inch DD/DS format.
1914 DW 77*8*2
1915
1916 IF CONVERT
1917OLDLDDRIVE:
1918 DW 1024
1919 DB 1
1920 DW 1
1921 DB 2
1922 DW 128 ; 128 directory entrys in old 8-inch DD/DS format.
1923 DW 77*8*2
1924 ENDIF
1925 ENDIF
1926
1927 ENDIF ; End of large drive DPTs.
1928
1929DOSSEG: EQU ($+15)/16+BIOSSEG ; Compute segment to use for 86-DOS.
1930DOSDIF: EQU 16*(DOSSEG-BIOSSEG)
1931STKSAV: EQU 1701H+DOSDIF
1932DMAADD: EQU 15B4H+DOSDIF
1933 END
1934 \ No newline at end of file
diff --git a/v1.25/source/MSDOS.ASM b/v1.25/source/MSDOS.ASM
new file mode 100644
index 0000000..8538b76
--- /dev/null
+++ b/v1.25/source/MSDOS.ASM
@@ -0,0 +1,4031 @@
1; 86-DOS High-performance operating system for the 8086 version 1.25
2; by Tim Paterson
3
4
5; ****************** Revision History *************************
6; >> EVERY change must noted below!! <<
7;
8; 0.34 12/29/80 General release, updating all past customers
9; 0.42 02/25/81 32-byte directory entries added
10; 0.56 03/23/81 Variable record and sector sizes
11; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack
12; 0.74 04/15/81 Recognize I/O devices with file names
13; 0.75 04/17/81 Improve and correct buffer handling
14; 0.76 04/23/81 Correct directory size when not 2^N entries
15; 0.80 04/27/81 Add console input without echo, Functions 7 & 8
16; 1.00 04/28/81 Renumber for general release
17; 1.01 05/12/81 Fix bug in `STORE'
18; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time,
19; RENAME fix, general cleanup
20; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE
21; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't)
22; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling
23; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR;
24; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG;
25; Lots of smaller improvements
26; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory
27; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write
28; 1.23 02/11/82 Add defaulting to parser; use variable escape character
29; Don't zero extent field in IBM version (back to 1.01!)
30; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28
31; 1.25 03/03/82 Put marker (00) at end of directory to speed searches
32;
33; *************************************************************
34
35
36; Interrupt Entry Points:
37
38; INTBASE: ABORT
39; INTBASE+4: COMMAND
40; INTBASE+8: BASE EXIT ADDRESS
41; INTBASE+C: CONTROL-C ABORT
42; INTBASE+10H: FATAL ERROR ABORT
43; INTBASE+14H: BIOS DISK READ
44; INTBASE+18H: BIOS DISK WRITE
45; INTBASE+40H: Long jump to CALL entry point
46
47 IF IBM
48ESCCH EQU 0
49CANCEL EQU 1BH ;Cancel with ESC
50TOGLINS EQU TRUE ;One key toggles insert mode
51TOGLPRN EQU TRUE ;One key toggles printer echo
52NUMDEV EQU 6 ;Include "COM1" as I/O device name
53ZEROEXT EQU TRUE
54 ELSE
55ESCCH EQU 1BH
56CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
57TOGLINS EQU FALSE ;Separate keys for insert mode on and off
58TOGLPRN EQU FALSE ;Separate keys for printer echo on and off
59NUMDEV EQU 5 ;Number of I/O device names
60ZEROEXT EQU FALSE
61 ENDIF
62
63MAXCALL EQU 36
64MAXCOM EQU 46
65INTBASE EQU 80H
66INTTAB EQU 20H
67ENTRYPOINTSEG EQU 0CH
68ENTRYPOINT EQU INTBASE+40H
69CONTC EQU INTTAB+3
70EXIT EQU INTBASE+8
71LONGJUMP EQU 0EAH
72LONGCALL EQU 9AH
73MAXDIF EQU 0FFFH
74SAVEXIT EQU 10
75
76; Field definition for FCBs
77
78FCBLOCK STRUC
79 DB 12 DUP (?) ;Drive code and name
80EXTENT DW ?
81RECSIZ DW ? ;Size of record (user settable)
82FILSIZ DW ? ;Size of file in bytes
83DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT
84FDATE DW ? ;Date of last writing
85FTIME DW ? ;Time of last writing
86DEVID DB ? ;Device ID number, bits 0-5
87 ;bit 7=0 for file, bit 7=1 for I/O device
88 ;If file, bit 6=0 if dirty
89 ;If I/O device, bit 6=0 if EOF (input)
90FIRCLUS DW ? ;First cluster of file
91LSTCLUS DW ? ;Last cluster accessed
92CLUSPOS DW ? ;Position of last cluster accessed
93 DB ? ;Forces NR to offset 32
94NR DB ? ;Next record
95RR DB 3 DUP (?) ;Random record
96FCBLOCK ENDS
97FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT
98
99; Description of 32-byte directory entry (same as returned by SEARCH FIRST
100; and SEARCH NEXT, functions 17 and 18).
101;
102; Location bytes Description
103;
104; 0 11 File name and extension ( 0E5H if empty)
105; 11 1 Attributes. Bits 1 or 2 make file hidden
106; 12 10 Zero field (for expansion)
107; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour
108; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
109; 26 2 First allocation unit ( < 4080 )
110; 28 4 File size, in bytes (LSB first, 30 bits max.)
111;
112; The File Allocation Table uses a 12-bit entry for each allocation unit on
113; the disk. These entries are packed, two for every three bytes. The contents
114; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result
115; to the base address of the Allocation Table; 3) fetching the 16-bit word at
116; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the
117; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number
118; zero is used as an end-of-file trap in the OS and as a flag for directory
119; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The
120; first available allocation unit is assigned entry number two, and even
121; though it is the first, is called cluster 2. Entries greater than 0FF8H are
122; end of file marks; entries of zero are unallocated. Otherwise, the contents
123; of a FAT entry is the number of the next cluster in the file.
124
125
126; Field definition for Drive Parameter Block
127
128DPBLOCK STRUC
129DEVNUM DB ? ;I/O driver number
130DRVNUM DB ? ;Physical Unit number
131SECSIZ DW ? ;Size of physical sector in bytes
132CLUSMSK DB ? ;Sectors/cluster - 1
133CLUSSHFT DB ? ;Log2 of sectors/cluster
134FIRFAT DW ? ;Starting record of FATs
135FATCNT DB ? ;Number of FATs for this drive
136MAXENT DW ? ;Number of directory entries
137FIRREC DW ? ;First sector of first cluster
138MAXCLUS DW ? ;Number of clusters on drive + 1
139FATSIZ DB ? ;Number of records occupied by FAT
140FIRDIR DW ? ;Starting record of directory
141FAT DW ? ;Pointer to start of FAT
142DPBLOCK ENDS
143
144DPBSIZ EQU 20 ;Size of the structure in bytes
145DIRSEC = FIRREC ;Number of dir. sectors (init temporary)
146DSKSIZ = MAXCLUS ;Size of disk (temp used during init only)
147
148;The following are all of the segments used
149;They are declared in the order that they should be placed in the executable
150
151CODE SEGMENT
152CODE ENDS
153
154CONSTANTS SEGMENT BYTE
155CONSTANTS ENDS
156
157DATA SEGMENT WORD
158DATA ENDS
159
160DOSGROUP GROUP CODE,CONSTANTS,DATA
161
162SEGBIOS SEGMENT
163SEGBIOS ENDS
164
165
166; BOIS entry point definitions
167
168 IF IBM
169BIOSSEG EQU 60H
170 ENDIF
171 IF NOT IBM
172BIOSSEG EQU 40H
173 ENDIF
174
175SEGBIOS SEGMENT AT BIOSSEG
176 ORG 0
177 DB 3 DUP (?) ;Reserve room for jump to init code
178BIOSSTAT DB 3 DUP (?) ;Console input status check
179BIOSIN DB 3 DUP (?) ;Get console character
180BIOSOUT DB 3 DUP (?) ;Output console character
181BIOSPRINT DB 3 DUP (?) ;Output to printer
182BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary
183BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary
184BIOSREAD DB 3 DUP (?) ;Disk read
185BIOSWRITE DB 3 DUP (?) ;Disk write
186BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status
187BIOSSETDATE DB 3 DUP (?) ;Set date
188BIOSSETTIME DB 3 DUP (?) ;Set time
189BIOSGETTIME DB 3 DUP (?) ;Get time and date
190BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer
191BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper
192
193SEGBIOS ENDS
194; Location of user registers relative user stack pointer
195
196STKPTRS STRUC
197AXSAVE DW ?
198BXSAVE DW ?
199CXSAVE DW ?
200DXSAVE DW ?
201SISAVE DW ?
202DISAVE DW ?
203BPSAVE DW ?
204DSSAVE DW ?
205ESSAVE DW ?
206IPSAVE DW ?
207CSSAVE DW ?
208FSAVE DW ?
209STKPTRS ENDS
210
211; Start of code
212
213CODE SEGMENT
214ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP
215
216 ORG 0
217CODSTRT EQU $
218 JMP DOSINIT
219
220ESCCHAR DB ESCCH ;Lead-in character for escape sequences
221ESCTAB:
222 IF NOT IBM
223 DB "S" ;Copy one char
224 DB "V" ;Skip one char
225 DB "T" ;Copy to char
226 DB "W" ;Skip to char
227 DB "U" ;Copy line
228 DB "E" ;Kill line (no change in template)
229 DB "J" ;Reedit line (new template)
230 DB "D" ;Backspace
231 DB "P" ;Enter insert mode
232 DB "Q" ;Exit insert mode
233 DB "R" ;Escape character
234 DB "R" ;End of table
235 ENDIF
236 IF IBM
237 DB 64 ;Crtl-Z - F6
238 DB 77 ;Copy one char - -->
239 DB 59 ;Copy one char - F1
240 DB 83 ;Skip one char - DEL
241 DB 60 ;Copy to char - F2
242 DB 62 ;Skip to char - F4
243 DB 61 ;Copy line - F3
244 DB 61 ;Kill line (no change to template ) - Not used
245 DB 63 ;Reedit line (new template) - F5
246 DB 75 ;Backspace - <--
247 DB 82 ;Enter insert mode - INS (toggle)
248 DB 65 ;Escape character - F7
249 DB 65 ;End of table
250 ENDIF
251
252ESCTABLEN EQU $-ESCTAB
253 IF NOT IBM
254HEADER DB 13,10,"MS-DOS version 1.25"
255 IF HIGHMEM
256 DB "H"
257 ENDIF
258 IF DSKTEST
259 DB "D"
260 ENDIF
261
262 DB 13,10
263 DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$"
264 ENDIF
265
266QUIT:
267 MOV AH,0
268 JMP SHORT SAVREGS
269
270COMMAND: ;Interrupt call entry point
271 CMP AH,MAXCOM
272 JBE SAVREGS
273BADCALL:
274 MOV AL,0
275IRET: IRET
276
277ENTRY: ;System call entry point and dispatcher
278 POP AX ;IP from the long call at 5
279 POP AX ;Segment from the long call at 5
280 POP CS:[TEMP] ;IP from the CALL 5
281 PUSHF ;Start re-ordering the stack
282 CLI
283 PUSH AX ;Save segment
284 PUSH CS:[TEMP] ;Stack now ordered as if INT had been used
285 CMP CL,MAXCALL ;This entry point doesn't get as many calls
286 JA BADCALL
287 MOV AH,CL
288SAVREGS:
289 PUSH ES
290 PUSH DS
291 PUSH BP
292 PUSH DI
293 PUSH SI
294 PUSH DX
295 PUSH CX
296 PUSH BX
297 PUSH AX
298
299 IF DSKTEST
300 MOV AX,CS:[SPSAVE]
301 MOV CS:[NSP],AX
302 MOV AX,CS:[SSSAVE]
303 MOV CS:[NSS],AX
304 POP AX
305 PUSH AX
306 ENDIF
307
308 MOV CS:[SPSAVE],SP
309 MOV CS:[SSSAVE],SS
310 MOV SP,CS
311 MOV SS,SP
312REDISP:
313 MOV SP,OFFSET DOSGROUP:IOSTACK
314 STI ;Stack OK now
315 MOV BL,AH
316 MOV BH,0
317 SHL BX,1
318 CLD
319 CMP AH,12
320 JLE SAMSTK
321 MOV SP,OFFSET DOSGROUP:DSKSTACK
322SAMSTK:
323 CALL CS:[BX+DISPATCH]
324LEAVE:
325 CLI
326 MOV SP,CS:[SPSAVE]
327 MOV SS,CS:[SSSAVE]
328 MOV BP,SP
329 MOV BYTE PTR [BP.AXSAVE],AL
330
331 IF DSKTEST
332 MOV AX,CS:[NSP]
333 MOV CS:[SPSAVE],AX
334 MOV AX,CS:[NSS]
335 MOV CS:[SSSAVE],AX
336 ENDIF
337
338 POP AX
339 POP BX
340 POP CX
341 POP DX
342 POP SI
343 POP DI
344 POP BP
345 POP DS
346 POP ES
347 IRET
348; Standard Functions
349DISPATCH DW ABORT ;0
350 DW CONIN
351 DW CONOUT
352 DW READER
353 DW PUNCH
354 DW LIST ;5
355 DW RAWIO
356 DW RAWINP
357 DW IN
358 DW PRTBUF
359 DW BUFIN ;10
360 DW CONSTAT
361 DW FLUSHKB
362 DW DSKRESET
363 DW SELDSK
364 DW OPEN ;15
365 DW CLOSE
366 DW SRCHFRST
367 DW SRCHNXT
368 DW DELETE
369 DW SEQRD ;20
370 DW SEQWRT
371 DW CREATE
372 DW RENAME
373 DW INUSE
374 DW GETDRV ;25
375 DW SETDMA
376 DW GETFATPT
377 DW GETFATPTDL
378 DW GETRDONLY
379 DW SETATTRIB ;30
380 DW GETDSKPT
381 DW USERCODE
382 DW RNDRD
383 DW RNDWRT
384 DW FILESIZE ;35
385 DW SETRNDREC
386; Extended Functions
387 DW SETVECT
388 DW NEWBASE
389 DW BLKRD
390 DW BLKWRT ;40
391 DW MAKEFCB
392 DW GETDATE
393 DW SETDATE
394 DW GETTIME
395 DW SETTIME ;45
396 DW VERIFY
397
398INUSE:
399GETIO:
400SETIO:
401GETRDONLY:
402SETATTRIB:
403USERCODE:
404 MOV AL,0
405 RET
406
407VERIFY:
408 AND AL,1
409 MOV CS:VERFLG,AL
410 RET
411
412FLUSHKB:
413 PUSH AX
414 CALL FAR PTR BIOSFLUSH
415 POP AX
416 MOV AH,AL
417 CMP AL,1
418 JZ REDISPJ
419 CMP AL,6
420 JZ REDISPJ
421 CMP AL,7
422 JZ REDISPJ
423 CMP AL,8
424 JZ REDISPJ
425 CMP AL,10
426 JZ REDISPJ
427 MOV AL,0
428 RET
429
430REDISPJ:JMP REDISP
431
432READER:
433AUXIN:
434 CALL STATCHK
435 CALL FAR PTR BIOSAUXIN
436 RET
437
438PUNCH:
439 MOV AL,DL
440AUXOUT:
441 PUSH AX
442 CALL STATCHK
443 POP AX
444 CALL FAR PTR BIOSAUXOUT
445 RET
446
447
448UNPACK:
449
450; Inputs:
451; DS = CS
452; BX = Cluster number
453; BP = Base of drive parameters
454; SI = Pointer to drive FAT
455; Outputs:
456; DI = Contents of FAT for given cluster
457; Zero set means DI=0 (free cluster)
458; No other registers affected. Fatal error if cluster too big.
459
460 CMP BX,[BP.MAXCLUS]
461 JA HURTFAT
462 LEA DI,[SI+BX]
463 SHR BX,1
464 MOV DI,[DI+BX]
465 JNC HAVCLUS
466 SHR DI,1
467 SHR DI,1
468 SHR DI,1
469 SHR DI,1
470 STC
471HAVCLUS:
472 RCL BX,1
473 AND DI,0FFFH
474 RET
475HURTFAT:
476 PUSH AX
477 MOV AH,80H ;Signal Bad FAT to INT 24H handler
478 MOV DI,0FFFH ;In case INT 24H returns (it shouldn't)
479 CALL FATAL
480 POP AX ;Try to ignore bad FAT
481 RET
482
483
484PACK:
485
486; Inputs:
487; DS = CS
488; BX = Cluster number
489; DX = Data
490; SI = Pointer to drive FAT
491; Outputs:
492; The data is stored in the FAT at the given cluster.
493; BX,DX,DI all destroyed
494; No other registers affected
495
496 MOV DI,BX
497 SHR BX,1
498 ADD BX,SI
499 ADD BX,DI
500 SHR DI,1
501 MOV DI,[BX]
502 JNC ALIGNED
503 SHL DX,1
504 SHL DX,1
505 SHL DX,1
506 SHL DX,1
507 AND DI,0FH
508 JMP SHORT PACKIN
509ALIGNED:
510 AND DI,0F000H
511PACKIN:
512 OR DI,DX
513 MOV [BX],DI
514 RET
515
516DEVNAME:
517 MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names
518 MOV BH,NUMDEV ;BH = number of device names
519LOOKIO:
520 MOV DI,OFFSET DOSGROUP:NAME1
521 MOV CX,4 ;All devices are 4 letters
522 REPE CMPSB ;Check for name in list
523 JZ IOCHK ;If first 3 letters OK, check for the rest
524 ADD SI,CX ;Point to next device name
525 DEC BH
526 JNZ LOOKIO
527CRET:
528 STC ;Not found
529 RET
530
531IOCHK:
532 IF IBM
533 CMP BH,NUMDEV ;Is it the first device?
534 JNZ NOTCOM1
535 MOV BH,2 ;Make it the same as AUX
536NOTCOM1:
537 ENDIF
538 NEG BH
539 MOV CX,2 ;Check rest of name but not extension
540 MOV AX,2020H
541 REPE SCASW ;Make sure rest of name is blanks
542 JNZ CRET
543RET1: RET ;Zero set so CREATE works
544
545GETFILE:
546; Same as GETNAME except ES:DI points to FCB on successful return
547 CALL MOVNAME
548 JC RET1
549 PUSH DX
550 PUSH DS
551 CALL FINDNAME
552 POP ES
553 POP DI
554RET2: RET
555
556
557GETNAME:
558
559; Inputs:
560; DS,DX point to FCB
561; Function:
562; Find file name in disk directory. First byte is
563; drive number (0=current disk). "?" matches any
564; character.
565; Outputs:
566; Carry set if file not found
567; ELSE
568; Zero set if attributes match (always except when creating)
569; BP = Base of drive parameters
570; DS = CS
571; ES = CS
572; BX = Pointer into directory buffer
573; SI = Pointer to First Cluster field in directory entry
574; [DIRBUF] has directory record with match
575; [NAME1] has file name
576; All other registers destroyed.
577
578 CALL MOVNAME
579 JC RET2 ;Bad file name?
580FINDNAME:
581 MOV AX,CS
582 MOV DS,AX
583 CALL DEVNAME
584 JNC RET2
585 CALL STARTSRCH
586CONTSRCH:
587 CALL GETENTRY
588 JC RET2
589SRCH:
590 MOV AH,BYTE PTR [BX]
591 OR AH,AH ;End of directory?
592 JZ FREE
593 CMP AH,[DELALL] ;Free entry?
594 JZ FREE
595 MOV SI,BX
596 MOV DI,OFFSET DOSGROUP:NAME1
597 MOV CX,11
598WILDCRD:
599 REPE CMPSB
600 JZ FOUND
601 CMP BYTE PTR [DI-1],"?"
602 JZ WILDCRD
603NEXTENT:
604 CALL NEXTENTRY
605 JNC SRCH
606RET3: RET
607
608FREE:
609 CMP [ENTFREE],-1 ;Found a free entry before?
610 JNZ TSTALL ;If so, ignore this one
611 MOV CX,[LASTENT]
612 MOV [ENTFREE],CX
613TSTALL:
614 CMP AH,[DELALL] ;At end of directory?
615 JZ NEXTENT ;No - continue search
616 STC ;Report not found
617 RET
618
619FOUND:
620;Check if attributes allow finding it
621 MOV AH,[ATTRIB] ;Attributes of search
622 NOT AH
623 AND AH,[SI] ;Compare with attributes of file
624 ADD SI,15
625 AND AH,6 ;Only look at bits 1 and 2
626 JZ RET3
627 TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating
628 JZ NEXTENT ;Otherwise continue searching
629 RET
630
631
632GETENTRY:
633
634; Inputs:
635; [LASTENT] has previously searched directory entry
636; Function:
637; Locates next sequential directory entry in preparation for search
638; Outputs:
639; Carry set if none
640; ELSE
641; AL = Current directory block
642; BX = Pointer to next directory entry in [DIRBUF]
643; DX = Pointer to first byte after end of DIRBUF
644; [LASTENT] = New directory entry number
645
646 MOV AX,[LASTENT]
647 INC AX ;Start with next entry
648 CMP AX,[BP.MAXENT]
649 JAE NONE
650GETENT:
651 MOV [LASTENT],AX
652 MOV CL,4
653 SHL AX,CL
654 XOR DX,DX
655 SHL AX,1
656 RCL DX,1 ;Account for overflow in last shift
657 MOV BX,[BP.SECSIZ]
658 AND BL,255-31 ;Must be multiple of 32
659 DIV BX
660 MOV BX,DX ;Position within sector
661 MOV AH,[BP.DEVNUM] ;AL=Directory sector no.
662 CMP AX,[DIRBUFID]
663 JZ HAVDIRBUF
664 PUSH BX
665 CALL DIRREAD
666 POP BX
667HAVDIRBUF:
668 MOV DX,OFFSET DOSGROUP:DIRBUF
669 ADD BX,DX
670 ADD DX,[BP.SECSIZ]
671 RET
672
673NEXTENTRY:
674
675; Inputs:
676; Same as outputs of GETENTRY, above
677; Function:
678; Update AL, BX, and [LASTENT] for next directory entry.
679; Carry set if no more.
680
681 MOV DI,[LASTENT]
682 INC DI
683 CMP DI,[BP.MAXENT]
684 JAE NONE
685 MOV [LASTENT],DI
686 ADD BX,32
687 CMP BX,DX
688 JB HAVIT
689 INC AL ;Next directory sector
690 PUSH DX ;Save limit
691 CALL DIRREAD
692 POP DX
693 MOV BX,OFFSET DOSGROUP:DIRBUF
694HAVIT:
695 CLC
696 RET
697
698NONE:
699 CALL CHKDIRWRITE
700 STC
701RET4: RET
702
703
704DELETE: ; System call 19
705 CALL MOVNAME
706 MOV AL,-1
707 JC RET4
708 MOV AL,CS:[ATTRIB]
709 AND AL,6 ;Look only at hidden bits
710 CMP AL,6 ;Both must be set
711 JNZ NOTALL
712 MOV CX,11
713 MOV AL,"?"
714 MOV DI,OFFSET DOSGROUP:NAME1
715 REPE SCASB ;See if name is *.*
716 JNZ NOTALL
717 MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all
718NOTALL:
719 CALL FINDNAME
720 MOV AL,-1
721 JC RET4
722 OR BH,BH ;Check if device name
723 JS RET4 ;Can't delete I/O devices
724DELFILE:
725 MOV BYTE PTR [DIRTYDIR],-1
726 MOV AH,[DELALL]
727 MOV BYTE PTR [BX],AH
728 MOV BX,[SI]
729 MOV SI,[BP.FAT]
730 OR BX,BX
731 JZ DELNXT
732 CMP BX,[BP.MAXCLUS]
733 JA DELNXT
734 CALL RELEASE
735DELNXT:
736 CALL CONTSRCH
737 JNC DELFILE
738 CALL FATWRT
739 CALL CHKDIRWRITE
740 XOR AL,AL
741 RET
742
743
744RENAME: ;System call 23
745 CALL MOVNAME
746 JC ERRET
747 ADD SI,5
748 MOV DI,OFFSET DOSGROUP:NAME2
749 CALL LODNAME
750 JC ERRET ;Report error if second name invalid
751 CALL FINDNAME
752 JC ERRET
753 OR BH,BH ;Check if I/O device name
754 JS ERRET ;If so, can't rename it
755 MOV SI,OFFSET DOSGROUP:NAME1
756 MOV DI,OFFSET DOSGROUP:NAME3
757 MOV CX,6 ;6 words (12 bytes)--include attribute byte
758 REP MOVSW ;Copy name to search for
759RENFIL:
760 MOV DI,OFFSET DOSGROUP:NAME1
761 MOV SI,OFFSET DOSGROUP:NAME2
762 MOV CX,11
763NEWNAM:
764 LODSB
765 CMP AL,"?"
766 JNZ NOCHG
767 MOV AL,[BX]
768NOCHG:
769 STOSB
770 INC BX
771 LOOP NEWNAM
772 MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes
773 CALL DEVNAME ;Check if giving it a device name
774 JNC RENERR
775 PUSH [LASTENT] ;Save position of match
776 MOV [LASTENT],-1 ;Search entire directory for duplicate
777 CALL CONTSRCH ;See if new name already exists
778 POP AX
779 JNC RENERR ;Error if found
780 CALL GETENT ;Re-read matching entry
781 MOV DI,BX
782 MOV SI,OFFSET DOSGROUP:NAME1
783 MOV CX,5
784 MOVSB
785 REP MOVSW ;Replace old name with new one
786 MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory
787 MOV SI,OFFSET DOSGROUP:NAME3
788 MOV DI,OFFSET DOSGROUP:NAME1
789 MOV CX,6 ;Include attribute byte
790 REP MOVSW ;Copy name back into search buffer
791 CALL CONTSRCH
792 JNC RENFIL
793 CALL CHKDIRWRITE
794 XOR AL,AL
795 RET
796
797RENERR:
798 CALL CHKDIRWRITE
799ERRET:
800 MOV AL,-1
801RET5: RET
802
803
804MOVNAME:
805
806; Inputs:
807; DS, DX point to FCB or extended FCB
808; Outputs:
809; DS:DX point to normal FCB
810; ES = CS
811; If file name OK:
812; BP has base of driver parameters
813; [NAME1] has name in upper case
814; All registers except DX destroyed
815; Carry set if bad file name or drive
816
817 MOV CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.*
818 MOV AX,CS
819 MOV ES,AX
820 MOV DI,OFFSET DOSGROUP:NAME1
821 MOV SI,DX
822 LODSB
823 MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use
824 MOV AH,0 ;Set default attributes
825 CMP AL,-1 ;Is it an extended FCB?
826 JNZ HAVATTRB
827 ADD DX,7 ;Adjust to point to normal FCB
828 ADD SI,6 ;Point to drive select byte
829 MOV AH,[SI-1] ;Get attribute byte
830 LODSB ;Get drive select byte
831HAVATTRB:
832 MOV CS:[ATTRIB],AH ;Save attributes
833 CALL GETTHISDRV
834LODNAME:
835; This entry point copies a file name from DS,SI
836; to ES,DI converting to upper case.
837 CMP BYTE PTR [SI]," " ;Don't allow blank as first letter
838 STC ;In case of error
839 JZ RET5
840 MOV CX,11
841MOVCHK:
842 CALL GETLET
843 JB RET5
844 JNZ STOLET ;Is it a delimiter?
845 CMP AL," " ;This is the only delimiter allowed
846 STC ;In case of error
847 JNZ RET5
848STOLET:
849 STOSB
850 LOOP MOVCHK
851 CLC ;Got through whole name - no error
852RET6: RET
853
854GETTHISDRV:
855 CMP CS:[NUMDRV],AL
856 JC RET6
857 DEC AL
858 JNS PHYDRV
859 MOV AL,CS:[CURDRV]
860PHYDRV:
861 MOV CS:[THISDRV],AL
862 RET
863
864
865OPEN: ;System call 15
866 CALL GETFILE
867DOOPEN:
868; Enter here to perform OPEN on file already found
869; in directory. DS=CS, BX points to directory
870; entry in DIRBUF, SI points to First Cluster field, and
871; ES:DI point to the FCB to be opened. This entry point
872; is used by CREATE.
873 JC ERRET
874 OR BH,BH ;Check if file is I/O device
875 JS OPENDEV ;Special handler if so
876 MOV AL,[THISDRV]
877 INC AX
878 STOSB
879 XOR AX,AX
880 IF ZEROEXT
881 ADD DI,11
882 STOSW ;Zero low byte of extent field if IBM only
883 ENDIF
884 IF NOT ZEROEXT
885 ADD DI,12 ;Point to high half of CURRENT BLOCK field
886 STOSB ;Set it to zero (CP/M programs set low byte)
887 ENDIF
888 MOV AL,128 ;Default record size
889 STOSW ;Set record size
890 LODSW ;Get starting cluster
891 MOV DX,AX ;Save it for the moment
892 MOVSW ;Transfer size to FCB
893 MOVSW
894 MOV AX,[SI-8] ;Get date
895 STOSW ;Save date in FCB
896 MOV AX,[SI-10] ;Get time
897 STOSW ;Save it in FCB
898 MOV AL,[BP.DEVNUM]
899 OR AL,40H
900 STOSB
901 MOV AX,DX ;Restore starting cluster
902 STOSW ; first cluster
903 STOSW ; last cluster accessed
904 XOR AX,AX
905 STOSW ; position of last cluster
906 RET
907
908
909OPENDEV:
910 ADD DI,13 ;point to 2nd half of extent field
911 XOR AX,AX
912 STOSB ;Set it to zero
913 MOV AL,128
914 STOSW ;Set record size to 128
915 XOR AX,AX
916 STOSW
917 STOSW ;Set current size to zero
918 CALL DATE16
919 STOSW ;Date is todays
920 XCHG AX,DX
921 STOSW ;Use current time
922 MOV AL,BH ;Get device number
923 STOSB
924 XOR AL,AL ;No error
925 RET
926FATERR:
927 XCHG AX,DI ;Put error code in DI
928 MOV AH,2 ;While trying to read FAT
929 MOV AL,[THISDRV] ;Tell which drive
930 CALL FATAL1
931 JMP SHORT FATREAD
932STARTSRCH:
933 MOV AX,-1
934 MOV [LASTENT],AX
935 MOV [ENTFREE],AX
936FATREAD:
937
938; Inputs:
939; DS = CS
940; Function:
941; If disk may have been changed, FAT is read in and buffers are
942; flagged invalid. If not, no action is taken.
943; Outputs:
944; BP = Base of drive parameters
945; Carry set if invalid drive returned by MAPDEV
946; All other registers destroyed
947
948 MOV AL,[THISDRV]
949 XOR AH,AH ;Set default response to zero & clear carry
950 CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say
951 JC FATERR
952 CALL GETBP
953 MOV AL,[THISDRV] ;Use physical unit number
954 MOV SI,[BP.FAT]
955 OR AH,[SI-1] ;Dirty byte for FAT
956 JS NEWDSK ;If either say new disk, then it's so
957 JNZ MAPDRV
958 MOV AH,1
959 CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive?
960 JZ MAPDRV
961NEWDSK:
962 CMP AL,[BUFDRVNO] ;See if buffer is for this drive
963 JNZ BUFOK ;If not, don't touch it
964 MOV [BUFSECNO],0 ;Flag buffers invalid
965 MOV WORD PTR [BUFDRVNO],00FFH
966BUFOK:
967 MOV [DIRBUFID],-1
968 CALL FIGFAT
969NEXTFAT:
970 PUSH AX
971 CALL DSKREAD
972 POP AX
973 JC BADFAT
974 SUB AL,[BP.FATCNT]
975 JZ NEWFAT
976 CALL FATWRT
977NEWFAT:
978 MOV SI,[BP.FAT]
979 MOV AL,[BP.DEVNUM]
980 MOV AH,[SI] ;Get first byte of FAT
981 OR AH,0F8H ;Put in range
982 CALL FAR PTR BIOSMAPDEV
983 MOV AH,0
984 MOV [SI-2],AX ;Set device no. and reset dirty bit
985MAPDRV:
986 MOV AL,[SI-2] ;Get device number
987GETBP:
988 MOV BP,[DRVTAB] ;Just in case drive isn't valid
989 AND AL,3FH ;Mask out dirty bit
990 CMP AL,[NUMIO]
991 CMC
992 JC RET7
993 PUSH AX
994 MOV AH,DPBSIZ
995 MUL AH
996 ADD BP,AX
997 POP AX
998RET7: RET
999
1000BADFAT:
1001 MOV CX,DI
1002 ADD DX,CX
1003 DEC AL
1004 JNZ NEXTFAT
1005 CALL FIGFAT ;Reset registers
1006 CALL DREAD ;Try first FAT once more
1007 JMP SHORT NEWFAT
1008
1009OKRET1:
1010 MOV AL,0
1011 RET
1012
1013CLOSE: ;System call 16
1014 MOV DI,DX
1015 CMP BYTE PTR [DI],-1 ;Check for extended FCB
1016 JNZ NORMFCB3
1017 ADD DI,7
1018NORMFCB3:
1019 TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files
1020 JNZ OKRET1 ;can't close if I/O device, or not writen
1021 MOV AL,[DI] ;Get physical unit number
1022 DEC AL ;Make zero = drive A
1023 MOV AH,1 ;Look for dirty buffer
1024 CMP AX,CS:WORD PTR [BUFDRVNO]
1025 JNZ FNDDIR
1026;Write back dirty buffer if on same drive
1027 PUSH DX
1028 PUSH DS
1029 PUSH CS
1030 POP DS
1031 MOV BYTE PTR [DIRTYBUF],0
1032 MOV BX,[BUFFER]
1033 MOV CX,1
1034 MOV DX,[BUFSECNO]
1035 MOV BP,[BUFDRVBP]
1036 CALL DWRITE
1037 POP DS
1038 POP DX
1039FNDDIR:
1040 CALL GETFILE
1041BADCLOSEJ:
1042 JC BADCLOSE
1043 MOV CX,ES:[DI.FIRCLUS]
1044 MOV [SI],CX
1045 MOV DX,ES:WORD PTR [DI.FILSIZ]
1046 MOV [SI+2],DX
1047 MOV DX,ES:WORD PTR [DI.FILSIZ+2]
1048 MOV [SI+4],DX
1049 MOV DX,ES:[DI.FDATE]
1050 MOV [SI-2],DX
1051 MOV DX,ES:[DI.FTIME]
1052 MOV [SI-4],DX
1053 CALL DIRWRITE
1054
1055CHKFATWRT:
1056; Do FATWRT only if FAT is dirty and uses same I/O driver
1057 MOV SI,[BP.FAT]
1058 MOV AL,[BP.DEVNUM]
1059 MOV AH,1
1060 CMP [SI-2],AX ;See if FAT dirty and uses same driver
1061 JNZ OKRET
1062
1063FATWRT:
1064
1065; Inputs:
1066; DS = CS
1067; BP = Base of drive parameter table
1068; Function:
1069; Write the FAT back to disk and reset FAT
1070; dirty bit.
1071; Outputs:
1072; AL = 0
1073; BP unchanged
1074; All other registers destroyed
1075
1076 CALL FIGFAT
1077 MOV BYTE PTR [BX-1],0
1078EACHFAT:
1079 PUSH DX
1080 PUSH CX
1081 PUSH BX
1082 PUSH AX
1083 CALL DWRITE
1084 POP AX
1085 POP BX
1086 POP CX
1087 POP DX
1088 ADD DX,CX
1089 DEC AL
1090 JNZ EACHFAT
1091OKRET:
1092 MOV AL,0
1093 RET
1094
1095BADCLOSE:
1096 MOV SI,[BP.FAT]
1097 MOV BYTE PTR [SI-1],0
1098 MOV AL,-1
1099 RET
1100
1101
1102FIGFAT:
1103; Loads registers with values needed to read or
1104; write a FAT.
1105 MOV AL,[BP.FATCNT]
1106 MOV BX,[BP.FAT]
1107 MOV CL,[BP.FATSIZ] ;No. of records occupied by FAT
1108 MOV CH,0
1109 MOV DX,[BP.FIRFAT] ;Record number of start of FATs
1110 RET
1111
1112
1113DIRCOMP:
1114; Prepare registers for directory read or write
1115 CBW
1116 ADD AX,[BP.FIRDIR]
1117 MOV DX,AX
1118 MOV BX,OFFSET DOSGROUP:DIRBUF
1119 MOV CX,1
1120 RET
1121
1122
1123CREATE: ;System call 22
1124 CALL MOVNAME
1125 JC ERRET3
1126 MOV DI,OFFSET DOSGROUP:NAME1
1127 MOV CX,11
1128 MOV AL,"?"
1129 REPNE SCASB
1130 JZ ERRET3
1131 MOV CS:BYTE PTR [CREATING],-1
1132 PUSH DX
1133 PUSH DS
1134 CALL FINDNAME
1135 JNC EXISTENT
1136 MOV AX,[ENTFREE] ;First free entry found in FINDNAME
1137 CMP AX,-1
1138 JZ ERRPOP
1139 CALL GETENT ;Point at that free entry
1140 JMP SHORT FREESPOT
1141ERRPOP:
1142 POP DS
1143 POP DX
1144ERRET3:
1145 MOV AL,-1
1146 RET
1147
1148EXISTENT:
1149 JNZ ERRPOP ;Error if attributes don't match
1150 OR BH,BH ;Check if file is I/O device
1151 JS OPENJMP ;If so, no action
1152 MOV CX,[SI] ;Get pointer to clusters
1153 JCXZ FREESPOT
1154 CMP CX,[BP.MAXCLUS]
1155 JA FREESPOT
1156 PUSH BX
1157 MOV BX,CX
1158 MOV SI,[BP.FAT]
1159 CALL RELEASE ;Free any data already allocated
1160 CALL FATWRT
1161 POP BX
1162FREESPOT:
1163 MOV DI,BX
1164 MOV SI,OFFSET DOSGROUP:NAME1
1165 MOV CX,5
1166 MOVSB
1167 REP MOVSW
1168 MOV AL,[ATTRIB]
1169 STOSB
1170 XOR AX,AX
1171 MOV CL,5
1172 REP STOSW
1173 CALL DATE16
1174 XCHG AX,DX
1175 STOSW
1176 XCHG AX,DX
1177 STOSW
1178 XOR AX,AX
1179 PUSH DI
1180 MOV CL,6
1181SMALLENT:
1182 REP STOSB
1183 PUSH BX
1184 CALL DIRWRITE
1185 POP BX
1186 POP SI
1187OPENJMP:
1188 CLC ;Clear carry so OPEN won't fail
1189 POP ES
1190 POP DI
1191 JMP DOOPEN
1192
1193
1194DIRREAD:
1195
1196; Inputs:
1197; DS = CS
1198; AL = Directory block number
1199; BP = Base of drive parameters
1200; Function:
1201; Read the directory block into DIRBUF.
1202; Outputs:
1203; AX,BP unchanged
1204; All other registers destroyed.
1205
1206 PUSH AX
1207 CALL CHKDIRWRITE
1208 POP AX
1209 PUSH AX
1210 MOV AH,[BP.DEVNUM]
1211 MOV [DIRBUFID],AX
1212 CALL DIRCOMP
1213 CALL DREAD
1214 POP AX
1215RET8: RET
1216
1217
1218DREAD:
1219
1220; Inputs:
1221; BX,DS = Transfer address
1222; CX = Number of sectors
1223; DX = Absolute record number
1224; BP = Base of drive parameters
1225; Function:
1226; Calls BIOS to perform disk read. If BIOS reports
1227; errors, will call HARDERR for further action.
1228; BP preserved. All other registers destroyed.
1229
1230 CALL DSKREAD
1231 JNC RET8
1232 MOV CS:BYTE PTR [READOP],0
1233 CALL HARDERR
1234 CMP AL,1 ;Check for retry
1235 JZ DREAD
1236 RET ;Ignore otherwise
1237
1238
1239HARDERR:
1240
1241;Hard disk error handler. Entry conditions:
1242; DS:BX = Original disk transfer address
1243; DX = Original logical sector number
1244; CX = Number of sectors to go (first one gave the error)
1245; AX = Hardware error code
1246; DI = Original sector transfer count
1247; BP = Base of drive parameters
1248; [READOP] = 0 for read, 1 for write
1249
1250 XCHG AX,DI ;Error code in DI, count in AX
1251 SUB AX,CX ;Number of sectors successfully transferred
1252 ADD DX,AX ;First sector number to retry
1253 PUSH DX
1254 MUL [BP.SECSIZ] ;Number of bytes transferred
1255 POP DX
1256 ADD BX,AX ;First address for retry
1257 MOV AH,0 ;Flag disk section in error
1258 CMP DX,[BP.FIRFAT] ;In reserved area?
1259 JB ERRINT
1260 INC AH ;Flag for FAT
1261 CMP DX,[BP.FIRDIR] ;In FAT?
1262 JB ERRINT
1263 INC AH
1264 CMP DX,[BP.FIRREC] ;In directory?
1265 JB ERRINT
1266 INC AH ;Must be in data area
1267ERRINT:
1268 SHL AH,1 ;Make room for read/write bit
1269 OR AH,CS:[READOP]
1270FATAL:
1271 MOV AL,[BP.DRVNUM] ;Get drive number
1272FATAL1:
1273 PUSH BP ;The only thing we preserve
1274 MOV CS:[CONTSTK],SP
1275 CLI ;Prepare to play with stack
1276 MOV SS,CS:[SSSAVE]
1277 MOV SP,CS:[SPSAVE] ;User stack pointer restored
1278 INT 24H ;Fatal error interrupt vector
1279 MOV CS:[SPSAVE],SP
1280 MOV CS:[SSSAVE],SS
1281 MOV SP,CS
1282 MOV SS,SP
1283 MOV SP,CS:[CONTSTK]
1284 STI
1285 POP BP
1286 CMP AL,2
1287 JZ ERROR
1288 RET
1289
1290DSKREAD:
1291 MOV AL,[BP.DEVNUM]
1292 PUSH BP
1293 PUSH BX
1294 PUSH CX
1295 PUSH DX
1296 CALL FAR PTR BIOSREAD
1297 POP DX
1298 POP DI
1299 POP BX
1300 POP BP
1301RET9: RET
1302
1303
1304CHKDIRWRITE:
1305 TEST BYTE PTR [DIRTYDIR],-1
1306 JZ RET9
1307
1308DIRWRITE:
1309
1310; Inputs:
1311; DS = CS
1312; AL = Directory block number
1313; BP = Base of drive parameters
1314; Function:
1315; Write the directory block into DIRBUF.
1316; Outputs:
1317; BP unchanged
1318; All other registers destroyed.
1319
1320 MOV BYTE PTR [DIRTYDIR],0
1321 MOV AL,BYTE PTR [DIRBUFID]
1322 CALL DIRCOMP
1323
1324
1325DWRITE:
1326
1327; Inputs:
1328; BX,DS = Transfer address
1329; CX = Number of sectors
1330; DX = Absolute record number
1331; BP = Base of drive parameters
1332; Function:
1333; Calls BIOS to perform disk write. If BIOS reports
1334; errors, will call HARDERR for further action.
1335; BP preserved. All other registers destroyed.
1336
1337 MOV AL,[BP.DEVNUM]
1338 MOV AH,CS:VERFLG
1339 PUSH BP
1340 PUSH BX
1341 PUSH CX
1342 PUSH DX
1343 CALL FAR PTR BIOSWRITE
1344 POP DX
1345 POP DI
1346 POP BX
1347 POP BP
1348 JNC RET9
1349 MOV CS:BYTE PTR [READOP],1
1350 CALL HARDERR
1351 CMP AL,1 ;Check for retry
1352 JZ DWRITE
1353 RET
1354
1355
1356ABORT:
1357 LDS SI,CS:DWORD PTR [SPSAVE]
1358 MOV DS,[SI.CSSAVE]
1359 XOR AX,AX
1360 MOV ES,AX
1361 MOV SI,SAVEXIT
1362 MOV DI,EXIT
1363 MOVSW
1364 MOVSW
1365 MOVSW
1366 MOVSW
1367 MOVSW
1368 MOVSW
1369ERROR:
1370 MOV AX,CS
1371 MOV DS,AX
1372 MOV ES,AX
1373 CALL WRTFATS
1374 XOR AX,AX
1375 CLI
1376 MOV SS,[SSSAVE]
1377 MOV SP,[SPSAVE]
1378 MOV DS,AX
1379 MOV SI,EXIT
1380 MOV DI,OFFSET DOSGROUP:EXITHOLD
1381 MOVSW
1382 MOVSW
1383 POP AX
1384 POP BX
1385 POP CX
1386 POP DX
1387 POP SI
1388 POP DI
1389 POP BP
1390 POP DS
1391 POP ES
1392 STI ;Stack OK now
1393 JMP CS:DWORD PTR [EXITHOLD]
1394
1395
1396SEQRD: ;System call 20
1397 CALL GETREC
1398 CALL LOAD
1399 JMP SHORT FINSEQ
1400
1401SEQWRT: ;System call 21
1402 CALL GETREC
1403 CALL STORE
1404FINSEQ:
1405 JCXZ SETNREX
1406 ADD AX,1
1407 ADC DX,0
1408 JMP SHORT SETNREX
1409
1410RNDRD: ;System call 33
1411 CALL GETRRPOS1
1412 CALL LOAD
1413 JMP SHORT FINRND
1414
1415RNDWRT: ;System call 34
1416 CALL GETRRPOS1
1417 CALL STORE
1418 JMP SHORT FINRND
1419
1420BLKRD: ;System call 39
1421 CALL GETRRPOS
1422 CALL LOAD
1423 JMP SHORT FINBLK
1424
1425BLKWRT: ;System call 40
1426 CALL GETRRPOS
1427 CALL STORE
1428FINBLK:
1429 LDS SI,DWORD PTR [SPSAVE]
1430 MOV [SI.CXSAVE],CX
1431 JCXZ FINRND
1432 ADD AX,1
1433 ADC DX,0
1434FINRND:
1435 MOV ES:WORD PTR [DI.RR],AX
1436 MOV ES:[DI.RR+2],DL
1437 OR DH,DH
1438 JZ SETNREX
1439 MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant
1440SETNREX:
1441 MOV CX,AX
1442 AND AL,7FH
1443 MOV ES:[DI.NR],AL
1444 AND CL,80H
1445 SHL CX,1
1446 RCL DX,1
1447 MOV AL,CH
1448 MOV AH,DL
1449 MOV ES:[DI.EXTENT],AX
1450 MOV AL,CS:[DSKERR]
1451 RET
1452
1453GETRRPOS1:
1454 MOV CX,1
1455GETRRPOS:
1456 MOV DI,DX
1457 CMP BYTE PTR [DI],-1
1458 JNZ NORMFCB1
1459 ADD DI,7
1460NORMFCB1:
1461 MOV AX,WORD PTR [DI.RR]
1462 MOV DX,WORD PTR [DI.RR+2]
1463 RET
1464
1465NOFILERR:
1466 XOR CX,CX
1467 MOV BYTE PTR [DSKERR],4
1468 POP BX
1469 RET
1470
1471SETUP:
1472
1473; Inputs:
1474; DS:DI point to FCB
1475; DX:AX = Record position in file of disk transfer
1476; CX = Record count
1477; Outputs:
1478; DS = CS
1479; ES:DI point to FCB
1480; BL = DEVID from FCB
1481; CX = No. of bytes to transfer
1482; BP = Base of drive parameters
1483; SI = FAT pointer
1484; [RECCNT] = Record count
1485; [RECPOS] = Record position in file
1486; [FCB] = DI
1487; [NEXTADD] = Displacement of disk transfer within segment
1488; [SECPOS] = Position of first sector
1489; [BYTPOS] = Byte position in file
1490; [BYTSECPOS] = Byte position in first sector
1491; [CLUSNUM] = First cluster
1492; [SECCLUSPOS] = Sector within first cluster
1493; [DSKERR] = 0 (no errors yet)
1494; [TRANS] = 0 (No transfers yet)
1495; [THISDRV] = Physical drive unit number
1496; If SETUP detects no records will be transfered, it returns 1 level up
1497; with CX = 0.
1498
1499 PUSH AX
1500 MOV AL,[DI]
1501 DEC AL
1502 MOV CS:[THISDRV],AL
1503 MOV AL,[DI.DEVID]
1504 MOV SI,[DI.RECSIZ]
1505 OR SI,SI
1506 JNZ HAVRECSIZ
1507 MOV SI,128
1508 MOV [DI.RECSIZ],SI
1509HAVRECSIZ:
1510 PUSH DS
1511 POP ES ;Set ES to DS
1512 PUSH CS
1513 POP DS ;Set DS to CS
1514 OR AL,AL ;Is it a device?
1515 JNS NOTDEVICE
1516 MOV AL,0 ;Fake in drive 0 so we can get SP
1517NOTDEVICE:
1518 CALL GETBP
1519 POP AX
1520 JC NOFILERR
1521 CMP SI,64 ;Check if highest byte of RECPOS is significant
1522 JB SMALREC
1523 MOV DH,0 ;Ignore MSB if record >= 64 bytes
1524SMALREC:
1525 MOV [RECCNT],CX
1526 MOV WORD PTR [RECPOS],AX
1527 MOV WORD PTR [RECPOS+2],DX
1528 MOV [FCB],DI
1529 MOV BX,[DMAADD]
1530 MOV [NEXTADD],BX
1531 MOV BYTE PTR [DSKERR],0
1532 MOV BYTE PTR [TRANS],0
1533 MOV BX,DX
1534 MUL SI
1535 MOV WORD PTR [BYTPOS],AX
1536 PUSH DX
1537 MOV AX,BX
1538 MUL SI
1539 POP BX
1540 ADD AX,BX
1541 ADC DX,0 ;Ripple carry
1542 JNZ EOFERR
1543 MOV WORD PTR [BYTPOS+2],AX
1544 MOV DX,AX
1545 MOV AX,WORD PTR [BYTPOS]
1546 MOV BX,[BP.SECSIZ]
1547 CMP DX,BX ;See if divide will overflow
1548 JNC EOFERR
1549 DIV BX
1550 MOV [SECPOS],AX
1551 MOV [BYTSECPOS],DX
1552 MOV DX,AX
1553 AND AL,[BP.CLUSMSK]
1554 MOV [SECCLUSPOS],AL
1555 MOV AX,CX ;Record count
1556 MOV CL,[BP.CLUSSHFT]
1557 SHR DX,CL
1558 MOV [CLUSNUM],DX
1559 MUL SI ;Multiply by bytes per record
1560 MOV CX,AX
1561 ADD AX,[DMAADD] ;See if it will fit in one segment
1562 ADC DX,0
1563 JZ OK ;Must be less than 64K
1564 MOV AX,[DMAADD]
1565 NEG AX ;Amount of room left in segment
1566 JNZ PARTSEG ;All 64K available?
1567 DEC AX ;If so, reduce by one
1568PARTSEG:
1569 XOR DX,DX
1570 DIV SI ;How many records will fit?
1571 MOV [RECCNT],AX
1572 MUL SI ;Translate that back into bytes
1573 MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place
1574 MOV CX,AX
1575 JCXZ NOROOM
1576OK:
1577 MOV BL,ES:[DI.DEVID]
1578 MOV SI,[BP.FAT]
1579 RET
1580
1581EOFERR:
1582 MOV BYTE PTR [DSKERR],1
1583 XOR CX,CX
1584NOROOM:
1585 POP BX ;Kill return address
1586 RET
1587
1588BREAKDOWN:
1589
1590;Inputs:
1591; DS = CS
1592; CX = Length of disk transfer in bytes
1593; BP = Base of drive parameters
1594; [BYTSECPOS] = Byte position witin first sector
1595;Outputs:
1596; [BYTCNT1] = Bytes to transfer in first sector
1597; [SECCNT] = No. of whole sectors to transfer
1598; [BYTCNT2] = Bytes to transfer in last sector
1599;AX, BX, DX destroyed. No other registers affected.
1600
1601 MOV AX,[BYTSECPOS]
1602 MOV BX,CX
1603 OR AX,AX
1604 JZ SAVFIR ;Partial first sector?
1605 SUB AX,[BP.SECSIZ]
1606 NEG AX ;Max number of bytes left in first sector
1607 SUB BX,AX ;Subtract from total length
1608 JAE SAVFIR
1609 ADD AX,BX ;Don't use all of the rest of the sector
1610 XOR BX,BX ;And no bytes are left
1611SAVFIR:
1612 MOV [BYTCNT1],AX
1613 MOV AX,BX
1614 XOR DX,DX
1615 DIV [BP.SECSIZ] ;How many whole sectors?
1616 MOV [SECCNT],AX
1617 MOV [BYTCNT2],DX ;Bytes remaining for last sector
1618RET10: RET
1619
1620
1621FNDCLUS:
1622
1623; Inputs:
1624; DS = CS
1625; CX = No. of clusters to skip
1626; BP = Base of drive parameters
1627; SI = FAT pointer
1628; ES:DI point to FCB
1629; Outputs:
1630; BX = Last cluster skipped to
1631; CX = No. of clusters remaining (0 unless EOF)
1632; DX = Position of last cluster
1633; DI destroyed. No other registers affected.
1634
1635 MOV BX,ES:[DI.LSTCLUS]
1636 MOV DX,ES:[DI.CLUSPOS]
1637 OR BX,BX
1638 JZ NOCLUS
1639 SUB CX,DX
1640 JNB FINDIT
1641 ADD CX,DX
1642 XOR DX,DX
1643 MOV BX,ES:[DI.FIRCLUS]
1644FINDIT:
1645 JCXZ RET10
1646SKPCLP:
1647 CALL UNPACK
1648 CMP DI,0FF8H
1649 JAE RET10
1650 XCHG BX,DI
1651 INC DX
1652 LOOP SKPCLP
1653 RET
1654NOCLUS:
1655 INC CX
1656 DEC DX
1657 RET
1658
1659
1660BUFSEC:
1661; Inputs:
1662; AL = 0 if buffer must be read, 1 if no pre-read needed
1663; BP = Base of drive parameters
1664; [CLUSNUM] = Physical cluster number
1665; [SECCLUSPOS] = Sector position of transfer within cluster
1666; [BYTCNT1] = Size of transfer
1667; Function:
1668; Insure specified sector is in buffer, flushing buffer before
1669; read if necessary.
1670; Outputs:
1671; SI = Pointer to buffer
1672; DI = Pointer to transfer address
1673; CX = Number of bytes
1674; [NEXTADD] updated
1675; [TRANS] set to indicate a transfer will occur
1676
1677 MOV DX,[CLUSNUM]
1678 MOV BL,[SECCLUSPOS]
1679 CALL FIGREC
1680 MOV [PREREAD],AL
1681 CMP DX,[BUFSECNO]
1682 JNZ GETSEC
1683 MOV AL,[BUFDRVNO]
1684 CMP AL,[THISDRV]
1685 JZ FINBUF ;Already have it?
1686GETSEC:
1687 XOR AL,AL
1688 XCHG [DIRTYBUF],AL ;Read dirty flag and reset it
1689 OR AL,AL
1690 JZ RDSEC
1691 PUSH DX
1692 PUSH BP
1693 MOV BP,[BUFDRVBP]
1694 MOV BX,[BUFFER]
1695 MOV CX,1
1696 MOV DX,[BUFSECNO]
1697 CALL DWRITE
1698 POP BP
1699 POP DX
1700RDSEC:
1701 TEST BYTE PTR [PREREAD],-1
1702 JNZ SETBUF
1703 XOR AX,AX
1704 MOV [BUFSECNO],AX ;Set buffer valid in case of disk error
1705 DEC AX
1706 MOV [BUFDRVNO],AL
1707 MOV BX,[BUFFER]
1708 MOV CX,1
1709 PUSH DX
1710 CALL DREAD
1711 POP DX
1712SETBUF:
1713 MOV [BUFSECNO],DX
1714 MOV AL,[THISDRV]
1715 MOV [BUFDRVNO],AL
1716 MOV [BUFDRVBP],BP
1717FINBUF:
1718 MOV BYTE PTR [TRANS],1 ;A transfer is taking place
1719 MOV DI,[NEXTADD]
1720 MOV SI,DI
1721 MOV CX,[BYTCNT1]
1722 ADD SI,CX
1723 MOV [NEXTADD],SI
1724 MOV SI,[BUFFER]
1725 ADD SI,[BYTSECPOS]
1726 RET
1727
1728BUFRD:
1729 XOR AL,AL ;Pre-read necessary
1730 CALL BUFSEC
1731 PUSH ES
1732 MOV ES,[DMAADD+2]
1733 SHR CX,1
1734 JNC EVENRD
1735 MOVSB
1736EVENRD:
1737 REP MOVSW
1738 POP ES
1739 RET
1740
1741BUFWRT:
1742 MOV AX,[SECPOS]
1743 INC AX ;Set for next sector
1744 MOV [SECPOS],AX
1745 CMP AX,[VALSEC] ;Has sector been written before?
1746 MOV AL,1
1747 JA NOREAD ;Skip preread if SECPOS>VALSEC
1748 MOV AL,0
1749NOREAD:
1750 CALL BUFSEC
1751 XCHG DI,SI
1752 PUSH DS
1753 PUSH ES
1754 PUSH CS
1755 POP ES
1756 MOV DS,[DMAADD+2]
1757 SHR CX,1
1758 JNC EVENWRT
1759 MOVSB
1760EVENWRT:
1761 REP MOVSW
1762 POP ES
1763 POP DS
1764 MOV BYTE PTR [DIRTYBUF],1
1765 RET
1766
1767NEXTSEC:
1768 TEST BYTE PTR [TRANS],-1
1769 JZ CLRET
1770 MOV AL,[SECCLUSPOS]
1771 INC AL
1772 CMP AL,[BP.CLUSMSK]
1773 JBE SAVPOS
1774 MOV BX,[CLUSNUM]
1775 CMP BX,0FF8H
1776 JAE NONEXT
1777 MOV SI,[BP.FAT]
1778 CALL UNPACK
1779 MOV [CLUSNUM],DI
1780 INC [LASTPOS]
1781 MOV AL,0
1782SAVPOS:
1783 MOV [SECCLUSPOS],AL
1784CLRET:
1785 CLC
1786 RET
1787NONEXT:
1788 STC
1789 RET
1790
1791TRANBUF:
1792 LODSB
1793 STOSB
1794 CMP AL,13 ;Check for carriage return
1795 JNZ NORMCH
1796 MOV BYTE PTR [SI],10
1797NORMCH:
1798 CMP AL,10
1799 LOOPNZ TRANBUF
1800 JNZ ENDRDCON
1801 CALL OUT ;Transmit linefeed
1802 XOR SI,SI
1803 OR CX,CX
1804 JNZ GETBUF
1805 OR AL,1 ;Clear zero flag--not end of file
1806ENDRDCON:
1807 MOV [CONTPOS],SI
1808ENDRDDEV:
1809 MOV [NEXTADD],DI
1810 POP ES
1811 JNZ SETFCBJ ;Zero set if Ctrl-Z found in input
1812 MOV DI,[FCB]
1813 AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available
1814SETFCBJ:
1815 JMP SETFCB
1816
1817READDEV:
1818 PUSH ES
1819 LES DI,DWORD PTR [DMAADD]
1820 INC BL
1821 JZ READCON
1822 INC BL
1823 JNZ ENDRDDEV
1824READAUX:
1825 CALL AUXIN
1826 STOSB
1827 CMP AL,1AH
1828 LOOPNZ READAUX
1829 JMP SHORT ENDRDDEV
1830
1831READCON:
1832 PUSH CS
1833 POP DS
1834 MOV SI,[CONTPOS]
1835 OR SI,SI
1836 JNZ TRANBUF
1837 CMP BYTE PTR [CONBUF],128
1838 JZ GETBUF
1839 MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template
1840GETBUF:
1841 PUSH CX
1842 PUSH ES
1843 PUSH DI
1844 MOV DX,OFFSET DOSGROUP:CONBUF
1845 CALL BUFIN ;Get input buffer
1846 POP DI
1847 POP ES
1848 POP CX
1849 MOV SI,2 + OFFSET DOSGROUP:CONBUF
1850 CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character
1851 JNZ TRANBUF
1852 MOV AL,1AH
1853 STOSB
1854 MOV AL,10
1855 CALL OUT ;Send linefeed
1856 XOR SI,SI
1857 JMP SHORT ENDRDCON
1858
1859RDERR:
1860 XOR CX,CX
1861 JMP WRTERR
1862
1863RDLASTJ:JMP RDLAST
1864
1865LOAD:
1866
1867; Inputs:
1868; DS:DI point to FCB
1869; DX:AX = Position in file to read
1870; CX = No. of records to read
1871; Outputs:
1872; DX:AX = Position of last record read
1873; CX = No. of bytes read
1874; ES:DI point to FCB
1875; LSTCLUS, CLUSPOS fields in FCB set
1876
1877 CALL SETUP
1878 OR BL,BL ;Check for named device I/O
1879 JS READDEV
1880 MOV AX,ES:WORD PTR [DI.FILSIZ]
1881 MOV BX,ES:WORD PTR [DI.FILSIZ+2]
1882 SUB AX,WORD PTR [BYTPOS]
1883 SBB BX,WORD PTR [BYTPOS+2]
1884 JB RDERR
1885 JNZ ENUF
1886 OR AX,AX
1887 JZ RDERR
1888 CMP AX,CX
1889 JAE ENUF
1890 MOV CX,AX
1891ENUF:
1892 CALL BREAKDOWN
1893 MOV CX,[CLUSNUM]
1894 CALL FNDCLUS
1895 OR CX,CX
1896 JNZ RDERR
1897 MOV [LASTPOS],DX
1898 MOV [CLUSNUM],BX
1899 CMP [BYTCNT1],0
1900 JZ RDMID
1901 CALL BUFRD
1902RDMID:
1903 CMP [SECCNT],0
1904 JZ RDLASTJ
1905 CALL NEXTSEC
1906 JC SETFCB
1907 MOV BYTE PTR [TRANS],1 ;A transfer is taking place
1908ONSEC:
1909 MOV DL,[SECCLUSPOS]
1910 MOV CX,[SECCNT]
1911 MOV BX,[CLUSNUM]
1912RDLP:
1913 CALL OPTIMIZE
1914 PUSH DI
1915 PUSH AX
1916 PUSH DS
1917 MOV DS,[DMAADD+2]
1918 PUSH DX
1919 PUSH BX
1920 PUSHF ;Save carry flag
1921 CALL DREAD
1922 POPF ;Restore carry flag
1923 POP DI ;Initial transfer address
1924 POP AX ;First sector transfered
1925 POP DS
1926 JC NOTBUFFED ;Was one of those sectors in the buffer?
1927 CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty?
1928 JZ NOTBUFFED ;If not no problem
1929;We have transfered in a sector from disk when a dirty copy of it is in the buffer.
1930;We must transfer the sector from the buffer to correct memory address
1931 SUB AX,[BUFSECNO] ;How many sectors into the transfer?
1932 NEG AX
1933 MOV CX,[BP.SECSIZ]
1934 MUL CX ;How many bytes into the transfer?
1935 ADD DI,AX
1936 MOV SI,[BUFFER]
1937 PUSH ES
1938 MOV ES,[DMAADD+2] ;Get disk transfer segment
1939 SHR CX,1
1940 REP MOVSW
1941 JNC EVENMOV
1942 MOVSB
1943EVENMOV:
1944 POP ES
1945NOTBUFFED:
1946 POP CX
1947 POP BX
1948 JCXZ RDLAST
1949 CMP BX,0FF8H
1950 JAE SETFCB
1951 MOV DL,0
1952 INC [LASTPOS] ;We'll be using next cluster
1953 JMP SHORT RDLP
1954
1955SETFCB:
1956 MOV SI,[FCB]
1957 MOV AX,[NEXTADD]
1958 MOV DI,AX
1959 SUB AX,[DMAADD] ;Number of bytes transfered
1960 XOR DX,DX
1961 MOV CX,ES:[SI.RECSIZ]
1962 DIV CX ;Number of records
1963 CMP AX,[RECCNT] ;Check if all records transferred
1964 JZ FULLREC
1965 MOV BYTE PTR [DSKERR],1
1966 OR DX,DX
1967 JZ FULLREC ;If remainder 0, then full record transfered
1968 MOV BYTE PTR [DSKERR],3 ;Flag partial last record
1969 SUB CX,DX ;Bytes left in last record
1970 PUSH ES
1971 MOV ES,[DMAADD+2]
1972 XCHG AX,BX ;Save the record count temporarily
1973 XOR AX,AX ;Fill with zeros
1974 SHR CX,1
1975 JNC EVENFIL
1976 STOSB
1977EVENFIL:
1978 REP STOSW
1979 XCHG AX,BX ;Restore record count to AX
1980 POP ES
1981 INC AX ;Add last (partial) record to total
1982FULLREC:
1983 MOV CX,AX
1984 MOV DI,SI ;ES:DI point to FCB
1985SETCLUS:
1986 MOV AX,[CLUSNUM]
1987 MOV ES:[DI.LSTCLUS],AX
1988 MOV AX,[LASTPOS]
1989 MOV ES:[DI.CLUSPOS],AX
1990ADDREC:
1991 MOV AX,WORD PTR [RECPOS]
1992 MOV DX,WORD PTR [RECPOS+2]
1993 JCXZ RET28 ;If no records read, don't change position
1994 DEC CX
1995 ADD AX,CX ;Update current record position
1996 ADC DX,0
1997 INC CX
1998RET28: RET
1999
2000RDLAST:
2001 MOV AX,[BYTCNT2]
2002 OR AX,AX
2003 JZ SETFCB
2004 MOV [BYTCNT1],AX
2005 CALL NEXTSEC
2006 JC SETFCB
2007 MOV [BYTSECPOS],0
2008 CALL BUFRD
2009 JMP SHORT SETFCB
2010
2011WRTDEV:
2012 PUSH DS
2013 LDS SI,DWORD PTR [DMAADD]
2014 OR BL,40H
2015 INC BL
2016 JZ WRTCON
2017 INC BL
2018 JZ WRTAUX
2019 INC BL
2020 JZ ENDWRDEV ;Done if device is NUL
2021WRTLST:
2022 LODSB
2023 CMP AL,1AH
2024 JZ ENDWRDEV
2025 CALL LISTOUT
2026 LOOP WRTLST
2027 JMP SHORT ENDWRDEV
2028
2029WRTAUX:
2030 LODSB
2031 CALL AUXOUT
2032 CMP AL,1AH
2033 LOOPNZ WRTAUX
2034 JMP SHORT ENDWRDEV
2035
2036WRTCON:
2037 LODSB
2038 CMP AL,1AH
2039 JZ ENDWRDEV
2040 CALL OUT
2041 LOOP WRTCON
2042ENDWRDEV:
2043 POP DS
2044 MOV CX,[RECCNT]
2045 MOV DI,[FCB]
2046 JMP SHORT ADDREC
2047
2048HAVSTART:
2049 MOV CX,AX
2050 CALL SKPCLP
2051 JCXZ DOWRTJ
2052 CALL ALLOCATE
2053 JNC DOWRTJ
2054WRTERR:
2055 MOV BYTE PTR [DSKERR],1
2056LVDSK:
2057 MOV AX,WORD PTR [RECPOS]
2058 MOV DX,WORD PTR [RECPOS+2]
2059 MOV DI,[FCB]
2060 RET
2061
2062DOWRTJ: JMP DOWRT
2063
2064WRTEOFJ:
2065 JMP WRTEOF
2066
2067STORE:
2068
2069; Inputs:
2070; DS:DI point to FCB
2071; DX:AX = Position in file of disk transfer
2072; CX = Record count
2073; Outputs:
2074; DX:AX = Position of last record written
2075; CX = No. of records written
2076; ES:DI point to FCB
2077; LSTCLUS, CLUSPOS fields in FCB set
2078
2079 CALL SETUP
2080 CALL DATE16
2081 MOV ES:[DI.FDATE],AX
2082 MOV ES:[DI.FTIME],DX
2083 OR BL,BL
2084 JS WRTDEV
2085 AND BL,3FH ;Mark file as dirty
2086 MOV ES:[DI.DEVID],BL
2087 CALL BREAKDOWN
2088 MOV AX,WORD PTR [BYTPOS]
2089 MOV DX,WORD PTR [BYTPOS+2]
2090 JCXZ WRTEOFJ
2091 DEC CX
2092 ADD AX,CX
2093 ADC DX,0 ;AX:DX=last byte accessed
2094 DIV [BP.SECSIZ] ;AX=last sector accessed
2095 MOV CL,[BP.CLUSSHFT]
2096 SHR AX,CL ;Last cluster to be accessed
2097 PUSH AX
2098 MOV AX,ES:WORD PTR [DI.FILSIZ]
2099 MOV DX,ES:WORD PTR [DI.FILSIZ+2]
2100 DIV [BP.SECSIZ]
2101 OR DX,DX
2102 JZ NORNDUP
2103 INC AX ;Round up if any remainder
2104NORNDUP:
2105 MOV [VALSEC],AX ;Number of sectors that have been written
2106 POP AX
2107 MOV CX,[CLUSNUM] ;First cluster accessed
2108 CALL FNDCLUS
2109 MOV [CLUSNUM],BX
2110 MOV [LASTPOS],DX
2111 SUB AX,DX ;Last cluster minus current cluster
2112 JZ DOWRT ;If we have last clus, we must have first
2113 JCXZ HAVSTART ;See if no more data
2114 PUSH CX ;No. of clusters short of first
2115 MOV CX,AX
2116 CALL ALLOCATE
2117 POP AX
2118 JC WRTERR
2119 MOV CX,AX
2120 MOV DX,[LASTPOS]
2121 INC DX
2122 DEC CX
2123 JZ NOSKIP
2124 CALL SKPCLP
2125NOSKIP:
2126 MOV [CLUSNUM],BX
2127 MOV [LASTPOS],DX
2128DOWRT:
2129 CMP [BYTCNT1],0
2130 JZ WRTMID
2131 MOV BX,[CLUSNUM]
2132 CALL BUFWRT
2133WRTMID:
2134 MOV AX,[SECCNT]
2135 OR AX,AX
2136 JZ WRTLAST
2137 ADD [SECPOS],AX
2138 CALL NEXTSEC
2139 MOV BYTE PTR [TRANS],1 ;A transfer is taking place
2140 MOV DL,[SECCLUSPOS]
2141 MOV BX,[CLUSNUM]
2142 MOV CX,[SECCNT]
2143WRTLP:
2144 CALL OPTIMIZE
2145 JC NOTINBUF ;Is one of the sectors buffered?
2146 MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're
2147 MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it
2148NOTINBUF:
2149 PUSH DI
2150 PUSH AX
2151 PUSH DS
2152 MOV DS,[DMAADD+2]
2153 CALL DWRITE
2154 POP DS
2155 POP CX
2156 POP BX
2157 JCXZ WRTLAST
2158 MOV DL,0
2159 INC [LASTPOS] ;We'll be using next cluster
2160 JMP SHORT WRTLP
2161WRTLAST:
2162 MOV AX,[BYTCNT2]
2163 OR AX,AX
2164 JZ FINWRT
2165 MOV [BYTCNT1],AX
2166 CALL NEXTSEC
2167 MOV [BYTSECPOS],0
2168 CALL BUFWRT
2169FINWRT:
2170 MOV AX,[NEXTADD]
2171 SUB AX,[DMAADD]
2172 ADD AX,WORD PTR [BYTPOS]
2173 MOV DX,WORD PTR [BYTPOS+2]
2174 ADC DX,0
2175 MOV CX,DX
2176 MOV DI,[FCB]
2177 CMP AX,ES:WORD PTR [DI.FILSIZ]
2178 SBB CX,ES:WORD PTR [DI.FILSIZ+2]
2179 JB SAMSIZ
2180 MOV ES:WORD PTR [DI.FILSIZ],AX
2181 MOV ES:WORD PTR [DI.FILSIZ+2],DX
2182SAMSIZ:
2183 MOV CX,[RECCNT]
2184 JMP SETCLUS
2185
2186
2187WRTERRJ:JMP WRTERR
2188
2189WRTEOF:
2190 MOV CX,AX
2191 OR CX,DX
2192 JZ KILLFIL
2193 SUB AX,1
2194 SBB DX,0
2195 DIV [BP.SECSIZ]
2196 MOV CL,[BP.CLUSSHFT]
2197 SHR AX,CL
2198 MOV CX,AX
2199 CALL FNDCLUS
2200 JCXZ RELFILE
2201 CALL ALLOCATE
2202 JC WRTERRJ
2203UPDATE:
2204 MOV DI,[FCB]
2205 MOV AX,WORD PTR [BYTPOS]
2206 MOV ES:WORD PTR [DI.FILSIZ],AX
2207 MOV AX,WORD PTR [BYTPOS+2]
2208 MOV ES:WORD PTR [DI.FILSIZ+2],AX
2209 XOR CX,CX
2210 JMP ADDREC
2211
2212RELFILE:
2213 MOV DX,0FFFH
2214 CALL RELBLKS
2215SETDIRT:
2216 MOV BYTE PTR [SI-1],1
2217 JMP SHORT UPDATE
2218
2219KILLFIL:
2220 XOR BX,BX
2221 XCHG BX,ES:[DI.FIRCLUS]
2222 OR BX,BX
2223 JZ UPDATE
2224 CALL RELEASE
2225 JMP SHORT SETDIRT
2226
2227
2228OPTIMIZE:
2229
2230; Inputs:
2231; DS = CS
2232; BX = Physical cluster
2233; CX = No. of records
2234; DL = sector within cluster
2235; BP = Base of drives parameters
2236; [NEXTADD] = transfer address
2237; Outputs:
2238; AX = No. of records remaining
2239; BX = Transfer address
2240; CX = No. or records to be transferred
2241; DX = Physical sector address
2242; DI = Next cluster
2243; Carry clear if a sector to transfer is in the buffer
2244; Carry set otherwise
2245; [CLUSNUM] = Last cluster accessed
2246; [NEXTADD] updated
2247; BP unchanged. Note that segment of transfer not set.
2248
2249 PUSH DX
2250 PUSH BX
2251 MOV AL,[BP.CLUSMSK]
2252 INC AL ;Number of sectors per cluster
2253 MOV AH,AL
2254 SUB AL,DL ;AL = Number of sectors left in first cluster
2255 MOV DX,CX
2256 MOV SI,[BP.FAT]
2257 MOV CX,0
2258OPTCLUS:
2259;AL has number of sectors available in current cluster
2260;AH has number of sectors available in next cluster
2261;BX has current physical cluster
2262;CX has number of sequential sectors found so far
2263;DX has number of sectors left to transfer
2264;SI has FAT pointer
2265 CALL UNPACK
2266 ADD CL,AL
2267 ADC CH,0
2268 CMP CX,DX
2269 JAE BLKDON
2270 MOV AL,AH
2271 INC BX
2272 CMP DI,BX
2273 JZ OPTCLUS
2274 DEC BX
2275FINCLUS:
2276 MOV [CLUSNUM],BX ;Last cluster accessed
2277 SUB DX,CX ;Number of sectors still needed
2278 PUSH DX
2279 MOV AX,CX
2280 MUL [BP.SECSIZ] ;Number of sectors times sector size
2281 MOV SI,[NEXTADD]
2282 ADD AX,SI ;Adjust by size of transfer
2283 MOV [NEXTADD],AX
2284 POP AX ;Number of sectors still needed
2285 POP DX ;Starting cluster
2286 SUB BX,DX ;Number of new clusters accessed
2287 ADD [LASTPOS],BX
2288 POP BX ;BL = sector postion within cluster
2289 CALL FIGREC
2290 MOV BX,SI
2291;Now let's see if any of these sectors are already in the buffer
2292 CMP [BUFSECNO],DX
2293 JC RET100 ;If DX > [BUFSECNO] then not in buffer
2294 MOV SI,DX
2295 ADD SI,CX ;Last sector + 1
2296 CMP [BUFSECNO],SI
2297 CMC
2298 JC RET100 ;If SI <= [BUFSECNO] then not in buffer
2299 PUSH AX
2300 MOV AL,[BP.DEVNUM]
2301 CMP AL,[BUFDRVNO] ;Is buffer for this drive?
2302 POP AX
2303 JZ RET100 ;If so, then we match
2304 STC ;No match
2305RET100: RET
2306BLKDON:
2307 SUB CX,DX ;Number of sectors in cluster we don't want
2308 SUB AH,CL ;Number of sectors in cluster we accepted
2309 DEC AH ;Adjust to mean position within cluster
2310 MOV [SECCLUSPOS],AH
2311 MOV CX,DX ;Anyway, make the total equal to the request
2312 JMP SHORT FINCLUS
2313
2314
2315FIGREC:
2316
2317;Inputs:
2318; DX = Physical cluster number
2319; BL = Sector postion within cluster
2320; BP = Base of drive parameters
2321;Outputs:
2322; DX = physical sector number
2323;No other registers affected.
2324
2325 PUSH CX
2326 MOV CL,[BP.CLUSSHFT]
2327 DEC DX
2328 DEC DX
2329 SHL DX,CL
2330 OR DL,BL
2331 ADD DX,[BP.FIRREC]
2332 POP CX
2333 RET
2334
2335GETREC:
2336
2337; Inputs:
2338; DS:DX point to FCB
2339; Outputs:
2340; CX = 1
2341; DX:AX = Record number determined by EXTENT and NR fields
2342; DS:DI point to FCB
2343; No other registers affected.
2344
2345 MOV DI,DX
2346 CMP BYTE PTR [DI],-1 ;Check for extended FCB
2347 JNZ NORMFCB2
2348 ADD DI,7
2349NORMFCB2:
2350 MOV CX,1
2351 MOV AL,[DI.NR]
2352 MOV DX,[DI.EXTENT]
2353 SHL AL,1
2354 SHR DX,1
2355 RCR AL,1
2356 MOV AH,DL
2357 MOV DL,DH
2358 MOV DH,0
2359 RET
2360
2361
2362ALLOCATE:
2363
2364; Inputs:
2365; DS = CS
2366; ES = Segment of FCB
2367; BX = Last cluster of file (0 if null file)
2368; CX = No. of clusters to allocate
2369; DX = Position of cluster BX
2370; BP = Base of drive parameters
2371; SI = FAT pointer
2372; [FCB] = Displacement of FCB within segment
2373; Outputs:
2374; IF insufficient space
2375; THEN
2376; Carry set
2377; CX = max. no. of records that could be added to file
2378; ELSE
2379; Carry clear
2380; BX = First cluster allocated
2381; FAT is fully updated including dirty bit
2382; FIRCLUS field of FCB set if file was null
2383; SI,BP unchanged. All other registers destroyed.
2384
2385 PUSH [SI]
2386 PUSH DX
2387 PUSH CX
2388 PUSH BX
2389 MOV AX,BX
2390ALLOC:
2391 MOV DX,BX
2392FINDFRE:
2393 INC BX
2394 CMP BX,[BP.MAXCLUS]
2395 JLE TRYOUT
2396 CMP AX,1
2397 JG TRYIN
2398 POP BX
2399 MOV DX,0FFFH
2400 CALL RELBLKS
2401 POP AX ;No. of clusters requested
2402 SUB AX,CX ;AX=No. of clusters allocated
2403 POP DX
2404 POP [SI]
2405 INC DX ;Position of first cluster allocated
2406 ADD AX,DX ;AX=max no. of cluster in file
2407 MOV DL,[BP.CLUSMSK]
2408 MOV DH,0
2409 INC DX ;DX=records/cluster
2410 MUL DX ;AX=max no. of records in file
2411 MOV CX,AX
2412 SUB CX,WORD PTR [RECPOS] ;CX=max no. of records that could be written
2413 JA MAXREC
2414 XOR CX,CX ;If CX was negative, zero it
2415MAXREC:
2416 STC
2417RET11: RET
2418
2419TRYOUT:
2420 CALL UNPACK
2421 JZ HAVFRE
2422TRYIN:
2423 DEC AX
2424 JLE FINDFRE
2425 XCHG AX,BX
2426 CALL UNPACK
2427 JZ HAVFRE
2428 XCHG AX,BX
2429 JMP SHORT FINDFRE
2430HAVFRE:
2431 XCHG BX,DX
2432 MOV AX,DX
2433 CALL PACK
2434 MOV BX,AX
2435 LOOP ALLOC
2436 MOV DX,0FFFH
2437 CALL PACK
2438 MOV BYTE PTR [SI-1],1
2439 POP BX
2440 POP CX ;Don't need this stuff since we're successful
2441 POP DX
2442 CALL UNPACK
2443 POP [SI]
2444 XCHG BX,DI
2445 OR DI,DI
2446 JNZ RET11
2447 MOV DI,[FCB]
2448 MOV ES:[DI.FIRCLUS],BX
2449RET12: RET
2450
2451
2452RELEASE:
2453
2454; Inputs:
2455; DS = CS
2456; BX = Cluster in file
2457; SI = FAT pointer
2458; BP = Base of drive parameters
2459; Function:
2460; Frees cluster chain starting with [BX]
2461; AX,BX,DX,DI all destroyed. Other registers unchanged.
2462
2463 XOR DX,DX
2464RELBLKS:
2465; Enter here with DX=0FFFH to put an end-of-file mark
2466; in the first cluster and free the rest in the chain.
2467 CALL UNPACK
2468 JZ RET12
2469 MOV AX,DI
2470 CALL PACK
2471 CMP AX,0FF8H
2472 MOV BX,AX
2473 JB RELEASE
2474RET13: RET
2475
2476
2477GETEOF:
2478
2479; Inputs:
2480; BX = Cluster in a file
2481; SI = Base of drive FAT
2482; DS = CS
2483; Outputs:
2484; BX = Last cluster in the file
2485; DI destroyed. No other registers affected.
2486
2487 CALL UNPACK
2488 CMP DI,0FF8H
2489 JAE RET13
2490 MOV BX,DI
2491 JMP SHORT GETEOF
2492
2493
2494SRCHFRST: ;System call 17
2495 CALL GETFILE
2496SAVPLCE:
2497; Search-for-next enters here to save place and report
2498; findings.
2499 JC KILLSRCH
2500 OR BH,BH
2501 JS SRCHDEV
2502 MOV AX,[LASTENT]
2503 MOV ES:[DI.FILDIRENT],AX
2504 MOV ES:[DI.DRVBP],BP
2505;Information in directory entry must be copied into the first
2506; 33 bytes starting at the disk transfer address.
2507 MOV SI,BX
2508 LES DI,DWORD PTR [DMAADD]
2509 MOV AX,00FFH
2510 CMP AL,[EXTFCB]
2511 JNZ NORMFCB
2512 STOSW
2513 INC AL
2514 STOSW
2515 STOSW
2516 MOV AL,[ATTRIB]
2517 STOSB
2518NORMFCB:
2519 MOV AL,[THISDRV]
2520 INC AL
2521 STOSB ;Set drive number
2522 MOV CX,16
2523 REP MOVSW ;Copy remaining 10 characters of name
2524 XOR AL,AL
2525 RET
2526
2527KILLSRCH:
2528KILLSRCH1 EQU KILLSRCH+1
2529;The purpose of the KILLSRCH1 label is to provide a jump label to the following
2530; instruction which leaves out the segment override.
2531 MOV WORD PTR ES:[DI.FILDIRENT],-1
2532 MOV AL,-1
2533 RET
2534
2535SRCHDEV:
2536 MOV ES:[DI.FILDIRENT],BX
2537 LES DI,DWORD PTR [DMAADD]
2538 XOR AX,AX
2539 STOSB ;Zero drive byte
2540 SUB SI,4 ;Point to device name
2541 MOVSW
2542 MOVSW
2543 MOV AX,2020H
2544 STOSB
2545 STOSW
2546 STOSW
2547 STOSW ;Fill with 8 blanks
2548 XOR AX,AX
2549 MOV CX,10
2550 REP STOSW
2551 STOSB
2552RET14: RET
2553
2554SRCHNXT: ;System call 18
2555 CALL MOVNAME
2556 MOV DI,DX
2557 JC NEAR PTR KILLSRCH1
2558 MOV BP,[DI.DRVBP]
2559 MOV AX,[DI.FILDIRENT]
2560 OR AX,AX
2561 JS NEAR PTR KILLSRCH1
2562 PUSH DX
2563 PUSH DS
2564 PUSH CS
2565 POP DS
2566 MOV [LASTENT],AX
2567 CALL CONTSRCH
2568 POP ES
2569 POP DI
2570 JMP SAVPLCE
2571
2572
2573FILESIZE: ;System call 35
2574 CALL GETFILE
2575 MOV AL,-1
2576 JC RET14
2577 ADD DI,33 ;Write size in RR field
2578 MOV CX,ES:[DI.RECSIZ-33]
2579 OR CX,CX
2580 JNZ RECOK
2581 MOV CX,128
2582RECOK:
2583 XOR AX,AX
2584 XOR DX,DX ;Intialize size to zero
2585 OR BH,BH ;Check for named I/O device
2586 JS DEVSIZ
2587 INC SI
2588 INC SI ;Point to length field
2589 MOV AX,[SI+2] ;Get high word of size
2590 DIV CX
2591 PUSH AX ;Save high part of result
2592 LODSW ;Get low word of size
2593 DIV CX
2594 OR DX,DX ;Check for zero remainder
2595 POP DX
2596 JZ DEVSIZ
2597 INC AX ;Round up for partial record
2598 JNZ DEVSIZ ;Propagate carry?
2599 INC DX
2600DEVSIZ:
2601 STOSW
2602 MOV AX,DX
2603 STOSB
2604 MOV AL,0
2605 CMP CX,64
2606 JAE RET14 ;Only 3-byte field if RECSIZ >= 64
2607 MOV ES:[DI],AH
2608 RET
2609
2610
2611SETDMA: ;System call 26
2612 MOV CS:[DMAADD],DX
2613 MOV CS:[DMAADD+2],DS
2614 RET
2615
2616NOSUCHDRV:
2617 MOV AL,-1
2618 RET
2619
2620GETFATPT: ;System call 27
2621 MOV DL,0 ;Use default drive
2622
2623GETFATPTDL: ;System call 28
2624 PUSH CS
2625 POP DS
2626 MOV AL,DL
2627 CALL GETTHISDRV
2628 JC NOSUCHDRV
2629 CALL FATREAD
2630 MOV BX,[BP.FAT]
2631 MOV AL,[BP.CLUSMSK]
2632 INC AL
2633 MOV DX,[BP.MAXCLUS]
2634 DEC DX
2635 MOV CX,[BP.SECSIZ]
2636 LDS SI,DWORD PTR [SPSAVE]
2637 MOV [SI.BXSAVE],BX
2638 MOV [SI.DXSAVE],DX
2639 MOV [SI.CXSAVE],CX
2640 MOV [SI.DSSAVE],CS
2641 RET
2642
2643
2644GETDSKPT: ;System call 31
2645 PUSH CS
2646 POP DS
2647 MOV AL,[CURDRV]
2648 MOV [THISDRV],AL
2649 CALL FATREAD
2650 LDS SI,DWORD PTR [SPSAVE]
2651 MOV [SI.BXSAVE],BP
2652 MOV [SI.DSSAVE],CS
2653 RET
2654
2655
2656DSKRESET: ;System call 13
2657 PUSH CS
2658 POP DS
2659WRTFATS:
2660; DS=CS. Writes back all dirty FATs. All registers destroyed.
2661 XOR AL,AL
2662 XCHG AL,[DIRTYBUF]
2663 OR AL,AL
2664 JZ NOBUF
2665 MOV BP,[BUFDRVBP]
2666 MOV DX,[BUFSECNO]
2667 MOV BX,[BUFFER]
2668 MOV CX,1
2669 CALL DWRITE
2670NOBUF:
2671 MOV CL,[NUMIO]
2672 MOV CH,0
2673 MOV BP,[DRVTAB]
2674WRTFAT:
2675 PUSH CX
2676 CALL CHKFATWRT
2677 POP CX
2678 ADD BP,DPBSIZ
2679 LOOP WRTFAT
2680 RET
2681
2682
2683GETDRV: ;System call 25
2684 MOV AL,CS:[CURDRV]
2685RET15: RET
2686
2687
2688SETRNDREC: ;System call 36
2689 CALL GETREC
2690 MOV [DI+33],AX
2691 MOV [DI+35],DL
2692 CMP [DI.RECSIZ],64
2693 JAE RET15
2694 MOV [DI+36],DH ;Set 4th byte only if record size < 64
2695RET16: RET
2696
2697
2698SELDSK: ;System call 14
2699 MOV AL,CS:[NUMDRV]
2700 CMP DL,AL
2701 JNB RET17
2702 MOV CS:[CURDRV],DL
2703RET17: RET
2704
2705BUFIN: ;System call 10
2706 MOV AX,CS
2707 MOV ES,AX
2708 MOV SI,DX
2709 MOV CH,0
2710 LODSW
2711 OR AL,AL
2712 JZ RET17
2713 MOV BL,AH
2714 MOV BH,CH
2715 CMP AL,BL
2716 JBE NOEDIT
2717 CMP BYTE PTR [BX+SI],0DH
2718 JZ EDITON
2719NOEDIT:
2720 MOV BL,CH
2721EDITON:
2722 MOV DL,AL
2723 DEC DX
2724NEWLIN:
2725 MOV AL,CS:[CARPOS]
2726 MOV CS:[STARTPOS],AL
2727 PUSH SI
2728 MOV DI,OFFSET DOSGROUP:INBUF
2729 MOV AH,CH
2730 MOV BH,CH
2731 MOV DH,CH
2732GETCH:
2733 CALL IN
2734 CMP AL,"F"-"@" ;Ignore ^F
2735 JZ GETCH
2736 CMP AL,CS:ESCCHAR
2737 JZ ESC
2738 CMP AL,7FH
2739 JZ BACKSP
2740 CMP AL,8
2741 JZ BACKSP
2742 CMP AL,13
2743 JZ ENDLIN
2744 CMP AL,10
2745 JZ PHYCRLF
2746 CMP AL,CANCEL
2747 JZ KILNEW
2748SAVCH:
2749 CMP DH,DL
2750 JAE BUFFUL
2751 STOSB
2752 INC DH
2753 CALL BUFOUT
2754 OR AH,AH
2755 JNZ GETCH
2756 CMP BH,BL
2757 JAE GETCH
2758 INC SI
2759 INC BH
2760 JMP SHORT GETCH
2761
2762BUFFUL:
2763 MOV AL,7
2764 CALL OUT
2765 JMP SHORT GETCH
2766
2767ESC:
2768 CALL IN
2769 MOV CL,ESCTABLEN
2770 PUSH DI
2771 MOV DI,OFFSET DOSGROUP:ESCTAB
2772 REPNE SCASB
2773 POP DI
2774 SHL CX,1
2775 MOV BP,CX
2776 JMP [BP+OFFSET DOSGROUP:ESCFUNC]
2777
2778ENDLIN:
2779 STOSB
2780 CALL OUT
2781 POP DI
2782 MOV [DI-1],DH
2783 INC DH
2784COPYNEW:
2785 MOV BP,ES
2786 MOV BX,DS
2787 MOV ES,BX
2788 MOV DS,BP
2789 MOV SI,OFFSET DOSGROUP:INBUF
2790 MOV CL,DH
2791 REP MOVSB
2792 RET
2793CRLF:
2794 MOV AL,13
2795 CALL OUT
2796 MOV AL,10
2797 JMP OUT
2798
2799PHYCRLF:
2800 CALL CRLF
2801 JMP SHORT GETCH
2802
2803KILNEW:
2804 MOV AL,"\"
2805 CALL OUT
2806 POP SI
2807PUTNEW:
2808 CALL CRLF
2809 MOV AL,CS:[STARTPOS]
2810 CALL TAB
2811 JMP NEWLIN
2812
2813BACKSP:
2814 OR DH,DH
2815 JZ OLDBAK
2816 CALL BACKUP
2817 MOV AL,ES:[DI]
2818 CMP AL," "
2819 JAE OLDBAK
2820 CMP AL,9
2821 JZ BAKTAB
2822 CALL BACKMES
2823OLDBAK:
2824 OR AH,AH
2825 JNZ GETCH1
2826 OR BH,BH
2827 JZ GETCH1
2828 DEC BH
2829 DEC SI
2830GETCH1:
2831 JMP GETCH
2832BAKTAB:
2833 PUSH DI
2834 DEC DI
2835 STD
2836 MOV CL,DH
2837 MOV AL," "
2838 PUSH BX
2839 MOV BL,7
2840 JCXZ FIGTAB
2841FNDPOS:
2842 SCASB
2843 JNA CHKCNT
2844 CMP ES:BYTE PTR [DI+1],9
2845 JZ HAVTAB
2846 DEC BL
2847CHKCNT:
2848 LOOP FNDPOS
2849FIGTAB:
2850 SUB BL,CS:[STARTPOS]
2851HAVTAB:
2852 SUB BL,DH
2853 ADD CL,BL
2854 AND CL,7
2855 CLD
2856 POP BX
2857 POP DI
2858 JZ OLDBAK
2859TABBAK:
2860 CALL BACKMES
2861 LOOP TABBAK
2862 JMP SHORT OLDBAK
2863BACKUP:
2864 DEC DH
2865 DEC DI
2866BACKMES:
2867 MOV AL,8
2868 CALL OUT
2869 MOV AL," "
2870 CALL OUT
2871 MOV AL,8
2872 JMP OUT
2873
2874TWOESC:
2875 MOV AL,ESCCH
2876 JMP SAVCH
2877
2878COPYLIN:
2879 MOV CL,BL
2880 SUB CL,BH
2881 JMP SHORT COPYEACH
2882
2883COPYSTR:
2884 CALL FINDOLD
2885 JMP SHORT COPYEACH
2886
2887COPYONE:
2888 MOV CL,1
2889COPYEACH:
2890 MOV AH,0
2891 CMP DH,DL
2892 JZ GETCH2
2893 CMP BH,BL
2894 JZ GETCH2
2895 LODSB
2896 STOSB
2897 CALL BUFOUT
2898 INC BH
2899 INC DH
2900 LOOP COPYEACH
2901GETCH2:
2902 JMP GETCH
2903
2904SKIPONE:
2905 CMP BH,BL
2906 JZ GETCH2
2907 INC BH
2908 INC SI
2909 JMP GETCH
2910
2911SKIPSTR:
2912 CALL FINDOLD
2913 ADD SI,CX
2914 ADD BH,CL
2915 JMP GETCH
2916
2917FINDOLD:
2918 CALL IN
2919 MOV CL,BL
2920 SUB CL,BH
2921 JZ NOTFND
2922 DEC CX
2923 JZ NOTFND
2924 PUSH ES
2925 PUSH DS
2926 POP ES
2927 PUSH DI
2928 MOV DI,SI
2929 INC DI
2930 REPNE SCASB
2931 POP DI
2932 POP ES
2933 JNZ NOTFND
2934 NOT CL
2935 ADD CL,BL
2936 SUB CL,BH
2937RET30: RET
2938NOTFND:
2939 POP BP
2940 JMP GETCH
2941
2942REEDIT:
2943 MOV AL,"@"
2944 CALL OUT
2945 POP DI
2946 PUSH DI
2947 PUSH ES
2948 PUSH DS
2949 CALL COPYNEW
2950 POP DS
2951 POP ES
2952 POP SI
2953 MOV BL,DH
2954 JMP PUTNEW
2955
2956ENTERINS:
2957 IF TOGLINS
2958 NOT AH
2959 JMP GETCH
2960 ENDIF
2961 IF NOT TOGLINS
2962 MOV AH,-1
2963 JMP GETCH
2964
2965EXITINS:
2966 MOV AH,0
2967 JMP GETCH
2968 ENDIF
2969
2970ESCFUNC DW GETCH
2971 DW TWOESC
2972 IF NOT TOGLINS
2973 DW EXITINS
2974 ENDIF
2975 DW ENTERINS
2976 DW BACKSP
2977 DW REEDIT
2978 DW KILNEW
2979 DW COPYLIN
2980 DW SKIPSTR
2981 DW COPYSTR
2982 DW SKIPONE
2983 DW COPYONE
2984
2985 IF IBM
2986 DW COPYONE
2987 DW CTRLZ
2988CTRLZ:
2989 MOV AL,"Z"-"@"
2990 JMP SAVCH
2991 ENDIF
2992BUFOUT:
2993 CMP AL," "
2994 JAE OUT
2995 CMP AL,9
2996 JZ OUT
2997 PUSH AX
2998 MOV AL,"^"
2999 CALL OUT
3000 POP AX
3001 OR AL,40H
3002 JMP SHORT OUT
3003
3004NOSTOP:
3005 CMP AL,"P"-"@"
3006 JZ INCHK
3007 IF NOT TOGLPRN
3008 CMP AL,"N"-"@"
3009 JZ INCHK
3010 ENDIF
3011 CMP AL,"C"-"@"
3012 JZ INCHK
3013 RET
3014
3015CONOUT: ;System call 2
3016 MOV AL,DL
3017OUT:
3018 CMP AL,20H
3019 JB CTRLOUT
3020 CMP AL,7FH
3021 JZ OUTCH
3022 INC CS:BYTE PTR [CARPOS]
3023OUTCH:
3024 PUSH AX
3025 CALL STATCHK
3026 POP AX
3027 CALL FAR PTR BIOSOUT
3028 TEST CS:BYTE PTR [PFLAG],-1
3029 JZ RET18
3030 CALL FAR PTR BIOSPRINT
3031RET18: RET
3032
3033STATCHK:
3034 CALL FAR PTR BIOSSTAT
3035 JZ RET18
3036 CMP AL,'S'-'@'
3037 JNZ NOSTOP
3038 CALL FAR PTR BIOSIN ;Eat Cntrl-S
3039INCHK:
3040 CALL FAR PTR BIOSIN
3041 CMP AL,'P'-'@'
3042 JZ PRINTON
3043 IF NOT TOGLPRN
3044 CMP AL,'N'-'@'
3045 JZ PRINTOFF
3046 ENDIF
3047 CMP AL,'C'-'@'
3048 JNZ RET18
3049; Ctrl-C handler.
3050; "^C" and CR/LF is printed. Then the user registers are restored and the
3051; user CTRL-C handler is executed. At this point the top of the stack has
3052; 1) the interrupt return address should the user CTRL-C handler wish to
3053; allow processing to continue; 2) the original interrupt return address
3054; to the code that performed the function call in the first place. If the
3055; user CTRL-C handler wishes to continue, it must leave all registers
3056; unchanged and IRET. The function that was interrupted will simply be
3057; repeated.
3058 MOV AL,3 ;Display "^C"
3059 CALL BUFOUT
3060 CALL CRLF
3061 CLI ;Prepare to play with stack
3062 MOV SS,CS:[SSSAVE]
3063 MOV SP,CS:[SPSAVE] ;User stack now restored
3064 POP AX
3065 POP BX
3066 POP CX
3067 POP DX
3068 POP SI
3069 POP DI
3070 POP BP
3071 POP DS
3072 POP ES ;User registers now restored
3073 INT CONTC ;Execute user Ctrl-C handler
3074 JMP COMMAND ;Repeat command otherwise
3075
3076PRINTON:
3077 IF TOGLPRN
3078 NOT CS:BYTE PTR [PFLAG]
3079 RET
3080 ENDIF
3081 IF NOT TOGLPRN
3082 MOV CS:BYTE PTR [PFLAG],1
3083 RET
3084
3085PRINTOFF:
3086 MOV CS:BYTE PTR [PFLAG],0
3087 RET
3088 ENDIF
3089
3090CTRLOUT:
3091 CMP AL,13
3092 JZ ZERPOS
3093 CMP AL,8
3094 JZ BACKPOS
3095 CMP AL,9
3096 JNZ OUTCHJ
3097 MOV AL,CS:[CARPOS]
3098 OR AL,0F8H
3099 NEG AL
3100TAB:
3101 PUSH CX
3102 MOV CL,AL
3103 MOV CH,0
3104 JCXZ POPTAB
3105TABLP:
3106 MOV AL," "
3107 CALL OUT
3108 LOOP TABLP
3109POPTAB:
3110 POP CX
3111RET19: RET
3112
3113ZERPOS:
3114 MOV CS:BYTE PTR [CARPOS],0
3115OUTCHJ: JMP OUTCH
3116
3117BACKPOS:
3118 DEC CS:BYTE PTR [CARPOS]
3119 JMP OUTCH
3120
3121
3122CONSTAT: ;System call 11
3123 CALL STATCHK
3124 MOV AL,0
3125 JZ RET19
3126 OR AL,-1
3127 RET
3128
3129
3130CONIN: ;System call 1
3131 CALL IN
3132 PUSH AX
3133 CALL OUT
3134 POP AX
3135 RET
3136
3137
3138IN: ;System call 8
3139 CALL INCHK
3140 JZ IN
3141RET29: RET
3142
3143RAWIO: ;System call 6
3144 MOV AL,DL
3145 CMP AL,-1
3146 JNZ RAWOUT
3147 LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area
3148 CALL FAR PTR BIOSSTAT
3149 JNZ RESFLG
3150 OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag
3151 XOR AL,AL
3152 RET
3153
3154RESFLG:
3155 AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag
3156RAWINP: ;System call 7
3157 CALL FAR PTR BIOSIN
3158 RET
3159RAWOUT:
3160 CALL FAR PTR BIOSOUT
3161 RET
3162
3163LIST: ;System call 5
3164 MOV AL,DL
3165LISTOUT:
3166 PUSH AX
3167 CALL STATCHK
3168 POP AX
3169 CALL FAR PTR BIOSPRINT
3170RET20: RET
3171
3172PRTBUF: ;System call 9
3173 MOV SI,DX
3174OUTSTR:
3175 LODSB
3176 CMP AL,"$"
3177 JZ RET20
3178 CALL OUT
3179 JMP SHORT OUTSTR
3180
3181OUTMES: ;String output for internal messages
3182 LODS CS:BYTE PTR [SI]
3183 CMP AL,"$"
3184 JZ RET20
3185 CALL OUT
3186 JMP SHORT OUTMES
3187
3188
3189MAKEFCB: ;Interrupt call 41
3190DRVBIT EQU 2
3191NAMBIT EQU 4
3192EXTBIT EQU 8
3193 MOV DL,0 ;Flag--not ambiguous file name
3194 TEST AL,DRVBIT ;Use current drive field if default?
3195 JNZ DEFDRV
3196 MOV BYTE PTR ES:[DI],0 ;No - use default drive
3197DEFDRV:
3198 INC DI
3199 MOV CX,8
3200 TEST AL,NAMBIT ;Use current name fiels as defualt?
3201 XCHG AX,BX ;Save bits in BX
3202 MOV AL," "
3203 JZ FILLB ;If not, go fill with blanks
3204 ADD DI,CX
3205 XOR CX,CX ;Don't fill any
3206FILLB:
3207 REP STOSB
3208 MOV CL,3
3209 TEST BL,EXTBIT ;Use current extension as default
3210 JZ FILLB2
3211 ADD DI,CX
3212 XOR CX,CX
3213FILLB2:
3214 REP STOSB
3215 XCHG AX,CX ;Put zero in AX
3216 STOSW
3217 STOSW ;Initialize two words after to zero
3218 SUB DI,16 ;Point back at start
3219 TEST BL,1 ;Scan off separators if not zero
3220 JZ SKPSPC
3221 CALL SCANB ;Peel off blanks and tabs
3222 CALL DELIM ;Is it a one-time-only delimiter?
3223 JNZ NOSCAN
3224 INC SI ;Skip over the delimiter
3225SKPSPC:
3226 CALL SCANB ;Always kill preceding blanks and tabs
3227NOSCAN:
3228 CALL GETLET
3229 JBE NODRV ;Quit if termination character
3230 CMP BYTE PTR[SI],":" ;Check for potential drive specifier
3231 JNZ NODRV
3232 INC SI ;Skip over colon
3233 SUB AL,"@" ;Convert drive letter to binary drive number
3234 JBE BADDRV ;Valid drive numbers are 1-15
3235 CMP AL,CS:[NUMDRV]
3236 JBE HAVDRV
3237BADDRV:
3238 MOV DL,-1
3239HAVDRV:
3240 STOSB ;Put drive specifier in first byte
3241 INC SI
3242 DEC DI ;Counteract next two instructions
3243NODRV:
3244 DEC SI ;Back up
3245 INC DI ;Skip drive byte
3246 MOV CX,8
3247 CALL GETWORD ;Get 8-letter file name
3248 CMP BYTE PTR [SI],"."
3249 JNZ NODOT
3250 INC SI ;Skip over dot if present
3251 MOV CX,3 ;Get 3-letter extension
3252 CALL MUSTGETWORD
3253NODOT:
3254 LDS BX,CS:DWORD PTR [SPSAVE]
3255 MOV [BX.SISAVE],SI
3256 MOV AL,DL
3257 RET
3258
3259NONAM:
3260 ADD DI,CX
3261 DEC SI
3262 RET
3263
3264GETWORD:
3265 CALL GETLET
3266 JBE NONAM ;Exit if invalid character
3267 DEC SI
3268MUSTGETWORD:
3269 CALL GETLET
3270 JBE FILLNAM
3271 JCXZ MUSTGETWORD
3272 DEC CX
3273 CMP AL,"*" ;Check for ambiguous file specifier
3274 JNZ NOSTAR
3275 MOV AL,"?"
3276 REP STOSB
3277NOSTAR:
3278 STOSB
3279 CMP AL,"?"
3280 JNZ MUSTGETWORD
3281 OR DL,1 ;Flag ambiguous file name
3282 JMP MUSTGETWORD
3283FILLNAM:
3284 MOV AL," "
3285 REP STOSB
3286 DEC SI
3287RET21: RET
3288
3289SCANB:
3290 LODSB
3291 CALL SPCHK
3292 JZ SCANB
3293 DEC SI
3294 RET
3295
3296GETLET:
3297;Get a byte from [SI], convert it to upper case, and compare for delimiter.
3298;ZF set if a delimiter, CY set if a control character (other than TAB).
3299 LODSB
3300 AND AL,7FH
3301 CMP AL,"a"
3302 JB CHK
3303 CMP AL,"z"
3304 JA CHK
3305 SUB AL,20H ;Convert to upper case
3306CHK:
3307 CMP AL,"."
3308 JZ RET21
3309 CMP AL,'"'
3310 JZ RET21
3311 CMP AL,"/"
3312 JZ RET21
3313 CMP AL,"["
3314 JZ RET21
3315 CMP AL,"]"
3316 JZ RET21
3317
3318 IF IBM
3319DELIM:
3320 ENDIF
3321 CMP AL,":" ;Allow ":" as separator in IBM version
3322 JZ RET21
3323 IF NOT IBM
3324DELIM:
3325 ENDIF
3326
3327 CMP AL,"+"
3328 JZ RET101
3329 CMP AL,"="
3330 JZ RET101
3331 CMP AL,";"
3332 JZ RET101
3333 CMP AL,","
3334 JZ RET101
3335SPCHK:
3336 CMP AL,9 ;Filter out tabs too
3337 JZ RET101
3338;WARNING! " " MUST be the last compare
3339 CMP AL," "
3340RET101: RET
3341
3342SETVECT: ; Interrupt call 37
3343 XOR BX,BX
3344 MOV ES,BX
3345 MOV BL,AL
3346 SHL BX,1
3347 SHL BX,1
3348 MOV ES:[BX],DX
3349 MOV ES:[BX+2],DS
3350 RET
3351
3352
3353NEWBASE: ; Interrupt call 38
3354 MOV ES,DX
3355 LDS SI,CS:DWORD PTR [SPSAVE]
3356 MOV DS,[SI.CSSAVE]
3357 XOR SI,SI
3358 MOV DI,SI
3359 MOV AX,DS:[2]
3360 MOV CX,80H
3361 REP MOVSW
3362
3363SETMEM:
3364
3365; Inputs:
3366; AX = Size of memory in paragraphs
3367; DX = Segment
3368; Function:
3369; Completely prepares a program base at the
3370; specified segment.
3371; Outputs:
3372; DS = DX
3373; ES = DX
3374; [0] has INT 20H
3375; [2] = First unavailable segment ([ENDMEM])
3376; [5] to [9] form a long call to the entry point
3377; [10] to [13] have exit address (from INT 22H)
3378; [14] to [17] have ctrl-C exit address (from INT 23H)
3379; [18] to [21] have fatal error address (from INT 24H)
3380; DX,BP unchanged. All other registers destroyed.
3381
3382 XOR CX,CX
3383 MOV DS,CX
3384 MOV ES,DX
3385 MOV SI,EXIT
3386 MOV DI,SAVEXIT
3387 MOVSW
3388 MOVSW
3389 MOVSW
3390 MOVSW
3391 MOVSW
3392 MOVSW
3393 MOV ES:[2],AX
3394 SUB AX,DX
3395 CMP AX,MAXDIF
3396 JBE HAVDIF
3397 MOV AX,MAXDIF
3398HAVDIF:
3399 MOV BX,ENTRYPOINTSEG
3400 SUB BX,AX
3401 SHL AX,1
3402 SHL AX,1
3403 SHL AX,1
3404 SHL AX,1
3405 MOV DS,DX
3406 MOV DS:[6],AX
3407 MOV DS:[8],BX
3408 MOV DS:[0],20CDH ;"INT INTTAB"
3409 MOV DS:(BYTE PTR [5]),LONGCALL
3410 RET
3411
3412DATE16:
3413 PUSH CX
3414 CALL READTIME
3415 SHL CL,1 ;Minutes to left part of byte
3416 SHL CL,1
3417 SHL CX,1 ;Push hours and minutes to left end
3418 SHL CX,1
3419 SHL CX,1
3420 SHR DH,1 ;Count every two seconds
3421 OR CL,DH ;Combine seconds with hours and minutes
3422 MOV DX,CX
3423 POP CX
3424 MOV AX,WORD PTR [MONTH] ;Fetch month and year
3425 SHL AL,1 ;Push month to left to make room for day
3426 SHL AL,1
3427 SHL AL,1
3428 SHL AL,1
3429 SHL AX,1
3430 OR AL,[DAY]
3431RET22: RET
3432
3433FOURYEARS EQU 3*365+366
3434
3435READTIME:
3436;Gets time in CX:DX. Figures new date if it has changed.
3437;Uses AX, CX, DX.
3438 CALL FAR PTR BIOSGETTIME
3439 CMP AX,[DAYCNT] ;See if day count is the same
3440 JZ RET22
3441 CMP AX,FOURYEARS*30 ;Number of days in 120 years
3442 JAE RET22 ;Ignore if too large
3443 MOV [DAYCNT],AX
3444 PUSH SI
3445 PUSH CX
3446 PUSH DX ;Save time
3447 XOR DX,DX
3448 MOV CX,FOURYEARS ;Number of days in 4 years
3449 DIV CX ;Compute number of 4-year units
3450 SHL AX,1
3451 SHL AX,1
3452 SHL AX,1 ;Multiply by 8 (no. of half-years)
3453 MOV CX,AX ;<240 implies AH=0
3454 MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year
3455 CALL DSLIDE ;Find out which of four years we're in
3456 SHR CX,1 ;Convert half-years to whole years
3457 JNC SK ;Extra half-year?
3458 ADD DX,200
3459SK:
3460 CALL SETYEAR
3461 MOV CL,1 ;At least at first month in year
3462 MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month
3463 CALL DSLIDE ;Find out which month we're in
3464 MOV [MONTH],CL
3465 INC DX ;Remainder is day of month (start with one)
3466 MOV [DAY],DL
3467 CALL WKDAY ;Set day of week
3468 POP DX
3469 POP CX
3470 POP SI
3471RET23: RET
3472
3473DSLIDE:
3474 MOV AH,0
3475DSLIDE1:
3476 LODSB ;Get count of days
3477 CMP DX,AX ;See if it will fit
3478 JB RET23 ;If not, done
3479 SUB DX,AX
3480 INC CX ;Count one more month/year
3481 JMP SHORT DSLIDE1
3482
3483SETYEAR:
3484;Set year with value in CX. Adjust length of February for this year.
3485 MOV BYTE PTR [YEAR],CL
3486CHKYR:
3487 TEST CL,3 ;Check for leap year
3488 MOV AL,28
3489 JNZ SAVFEB ;28 days if no leap year
3490 INC AL ;Add leap day
3491SAVFEB:
3492 MOV [MONTAB+1],AL ;Store for February
3493 RET
3494
3495;Days in year
3496YRTAB DB 200,166 ;Leap year
3497 DB 200,165
3498 DB 200,165
3499 DB 200,165
3500
3501;Days of each month
3502MONTAB DB 31 ;January
3503 DB 28 ;February--reset each time year changes
3504 DB 31 ;March
3505 DB 30 ;April
3506 DB 31 ;May
3507 DB 30 ;June
3508 DB 31 ;July
3509 DB 31 ;August
3510 DB 30 ;September
3511 DB 31 ;October
3512 DB 30 ;November
3513 DB 31 ;December
3514
3515GETDATE: ;Function call 42
3516 PUSH CS
3517 POP DS
3518 CALL READTIME ;Check for rollover to next day
3519 MOV AX,[YEAR]
3520 MOV BX,WORD PTR [DAY]
3521 LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers
3522 MOV [SI.DXSAVE],BX ;DH=month, DL=day
3523 ADD AX,1980 ;Put bias back
3524 MOV [SI.CXSAVE],AX ;CX=year
3525 MOV AL,CS:[WEEKDAY]
3526RET24: RET
3527
3528SETDATE: ;Function call 43
3529 MOV AL,-1 ;Be ready to flag error
3530 SUB CX,1980 ;Fix bias in year
3531 JC RET24 ;Error if not big enough
3532 CMP CX,119 ;Year must be less than 2100
3533 JA RET24
3534 OR DH,DH
3535 JZ RET24
3536 OR DL,DL
3537 JZ RET24 ;Error if either month or day is 0
3538 CMP DH,12 ;Check against max. month
3539 JA RET24
3540 PUSH CS
3541 POP DS
3542 CALL CHKYR ;Set Feb. up for new year
3543 MOV AL,DH
3544 MOV BX,OFFSET DOSGROUP:MONTAB-1
3545 XLAT ;Look up days in month
3546 CMP AL,DL
3547 MOV AL,-1 ;Restore error flag, just in case
3548 JB RET24 ;Error if too many days
3549 CALL SETYEAR
3550 MOV WORD PTR [DAY],DX ;Set both day and month
3551 SHR CX,1
3552 SHR CX,1
3553 MOV AX,FOURYEARS
3554 MOV BX,DX
3555 MUL CX
3556 MOV CL,BYTE PTR [YEAR]
3557 AND CL,3
3558 MOV SI,OFFSET DOSGROUP:YRTAB
3559 MOV DX,AX
3560 SHL CX,1 ;Two entries per year, so double count
3561 CALL DSUM ;Add up the days in each year
3562 MOV CL,BH ;Month of year
3563 MOV SI,OFFSET DOSGROUP:MONTAB
3564 DEC CX ;Account for months starting with one
3565 CALL DSUM ;Add up days in each month
3566 MOV CL,BL ;Day of month
3567 DEC CX ;Account for days starting with one
3568 ADD DX,CX ;Add in to day total
3569 XCHG AX,DX ;Get day count in AX
3570 MOV [DAYCNT],AX
3571 CALL FAR PTR BIOSSETDATE
3572WKDAY:
3573 MOV AX,[DAYCNT]
3574 XOR DX,DX
3575 MOV CX,7
3576 INC AX
3577 INC AX ;First day was Tuesday
3578 DIV CX ;Compute day of week
3579 MOV [WEEKDAY],DL
3580 XOR AL,AL ;Flag OK
3581RET25: RET
3582
3583DSUM:
3584 MOV AH,0
3585 JCXZ RET25
3586DSUM1:
3587 LODSB
3588 ADD DX,AX
3589 LOOP DSUM1
3590 RET
3591
3592GETTIME: ;Function call 44
3593 PUSH CS
3594 POP DS
3595 CALL READTIME
3596 LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers
3597 MOV [SI.DXSAVE],DX
3598 MOV [SI.CXSAVE],CX
3599 XOR AL,AL
3600RET26: RET
3601
3602SETTIME: ;Function call 45
3603;Time is in CX:DX in hours, minutes, seconds, 1/100 sec.
3604 MOV AL,-1 ;Flag in case of error
3605 CMP CH,24 ;Check hours
3606 JAE RET26
3607 CMP CL,60 ;Check minutes
3608 JAE RET26
3609 CMP DH,60 ;Check seconds
3610 JAE RET26
3611 CMP DL,100 ;Check 1/100's
3612 JAE RET26
3613 CALL FAR PTR BIOSSETTIME
3614 XOR AL,AL
3615 RET
3616
3617
3618; Default handler for division overflow trap
3619DIVOV:
3620 PUSH SI
3621 PUSH AX
3622 MOV SI,OFFSET DOSGROUP:DIVMES
3623 CALL OUTMES
3624 POP AX
3625 POP SI
3626 INT 23H ;Use Ctrl-C abort on divide overflow
3627 IRET
3628
3629CODSIZ EQU $-CODSTRT ;Size of code segment
3630CODE ENDS
3631
3632
3633;***** DATA AREA *****
3634CONSTANTS SEGMENT BYTE
3635 ORG 0
3636CONSTRT EQU $ ;Start of constants segment
3637
3638IONAME:
3639 IF NOT IBM
3640 DB "PRN ","LST ","NUL ","AUX ","CON "
3641 ENDIF
3642 IF IBM
3643 DB "COM1","PRN ","LPT1","NUL ","AUX ","CON "
3644 ENDIF
3645DIVMES DB 13,10,"Divide overflow",13,10,"$"
3646CARPOS DB 0
3647STARTPOS DB 0
3648PFLAG DB 0
3649DIRTYDIR DB 0 ;Dirty buffer flag
3650NUMDRV DB 0 ;Number of drives
3651NUMIO DB ? ;Number of disk tables
3652VERFLG DB 0 ;Initialize with verify off
3653CONTPOS DW 0
3654DMAADD DW 80H ;User's disk transfer address (disp/seg)
3655 DW ?
3656ENDMEM DW ?
3657MAXSEC DW 0
3658BUFFER DW ?
3659BUFSECNO DW 0
3660BUFDRVNO DB -1
3661DIRTYBUF DB 0
3662BUFDRVBP DW ?
3663DIRBUFID DW -1
3664DAY DB 0
3665MONTH DB 0
3666YEAR DW 0
3667DAYCNT DW -1
3668WEEKDAY DB 0
3669CURDRV DB 0 ;Default to drive A
3670DRVTAB DW 0 ;Address of start of DPBs
3671DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments
3672CONSTANTS ENDS
3673
3674DATA SEGMENT WORD
3675; Init code overlaps with data area below
3676
3677 ORG 0
3678INBUF DB 128 DUP (?)
3679CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer
3680LASTENT DW ?
3681EXITHOLD DB 4 DUP (?)
3682FATBASE DW ?
3683NAME1 DB 11 DUP (?) ;File name buffer
3684ATTRIB DB ?
3685NAME2 DB 11 DUP (?)
3686NAME3 DB 12 DUP (?)
3687EXTFCB DB ?
3688;WARNING - the following two items are accessed as a word
3689CREATING DB ?
3690DELALL DB ?
3691TEMP LABEL WORD
3692SPSAVE DW ?
3693SSSAVE DW ?
3694CONTSTK DW ?
3695SECCLUSPOS DB ? ;Position of first sector within cluster
3696DSKERR DB ?
3697TRANS DB ?
3698PREREAD DB ? ;0 means preread; 1 means optional
3699READOP DB ?
3700THISDRV DB ?
3701
3702 EVEN
3703FCB DW ? ;Address of user FCB
3704NEXTADD DW ?
3705RECPOS DB 4 DUP (?)
3706RECCNT DW ?
3707LASTPOS DW ?
3708CLUSNUM DW ?
3709SECPOS DW ? ;Position of first sector accessed
3710VALSEC DW ? ;Number of valid (previously written) sectors
3711BYTSECPOS DW ? ;Position of first byte within sector
3712BYTPOS DB 4 DUP (?) ;Byte position in file of access
3713BYTCNT1 DW ? ;No. of bytes in first sector
3714BYTCNT2 DW ? ;No. of bytes in last sector
3715SECCNT DW ? ;No. of whole sectors
3716ENTFREE DW ?
3717
3718 DB 80H DUP (?) ;Stack space
3719IOSTACK LABEL BYTE
3720 DB 80H DUP (?)
3721DSKSTACK LABEL BYTE
3722
3723 IF DSKTEST
3724NSS DW ?
3725NSP DW ?
3726 ENDIF
3727
3728DIRBUF LABEL WORD
3729
3730;Init code below overlaps with data area above
3731
3732 ORG 0
3733
3734MOVFAT:
3735;This section of code is safe from being overwritten by block move
3736 REP MOVS BYTE PTR [DI],[SI]
3737 CLD
3738 MOV ES:[DMAADD+2],DX
3739 MOV SI,[DRVTAB] ;Address of first DPB
3740 MOV AL,-1
3741 MOV CL,[NUMIO] ;Number of DPBs
3742FLGFAT:
3743 MOV DI,ES:[SI.FAT] ;get pointer to FAT
3744 DEC DI ;Point to dirty byte
3745 STOSB ;Flag as unused
3746 ADD SI,DPBSIZ ;Point to next DPB
3747 LOOP FLGFAT
3748 MOV AX,[ENDMEM]
3749 CALL SETMEM ;Set up segment
3750
3751XXX PROC FAR
3752 RET
3753XXX ENDP
3754
3755DOSINIT:
3756 CLI
3757 CLD
3758 PUSH CS
3759 POP ES
3760 MOV ES:[ENDMEM],DX
3761 LODSB ;Get no. of drives & no. of I/O drivers
3762 MOV ES:[NUMIO],AL
3763 MOV DI,OFFSET DOSGROUP:MEMSTRT
3764PERDRV:
3765 MOV BP,DI
3766 MOV AL,ES:[DRVCNT]
3767 STOSB ;DEVNUM
3768 LODSB ;Physical unit no.
3769 STOSB ;DRVNUM
3770 CMP AL,15
3771 JA BADINIT
3772 CBW ;Index into FAT size table
3773 SHL AX,1
3774 ADD AX,OFFSET DOSGROUP:FATSIZTAB
3775 XCHG BX,AX
3776 LODSW ;Pointer to DPT
3777 PUSH SI
3778 MOV SI,AX
3779 LODSW
3780 STOSW ;SECSIZ
3781 MOV DX,AX
3782 CMP AX,ES:[MAXSEC]
3783 JBE NOTMAX
3784 MOV ES:[MAXSEC],AX
3785NOTMAX:
3786 LODSB
3787 DEC AL
3788 STOSB ;CLUSMSK
3789 JZ HAVSHFT
3790 CBW
3791FIGSHFT:
3792 INC AH
3793 SAR AL,1
3794 JNZ FIGSHFT
3795 MOV AL,AH
3796HAVSHFT:
3797 STOSB ;CLUSSHFT
3798 MOVSW ;FIRFAT (= number of reserved sectors)
3799 MOVSB ;FATCNT
3800 MOVSW ;MAXENT
3801 MOV AX,DX ;SECSIZ again
3802 MOV CL,5
3803 SHR AX,CL
3804 MOV CX,AX ;Directory entries per sector
3805 DEC AX
3806 ADD AX,ES:[BP.MAXENT]
3807 XOR DX,DX
3808 DIV CX
3809 STOSW ;DIRSEC (temporarily)
3810 MOVSW ;DSKSIZ (temporarily)
3811FNDFATSIZ:
3812 MOV AL,1
3813 MOV DX,1
3814GETFATSIZ:
3815 PUSH DX
3816 CALL FIGFATSIZ
3817 POP DX
3818 CMP AL,DL ;Compare newly computed FAT size with trial
3819 JZ HAVFATSIZ ;Has sequence converged?
3820 CMP AL,DH ;Compare with previous trial
3821 MOV DH,DL
3822 MOV DL,AL ;Shuffle trials
3823 JNZ GETFATSIZ ;Continue iterations if not oscillating
3824 DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations
3825 JMP SHORT FNDFATSIZ ;Try again
3826
3827BADINIT:
3828 MOV SI,OFFSET DOSGROUP:BADMES
3829 CALL OUTMES
3830 STI
3831 HLT
3832
3833HAVFATSIZ:
3834 STOSB ;FATSIZ
3835 MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs
3836 ADD AX,ES:[BP.FIRFAT]
3837 STOSW ;FIRDIR
3838 ADD AX,ES:[BP.DIRSEC]
3839 MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC
3840 CALL FIGMAX
3841 MOV ES:[BP.MAXCLUS],CX
3842 MOV AX,BX ;Pointer into FAT size table
3843 STOSW ;Allocate space for FAT pointer
3844 MOV AL,ES:[BP.FATSIZ]
3845 XOR AH,AH
3846 MUL ES:[BP.SECSIZ]
3847 CMP AX,ES:[BX] ;Bigger than already allocated
3848 JBE SMFAT
3849 MOV ES:[BX],AX
3850SMFAT:
3851 POP SI ;Restore pointer to init. table
3852 MOV AL,ES:[DRVCNT]
3853 INC AL
3854 MOV ES:[DRVCNT],AL
3855 CMP AL,ES:[NUMIO]
3856 JAE CONTINIT
3857 JMP PERDRV
3858
3859BADINITJ:
3860 JMP BADINIT
3861
3862CONTINIT:
3863 PUSH CS
3864 POP DS
3865;Calculate true address of buffers, FATs, free space
3866 MOV BP,[MAXSEC]
3867 MOV AX,OFFSET DOSGROUP:DIRBUF
3868 ADD AX,BP
3869 MOV [BUFFER],AX ;Start of buffer
3870 ADD AX,BP
3871 MOV [DRVTAB],AX ;Start of DPBs
3872 SHL BP,1 ;Two sectors - directory and buffer
3873 ADD BP,DI ;Allocate buffer space
3874 ADD BP,ADJFAC ;True address of FATs
3875 PUSH BP
3876 MOV SI,OFFSET DOSGROUP:FATSIZTAB
3877 MOV DI,SI
3878 MOV CX,16
3879TOTFATSIZ:
3880 INC BP ;Add one for Dirty byte
3881 INC BP ;Add one for I/O device number
3882 LODSW ;Get size of this FAT
3883 XCHG AX,BP
3884 STOSW ;Save address of this FAT
3885 ADD BP,AX ;Compute size of next FAT
3886 CMP AX,BP ;If size was zero done
3887 LOOPNZ TOTFATSIZ
3888 MOV AL,15
3889 SUB AL,CL ;Compute number of FATs used
3890 MOV [NUMDRV],AL
3891 XOR AX,AX ;Set zero flag
3892 REPZ SCASW ;Make sure all other entries are zero
3893 JNZ BADINITJ
3894 ADD BP,15 ;True start of free space
3895 MOV CL,4
3896 SHR BP,CL ;First free segment
3897 MOV DX,CS
3898 ADD DX,BP
3899 MOV BX,0FH
3900 MOV CX,[ENDMEM]
3901 CMP CX,1 ;Use memory scan?
3902 JNZ SETEND
3903 MOV CX,DX ;Start scanning just after DOS
3904MEMSCAN:
3905 INC CX
3906 JZ SETEND
3907 MOV DS,CX
3908 MOV AL,[BX]
3909 NOT AL
3910 MOV [BX],AL
3911 CMP AL,[BX]
3912 NOT AL
3913 MOV [BX],AL
3914 JZ MEMSCAN
3915SETEND:
3916 IF HIGHMEM
3917 SUB CX,BP
3918 MOV BP,CX ;Segment of DOS
3919 MOV DX,CS ;Program segment
3920 ENDIF
3921 IF NOT HIGHMEM
3922 MOV BP,CS
3923 ENDIF
3924; BP has segment of DOS (whether to load high or run in place)
3925; DX has program segment (whether after DOS or overlaying DOS)
3926; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM)
3927 MOV CS:[ENDMEM],CX
3928 IF HIGHMEM
3929 MOV ES,BP
3930 XOR SI,SI
3931 MOV DI,SI
3932 MOV CX,(DOSLEN+1)/2
3933 PUSH CS
3934 POP DS
3935 REP MOVSW ;Move DOS to high memory
3936 ENDIF
3937 XOR AX,AX
3938 MOV DS,AX
3939 MOV ES,AX
3940 MOV DI,INTBASE
3941 MOV AX,OFFSET DOSGROUP:QUIT
3942 STOSW ;Set abort address--displacement
3943 MOV AX,BP
3944 MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP
3945 MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY
3946 MOV WORD PTR DS:[ENTRYPOINT+3],AX
3947 MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address
3948 MOV DS:[2],AX
3949 MOV CX,9
3950 REP STOSW ;Set 5 segments (skip 2 between each)
3951 MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND
3952 MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit
3953 MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit
3954 MOV AX,OFFSET BIOSREAD
3955 STOSW
3956 MOV AX,BIOSSEG
3957 STOSW
3958 STOSW ;Add 2 to DI
3959 STOSW
3960 MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE
3961 MOV WORD PTR DS:[EXIT],100H
3962 MOV WORD PTR DS:[EXIT+2],DX
3963 IF NOT IBM
3964 MOV SI,OFFSET DOSGROUP:HEADER
3965 CALL OUTMES
3966 ENDIF
3967 PUSH CS
3968 POP DS
3969 PUSH CS
3970 POP ES
3971;Move the FATs into position
3972 MOV AL,[NUMIO]
3973 CBW
3974 XCHG AX,CX
3975 MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT
3976FATPOINT:
3977 MOV SI,WORD PTR [DI] ;Get address within FAT address table
3978 MOVSW ;Set address of this FAT
3979 ADD DI,DPBSIZ-2 ;Point to next DPB
3980 LOOP FATPOINT
3981 POP CX ;True address of first FAT
3982 MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from
3983 MOV DI,[DRVTAB] ;Place to move DPBs to
3984 SUB CX,DI ;Total length of DPBs
3985 CMP DI,SI
3986 JBE MOVJMP ;Are we moving to higher or lower memory?
3987 DEC CX ;Move backwards to higher memory
3988 ADD DI,CX
3989 ADD SI,CX
3990 INC CX
3991 STD
3992MOVJMP:
3993 MOV ES,BP
3994 JMP MOVFAT
3995
3996FIGFATSIZ:
3997 MUL ES:BYTE PTR[BP.FATCNT]
3998 ADD AX,ES:[BP.FIRFAT]
3999 ADD AX,ES:[BP.DIRSEC]
4000FIGMAX:
4001;AX has equivalent of FIRREC
4002 SUB AX,ES:[BP.DSKSIZ]
4003 NEG AX
4004 MOV CL,ES:[BP.CLUSSHFT]
4005 SHR AX,CL
4006 INC AX
4007 MOV CX,AX ;MAXCLUS
4008 INC AX
4009 MOV DX,AX
4010 SHR DX,1
4011 ADC AX,DX ;Size of FAT in bytes
4012 MOV SI,ES:[BP.SECSIZ]
4013 ADD AX,SI
4014 DEC AX
4015 XOR DX,DX
4016 DIV SI
4017 RET
4018
4019BADMES:
4020 DB 13,10,"INIT TABLE BAD",13,10,"$"
4021
4022FATSIZTAB:
4023 DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
4024
4025DRVCNT DB 0
4026
4027MEMSTRT LABEL WORD
4028ADJFAC EQU DIRBUF-MEMSTRT
4029DATA ENDS
4030 END
4031 \ No newline at end of file
diff --git a/v1.25/source/STDDOS.ASM b/v1.25/source/STDDOS.ASM
new file mode 100644
index 0000000..1216b4c
--- /dev/null
+++ b/v1.25/source/STDDOS.ASM
@@ -0,0 +1,23 @@
1 TITLE MS-DOS version 1.25 by Tim Paterson March 3, 1982
2 PAGE 60,132
3; Use the following booleans to set the switches
4FALSE EQU 0
5TRUE EQU NOT FALSE
6
7; Use the switches below to produce the standard Microsoft version of the IBM
8; version of the operating system
9MSVER EQU TRUE
10IBM EQU FALSE
11
12; Set this switch to cause DOS to move itself to the end of memory
13HIGHMEM EQU FALSE
14
15; Turn on switch below to allow testing disk code with DEBUG. It sets
16; up a different stack for disk I/O (functions > 11) than that used for
17; character I/O which effectively makes the DOS re-entrant.
18
19DSKTEST EQU FALSE
20
21 INCLUDE MSDOS.ASM
22
23 \ No newline at end of file
diff --git a/v1.25/source/TRANS.ASM b/v1.25/source/TRANS.ASM
new file mode 100644
index 0000000..6b06619
--- /dev/null
+++ b/v1.25/source/TRANS.ASM
@@ -0,0 +1,1213 @@
1; Z80 to 8086 Translator version 2.21
2; Runs on the 8086 under 86-DOS
3; by Tim Paterson
4;
5 ORG 100H
6EOF: EQU 1AH ;End of file
7EOL: EQU 0DH
8FCB: EQU 5CH
9SYSTEM: EQU 5
10OPEN: EQU 15
11CLOSE: EQU 16
12SETDMA: EQU 26
13CREATE: EQU 22
14DELETE: EQU 19
15READ: EQU 20
16WRITE: EQU 21
17PRNBUF: EQU 9
18 MOV SP,STACK
19 MOV DX,HEADER
20 MOV CL,9
21 CALL SYSTEM
22 MOV BX,FCB+12
23 XOR AL,AL
24 MOV CH,4
25CLRFCB:
26 MOV [BX],AL
27 INC BX
28 DEC CH
29 JNZ CLRFCB
30 MOV [FCB+32],AL
31 MOV BX,FCB
32 MOV DX,PUTFCB
33 MOV CX,16
34 UP
35 MOV SI,BX
36 MOV DI,DX
37 REP
38 MOVB
39 MOV DX,DI
40 MOV BX,SI
41 MOV [PUTFCB+32],AL
42 MOV BX,"A"+5300H ;"AS"
43 MOV [PUTFCB+9],BX
44 MOV AL,'M'
45 MOV [PUTFCB+11],AL
46 MOV DX,FCB
47 MOV CL,OPEN
48 CALL SYSTEM
49 INC AL
50 MOV DX,NOFILE
51 JZ ABORTJ
52 MOV DX,PUTFCB
53 MOV CL,DELETE
54 CALL SYSTEM
55 MOV DX,PUTFCB
56 MOV CL,CREATE
57 CALL SYSTEM
58 INC AL
59 MOV DX,NOROOM
60ABORTJ:
61 JZ ABORT
62 MOV DX,PUTFCB
63 MOV CL,OPEN
64 CALL SYSTEM
65 MOV BX,PUTBUF
66 MOV [PUTPT],BX
67 MOV BX,GETBUF+80H
68 MOV [GETPT],BX
69TRANLN:
70 XOR AL,AL
71 MOV [OP1],AL
72 MOV [OP2],AL
73 MOV BX,OPCODE
74 CALL LOAD
75 MOV BX,OP1
76 CALL GETOP
77 MOV B,[BX],0
78 MOV BX,OP2
79 CALL GETOP
80DOLIN:
81 MOV B,[BX],0
82 CALL FINDOP
83ENLIN:
84 MOV SP,STACK
85 MOV AL,[CHAR]
86 CMP AL,';'
87 JNZ NOCOM
88 MOV AL,9
89 CALL PUTCH
90 MOV AL,';'
91NOCOM:
92 CALL PUTCH
93PUTLIN:
94 CMP AL,EOF
95 JZ END
96 CALL GETCH
97 CALL PUTCH
98 CMP AL,10
99 JNZ PUTLIN
100 JP TRANLN
101END:
102 MOV CH,127
103 MOV AL,1AH
104FILL:
105 CALL PUTCH
106 DEC CH
107 JNZ FILL
108 MOV DX,PUTFCB
109 MOV CL,CLOSE
110 CALL SYSTEM
111 MOV DX,ENDMES
112ABORT:
113 MOV CL,PRNBUF
114 CALL SYSTEM
115 JMP 0
116DELIM:
117 CALL GETCH
118DELCHK:
119 CMP AL,EOL
120 JZ DOLIN
121 CMP AL,EOF
122 JZ DOLIN
123 CMP AL,';'
124 JZ DOLIN
125 CMP AL,' '
126 JZ RET
127 CMP AL,':'
128 JZ RET
129 CMP AL,','
130 JZ RET
131 CMP AL,9
132 RET
133HEX:
134 AND AL,0FH
135 ADD AL,90H
136 DAA
137 ADC AL,40H
138 DAA
139PUTCH:
140 PUSH BX
141 PUSH DX
142 PUSH CX
143 LAHF
144 XCHG AH,AL
145 PUSH AX
146 XCHG AH,AL
147 AND AL,7FH
148 MOV BX,[PUTPT]
149 MOV [BX],AL
150 INC BX
151 MOV [PUTPT],BX
152 CMP BX,PUTBUF+80H
153 JNZ POPRET
154 MOV DX,PUTBUF
155 MOV [PUTPT],DX
156 MOV CL,SETDMA
157 CALL SYSTEM
158 MOV DX,PUTFCB
159 MOV CL,WRITE
160 CALL SYSTEM
161 OR AL,AL
162 MOV DX,WRTERR
163 JNZ ABORT
164POPRET:
165 POP AX
166 XCHG AH,AL
167 SAHF
168NOTAF:
169 POP CX
170 POP DX
171 POP BX
172 RET
173;
174; Get character from source file.
175;
176GETCH:
177 PUSH BX
178 PUSH DX
179 PUSH CX
180 MOV BX,[GETPT] ; Get buffer pointer.
181 CMP BX,GETBUF+80H ; Past end-of-buffer?
182 JNZ GETIT ; Jump if not.
183 MOV DX,GETBUF ; Set `DMA address'.
184 MOV CL,SETDMA
185 CALL SYSTEM
186 MOV DX,FCB ; Read the next record from source file.
187 MOV CL,READ
188 CALL SYSTEM
189 CMP AL,0 ; Entire record read OK?
190 JE OKRECORD
191 CMP AL,3 ; Partial record read?
192 JE OKRECORD
193 MOV AL,EOF ; Force end-of-file character in case
194 JP TESEND ; there is nothing in the record.
195OKRECORD:
196 MOV BX,GETBUF ; Reset buffer pointer.
197GETIT:
198 MOV AL,[BX] ; Get next character from buffer.
199 INC BX ; Point to next character.
200 MOV [GETPT],BX ; Save new pointer.
201TESEND:
202 MOV [CHAR],AL
203 JP NOTAF ; Pop registers and return.
204LOAD:
205 CALL DELIM
206 JZ LOADOP
207EATLAB:
208 CALL PUTCH
209 CALL DELIM
210 JNZ EATLAB
211ENLAB:
212 MOV AL,':'
213 CALL PUTCH
214LOADOP:
215 MOV BX,OPCODE
216EATEM:
217 CALL DELIM
218 JZ EATEM
219LOADLP:
220 CALL IDCHK
221 JNC $+5
222 JMP OPERR
223 MOV [BX],AL
224 INC BX
225 CALL DELIM
226 JNZ LOADLP
227 MOV B,[BX],0
228 CMP AL,':'
229 JNZ RET
230 MOV BX,OPCODE
231 CALL TRANS
232 JP ENLAB
233GETOP:
234 XOR AL,AL
235 LAHF
236 XCHG AX,BP
237 SAHF
238GETLP:
239 CALL DELIM
240 JZ GETLP
241OPCHAR:
242 CMP AL,'('
243 JNZ NOTLEF
244 LAHF
245 XCHG AX,BP
246 SAHF
247 INC AL
248 LAHF
249 XCHG AX,BP
250 SAHF
251 MOV B,[BX],'['
252 JP NEXCH
253NOTLEF:
254 CMP AL,')'
255 JNZ NOTRIT
256 LAHF
257 XCHG AX,BP
258 SAHF
259 DEC AL
260 LAHF
261 XCHG AX,BP
262 SAHF
263 MOV B,[BX],']'
264 JP NEXCH
265NOTRIT:
266 MOV [BX],AL
267 CMP AL,''''
268 JZ EATQUO
269 CALL IDCHK
270 JNC GETID
271NEXCH:
272 INC BX
273 CALL GETCH
274IDRET:
275 CALL DELCHK
276 JNZ OPCHAR
277 CMP AL,' '
278 JZ OPCHAR
279 RET
280EATQUO:
281 INC BX
282 CALL GETCH
283 MOV [BX],AL
284 CMP AL,';'
285 JZ L0000
286 CALL DELCHK
287L0000:
288 CMP AL,''''
289 JNZ EATQUO
290 JP NEXCH
291IDCHK:
292 CMP AL,'0'
293 JC RET
294 CMP AL,'9'+1
295 CMC
296 JNC RET
297 CMP AL,40H
298 JC RET
299 AND AL,5FH
300 CMP AL,'A'
301 JC RET
302 CMP AL,'Z'+1
303 CMC
304 RET
305GETID:
306 MOV [BX],AL
307 MOV CH,1
308LODID:
309 INC BX
310 CALL GETCH
311 CALL IDCHK
312 JC RWCHK
313 MOV [BX],AL
314 INC CH
315 JP LODID
316RWCHK:
317 LAHF
318 XCHG AH,AL
319 PUSH AX
320 XCHG AH,AL
321 PUSH BX
322 DEC BX
323 DEC CH
324 MOV DL,CH
325 JZ LOOKRW
326 MOV DL,[BX]
327 DEC BX
328 DEC CH
329 JNZ NORW
330LOOKRW:
331 MOV AL,[BX]
332 MOV DH,AL
333 PUSH BX
334 MOV BX,RWTAB
335 MOV CX,LENRW
336RWLK:
337 UP
338 MOV DI,BX
339 REPNZ
340 SCAB
341 MOV BX,DI
342 JNZ NOTRW
343 PUSH BX
344 PUSH CX
345 MOV CX,LENRW-1
346 LAHF
347 ADD BX,CX
348 RCR SI
349 SAHF
350 RCL SI
351 MOV AL,[BX]
352 POP CX
353 POP BX
354 CMP AL,DL
355 JZ HAVRW
356 MOV AL,CL
357 OR AL,AL
358 MOV AL,DH
359 JNZ RWLK
360NOTRW:
361 POP BX
362NORW:
363 POP BX
364ENDRW:
365 POP AX
366 XCHG AH,AL
367 SAHF
368 JMP IDRET
369HAVRW:
370 POP BX
371 INC CL
372 MOV [BX],CL
373 INC BX
374 POP DX
375 PUSH BX
376 MOV AL,CL
377 MOV BX,IXSI
378 CMP AL,RSI
379 JZ IXIY
380 MOV BX,IYDI
381 CMP AL,RDI
382 JNZ NORW
383IXIY:
384 LAHF
385 XCHG AX,BP
386 SAHF
387 JZ NOTENC
388 LAHF
389 XCHG AX,BP
390 SAHF
391 CALL OUTSTR
392 JP NORW
393NOTENC:
394 LAHF
395 XCHG AX,BP
396 SAHF
397 POP BX
398 DEC BX
399 MOV B,[BX],'['
400 INC BX
401 ADD AL,RIX-1
402 MOV [BX],AL
403 INC BX
404 MOV B,[BX],']'
405 INC BX
406 JP ENDRW
407 RET
408FINDOP:
409 MOV BX,OPCODE
410 MOV CX,5
411 XOR AL,AL
412 UP
413 MOV DI,BX
414 REPNZ
415 SCAB
416 MOV BX,DI
417 JNZ OPERR
418 MOV AL,4
419 SUB AL,CL
420 JZ RET
421 DEC AL
422 JZ OPERR
423 MOV CL,AL
424 DEC BX
425 DEC BX
426 OR B,[BX],080H
427 MOV AL,[OPCODE]
428 SUB AL,'A'
429 JC OPERR
430 ADD AL,AL
431 MOV DL,AL
432 MOV DH,0
433 MOV BX,OPTAB
434 LAHF
435 ADD BX,DX
436 RCR SI
437 SAHF
438 RCL SI
439 MOV DL,[BX]
440 INC BX
441 MOV DH,[BX]
442 XCHG DX,BX
443 MOV AL,9
444 CALL PUTCH
445LOOKOP:
446 MOV AL,[BX]
447 OR AL,AL
448 JZ OPERR
449 MOV DX,OPCODE+1
450 MOV CH,CL
451LOOKLP:
452 MOV SI,DX
453 LODB
454 CMP AL,[BX]
455 JNZ NEXOP
456 INC DX
457 INC BX
458 DEC CH
459 JNZ LOOKLP
460 MOV DX,[BX]
461 MOV BX,[BX+2]
462 JMP DX
463NEXOP:
464 RCR SI
465 TEST B,[BX],080H
466 RCL SI
467 LAHF
468 INC BX
469 SAHF
470 JZ NEXOP
471 MOV DX,4
472 LAHF
473 ADD BX,DX
474 RCR SI
475 SAHF
476 RCL SI
477 JP LOOKOP
478OPERR:
479 MOV BX,OPCODE
480 CALL OUTSTR
481 CALL TWOOPS
482 MOV BX,OPCDER
483 CALL OUTSTR
484 JMP ENLIN
485LD:
486 CALL OUTSTR
487 MOV BX,OP1
488 MOV DX,OP2+1
489 CALL LCHECK
490 JNZ $+5
491 JMP LDAX
492 XCHG DX,BX
493 DEC BX
494 INC DX
495 CALL LCHECK
496 JNZ $+5
497 JMP STAX
498;If immediate move, check for byte memory reference
499 MOV AL,[OP2]
500 CMP AL,20H ;Could be immediate?
501 MOV AL,9
502 JC L0001
503 CALL BYTCHK ;Add "B," if memory reference
504L0001:
505 CALL TRAN1
506 JP TRNOP2
507TWOOPS:
508 CALL TRNOP1
509TRNOP2:
510 MOV AL,','
511TRAN2:
512 MOV BX,OP2
513PTRANS:
514 CALL PUTCH
515TRANS:
516 MOV AL,[BX]
517 LAHF
518 INC BX
519 SAHF
520 OR AL,AL
521 JZ RET
522 CALL TRNTOK
523 JP TRANS
524LCHECK:
525 MOV AL,[BX]
526 CMP AL,RAL
527 JNZ RET
528 MOV SI,DX
529 LODB
530 CMP AL,RCX
531 JZ RET
532 CMP AL,RDX
533 RET
534
535ONEOP:
536 CALL OUTSTR
537 MOV AL,9
538 CALL BYTCHK ;If memory reference, add "B," flag
539 JMPS TRAN1
540
541TRNOP1:
542 MOV AL,9
543TRAN1:
544 MOV BX,OP1
545 JP PTRANS
546IN:
547 MOV AL,[OP1]
548 CMP AL,RAL
549 XCHG DX,BX
550 MOV BX,OP2
551 JZ GETPORT
552 MOV BX,SAVEAX
553 CALL OUTSTR
554 CALL OUTSTR
555 MOV BX,OP2
556 CALL GETPORT
557 MOV BX,MOV0
558 CALL ONEOP
559 MOV AL,','
560 CALL PUTCH
561 MOV AL,RAL
562 CALL TRNTOK
563IODONE:
564 MOV BX,RESTAX
565 JMP OUTSTR
566OUT:
567 MOV AL,[OP2]
568 XCHG DX,BX
569 MOV BX,OP1
570 CMP AL,RAL
571 JZ GETOUT
572 MOV BX,SAVEAX
573 CALL OUTSTR
574 MOV BX,MOVAL
575 CALL OUTSTR
576 CALL TRNOP2
577 MOV BX,CRLFTB
578 CALL OUTSTR
579 MOV BX,OP1
580 CALL GETOUT
581 JP IODONE
582GETPORT:
583 MOV AL,[BX]
584 CMP AL,'['
585 JNZ NOBRAK
586 LAHF
587 INC BX
588 SAHF
589 PUSH BX
590 MOV CX,80
591 MOV AL,']'
592 UP
593 MOV DI,BX
594 REPNZ
595 SCAB
596 MOV BX,DI
597 LAHF
598 DEC BX
599 SAHF
600 MOV B,[BX],0
601 POP BX
602NOBRAK:
603 MOV AL,[BX]
604 CMP AL,RGCL
605 JNZ FIXPOR
606 MOV BX,IO1
607 CALL OUTSTR
608 XCHG DX,BX
609 CALL OUTSTR
610 MOV AL,RDX
611 CALL TRNTOK
612 MOV BX,IO2
613 JMP OUTSTR
614GETOUT:
615 CALL GETPORT
616 JNC RET
617 MOV BX,BADIO
618 JMP OUTSTR
619FIXPOR:
620 XCHG DX,BX
621 CALL OUTSTR
622 XCHG DX,BX
623 JMP TRANS
624LDAX:
625 MOV BX,LDAX1
626LSAX:
627 CALL OUTSTR
628 MOV SI,DX
629 LODB
630 CALL TRNTOK
631 JP OUTSTR
632STAX:
633 MOV BX,STAX1
634 JP LSAX
635TRNTOK:
636 CMP AL,' '
637 JC $+5
638 JMP PUTCH
639 PUSH BX
640 PUSH CX
641 MOV CL,AL
642 MOV CH,0
643 MOV BX,TOKTAB-2
644 LAHF
645 ADD BX,CX
646 RCR SI
647 SAHF
648 RCL SI
649 LAHF
650 ADD BX,CX
651 RCR SI
652 SAHF
653 RCL SI
654 MOV AL,[BX]
655 CALL PUTCH
656 INC BX
657 MOV AL,[BX]
658 POP CX
659 POP BX
660 OR AL,AL
661 JZ RET
662 JMP PUTCH
663PUSH:
664 MOV DX,PUSHAF
665 JP AFCHK
666POP:
667 MOV DX,POPAF
668AFCHK:
669 MOV AL,[OP1]
670 CMP AL,RAX
671 JNZ ONEOPJ
672 XCHG DX,BX
673OUTSTR:
674 MOV AL,[BX]
675 OR AL,AL
676 JNZ L0002
677 CALL NEWOP
678L0002:
679 CALL PUTCH
680 INC BX
681 ADD AL,AL
682 JNC OUTSTR
683 RET
684NEWOP:
685 MOV AL,13
686 CALL PUTCH
687 MOV AL,10
688 CALL PUTCH
689 MOV AL,9
690 RET
691LDDR:
692 CALL OUTSTR
693 MOV BX,BLMOVE
694 JP OUTSTR
695CPDR:
696 CALL OUTSTR
697 MOV BX,CMPREP
698 JP OUTSTR
699ADD:
700 MOV AL,[OP1]
701 CMP AL,RBX
702 JZ DAD
703ARITH:
704 CALL OUTSTR
705 MOV AL,[OP2]
706 OR AL,AL
707 JZ $+5
708 JMP TWOOPS
709 MOV AL,9
710 CALL PUTCH
711 MOV AL,RAL
712 CALL TRNTOK
713 MOV AL,','
714 JMP TRAN1
715ACCUM:
716 CALL OUTSTR
717 MOV AL,9
718 CALL PUTCH
719 MOV AL,RAL
720 JMP TRNTOK
721ONEOPJ: JMP ONEOP
722DAD:
723 MOV BX,DAD1
724 CALL OUTSTR
725 CALL TWOOPS
726 MOV BX,DAD2
727 JP OUTSTR
728
729INCDEC:
730 MOV AL,[OP1]
731 CMP AL,RCX+1 ;16-bit?
732 JNC ONEOPJ
733 MOV BX,LAHF
734 CALL OUTSTR
735 XCHG DX,BX
736 MOV BX,OPCODE-1
737 CALL ONEOP
738 XCHG DX,BX
739OUTSTRJ:
740 JMP OUTSTR
741JUMP:
742 MOV AL,[OP1]
743 CMP AL,'['
744 JNZ DIRECT
745 MOV AL,[OP1+1]
746 MOV [OP1],AL
747 XOR AL,AL
748 MOV [OP1+1],AL
749DIRECT:
750 MOV AL,[OP2]
751 OR AL,AL
752 JZ ONEOPJ
753 CALL FIXCON
754 MOV BX,OP2
755OUTCON:
756 MOV CH,AL
757 MOV AL,'J'
758 CALL PUTCH
759 MOV AL,CH
760 CALL TRNTOK
761 MOV AL,9
762 CALL PTRANS
763 MOV AL,CH
764 CMP AL,ODDPAR
765 MOV BX,WARNPA
766 JZ OUTSTRJ
767 CMP AL,EVEPAR
768 JZ OUTSTRJ
769 RET
770FIXCON:
771 MOV AL,[OP1]
772 CMP AL,RGCL
773 JNZ RET
774 MOV AL,CY
775 RET
776RETURN:
777 MOV AL,[OP1]
778 OR AL,AL
779 JZ OUTSTRJ
780 MOV BX,'R'+4500H ;"RE"
781 MOV [OP2],BX
782 MOV BX,'T'
783 MOV [OP2+2],BX
784 JP DIRECT
785ONEOPJ1:
786 JMP ONEOP
787DOCALL:
788 MOV AL,[OP2]
789 OR AL,AL
790 JZ ONEOPJ1
791 CALL FIXCON
792 DEC AL
793 XOR AL,1
794 INC AL
795 MOV BX,LABEL
796 CALL OUTCON
797 MOV BX,OPCODE-1
798 CALL OUTSTR
799 MOV AL,[OP2]
800 OR AL,AL
801 MOV AL,9
802 MOV BX,OP2
803 JZ L0003
804 CALL PTRANS
805L0003:
806 MOV BX,CRLF
807 CALL OUTSTR
808 CALL TRANS
809 CALL OUTSTR
810 MOV BX,LABEL+4
811NEXLAB:
812 INC [BX]
813 MOV AL,[BX]
814 CMP AL,'9'+1
815 JNZ RET
816 MOV B,[BX],'0'
817 LAHF
818 DEC BX
819 SAHF
820 JP NEXLAB
821EX:
822 MOV AL,[OP1]
823 CMP AL,RAX
824 JZ OUTSTRJ1
825 MOV AL,[OP1+1]
826 CMP AL,STP
827 JZ XTHL
828 MOV BX,XCHG
829 CALL OUTSTR
830 JMP TWOOPS
831XTHL:
832 MOV BX,XTHL1
833 CALL OUTSTR
834 CALL TRNOP2
835 MOV BX,XTHL2
836OUTSTRJ1:
837 JMP OUTSTR
838PSEUDO:
839 CALL ONEOP
840 MOV AL,[OP2]
841 OR AL,AL
842 JZ RET
843 JMP TRNOP2
844 RET
845BITSET:
846 MOV CL,0
847 JP SETRES
848RES:
849 MOV CL,-1
850SETRES:
851 CALL OUTSTR
852 PUSH BX
853 MOV AL,[OP2]
854 CMP AL,'['
855 MOV AL,9
856 JNZ L0004
857 CALL BFLAG
858L0004:
859 CALL TRAN2
860 MOV AL,','
861 CALL PUTCH
862 CALL GETBIT
863 MOV BX,BITERR
864 JNC L0005
865 CALL OUTSTR
866L0005:
867 POP BX
868 JMP OUTSTR
869
870BYTCHK:
871;Check if memory reference and add "B," for byte mode
872 CMP B,[OP1],"[" ;Memory reference?
873 JNZ RET
874 CMP B,[OP1+1],RIX ;Referencing IX as a word?
875 JZ RET
876 CMP B,[OP1+1],RIY
877 JZ RET
878BFLAG:
879 CALL PUTCH
880 MOV AL,'B'
881 CALL PUTCH
882 MOV AL,','
883 RET
884
885GETBIT:
886 MOV AL,[OP1+1]
887 OR AL,AL
888 STC
889 JNZ RET
890 MOV AL,[OP1]
891 SUB AL,'0'
892 JC RET
893 CMP AL,8
894 CMC
895 JC RET
896 MOV CH,AL
897 INC CH
898 XOR AL,AL
899 STC
900SHFT:
901 RCL AL
902 DEC CH
903 JNZ SHFT
904 XOR AL,CL
905 MOV CH,AL
906 MOV AL,'0'
907 CALL PUTCH
908 MOV AL,CH
909 RCR AL
910 RCR AL
911 RCR AL
912 RCR AL
913 CALL HEX
914 MOV AL,CH
915 CALL HEX
916 MOV AL,'H'
917 JMP PUTCH
918OPTAB:
919 DW AOPS,BOPS,COPS,DOPS,EOPS
920 DW FOPS,GOPS,HOPS,IOPS,JOPS
921 DW KOPS,LOPS,MOPS,NOPS,OOPS
922 DW POPS,QOPS,ROPS,SOPS,TOPS
923 DW UOPS,VOPS,WOPS,XOPS,YOPS
924 DW ZOPS
925AOPS:
926 DM 'DD'
927 DW ADD,OPCODE
928 DM 'DC'
929 DW ARITH,OPCODE
930 DM 'ND'
931 DW ARITH,OPCODE
932 DB 0
933BOPS:
934 DM 'IT'
935 DW BITSET,TESBIT
936 DB 0
937COPS:
938 DM 'ALL'
939 DW DOCALL,OPCODE
940 DM 'P'
941 DW ARITH,CMP
942 DM 'PL'
943 DW ACCUM,NOT
944 DM 'PIR'
945 DW OUTSTR,CPIR
946 DM 'PDR'
947 DW CPDR,DOWN
948 DM 'CF'
949 DW OUTSTR,CMC
950 DB 0
951DOPS:
952 DM 'EC'
953 DW INCDEC,OPCODE
954 DM 'JNZ'
955 DW ONEOP,DJNZ
956 DM 'AA'
957 DW OUTSTR,OPCODE
958 DM 'I'
959 DW OUTSTR,OPCODE
960 DM 'W'
961 DW PSEUDO,OPCODE
962 DM 'B'
963 DW PSEUDO,OPCODE
964 DM 'M'
965 DW PSEUDO,OPCODE
966 DM 'S'
967 DW ONEOP,OPCODE
968 DB 0
969EOPS:
970 DM 'X'
971 DW EX,EXAF
972 DM 'I'
973 DW OUTSTR,OPCODE
974 DM 'XX'
975 DW OUTSTR,EXX
976 DM 'QU'
977 DW ONEOP,OPCODE
978 DM 'NDIF'
979 DW OUTSTR,OPCODE
980 DB 0
981FOPS:
982 DB 0
983GOPS:
984 DB 0
985HOPS:
986 DM 'ALT'
987 DW OUTSTR,HLT
988 DB 0
989IOPS:
990 DM 'NC'
991 DW INCDEC,OPCODE
992 DM 'N'
993 DW IN,INB
994 DM 'F'
995 DW ONEOP,OPCODE
996 DB 0
997JOPS:
998 DM 'R'
999 DW JUMP,JR
1000 DM 'P'
1001 DW JUMP,JMP
1002 DB 0
1003KOPS:
1004 DB 0
1005LOPS:
1006 DM 'D'
1007 DW LD,MOV
1008 DM 'DIR'
1009 DW OUTSTR,UP
1010 DM 'DDR'
1011 DW LDDR,DOWN
1012 DB 0
1013MOPS:
1014 DB 0
1015NOPS:
1016 DM 'EG'
1017 DW ACCUM,OPCODE
1018 DB 0
1019OOPS:
1020 DM 'R'
1021 DW ARITH,OPCODE
1022 DM 'UT'
1023 DW OUT,OUTB
1024 DM 'RG'
1025 DW ONEOP,OPCODE
1026 DB 0
1027POPS:
1028 DM 'OP'
1029 DW POP,OPCODE
1030 DM 'USH'
1031 DW PUSH,OPCODE
1032 DB 0
1033QOPS:
1034 DB 0
1035ROPS:
1036 DM 'ET'
1037 DW RETURN,OPCODE
1038 DM 'LA'
1039 DW ACCUM,RCL
1040 DM 'RA'
1041 DW ACCUM,RCR
1042 DM 'LCA'
1043 DW ACCUM,ROL
1044 DM 'RCA'
1045 DW ACCUM,ROR
1046 DM 'L'
1047 DW ONEOP,RCL
1048 DM 'R'
1049 DW ONEOP,RCR
1050 DM 'LC'
1051 DW ONEOP,ROL
1052 DM 'RC'
1053 DW ONEOP,ROR
1054 DM 'ES'
1055 DW RES,RESBIT
1056 DM 'ETI'
1057 DW OUTSTR,IRET
1058 DM 'ETN'
1059 DW OUTSTR,IRET
1060 DM 'ST'
1061 DW ONEOP,CALL
1062 DB 0
1063SOPS:
1064 DM 'UB'
1065 DW ARITH,OPCODE
1066 DM 'BC'
1067 DW ARITH,SBB
1068 DM 'LA'
1069 DW ONEOP,SAL
1070 DM 'RA'
1071 DW ONEOP,SAR
1072 DM 'RL'
1073 DW ONEOP,SHR
1074 DM 'CF'
1075 DW OUTSTR,STC
1076 DM 'ET'
1077 DW BITSET,SETBIT
1078 DB 0
1079TOPS:
1080 DB 0
1081UOPS:
1082 DB 0
1083VOPS:
1084 DB 0
1085WOPS:
1086 DB 0
1087XOPS:
1088 DM 'OR'
1089 DW ARITH,OPCODE
1090 DB 0
1091YOPS:
1092 DB 0
1093ZOPS:
1094 DB 0
1095LDAX1: DM 9,'SI,'
1096 DM 0,'LODB'
1097STAX1: DM 9,'DI,'
1098 DM 0,'STOB'
1099PUSHAF: DB 'LAHF',0,'XCHG',9,'AH,AL',0,'PUSH',9,'AX',0
1100 DM 'XCHG',9,'AH,AL'
1101POPAF: DM 'POP',9,'AX',0,'XCHG',9,'AH,AL',0,'SAHF'
1102DOWN: DM 'DOWN'
1103UP: DB 'UP'
1104BLMOVE: DB 0,'MOV',9,'SI,BX',0,'MOV',9,'DI,DX'
1105 DB 0,'REP',0,'MOVB',0,'MOV',9,'DX,DI'
1106 DM 0,'MOV',9,'BX,SI'
1107CPIR: DB 'UP'
1108CMPREP: DB 0,'MOV',9,'DI,BX',0,'REPNZ',0,'SCAB'
1109 DM 0,'MOV',9,'BX,DI'
1110DAD1: DM 'LAHF',0,'ADD'
1111DAD2: DM 0,'RCR',9,'SI',0,'SAHF',0,'RCL',9,'SI'
1112LAHF: DM 'LAHF'
1113 DM 0,'SAHF'
1114DJNZ: DB 'DEC',9,'CH',13,10
1115 DB '; *** WARNING: DJNZ does not affect flags - DEC does.',0
1116 DM 'JNZ'
1117WARNPA: DM 13,10,'; *** WARNING: Parity flag not always same as Z80.'
1118IO1: DB 'MOV',9,'DI,DX',0,'MOV',9,'DL,CL',0
1119 DM 'XOR',9,'DH,DH',13,10,9
1120IO2: DM 0,'MOV',9,'DX,DI'
1121BADIO: DM 13,10,'; *** WARNING: Flags not same as Z80.'
1122BITERR: DM 13,10,' *** ERROR: Cannot determine bit number.'
1123SETBIT: DM 'LAHF',0,'OR'
1124 DM 0,'SAHF'
1125RESBIT: DM 'LAHF',0,'AND'
1126 DM 0,'SAHF'
1127TESBIT: DM 'RCR',9,'AH',0,'TEST'
1128 DM 0,'RCL',9,'AH'
1129XTHL1: DM 'POP',9,'SI',0,'XCHG',9,'SI'
1130XTHL2: DM 0,'PUSH',9,'SI'
1131EXX: DB 'XCHG',9,'BX,[HL]',0,'XCHG',9,'DX,[DE]',0
1132 DM 'XCHG',9,'CX,[BC]'
1133EXAF: DM 'LAHF',0,'XCHG',9,'AX,BP',0,'SAHF'
1134MOVAL: DM 0,'MOV',9,'AL'
1135IXSI: DM 9,'MOV',9,'SI,[IX]',13,10
1136IYDI: DM 9,'MOV',9,'DI,[IY]',13,10
1137RESTAX: DB 0
1138SAVEAX: DM 'XCHG',9,'AX,SI'
1139CRLFTB: DM 13,10,9
1140INB: DM 'INB',9
1141OUTB: DM 'OUTB',9
1142XCHG: DM 'XCHG'
1143JMP: DM 'JMP'
1144JR: DM 'JMPS'
1145RCL: DM 'RCL'
1146RCR: DM 'RCR'
1147ROL: DM 'ROL'
1148ROR: DM 'ROR'
1149SAL: DM 'SAL'
1150SAR: DM 'SAR'
1151SHR: DM 'SHR'
1152STC: DM 'STC'
1153IRET: DM 'IRET'
1154HLT: DM 'HLT'
1155CMC: DM 'CMC'
1156NOT: DM 'NOT'
1157MOV0: DB 0
1158MOV: DM 'MOV'
1159CMP: DM 'CMP'
1160SBB: DM 'SBB'
1161CALL: DM 'CALL'
1162TOKTAB:
1163 DB 'SIDI'
1164 DB 'PEPOS',0,'NSNZZ',0,'NCC',0
1165 DB 'AXSPBXDXCX'
1166 DB 'BLBHDLDHCLCHALIXIY'
1167RWTAB:
1168 DB 'ABCDEHLBDHSACNZNPMPPII'
1169LENRW: EQU $-RWTAB
1170 DB 0,0,0,0,0,0,0,'CELPF',0,'C',0,'Z',0,0,'OEYX'
1171HEADER: DB 13,10,'Z80 to 8086 Translator version 2.21',13,10,'$'
1172NOROOM: DB 13,10,'File creation error',13,10,'$'
1173NOFILE: DB 13,10,'File not found',13,10,'$'
1174ENDMES: DB 13,10,'Translation complete',13,10,'$'
1175WRTERR: DB 13,10,'Out of disk space',13,10,'$'
1176OPCDER: DM 13,10,'*** Opcode Error '
1177CRLF: DM 13,10
1178LABEL: DB 'L0000',0
1179 DM ':',9
1180PUTPT: DS 2
1181GETPT: DS 2
1182CHAR: DS 1
1183 DB 0
1184OPCODE: DS 80
1185OP1: DS 80
1186OP2: DS 80
1187PUTBUF: DS 128
1188GETBUF: DS 128
1189PUTFCB: DS 33
1190 DS 50
1191STACK: EQU $
1192 ORG 1 ;This is really just for equates without EQU
1193RSI: DS 1
1194RDI: DS 1
1195ODDPAR: DS 1
1196EVEPAR: DS 1
1197 DS 5 ;MINUS,PLUS,NOT ZERO,ZERO,NOT CARRY
1198CY: DS 1
1199RAX: DS 1
1200STP: DS 1
1201RBX: DS 1
1202RDX: DS 1
1203RCX: DS 1
1204RBL: DS 1
1205RBH: DS 1
1206RDL: DS 1
1207RDH: DS 1
1208RGCL: DS 1
1209RCH: DS 1
1210RAL: DS 1
1211RIX: DS 1
1212RIY: DS 1
1213 \ No newline at end of file