mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-12-12 01:11:13 -08:00
4006 lines
58 KiB
NASM
4006 lines
58 KiB
NASM
; Seattle Computer Products 8086 Assembler version 2.44
|
||
; by Tim Paterson
|
||
; Runs on the 8086 under MS-DOS
|
||
|
||
;* * * * * * REVISION HISTORY * * * * * *
|
||
;
|
||
; 12/29/80 2.01 General release with 86-DOS version 0.34
|
||
; 02/22/81 2.10 Increased buffer size from 128 bytes to 1024 bytes
|
||
; 03/18/81 2.11 General cleanup and more documentation
|
||
; 03/24/81 2.20 Modify ESC handling for full 8087 operation
|
||
; 04/01/81 2.21 Fix date in HEX and PRN files; modify buffer handling
|
||
; 04/03/81 2.22 Fix 2.21 buffer handling
|
||
; 04/13/81 2.23 Re-open source file for listing to allow assembling CON:
|
||
; 04/28/81 2.24 Allow nested IFs
|
||
; 07/30/81 2.25 Add Intel string mnemonics; clean up a little
|
||
; 08/02/81 2.30 Re-write pass 2:
|
||
; Always report errors to console
|
||
; Exact byte lengths for HEX and PRN files
|
||
; 11/08/81 2.40 Add 8087 mnemonics; print full error messages;
|
||
; allow expressions with *, /, and ()
|
||
; 07/04/82 2.41 Fix Intel's 8087 "reverse-bit" bug; don't copy date
|
||
; 08/18/82 2.42 Increase stack from 80 to 256 (Damn! Overflowed again!)
|
||
; 01/05/83 2.43 Correct over-zealous optimization in 2.42
|
||
; 05/09/83 2.44 Add memory usage report
|
||
;
|
||
;* * * * * * * * * * * * * * * * * * * * *
|
||
|
||
SYMWID: EQU 5 ;5 symbols per line in dump
|
||
FCB: EQU 5CH
|
||
BUFSIZ: EQU 1024 ;Source code buffer
|
||
LSTBUFSIZ:EQU BUFSIZ ;List file buffer
|
||
HEXBUFSIZ:EQU 70 ;Hex file buffer (26*2 + 5*2 + 3 + EXTRA)
|
||
EOL: EQU 13 ;ASCII carriage return
|
||
OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS
|
||
|
||
;System call function codes
|
||
PRINTMES: EQU 9
|
||
OPEN: EQU 15
|
||
CLOSE: EQU 16
|
||
READ: EQU 20
|
||
SETDMA: EQU 26
|
||
MAKE: EQU 22
|
||
BLKWRT: EQU 40
|
||
|
||
;The following equates define some token values returned by GETSYM
|
||
UNDEFID:EQU 0 ;Undefined identifier (including no nearby RET)
|
||
CONST: EQU 1 ;Constant (including $)
|
||
REG: EQU 2 ;8-bit register
|
||
XREG: EQU 3 ;16-bit register (except segment registers)
|
||
SREG: EQU 4 ;Segment register
|
||
FREG: EQU 6 ;8087 floating point register
|
||
|
||
;Bits to build 8087 opcode table entries
|
||
ONEREG: EQU 40H ;Single ST register OK as operand
|
||
NEEDOP: EQU 80H ;Must have an operand
|
||
INTEGER:EQU 20H ;For integer operations
|
||
REAL: EQU 28H ;For real operations
|
||
EXTENDED EQU 10H ;For Long integers or Temporary real
|
||
MEMORY: EQU 18H ;For general memory operations
|
||
STACKOP:EQU 10H ;Two register arithmetic with pop
|
||
ARITH: EQU 8 ;Non-pop arithmetic operations
|
||
|
||
ORG 100H
|
||
PUT 100H
|
||
|
||
JMPS BEGIN
|
||
|
||
HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.44'
|
||
DB 13,10,'Copyright 1979-1983 by Seattle Computer Products, Inc.'
|
||
DB 13,10,13,10,'$'
|
||
|
||
BEGIN:
|
||
MOV SP,STACK
|
||
MOV DX,HEADER
|
||
MOV AH,PRINTMES
|
||
INT 33
|
||
MOV AL,[FCB+17]
|
||
MOV [SYMFLG],AL ;Save symbol table request flag
|
||
MOV SI,FCB+9 ;Point to file extension
|
||
LODB ;Get source drive letter
|
||
CALL CHKDSK ;Valid drive?
|
||
OR AL,AL
|
||
JZ DEFAULT ;If no extension, use existing drive spec
|
||
MOV [FCB],AL
|
||
DEFAULT:
|
||
LODB ;Get HEX file drive letter
|
||
CMP AL,'Z' ;Suppress HEX file?
|
||
JZ L0000
|
||
CALL CHKDSK
|
||
L0000:
|
||
MOV [HEXFCB],AL
|
||
LODB ;Get PRN file drive letter
|
||
MOV AH,0 ;Signal no PRN file
|
||
CMP AL,'Z' ;Suppress PRN file?
|
||
JZ NOPRN
|
||
CMP AL,'Y' ;Print errors only on console?
|
||
JZ NOPRN
|
||
MOV AH,2
|
||
CMP AL,'X' ;PRN file to console?
|
||
JZ NOPRN
|
||
MOV AH,4
|
||
CMP AL,'P' ;PRN file to printer?
|
||
JZ NOPRN
|
||
CALL CHKDSK
|
||
MOV AH,80H
|
||
NOPRN:
|
||
MOV [LSTFCB],AL
|
||
MOV [LSTDEV],AH ;Flag device for list ouput
|
||
MOV SI,EXTEND
|
||
MOV DI,FCB+9
|
||
MOVW
|
||
MOVB ;Set extension to ASM
|
||
MOVW ;Zero extent field
|
||
MOV DX,FCB
|
||
MOV AH,OPEN
|
||
INT 33
|
||
MOV BX,NOFILE
|
||
OR AL,AL
|
||
JZ $+5
|
||
JMP PRERR
|
||
MOV DX,HEXFCB
|
||
CALL MAKFIL
|
||
MOV DX,LSTFCB
|
||
CALL MAKFIL
|
||
XOR AX,AX
|
||
MOV [FCB+12],AX ;Zero CURRENT BLOCK field
|
||
MOV [FCB+32],AL ;Zero Next Record field
|
||
MOV [FCB+14],BUFSIZ ;Set record size
|
||
MOV [BUFPT],SRCBUF ;Initialize buffer pointer
|
||
MOV [CODE],START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE
|
||
MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE
|
||
XOR AX,AX
|
||
MOV [PC],AX ;DEFAULT PROGRAM COUNTER
|
||
MOV [BASE],AX ;POINTER TO ROOT OF ID TREE=NIL
|
||
MOV [RETPT],AX ;Pointer to last RET record
|
||
MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF
|
||
MOV [CHKLAB],AL ;LOOKUP ALL LABELS
|
||
DEC AX
|
||
MOV [LSTRET],AX ;Location of last RET
|
||
MOV AX,[6] ;HL=END OF MEMORY
|
||
MOV [HEAP],AX ;BACK END OF SYMBOL TABLE SPACE
|
||
MOV [BCOUNT],4 ;CODE BYTES PER RELOCATION BYTE
|
||
|
||
;Assemble each line of code
|
||
|
||
LOOP:
|
||
CALL NEXTCHR ;Get first character on line
|
||
CMP AL,1AH
|
||
JZ ENDJ
|
||
MOV AL,-1 ;Flag that no tokens have been read yet
|
||
MOV [SYM],AL
|
||
CALL ASMLIN ;Assemble the line
|
||
MOV AL,[SYM]
|
||
CMP AL,-1 ;Any tokens found on line?
|
||
JNZ L0002
|
||
CALL GETSYM ;If no tokens read yet, read first one
|
||
L0002:
|
||
CMP AL,';'
|
||
JZ ENDLN
|
||
CMP AL,EOL
|
||
JZ ENDLN
|
||
MOV AL,14H ;Garbage at end of line error
|
||
JP ENDLIN
|
||
ENDJ: JMP END
|
||
|
||
ENDLN:
|
||
XOR AL,AL ;Flag no errors on line
|
||
ENDLIN:
|
||
;AL = error code for line. Stack depth unknown
|
||
MOV SP,STACK
|
||
CALL NEXLIN
|
||
JP LOOP
|
||
|
||
NEXLIN:
|
||
MOV CH,0C0H ;Put end of line marker and error code (AL)
|
||
CALL PUTCD
|
||
CALL GEN1
|
||
MOV AL,[CHR]
|
||
GETEOL:
|
||
CMP AL,10
|
||
JZ RET
|
||
CMP AL,1AH
|
||
JZ ENDJ
|
||
CALL NEXTCHR ;Scan over comments for linefeed
|
||
JP GETEOL
|
||
|
||
ABORT:
|
||
MOV BX,NOMEM
|
||
PRERR:
|
||
MOV DX,BX
|
||
MOV AH,PRINTMES
|
||
INT 33
|
||
INT 32
|
||
|
||
MAKFIL:
|
||
MOV SI,DX
|
||
LODB ;Get drive select byte
|
||
CMP AL,20H ;If not valid, don't make file
|
||
JNC RET
|
||
MOV CX,4
|
||
MOV DI,SI
|
||
MOV SI,FCB+1
|
||
REP
|
||
MOVW ;Copy source file name
|
||
MOV AH,MAKE
|
||
INT 33
|
||
MOV [DI-9+14],1 ;Set record length to 1 byte
|
||
MOV BX,NOSPAC
|
||
OR AL,AL ;Success?
|
||
JNZ PRERR
|
||
RET
|
||
|
||
CHKDSK:
|
||
SUB AL,' ' ;If not present, set zero flag
|
||
JZ RET
|
||
SUB AL,20H
|
||
JZ DSKERR ;Must be in range A-O
|
||
CMP AL,'P'-'@'
|
||
JC RET
|
||
DSKERR:
|
||
MOV BX,BADDSK
|
||
JP PRERR
|
||
|
||
ERROR:
|
||
MOV AL,CL
|
||
JMP ENDLIN
|
||
|
||
NEXTCHR:
|
||
MOV SI,[BUFPT]
|
||
CMP SI,SRCBUF
|
||
JNZ GETCH
|
||
;Buffer empty so refill it
|
||
PUSH DX
|
||
PUSH AX ;AH must be saved
|
||
MOV DX,SI
|
||
MOV AH,SETDMA
|
||
INT 33
|
||
MOV DX,FCB
|
||
MOV AH,READ
|
||
INT 33
|
||
XCHG AX,DX ;Put error code in DL
|
||
POP AX ;Restore AH
|
||
MOV AL,DL ;Error code back in AL
|
||
POP DX
|
||
CMP AL,1
|
||
MOV AL,1AH ;Possibly signal End of File
|
||
JZ NOMOD ;If nothing read
|
||
GETCH:
|
||
LODB
|
||
CMP SI,SRCBUF+BUFSIZ
|
||
JNZ NOMOD
|
||
MOV SI,SRCBUF
|
||
NOMOD:
|
||
MOV [BUFPT],SI
|
||
MOV [CHR],AL
|
||
RET
|
||
|
||
|
||
MROPS:
|
||
|
||
; Get two operands and check for certain types, according to flag byte
|
||
; in CL. OP code in CH. Returns only if immediate operation.
|
||
|
||
PUSH CX ;Save type flags
|
||
CALL GETOP
|
||
PUSH DX ;Save first operand
|
||
CALL GETOP2
|
||
POP BX ;First op in BX, second op in DX
|
||
MOV AL,SREG ;Check for a segment register
|
||
CMP AL,BH
|
||
JZ SEGCHK
|
||
CMP AL,DH
|
||
JZ SEGCHK
|
||
MOV AL,CONST ;Check if the first operand is immediate
|
||
MOV CL,26
|
||
CMP AL,BH
|
||
JZ ERROR ;Error if so
|
||
POP CX ;Restore type flags
|
||
CMP AL,DH ;If second operand is immediate, then done
|
||
JZ RET
|
||
MOV AL,UNDEFID ;Check for memory reference
|
||
CMP AL,BH
|
||
JZ STORE ;Is destination memory?
|
||
CMP AL,DH
|
||
JZ LOAD ;Is source memory?
|
||
TEST CL,1 ;Check if register-to-register operation OK
|
||
MOV CL,27
|
||
JZ ERROR
|
||
MOV AL,DH
|
||
CMP AL,BH ;Registers must be of same length
|
||
RR:
|
||
MOV CL,22
|
||
JNZ ERROR
|
||
RR1:
|
||
AND AL,1 ;Get register length (1=16 bits)
|
||
OR AL,CH ;Or in to OP code
|
||
CALL PUT ;And write it
|
||
POP CX ;Dump return address
|
||
MOV AL,BL
|
||
ADD AL,AL ;Rotate register number into middle position
|
||
ADD AL,AL
|
||
ADD AL,AL
|
||
OR AL,0C0H ;Set register-to-register mode
|
||
OR AL,DL ;Combine with other register number
|
||
JMP PUT
|
||
|
||
SEGCHK:
|
||
;Come here if at least one operand is a segment register
|
||
POP CX ;Restore flags
|
||
TEST CL,8 ;Check if segment register OK
|
||
MOV CL,22
|
||
JZ ERR1
|
||
MOV CX,8E03H ;Segment register move OP code
|
||
MOV AL,UNDEFID
|
||
CMP AL,DH ;Check if source is memory
|
||
JZ LOAD
|
||
CMP AL,BH ;Check if destination is memory
|
||
JZ STORE
|
||
MOV AL,XREG
|
||
SUB AL,DH ;Check if source is 16-bit register
|
||
JZ RR ;If so, AL must be zero
|
||
MOV CH,8CH ;Change direction
|
||
XCHG DX,BX ;Flip which operand is first and second
|
||
MOV AL,XREG
|
||
SUB AL,DH ;Let RR perform finish the test
|
||
JP RR
|
||
|
||
STORE:
|
||
TEST CL,004H ;Check if storing is OK
|
||
JNZ STERR
|
||
XCHG DX,BX ;If so, flip operands
|
||
AND CH,0FDH ; and zero direction bit
|
||
LOAD:
|
||
MOV DH,25
|
||
CMP AL,BH ;Check if memory-to-memory
|
||
JZ MRERR
|
||
MOV AL,BH
|
||
CMP AL,REG ;Check if 8-bit operation
|
||
JNZ XRG
|
||
MOV DH,22
|
||
TEST CL,1 ;See if 8-bit operation is OK
|
||
JZ MRERR
|
||
XRG:
|
||
MOV AL,DL
|
||
SUB AL,6 ;Check for R/M mode 6 and register 0
|
||
OR AL,BL ; meaning direct load/store of accumulator
|
||
JNZ NOTAC
|
||
TEST CL,8 ;See if direct load/store of accumulator
|
||
JZ NOTAC ; means anything in this case
|
||
; Process direct load/store of accumulator
|
||
MOV AL,CH
|
||
AND AL,2 ;Preserve direction bit only
|
||
XOR AL,2 ; but flip it
|
||
OR AL,0A0H ;Combine with OP code
|
||
MOV CH,AL
|
||
MOV AL,BH ;Check byte/word operation
|
||
AND AL,1
|
||
OR AL,CH
|
||
POP CX ;Dump return address
|
||
JMP PUTADD ;Write the address
|
||
|
||
NOTAC:
|
||
MOV AL,BH
|
||
AND AL,1 ;Get byte/word bit
|
||
AND AL,CL ;But don't use it in word-only operations
|
||
OR AL,CH ;Combine with OP code
|
||
CALL PUT
|
||
MOV AL,BL
|
||
ADD AL,AL ;Rotate to middle position
|
||
ADD AL,AL
|
||
ADD AL,AL
|
||
OR AL,DL ;Combine register field
|
||
POP CX ;Dump return address
|
||
JMP PUTADD ;Write the address
|
||
|
||
STERR:
|
||
MOV DH,29
|
||
MRERR:
|
||
MOV CL,DH
|
||
|
||
ERR1: JMP ERROR
|
||
|
||
GETOP2:
|
||
;Get the second operand: look for a comma and drop into GETOP
|
||
MOV AL,[SYM]
|
||
CMP AL,','
|
||
MOV CL,21
|
||
JNZ ERR1
|
||
|
||
|
||
GETOP:
|
||
|
||
; Get one operand. Operand may be a memory reference in brackets, a register,
|
||
; or a constant. If a flag (such as "B" for byte operation) is encountered,
|
||
; it is noted and processing continues to find the operand.
|
||
;
|
||
; On exit, AL (=DH) has the type of operand. Other information depends
|
||
; on the actual operand:
|
||
;
|
||
; AL=DH=0 Memory Reference. DL has the address mode properly prepared in
|
||
; the 8086 R/M format (middle bits zero). The constant part of the address
|
||
; is in ADDR. If an undefined label needs to be added to this, a pointer to
|
||
; its information fields is in ALABEL, otherwise ALABEL is zero.
|
||
;
|
||
; AL=DH=1 Value. The constant part is in DATA. If an undefined label needs
|
||
; to be added to this, a pointer to its information fields is in DLABEL,
|
||
; otherwise DLABEL is zero. "$" and "RET" are in this class.
|
||
;
|
||
; AL=DH=2 8-bit Register. DL has the register number.
|
||
;
|
||
; AL=DH=3 16-bit Register. DL has the register number.
|
||
;
|
||
; AL=DH=4 Segment Register. DL has the register number.
|
||
|
||
CALL GETSYM
|
||
GETOP1:
|
||
;Enter here if we don't need a GETSYM first
|
||
CMP AL,'[' ;Memory reference?
|
||
JZ MEM
|
||
CMP AL,5 ;Flag ("B", "W", etc.)?
|
||
JZ FLG
|
||
CMP AL,REG ;8-Bit register?
|
||
JZ NREG
|
||
CMP AL,XREG ;16-Bit register?
|
||
JZ NREG
|
||
CMP AL,SREG ;Segment register?
|
||
JZ NREG
|
||
VAL: ;Must be immediate
|
||
XOR AL,AL ;No addressing modes allowed
|
||
VAL1:
|
||
CALL GETVAL
|
||
MOV AX,[CON] ;Defined part
|
||
MOV [DATA],AX
|
||
MOV AX,[UNDEF] ;Undefined part
|
||
MOV [DLABEL],AX
|
||
MOV DL,CH
|
||
MOV DH,CONST
|
||
MOV AL,DH
|
||
RET
|
||
NREG:
|
||
PUSH DX
|
||
CALL GETSYM
|
||
POP DX
|
||
MOV AL,DH
|
||
RET
|
||
MEM:
|
||
CALL GETSYM
|
||
MOV AL,1
|
||
CALL GETVAL
|
||
MOV AL,[SYM]
|
||
CMP AL,']'
|
||
MOV CL,24
|
||
JNZ ERR1
|
||
CALL GETSYM
|
||
MOV BX,[CON]
|
||
MOV [ADDR],BX
|
||
MOV BX,[UNDEF]
|
||
MOV [ALABEL],BX
|
||
MOV DL,CH
|
||
MOV DH,UNDEFID
|
||
MOV AL,DH
|
||
RET
|
||
FLG:
|
||
CMP DL,[MAXFLG] ;Invalid flag for this operation?
|
||
MOV CL,27H
|
||
JG ERR1
|
||
CALL GETSYM
|
||
CMP AL,','
|
||
JZ GETOP
|
||
JP GETOP1
|
||
|
||
|
||
GETVAL:
|
||
|
||
; Expression analyzer. On entry, if AL=0 then do not allow base or index
|
||
; registers. If AL=1, we are analyzing a memory reference, so allow base
|
||
; and index registers, and compute addressing mode when done. The constant
|
||
; part of the expression will be found in CON. If an undefined label is to
|
||
; be added to this, a pointer to its information fields will be found in
|
||
; UNDEF.
|
||
|
||
MOV AH,AL ;Flag is kept in AH
|
||
MOV [UNDEF],0
|
||
MOV AL,[SYM]
|
||
CALL EXPRESSION
|
||
MOV [CON],DX
|
||
MOV AL,AH
|
||
MOV CH,0 ;Initial mode
|
||
TEST AL,10H ;Test INDEX bit
|
||
RCL AL ;BASE bit (zero flag not affected)
|
||
JZ NOIND ;Jump if not indexed, with BASE bit in carry
|
||
CMC
|
||
RCL CH ;Rotate in BASE bit
|
||
RCL AL ;BP bit
|
||
RCL CH
|
||
RCL AL ;DI bit
|
||
RCL CH ;The low 3 bits now have indexing mode
|
||
MODE:
|
||
OR CH,080H ;If undefined label, force 16-bit displacement
|
||
TEST [UNDEF],-1
|
||
JNZ RET
|
||
MOV BX,[CON]
|
||
MOV AL,BL
|
||
CBW ;Extend sign
|
||
CMP AX,BX ;Is it a signed 8-bit number?
|
||
JNZ RET ;If not, use 16-bit displacement
|
||
AND CH,07FH ;Reset 16-bit displacement
|
||
OR CH,040H ;Set 8-bit displacement
|
||
OR BX,BX
|
||
JNZ RET ;Use it if not zero displacement
|
||
AND CH,7 ;Specify no displacement
|
||
CMP CH,6 ;Check for BP+0 addressing mode
|
||
JNZ RET
|
||
OR CH,040H ;If BP+0, use 8-bit displacement
|
||
RET
|
||
|
||
NOIND:
|
||
MOV CH,6 ;Try direct address mode
|
||
JNC RET ;If no base register, that's right
|
||
RCL AL ;Check BP bit
|
||
JC MODE
|
||
INC CH ;If not, must be BX
|
||
JP MODE
|
||
|
||
EXPRESSION:
|
||
;Analyze arbitrary expression. Flag byte in AH.
|
||
;On exit, AL has type byte: 0=register or undefined label
|
||
MOV CH,-1 ;Initial type
|
||
MOV DI,DX
|
||
XOR DX,DX ;Initial value
|
||
CMP AL,'+'
|
||
JZ PLSMNS
|
||
CMP AL,'-'
|
||
JZ PLSMNS
|
||
MOV CL,'+'
|
||
PUSH DX
|
||
PUSH CX
|
||
MOV DX,DI
|
||
JP OPERATE
|
||
PLSMNS:
|
||
MOV CL,AL
|
||
PUSH DX
|
||
PUSH CX
|
||
OR AH,4 ;Flag that a sign was found
|
||
CALL GETSYM
|
||
OPERATE:
|
||
CALL TERM
|
||
POP CX ;Recover operator
|
||
POP BX ;Recover current value
|
||
XCHG DX,BX
|
||
AND CH,AL
|
||
OR AL,AL ;Is it register or undefined label?
|
||
JZ NOCON ;If so, then no constant part
|
||
CMP CL,"-" ;Subtract it?
|
||
JNZ ADD
|
||
NEG BX
|
||
ADD:
|
||
ADD DX,BX
|
||
NEXTERM:
|
||
MOV AL,[SYM]
|
||
CMP AL,'+'
|
||
JZ PLSMNS
|
||
CMP AL,'-'
|
||
JZ PLSMNS
|
||
MOV AL,CH
|
||
RET
|
||
NOCON:
|
||
CMP CL,"-"
|
||
JNZ NEXTERM
|
||
BADOP:
|
||
MOV CL,5
|
||
JMP ERROR
|
||
|
||
TERM:
|
||
CALL FACTOR
|
||
MULOP:
|
||
PUSH DX ;Save value
|
||
PUSH AX ;Save type
|
||
CALL GETSYM
|
||
POP CX
|
||
CMP AL,"*"
|
||
JZ GETFACT
|
||
CMP AL,"/"
|
||
JNZ ENDTERM
|
||
GETFACT:
|
||
OR CL,CL ;Can we operate on this type?
|
||
JZ BADOP
|
||
PUSH AX ;Save operator
|
||
CALL GETSYM ;Get past operator
|
||
CALL FACTOR
|
||
OR AL,AL
|
||
JZ BADOP
|
||
POP CX ;Recover operator
|
||
POP BP ;And current value
|
||
XCHG AX,BP ;Save AH in BP
|
||
CMP CL,"/" ;Do we divide?
|
||
JNZ DOMUL
|
||
OR DX,DX ;Dividing by zero?
|
||
MOV CL,29H
|
||
JZ ERR2
|
||
MOV BX,DX
|
||
XOR DX,DX ;Make 32-bit dividend
|
||
DIV AX,BX
|
||
JMPS NEXFACT
|
||
DOMUL:
|
||
MUL AX,DX
|
||
NEXFACT:
|
||
MOV DX,AX ;Result in DX
|
||
XCHG AX,BP ;Restore flags to AH
|
||
MOV AL,-1 ;Indicate a number
|
||
JMPS MULOP
|
||
ENDTERM:
|
||
POP DX
|
||
MOV AL,CL
|
||
RET
|
||
|
||
FACTOR:
|
||
MOV AL,[SYM]
|
||
CMP AL,CONST
|
||
JZ RET
|
||
CMP AL,UNDEFID
|
||
JZ UVAL
|
||
CMP AL,"("
|
||
JZ PAREN
|
||
CMP AL,'"'
|
||
JZ STRING
|
||
CMP AL,"'"
|
||
JZ STRING
|
||
CMP AL,XREG ;Only 16-bit register may index
|
||
MOV CL,20
|
||
JNZ ERR2
|
||
TEST AH,1 ;Check to see if indexing is OK
|
||
MOV CL,1
|
||
JZ ERR2
|
||
MOV AL,DL
|
||
MOV CL,3
|
||
SUB AL,3 ;Check for BX
|
||
JZ BXJ
|
||
SUB AL,2 ;Check for BP
|
||
JZ BPJ
|
||
DEC AL ;Check for SI
|
||
MOV CL,4
|
||
JZ SIJ
|
||
DEC AL ;Check for DI
|
||
JZ DIJ
|
||
MOV CL,2 ;Invalid base/index register
|
||
ERR2: JMP ERROR
|
||
|
||
DIJ:
|
||
OR AH,20H ;Flag seeing index register DI
|
||
SIJ:
|
||
TEST AH,10H ;Check if already seen index register
|
||
JNZ ERR2
|
||
OR AH,10H ;Flag seeing index register
|
||
RET
|
||
|
||
BPJ:
|
||
OR AH,40H ;Flag seeing base register BP
|
||
BXJ:
|
||
TEST AH,80H ;Check if already seen base register
|
||
JNZ ERR2
|
||
OR AH,80H ;Flag seeing base register
|
||
RET
|
||
|
||
PAREN:
|
||
CALL GETSYM ;Eat the "("
|
||
CALL EXPRESSION
|
||
CMP B,[SYM],")" ;Better have closing paren
|
||
MOV CL,20
|
||
JNZ ERR30
|
||
RET
|
||
|
||
UVAL:
|
||
MOV CL,6
|
||
TEST AH,8 ;Check if undefined label has been seen
|
||
JNZ ERR30
|
||
OR AH,8 ;Flag seeing undefined label
|
||
MOV [UNDEF],BX
|
||
RET
|
||
|
||
ERR30: JMP ERROR
|
||
|
||
STRING:
|
||
MOV CH,AL
|
||
MOV AL,[CHR]
|
||
CMP AL,CH
|
||
MOV CL,35
|
||
MOV DL,AL
|
||
MOV DH,0
|
||
JNZ L0003
|
||
CALL ZERLEN
|
||
L0003:
|
||
CALL GETCHR
|
||
MOV CL,37
|
||
TEST AH,2
|
||
JZ ERR30
|
||
TEST AH,4
|
||
MOV CL,38
|
||
JNZ ERR30
|
||
STRGDAT:
|
||
MOV AL,DL
|
||
CMP AL,EOL
|
||
MOV CL,39
|
||
JZ ERR30
|
||
CALL PUT
|
||
MOV AL,[DATSIZ]
|
||
OR AL,AL
|
||
JNZ BYTSIZ
|
||
MOV AL,DH
|
||
CALL PUT
|
||
BYTSIZ:
|
||
MOV AL,[CHR]
|
||
MOV DL,AL
|
||
CALL GETCHR
|
||
JP STRGDAT
|
||
|
||
ZERLEN:
|
||
CALL NEXTCHR
|
||
CMP AL,CH
|
||
JNZ ERR30
|
||
RET
|
||
|
||
GETCHR:
|
||
CALL NEXTCHR
|
||
CMP AL,CH
|
||
JNZ RET
|
||
CALL NEXTCHR
|
||
CMP AL,CH
|
||
JZ RET
|
||
POP BX ;Kill return address to STRGDAT loop
|
||
MOV AL,-1 ;Flag type as constant
|
||
RET
|
||
|
||
|
||
GETSYM:
|
||
|
||
; The lexical scanner. Used only in the operand field. Returns with the token
|
||
; in SYM and AL, sometimes with additional info in BX or DX.
|
||
;
|
||
; AL=SYM=0 Undefined label. BX has pointer to information fields.
|
||
;
|
||
; AL=SYM=1 Constant (or defined label). DX has value.
|
||
;
|
||
; AL=SYM=2,3,4 8-bit register, 16-bit register, or segment register,
|
||
; respectively. DL has register number.
|
||
;
|
||
; AL=SYM=5 A mode flag (such as "B" for byte operation). Type of flag in DL
|
||
; and also stored in FLAG: -1=no flags, 0=B, 1=W, 2=S, 3=L, 4=T.
|
||
;
|
||
; AL=SYM=6 8087 floating point register, ST(n) or ST. DL has register number.
|
||
;
|
||
; All other values are the ASCII code of the character. Note that this may
|
||
; never be a letter or number.
|
||
|
||
PUSH AX ;Save AH
|
||
CALL GETSY
|
||
POP AX
|
||
MOV AL,[SYM]
|
||
RET
|
||
|
||
SCANB:
|
||
MOV AL,[CHR]
|
||
SCANT:
|
||
CMP AL,' '
|
||
JZ NEXB
|
||
CMP AL,9
|
||
JNZ RET
|
||
NEXB:
|
||
CALL NEXTCHR
|
||
JP SCANT
|
||
|
||
DOLLAR:
|
||
MOV DX,[OLDPC]
|
||
MOV AL,CONST
|
||
MOV [SYM],AL
|
||
NEXTCHJ:
|
||
JMP NEXTCHR
|
||
|
||
GETSY:
|
||
CALL SCANB
|
||
CMP AL,'$'
|
||
JZ DOLLAR
|
||
MOV [SYM],AL
|
||
OR AL,20H
|
||
CMP AL,'z'+1
|
||
JNC NEXTCHJ
|
||
CMP AL,'a'
|
||
JC $+5
|
||
JMP LETTER
|
||
CMP AL,'9'+1
|
||
JNC NEXTCHJ
|
||
CMP AL,'0'
|
||
JC NEXTCHJ
|
||
MOV BX,SYM
|
||
MOV B,[BX],CONST
|
||
CALL READID
|
||
DEC BX
|
||
MOV AL,[BX]
|
||
MOV CL,7
|
||
MOV BX,0
|
||
CMP AL,'h'
|
||
JNZ $+5
|
||
JMP HEX
|
||
INC CL
|
||
MOV [IX],ID
|
||
DEC:
|
||
MOV SI,[IX]
|
||
MOV AL,[SI]
|
||
INC [IX]
|
||
CMP AL,'9'+1
|
||
JC $+5
|
||
JMP ERROR
|
||
SUB AL,'0'
|
||
MOV DX,BX
|
||
SHL BX
|
||
SHL BX
|
||
ADD BX,DX
|
||
SHL BX
|
||
MOV DL,AL
|
||
MOV DH,0
|
||
ADD BX,DX
|
||
DEC CH
|
||
JNZ DEC
|
||
XCHG DX,BX
|
||
RET
|
||
|
||
HEX:
|
||
MOV DX,ID
|
||
DEC CH
|
||
HEX1:
|
||
MOV SI,DX
|
||
LODB
|
||
INC DX
|
||
SUB AL,'0'
|
||
CMP AL,10
|
||
JC GOTIT
|
||
CMP AL,'g'-'0'
|
||
JNC ERR4
|
||
SUB AL,'a'-10-'0'
|
||
GOTIT:
|
||
SHL BX
|
||
SHL BX
|
||
SHL BX
|
||
SHL BX
|
||
ADD BL,AL
|
||
DEC CH
|
||
JNZ HEX1
|
||
XCHG DX,BX
|
||
RET
|
||
|
||
ERR4: JMP ERROR
|
||
|
||
GETLET:
|
||
CALL SCANB
|
||
CMP AL,EOL
|
||
STC
|
||
JZ RET
|
||
CMP AL,';'
|
||
STC
|
||
JZ RET
|
||
MOV CL,10
|
||
OR AL,20H
|
||
CMP AL,'a'
|
||
JC ERR4
|
||
CMP AL,'z'+1
|
||
JNC ERR4
|
||
READID:
|
||
MOV BX,ID
|
||
MOV CH,0
|
||
MOREID:
|
||
MOV [BX],AL
|
||
INC CH
|
||
INC BX
|
||
CALL NEXTCHR
|
||
CMP AL,'0'
|
||
JC NOMORE
|
||
OR AL,20H
|
||
CMP AL,'z'+1
|
||
JNC NOMORE
|
||
CMP AL,'9'+1
|
||
JC MOREID
|
||
CMP AL,'a'
|
||
JNC MOREID
|
||
NOMORE:
|
||
MOV CL,AL
|
||
MOV AL,CH
|
||
MOV [LENID],AL
|
||
OR AL,AL
|
||
MOV AL,CL
|
||
RET
|
||
|
||
LETTER:
|
||
CALL READID
|
||
MOV AL,CH
|
||
DEC AL
|
||
JNZ NOFLG
|
||
MOV AL,[ID]
|
||
MOV CX,5
|
||
MOV DI,FLGTAB
|
||
UP
|
||
REPNE
|
||
SCAB ;See if one of B,W,S,L,T
|
||
JZ SAVFLG ;Go save flag
|
||
XOR AL,AL
|
||
MOV CH,[LENID]
|
||
NOFLG:
|
||
DEC AL
|
||
PUSH BX
|
||
JNZ L0004
|
||
CALL REGCHK
|
||
L0004:
|
||
POP BX
|
||
MOV AL,DH
|
||
JZ SYMSAV
|
||
CALL LOOKRET
|
||
SYMSAV:
|
||
MOV [SYM],AL
|
||
RET
|
||
|
||
SAVFLG:
|
||
MOV DL,CL ;Need flag type in DL
|
||
XCHG [FLAG],CL
|
||
CMP CL,-1
|
||
MOV CL,32
|
||
MOV AL,5
|
||
JZ SYMSAV
|
||
ERRJ3: JMP ERROR
|
||
|
||
FLGTAB: DB "tlswb"
|
||
|
||
FPREG:
|
||
;Have detected "ST" for 8087 floating point stack register
|
||
MOV DL,0 ;Default is ST(0)
|
||
CALL SCANB ;Get next character
|
||
CMP AL,"(" ;Specifying register number?
|
||
JNZ HAVREG
|
||
;Get register number
|
||
CALL NEXTCHR ;Skip over the "("
|
||
CALL GETOP ;A little recursion never hurt anybody
|
||
CMP AL,CONST ;Better have found a constant
|
||
MOV CL,20 ;Operand error if not
|
||
JNZ ERRJ3
|
||
CMP [DLABEL],0 ;Constant must be defined
|
||
MOV CL,30
|
||
JNZ ERRJ3
|
||
MOV DX,[DATA] ;Get constant
|
||
CMP DX,7 ;Constant must be in range 0-7
|
||
MOV CL,31
|
||
JA ERRJ3
|
||
MOV AL,[SYM]
|
||
CMP AL,")"
|
||
MOV CL,24
|
||
JNZ ERRJ3
|
||
HAVREG:
|
||
MOV DH,FREG
|
||
XOR AL,AL ;Zero set means register found
|
||
RET
|
||
|
||
REGCHK:
|
||
MOV BX,ID
|
||
CMP [BX],"s"+7400H ;"st"
|
||
JZ FPREG
|
||
MOV CL,[BX]
|
||
INC BX
|
||
MOV AL,[BX]
|
||
MOV BX,REGTAB
|
||
MOV DH,XREG
|
||
MOV DL,0
|
||
CMP AL,'x'
|
||
JZ SCANREG
|
||
MOV DH,REG
|
||
CMP AL,'l'
|
||
JZ SCANREG
|
||
MOV DL,4
|
||
CMP AL,'h'
|
||
JZ SCANREG
|
||
MOV DH,SREG
|
||
MOV DL,0
|
||
MOV BX,SEGTAB
|
||
CMP AL,'s'
|
||
JZ SCANREG
|
||
MOV DH,XREG
|
||
CMP AL,'p'
|
||
JZ PREG
|
||
CMP AL,'i'
|
||
JNZ RET
|
||
MOV DL,6
|
||
MOV AL,CL
|
||
CMP AL,'s'
|
||
JZ RET
|
||
INC DL
|
||
CMP AL,'d'
|
||
RET
|
||
PREG:
|
||
MOV DL,4
|
||
MOV AL,CL
|
||
CMP AL,'s'
|
||
JZ RET
|
||
INC DL
|
||
CMP AL,'b'
|
||
RET
|
||
SCANREG:
|
||
MOV AL,CL
|
||
MOV CX,4
|
||
UP
|
||
MOV DI,BX
|
||
REPNZ
|
||
SCAB
|
||
MOV BX,DI
|
||
JNZ RET
|
||
MOV AL,CL
|
||
ADD AL,DL
|
||
MOV DL,AL
|
||
XOR AL,AL
|
||
RET
|
||
|
||
REGTAB: DB 'bdca'
|
||
|
||
SEGTAB: DB 'dsce'
|
||
|
||
LOOK:
|
||
MOV CH,[BX]
|
||
INC BX
|
||
MOV DX,ID
|
||
CALL CPSLP
|
||
JZ RET
|
||
XOR AL,80H
|
||
ROL AL ;Make end-of-symbol bit least significant
|
||
MOV CL,AL
|
||
DEC BX
|
||
MOV AL,[BX]
|
||
XOR AL,80H
|
||
ROL AL
|
||
CMP AL,CL
|
||
JNC SMALL
|
||
INC CH
|
||
INC CH
|
||
SMALL:
|
||
MOV DL,CH
|
||
MOV DH,0
|
||
ADD BX,DX
|
||
MOV DX,[BX]
|
||
INC BX
|
||
MOV AL,DL
|
||
OR AL,DH
|
||
STC
|
||
JZ RET
|
||
XCHG DX,BX
|
||
JP LOOK
|
||
|
||
LOOKRET:
|
||
MOV AL,CH
|
||
CMP AL,3 ;RET has 3 letters
|
||
JNZ LOOKUP
|
||
DEC BX
|
||
OR B,[BX],080H
|
||
MOV DX,RETSTR+2
|
||
CHKRET:
|
||
MOV SI,DX
|
||
LODB
|
||
CMP AL,[BX]
|
||
JNZ LOOKIT
|
||
DEC BX
|
||
DEC DX
|
||
DEC CH
|
||
JNZ CHKRET
|
||
MOV DX,[LSTRET]
|
||
MOV AL,DL
|
||
AND AL,DH
|
||
INC AL
|
||
JZ ALLRET
|
||
MOV BX,[PC]
|
||
SUB BX,DX
|
||
MOV AL,BL
|
||
CBW
|
||
CMP AX,BX ;Signed 8-bit number?
|
||
MOV AL,1
|
||
JZ RET
|
||
ALLRET:
|
||
MOV BX,[RETPT]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
MOV AL,0
|
||
JNZ RET
|
||
MOV BX,[HEAP]
|
||
DEC BX
|
||
DEC BX
|
||
DEC BX
|
||
MOV [HEAP],BX
|
||
XOR AL,AL
|
||
MOV [BX],AL
|
||
MOV [RETPT],BX
|
||
RET
|
||
|
||
LOOKUP:
|
||
DEC BX
|
||
OR B,[BX],080H
|
||
LOOKIT:
|
||
MOV BX,[BASE]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
JZ EMPTY
|
||
CALL LOOK
|
||
JC ENTER
|
||
MOV DX,4
|
||
ADD BX,DX
|
||
MOV AL,[BX]
|
||
OR AL,AL
|
||
JZ RET
|
||
INC BX
|
||
MOV DX,[BX]
|
||
INC BX
|
||
RET
|
||
|
||
ENTER:
|
||
PUSH BX ;Save pointer to link field
|
||
CALL CREATE ;Add the node
|
||
POP SI
|
||
MOV [SI-1],DX ;Link new node
|
||
RET ;Zero was set by CREATE
|
||
|
||
EMPTY:
|
||
CALL CREATE
|
||
MOV [BASE],DX
|
||
RET
|
||
|
||
|
||
CREATE:
|
||
|
||
; Add a new node to the identifier tree. The identifier is at ID with
|
||
; bit 7 of the last character set to one. The length of the identifier is
|
||
; in LENID, which is ID-1.
|
||
;
|
||
; Node format:
|
||
; 1. Length of identifier (1 byte)
|
||
; 2. Identifier (1-80 bytes)
|
||
; 3. Left link (2-byte pointer to alphabetically smaller identifiers)
|
||
; 4. Right link (0 if none larger)
|
||
; 5. Data field:
|
||
; a. Defined flag (0=undefined, 1=defined)
|
||
; b. Value (2 bytes)
|
||
;
|
||
; This routine returns with AL=zero and zero flag set (which indicates
|
||
; on return from LOOKUP that it has not yet been defined), DX points
|
||
; to start of new node, and BX points to data field of new node.
|
||
|
||
MOV AL,[LENID]
|
||
ADD AL,8 ;Storage needed for the node
|
||
MOV BX,[HEAP]
|
||
MOV DL,AL
|
||
MOV DH,0
|
||
SUB BX,DX ;Heap grows downward
|
||
MOV [HEAP],BX
|
||
XCHG DX,BX
|
||
MOV BX,[CODE] ;Check to make sure there's enough
|
||
CMP BX,DX
|
||
JB $+5
|
||
JMP ABORT
|
||
PUSH DX
|
||
MOV BX,LENID
|
||
MOV CL,[BX]
|
||
INC CL
|
||
MOV CH,0
|
||
UP
|
||
MOV SI,BX
|
||
MOV DI,DX
|
||
REP
|
||
MOVB ;Move identifier and length into node
|
||
MOV DX,DI
|
||
MOV BX,SI
|
||
MOV CH,4
|
||
XCHG DX,BX
|
||
NILIFY:
|
||
MOV [BX],CL ;Zero left and right links
|
||
INC BX
|
||
DEC CH
|
||
JNZ NILIFY
|
||
XOR AL,AL ;Set zero flag
|
||
MOV [BX],AL ;Zero defined flag
|
||
POP DX ;Restore pointer to node
|
||
RET
|
||
|
||
CPSLP:
|
||
MOV SI,DX
|
||
LODB
|
||
CMP AL,[BX]
|
||
LAHF
|
||
INC DX
|
||
INC BX
|
||
SAHF
|
||
JNZ RET
|
||
DEC CH
|
||
JNZ CPSLP
|
||
RET
|
||
|
||
GETLAB:
|
||
MOV BX,0
|
||
MOV [LABPT],BX
|
||
MOV B,[FLAG],-1
|
||
MOV DH,0
|
||
MOV AL,[CHR]
|
||
CMP AL,' '+1
|
||
JC NOT1
|
||
OR DH,001H
|
||
NOT1:
|
||
CALL GETLET
|
||
JC RET
|
||
CMP AL,':'
|
||
JNZ LABCHK
|
||
CALL NEXTCHR
|
||
JP LABEL
|
||
LABCHK:
|
||
OR AL,AL
|
||
TEST DH,001H
|
||
JZ RET
|
||
LABEL:
|
||
MOV AL,[CHKLAB]
|
||
OR AL,AL
|
||
JZ $+5
|
||
JMP GETLET
|
||
CALL LOOKUP
|
||
MOV CL,11
|
||
JNZ ERR5
|
||
MOV DX,[PC]
|
||
MOV B,[BX],1
|
||
INC BX
|
||
MOV [BX],DX
|
||
MOV [LABPT],BX
|
||
JMP GETLET
|
||
|
||
ERR5: JMP ERROR
|
||
|
||
ASMLIN:
|
||
MOV B,[MAXFLG],1 ;Allow only B and W flags normally
|
||
MOV BX,[PC]
|
||
MOV [OLDPC],BX
|
||
CALL GETLAB
|
||
JNC $+5
|
||
JMP ENDLN
|
||
MOV BX,LENID
|
||
MOV AL,[BX]
|
||
MOV CL,12
|
||
SUB AL,2
|
||
MOV CH,AL
|
||
JC ERR5
|
||
INC BX
|
||
CMP B,[BX],"f" ;See if an 8087 mnemonic
|
||
JZ NDPOP
|
||
CMP AL,5
|
||
JNC ERR5
|
||
MOV AL,[BX]
|
||
SUB AL,'a'
|
||
MOV CL,AL
|
||
ADD AL,AL
|
||
ADD AL,AL
|
||
ADD AL,CL
|
||
ADD AL,CH
|
||
ADD AL,AL
|
||
MOV BX,OPTAB
|
||
MOV DL,AL
|
||
MOV DH,0
|
||
ADD BX,DX
|
||
MOV BX,[BX]
|
||
INC CH
|
||
MOV CL,CH
|
||
MOV AH,[BX]
|
||
INC BX
|
||
OR AH,AH
|
||
JZ OPERR
|
||
FINDOP:
|
||
MOV CH,CL
|
||
MOV DX,ID+1
|
||
XCHG AX,BP ;Save count of opcodes in BP
|
||
CALL CPSLP
|
||
JZ HAVOP
|
||
XCHG AX,BP
|
||
MOV DH,0
|
||
MOV DL,CH
|
||
INC DX
|
||
INC DX
|
||
ADD BX,DX
|
||
DEC AH
|
||
JNZ FINDOP
|
||
OPERR:
|
||
MOV CL,12
|
||
JMP ERROR
|
||
|
||
HAVOP:
|
||
MOV AL,[BX+2] ;Get opcode
|
||
JMP [BX]
|
||
|
||
NDPOP: ;First letter is "F" so must be 8087 opcode ("Numeric Data Processor")
|
||
MOV B,[MAXFLG],4 ;Allow all type flags
|
||
INC BX
|
||
CMP B,[BX],"n" ;"No-wait" form?
|
||
MOV AH,0
|
||
JNZ SAVNFLG
|
||
MOV AH,1
|
||
DEC AL
|
||
INC BX ;Skip over the "N"
|
||
SAVNFLG:
|
||
MOV [NOWAIT],AH ;0 for wait, 1 for no wait
|
||
CMP AL,1
|
||
JB OPERR ;Not enough char left for valid opcode?
|
||
CMP AL,5
|
||
JA OPERR ;Too many?
|
||
CBW
|
||
XCHG AX,DX ;Save length in DX
|
||
MOV SI,DX
|
||
OR B,[SI+BX],80H ;Set high bit of last character
|
||
MOV AL,[BX] ;Get first char of opcode
|
||
INC BX
|
||
SUB AL,"a"
|
||
JB TRY2XM1 ;Go see if opcode starts with "2"
|
||
CMP AL,"z"-"a"
|
||
JA OPERR
|
||
CBW
|
||
SHL AX ;Double to index into address table
|
||
XCHG AX,SI ;Put in index register
|
||
MOV DI,[SI+NDPTAB] ;Get start of opcode table for this letter
|
||
LOOKNDP:
|
||
MOV AH,[DI] ;Number of opcodes starting with this letter
|
||
OR AH,AH
|
||
JZ OPERR ;Any start with this letter?
|
||
FNDNDP:
|
||
INC DI
|
||
MOV SI,BX ;Pointer to start of opcode
|
||
MOV CX,DX ;Get length of opcode
|
||
REPE
|
||
CMPB ;Compare opcode to table entry
|
||
JZ HAVNDP
|
||
DEC DI ;Back up in case that was last letter
|
||
MOV AL,80H ;Look for char with high bit set
|
||
ENDOP:
|
||
SCASB
|
||
JA ENDOP
|
||
INC DI ;Skip over info about opcode
|
||
DEC AH
|
||
JNZ FNDNDP
|
||
OPERRJ: JP OPERR
|
||
|
||
TRY2XM1:
|
||
CMP AL,"2"-"a"
|
||
JNZ OPERR
|
||
MOV DI,XM1
|
||
JP LOOKNDP
|
||
|
||
SPECIALOP:
|
||
AND AL,7 ;Mask to special op number
|
||
JZ FWAIT ;If zero, go handle FWAIT
|
||
;Handle FNOP
|
||
CMP B,[NOWAIT],0 ;Was "N" present (If not opcode was "FOP")
|
||
JZ OPERR
|
||
MOV AL,9BH ;Need Wait opcode after all
|
||
CALL PUT
|
||
MOV AL,0D9H
|
||
CALL PUT
|
||
MOV AL,0D0H
|
||
JMP PUT
|
||
|
||
FWAIT:
|
||
CMP B,[NOWAIT],0 ;"FNWAIT" not legal
|
||
JNZ OPERRJ
|
||
RET ;Nothing to do - "WAIT" already sent
|
||
|
||
HAVNDP:
|
||
MOV SI,DI
|
||
CMP B,[NOWAIT],0
|
||
JNZ NWAIT
|
||
MOV AL,9BH ;Wait opcode
|
||
CALL PUT
|
||
NWAIT:
|
||
LODW ;Get opcode info
|
||
TEST AL,0F8H ;Any operand bits set?
|
||
JZ NOOPS ;If no operands, output code
|
||
TEST AL,78H ;Special case?
|
||
JZ SPECIALOP
|
||
PUSH AX
|
||
CALL GETSYM ;See if any operands
|
||
POP CX
|
||
CMP AL,";"
|
||
JZ NOOPCHK
|
||
CMP AL,EOL
|
||
JZ NOOPCHK
|
||
CMP AL,FREG ;Is it 8087 register?
|
||
JNZ MEMOP
|
||
XCHG AX,CX
|
||
TEST AL,ONEREG ;One register OK as operand?
|
||
JNZ PUTREG ;Yes - save it
|
||
TEST AL,20H ;Memory-only operation?
|
||
MOV CL,20
|
||
JNZ ERRJ4
|
||
TEST AL,18H ;Two-register operation?
|
||
JPE ERRJ4 ;Must be exactly one bit set
|
||
PUSH DX ;Save register number
|
||
PUSH AX ;Save opcode
|
||
CALL GETSYM
|
||
CMP AL,","
|
||
MOV CL,15H
|
||
JNZ ERRJ4
|
||
CALL GETSYM
|
||
MOV CL,20
|
||
CMP AL,FREG
|
||
JNZ ERRJ4
|
||
POP AX
|
||
POP BX
|
||
XOR AL,2 ;Flip "POP" bit
|
||
AND AL,0FBH ;Reset direction bit to ST(0)
|
||
OR BL,BL ;Is first register ST(0)?
|
||
JZ ST0DEST
|
||
XCHG DX,BX
|
||
OR BL,BL ;One of these must be ST(0)
|
||
JNZ ERRJ4
|
||
XOR AL,4 ;Flip direction
|
||
JMPS PUTREG
|
||
ST0DEST:
|
||
TEST AL,2 ;Is POP bit set?
|
||
JNZ ERRJ4 ;Don't allow destination ST(0) then pop
|
||
PUTREG:
|
||
AND AH,0F8H ;Zero out register field
|
||
OR AH,DL
|
||
OR AH,0C0H
|
||
PUSH AX
|
||
CALL GETSYM ;Get to next symbol
|
||
POP AX
|
||
JMPS NOOPS
|
||
|
||
NOOPCHK:
|
||
XCHG AX,CX
|
||
TEST AL,80H ;Is no operands OK?
|
||
MOV CL,20
|
||
JNZ ERRJ4
|
||
NOOPS:
|
||
;First test for FDIV or FSUB and reverse "R" bit if "D" bit is set
|
||
PUSH AX
|
||
AND AX,0E005H
|
||
CMP AX,0E004H
|
||
POP AX
|
||
JNZ NOREV
|
||
XOR AH,8 ;Reverse "R" bit
|
||
NOREV:
|
||
AND AL,7
|
||
OR AL,0D8H ;ESC hook
|
||
CALL PUT
|
||
MOV AL,AH
|
||
JMP PUT
|
||
|
||
BADFLAG:
|
||
MOV CL,20H
|
||
ERRJ4: JMP ERROR
|
||
|
||
MEMOP:
|
||
PUSH CX ;Save opcode
|
||
CALL GETOP1 ;Get memory operand
|
||
CMP AL,UNDEFID ;Is it?
|
||
MOV CL,20
|
||
JNZ ERRJ4
|
||
POP AX
|
||
TEST AL,20H ;Does it have memory format field?
|
||
JNZ GETFORMAT
|
||
TEST AL,8 ;Check if any memory operand legal
|
||
JZ ERRJ4
|
||
TEST AL,10H ;Check for 2-op arithmetic
|
||
JNZ PUTMEM ;If not, just use as plain memory op
|
||
GETFORMAT:
|
||
AND AL,0F9H ;Zero memory format bits
|
||
MOV CL,[FLAG]
|
||
DEC CL ;Must now be in range 0-3
|
||
JL BADFLAG
|
||
MOV CH,AL ;Save opcode byte
|
||
SHR AL ;Put format bits in bits 2 & 3
|
||
AND AL,0CH
|
||
OR AL,CL ;Combine format bits with flag
|
||
MOV BX,FORMATTAB
|
||
XLAT
|
||
OR AL,AL ;Valid combination?
|
||
JS BADFLAG
|
||
OR AH,AL ;Possibly set new bits in second byte
|
||
OR AL,CH ;Set memory format bits
|
||
PUTMEM:
|
||
AND AL,7
|
||
OR AL,0D8H
|
||
CALL PUT
|
||
MOV AL,AH
|
||
AND AL,38H
|
||
OR AL,DL ;Combine addressing mode
|
||
JMP PUTADD
|
||
|
||
FORMATTAB:
|
||
;There are 16 entries in this table. The 4-bit index is built like this:
|
||
; Bit 3 0 for normal memory ops, 1 if extended is OK
|
||
; Bit 2 0 for integer, 1 for real
|
||
; Bit 0 & 1 Flag: 00=W, 01=S, 10=L, 11=T
|
||
;
|
||
;The entries in the table are used as two 3-bit fields. Bits 0-2 are ORed
|
||
;into the first byte of the opcode for the Memory Format field. Bits 3-6
|
||
;are ORed into the second byte to modify the opcode for extended operands.
|
||
;If bit 7 is set, then that combination is illegal.
|
||
|
||
DB 6,2,80H,80H ;Normal integers
|
||
DB 80H,0,4,80H ;Normal reals
|
||
DB 6,2,2EH,80H ;Extended integers
|
||
DB 80H,0,4,2BH ;Extended reals
|
||
|
||
GRP1:
|
||
MOV CX,8A09H
|
||
CALL MROPS
|
||
MOV CX,0C6H
|
||
MOV AL,BH
|
||
CMP AL,UNDEFID
|
||
JNZ L0006
|
||
CALL STIMM
|
||
L0006:
|
||
AND AL,1
|
||
JZ BYTIMM
|
||
MOV AL,0B8H
|
||
OR AL,BL
|
||
CALL PUT
|
||
JMP PUTWOR
|
||
|
||
BYTIMM:
|
||
MOV AL,0B0H
|
||
OR AL,BL
|
||
CALL PUT
|
||
PUTBJ: JMP PUTBYT
|
||
|
||
IMMED:
|
||
MOV AL,BH
|
||
CMP AL,UNDEFID
|
||
JZ STIMM
|
||
MOV AL,BL
|
||
OR AL,AL
|
||
JZ RET
|
||
MOV AL,BH
|
||
CALL IMM
|
||
OR AL,0C0H
|
||
CALL PUT
|
||
FINIMM:
|
||
MOV AL,CL
|
||
POP CX
|
||
TEST AL,1
|
||
JZ PUTBJ
|
||
CMP AL,83H
|
||
JZ PUTBJ
|
||
JMP PUTWOR
|
||
|
||
STIMM:
|
||
MOV AL,[FLAG]
|
||
CALL IMM
|
||
CALL PUTADD
|
||
JP FINIMM
|
||
|
||
IMM:
|
||
AND AL,1
|
||
OR AL,CL
|
||
MOV CL,AL
|
||
CALL PUT
|
||
MOV AL,CH
|
||
AND AL,38H
|
||
OR AL,BL
|
||
RET
|
||
|
||
PUT:
|
||
;Save byte in AL as pure code, with intermediate code bits 00. AL and
|
||
;DI destroyed, no other registers affected.
|
||
PUSH BX
|
||
PUSH CX
|
||
MOV CH,0 ;Flag as pure code
|
||
CALL GEN
|
||
POP CX
|
||
POP BX
|
||
RET
|
||
|
||
GEN:
|
||
;Save byte of code in AL, given intermediate code bits in bits 7&8 of CH.
|
||
CALL PUTINC ;Save it and bump code pointer
|
||
GEN1:
|
||
MOV AL,[RELOC]
|
||
RCL CH
|
||
RCL AL
|
||
RCL CH
|
||
RCL AL
|
||
MOV [RELOC],AL
|
||
MOV BX,BCOUNT
|
||
DEC B,[BX]
|
||
JNZ RET
|
||
MOV B,[BX],4
|
||
MOV BX,RELOC
|
||
MOV AL,[BX]
|
||
MOV B,[BX],0
|
||
MOV DI,[IY]
|
||
MOV [DI],AL
|
||
MOV BX,[CODE]
|
||
MOV [IY],BX
|
||
INC BX
|
||
MOV [CODE],BX
|
||
RET
|
||
|
||
PUTINC:
|
||
INC [PC]
|
||
PUTCD:
|
||
MOV DI,[CODE]
|
||
STOB
|
||
MOV [CODE],DI
|
||
RET
|
||
|
||
PUTWOR:
|
||
;Save the word value described by [DLABEL] and [DATA] as code. If defined,
|
||
;two bytes of pure code will be produced. Otherwise, appropriate intermediate
|
||
;code will be generated.
|
||
PUSH CX
|
||
MOV CH,80H
|
||
PUSH DX
|
||
PUSH BX
|
||
JP PUTBW
|
||
|
||
PUTBYT:
|
||
;Same as PUTWOR, above, but for byte value.
|
||
PUSH CX
|
||
MOV CH,40H
|
||
PUSH DX
|
||
PUSH BX
|
||
MOV BX,[DLABEL]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
JNZ PUTBW
|
||
MOV BX,[DATA]
|
||
OR AL,BH
|
||
JZ PUTBW
|
||
INC BH
|
||
JZ PUTBW
|
||
MOV CL,31
|
||
JMP ERROR
|
||
PUTBW:
|
||
MOV DX,[DLABEL]
|
||
MOV BX,[DATA]
|
||
PUTCHK:
|
||
OR DX,DX
|
||
JZ NOUNDEF
|
||
MOV AL,DL
|
||
CALL PUTCD
|
||
MOV AL,DH
|
||
CALL PUTCD
|
||
MOV AL,BL
|
||
CALL PUTINC
|
||
MOV AL,BH
|
||
TEST CH,080H
|
||
JZ SMPUT
|
||
CALL GEN
|
||
JP PRET
|
||
SMPUT:
|
||
CALL PUTCD
|
||
CALL GEN1
|
||
PRET:
|
||
POP BX
|
||
POP DX
|
||
POP CX
|
||
RET
|
||
|
||
NOUNDEF:
|
||
MOV AL,BL
|
||
MOV CL,BH
|
||
PUSH CX
|
||
MOV CH,0
|
||
CALL GEN
|
||
POP CX
|
||
MOV AL,CL
|
||
TEST CH,080H
|
||
MOV CH,0
|
||
JZ PRET
|
||
CALL GEN
|
||
JP PRET
|
||
|
||
PUTADD:
|
||
;Save complete addressing mode. Addressing mode is in AL; if this is a register
|
||
;operation (>=C0), then the one byte will be saved as pure code. Otherwise,
|
||
;the details of the addressing mode will be investigated and the optional one-
|
||
;or two-byte displacement will be added, as described by [ADDR] and [ALABEL].
|
||
PUSH CX
|
||
PUSH DX
|
||
PUSH BX
|
||
MOV CH,0
|
||
MOV CL,AL
|
||
CALL GEN ;Save the addressing mode as pure code
|
||
MOV AL,CL
|
||
MOV CH,80H
|
||
AND AL,0C7H
|
||
CMP AL,6
|
||
JZ TWOBT ;Direct address?
|
||
AND AL,0C0H
|
||
JZ PRET ;Indirect through reg, no displacement?
|
||
CMP AL,0C0H
|
||
JZ PRET ;Register to register operation?
|
||
MOV CH,AL ;Save whether one- or two-byte displacement
|
||
TWOBT:
|
||
MOV BX,[ADDR]
|
||
MOV DX,[ALABEL]
|
||
JP PUTCHK
|
||
|
||
GRP2:
|
||
CALL GETOP
|
||
MOV CX,0FF30H
|
||
CMP AL,UNDEFID
|
||
JZ PMEM
|
||
MOV CH,50H
|
||
CMP AL,XREG
|
||
JZ PXREG
|
||
MOV CH,6
|
||
CMP AL,SREG
|
||
JNZ $+5
|
||
JMP PACKREG
|
||
MOV CL,20
|
||
JMP ERROR
|
||
|
||
PMEM:
|
||
MOV AL,CH
|
||
CALL PUT
|
||
MOV AL,CL
|
||
OR AL,DL
|
||
JMP PUTADD
|
||
|
||
PXREG:
|
||
MOV AL,CH
|
||
OR AL,DL
|
||
JMP PUT
|
||
|
||
GRP3:
|
||
CALL GETOP
|
||
PUSH DX
|
||
CALL GETOP2
|
||
POP BX
|
||
MOV CX,8614H
|
||
MOV AL,SREG
|
||
CMP AL,BH
|
||
JZ ERR6
|
||
CMP AL,DH
|
||
JZ ERR6
|
||
MOV AL,CONST
|
||
CMP AL,BH
|
||
JZ ERR6
|
||
CMP AL,DH
|
||
JZ ERR6
|
||
MOV AL,UNDEFID
|
||
CMP AL,BH
|
||
JZ EXMEM
|
||
CMP AL,DH
|
||
JZ EXMEM1
|
||
MOV AL,BH
|
||
CMP AL,DH
|
||
MOV CL,22
|
||
JNZ ERR6
|
||
CMP AL,XREG
|
||
JZ L0008
|
||
CALL RR1
|
||
L0008: ;RR1 never returns
|
||
MOV AL,BL
|
||
OR AL,AL
|
||
JZ EXACC
|
||
XCHG DX,BX
|
||
MOV AL,BL
|
||
OR AL,AL
|
||
MOV AL,BH
|
||
JZ EXACC
|
||
CALL RR1
|
||
EXACC:
|
||
MOV AL,90H
|
||
OR AL,DL
|
||
JMP PUT
|
||
|
||
EXMEM:
|
||
XCHG DX,BX
|
||
EXMEM1:
|
||
CMP AL,BH
|
||
JZ ERR6
|
||
MOV CL,1 ;Flag word as OK
|
||
CALL NOTAC ;NOTAC never returns
|
||
ERR6: JMP ERROR
|
||
|
||
GRP4:
|
||
PUSH AX
|
||
CALL GETOP
|
||
POP CX
|
||
XCHG CL,CH
|
||
CMP AL,CONST
|
||
JZ FIXED
|
||
SUB AL,XREG
|
||
DEC DL
|
||
DEC DL
|
||
OR AL,DL
|
||
MOV CL,20
|
||
JNZ ERR6
|
||
MOV AL,CH
|
||
OR AL,8
|
||
JMP PUT
|
||
FIXED:
|
||
MOV AL,CH
|
||
CALL PUT
|
||
JMP PUTBYT
|
||
|
||
GRP5:
|
||
PUSH AX
|
||
CALL GETOP
|
||
MOV CL,20
|
||
CMP AL,CONST
|
||
JNZ ERR6
|
||
MOV BX,[DLABEL]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
MOV CL,30
|
||
JNZ ERR6
|
||
MOV BX,[DATA]
|
||
POP AX
|
||
OR AL,AL
|
||
JZ ORG
|
||
DEC AL
|
||
JZ DSJ
|
||
DEC AL
|
||
JZ EQU
|
||
DEC AL
|
||
JZ $+5
|
||
JMP IF
|
||
PUTOP:
|
||
MOV AL,-3
|
||
JP NEWLOC
|
||
ALIGN:
|
||
MOV AL,[PC]
|
||
AND AL,1
|
||
JZ RET
|
||
MOV BX,1
|
||
DSJ:
|
||
XCHG DX,BX
|
||
MOV BX,[PC]
|
||
ADD BX,DX
|
||
MOV [PC],BX
|
||
XCHG DX,BX
|
||
MOV AL,-4
|
||
JP NEWLOC
|
||
EQU:
|
||
XCHG DX,BX
|
||
MOV BX,[LABPT]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
MOV CL,34
|
||
JZ ERR7
|
||
MOV [BX],DL
|
||
INC BX
|
||
MOV [BX],DH
|
||
RET
|
||
ORG:
|
||
MOV [PC],BX
|
||
MOV AL,-2
|
||
NEWLOC:
|
||
CALL PUTCD
|
||
MOV AL,BL
|
||
CALL PUTCD
|
||
MOV AL,BH
|
||
CALL PUTCD
|
||
MOV CH,0C0H
|
||
JMP GEN1
|
||
GRP6:
|
||
MOV CH,AL
|
||
MOV CL,4
|
||
CALL MROPS
|
||
MOV CL,23
|
||
ERR7: JMP ERROR
|
||
GRP7:
|
||
MOV CH,AL
|
||
MOV CL,1
|
||
CALL MROPS
|
||
MOV CL,80H
|
||
MOV DX,[DLABEL]
|
||
MOV AL,DH
|
||
OR AL,DL
|
||
JNZ ACCJ
|
||
XCHG DX,BX
|
||
MOV BX,[DATA]
|
||
MOV AL,BL
|
||
CBW
|
||
CMP AX,BX
|
||
XCHG DX,BX
|
||
JNZ ACCJ
|
||
OR CL,002H
|
||
ACCJ: JMP ACCIMM
|
||
GRP8:
|
||
MOV CL,AL
|
||
MOV CH,0FEH
|
||
JP ONEOP
|
||
GRP9:
|
||
MOV CL,AL
|
||
MOV CH,0F6H
|
||
ONEOP:
|
||
PUSH CX
|
||
CALL GETOP
|
||
ONE:
|
||
MOV CL,26
|
||
CMP AL,CONST
|
||
JZ ERR7
|
||
CMP AL,SREG
|
||
MOV CL,22
|
||
JZ ERR7
|
||
POP CX
|
||
CMP AL,UNDEFID
|
||
JZ MOP
|
||
AND AL,1
|
||
JZ ROP
|
||
TEST CL,001H
|
||
JZ ROP
|
||
MOV AL,CL
|
||
AND AL,0F8H
|
||
OR AL,DL
|
||
JMP PUT
|
||
MOP:
|
||
MOV AL,[FLAG]
|
||
AND AL,1
|
||
OR AL,CH
|
||
CALL PUT
|
||
MOV AL,CL
|
||
AND AL,38H
|
||
OR AL,DL
|
||
JMP PUTADD
|
||
ROP:
|
||
OR AL,CH
|
||
CALL PUT
|
||
MOV AL,CL
|
||
AND AL,38H
|
||
OR AL,0C0H
|
||
OR AL,DL
|
||
JMP PUT
|
||
GRP10:
|
||
MOV CL,AL
|
||
MOV CH,0F6H
|
||
PUSH CX
|
||
CALL GETOP
|
||
MOV CL,20
|
||
MOV AL,DL
|
||
OR AL,AL
|
||
JNZ ERRJ1
|
||
MOV AL,DH
|
||
CMP AL,XREG
|
||
JZ G10
|
||
CMP AL,REG
|
||
ERRJ1: JNZ ERR8
|
||
G10:
|
||
PUSH AX
|
||
CALL GETOP
|
||
POP AX
|
||
AND AL,1
|
||
MOV [FLAG],AL
|
||
MOV AL,DH
|
||
ONEJ: JP ONE
|
||
GRP11:
|
||
CALL PUT
|
||
MOV AL,0AH
|
||
JMP PUT
|
||
GRP12:
|
||
MOV CL,AL
|
||
MOV CH,0D0H
|
||
PUSH CX
|
||
CALL GETOP
|
||
MOV AL,[SYM]
|
||
CMP AL,','
|
||
MOV AL,DH
|
||
JNZ ONEJ
|
||
PUSH DX
|
||
CALL GETOP
|
||
SUB AL,REG
|
||
MOV CL,20
|
||
DEC DL
|
||
OR AL,DL
|
||
JNZ ERR8
|
||
POP DX
|
||
MOV AL,DH
|
||
POP CX
|
||
OR CH,002H
|
||
PUSH CX
|
||
JMP ONE
|
||
GRP13:
|
||
MOV CH,AL
|
||
MOV CL,1
|
||
CALL MROPS
|
||
MOV CL,80H
|
||
ACCIMM:
|
||
CALL IMMED
|
||
OR CH,004H
|
||
AND CH,0FDH
|
||
AIMM:
|
||
MOV AL,BH
|
||
AND AL,1
|
||
LAHF
|
||
PUSH AX
|
||
OR AL,CH
|
||
CALL PUT
|
||
POP AX
|
||
SAHF
|
||
JNZ $+5
|
||
JMP PUTBYT
|
||
JMP PUTWOR
|
||
|
||
ERR8: JMP ERROR
|
||
|
||
GRP14:
|
||
;JMP and CALL mnemonics
|
||
LAHF
|
||
XCHG AH,AL
|
||
PUSH AX
|
||
XCHG AH,AL
|
||
MOV B,[MAXFLG],3 ;Allow "L" flag
|
||
CALL GETOP
|
||
CMP AL,CONST
|
||
JZ DIRECT
|
||
MOV CL,20
|
||
CMP AL,REG
|
||
JZ ERR8
|
||
CMP AL,SREG
|
||
JZ ERR8
|
||
CMP AL,XREG
|
||
JNZ NOTRG
|
||
OR DL,0C0H
|
||
NOTRG:
|
||
;Indirect jump. DL has addressing mode.
|
||
MOV AL,0FFH
|
||
CALL PUT
|
||
POP AX
|
||
XCHG AH,AL
|
||
SAHF
|
||
AND AL,38H
|
||
OR AL,DL
|
||
MOV CH,[FLAG]
|
||
CMP CH,3 ;Flag "L" present?
|
||
JZ PUTADDJ ;If so, do inter-segment
|
||
MOV CL,27H
|
||
CMP CH,-1 ;Better not be a flag
|
||
JNZ ERR8
|
||
AND AL,0F7H ;Convert to intra-segment
|
||
PUTADDJ:
|
||
JMP PUTADD
|
||
DIRECT:
|
||
MOV AL,[SYM]
|
||
CMP AL,','
|
||
JZ LONGJ
|
||
POP AX
|
||
XCHG AH,AL
|
||
SAHF
|
||
DEC AL
|
||
CMP AL,0E9H
|
||
JZ GOTOP
|
||
MOV AL,0E8H
|
||
GOTOP:
|
||
CALL PUT
|
||
MOV DX,[PC]
|
||
INC DX
|
||
INC DX
|
||
SUB [DATA],DX
|
||
JMP PUTWOR
|
||
LONGJ:
|
||
POP AX
|
||
XCHG AH,AL
|
||
SAHF
|
||
CALL PUT
|
||
CALL PUTWOR
|
||
CALL GETOP
|
||
MOV CL,20
|
||
CMP AL,CONST
|
||
JNZ ERR8
|
||
JMP PUTWOR
|
||
|
||
GRP16:
|
||
;RET mnemonic
|
||
LAHF
|
||
XCHG AH,AL
|
||
PUSH AX
|
||
XCHG AH,AL
|
||
CALL GETSYM
|
||
CMP AL,5
|
||
JZ LONGR
|
||
CMP AL,EOL
|
||
JZ NODEC
|
||
CMP AL,';'
|
||
JZ NODEC
|
||
GETSP:
|
||
CALL GETOP1
|
||
POP CX
|
||
CMP AL,CONST
|
||
MOV CL,20
|
||
JNZ ERR9
|
||
MOV AL,CH
|
||
AND AL,0FEH
|
||
CALL PUT
|
||
JMP PUTWOR
|
||
LONGR:
|
||
CMP DL,3 ;Is flag "L"?
|
||
MOV CL,27H
|
||
JNZ ERR10 ;If not, bad flag
|
||
POP AX
|
||
XCHG AH,AL
|
||
SAHF
|
||
OR AL,8
|
||
LAHF
|
||
XCHG AH,AL
|
||
PUSH AX
|
||
XCHG AH,AL
|
||
NOTLON:
|
||
CALL GETSYM
|
||
CMP AL,EOL
|
||
JZ DORET
|
||
CMP AL,';'
|
||
JZ DORET
|
||
CMP AL,','
|
||
JNZ L0011
|
||
CALL GETSYM
|
||
L0011:
|
||
JP GETSP
|
||
NODEC:
|
||
;Return is intra-segment (short) without add to SP.
|
||
;Record position for RET symbol.
|
||
MOV BX,[PC]
|
||
MOV [LSTRET],BX
|
||
XCHG DX,BX
|
||
MOV BX,[RETPT]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
JZ DORET
|
||
MOV B,[BX],1
|
||
INC BX
|
||
MOV [BX],DX
|
||
MOV BX,0
|
||
MOV [RETPT],BX
|
||
DORET:
|
||
POP AX
|
||
XCHG AH,AL
|
||
SAHF
|
||
JMP PUT
|
||
|
||
GRP17:
|
||
CALL PUT
|
||
CALL GETOP
|
||
CMP AL,CONST
|
||
MOV CL,20
|
||
ERR9: JNZ ERR10
|
||
MOV BX,[DATA]
|
||
MOV DX,[PC]
|
||
INC DX
|
||
SUB BX,DX
|
||
MOV [DATA],BX
|
||
CALL PUTBYT
|
||
MOV BX,[DLABEL]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
JNZ RET
|
||
MOV BX,[DATA]
|
||
MOV AL,BL
|
||
CBW
|
||
CMP AX,BX ;Signed 8-bit number?
|
||
JZ RET
|
||
MOV CL,31
|
||
ERR10: JMP ERROR
|
||
RET
|
||
GRP18:
|
||
CALL GETOP
|
||
CMP AL,CONST
|
||
MOV CL,20
|
||
JNZ ERR10
|
||
MOV BX,[DLABEL]
|
||
MOV AL,BH
|
||
OR AL,BL
|
||
JNZ GENINT
|
||
MOV BX,[DATA]
|
||
MOV DX,3
|
||
SBB BX,DX
|
||
JNZ GENINT
|
||
MOV AL,0CCH
|
||
JMP PUT
|
||
GENINT:
|
||
MOV AL,0CDH
|
||
CALL PUT
|
||
JMP PUTBYT
|
||
|
||
GRP19: ;ESC opcode
|
||
CALL GETOP
|
||
MOV CL,20
|
||
CMP AL,CONST
|
||
JNZ ERRJ ;First operand must be immediate
|
||
MOV CL,1EH
|
||
TEST [DLABEL],-1 ;See if all labels have been defined
|
||
JNZ ERRJ
|
||
MOV AX,[DATA]
|
||
CMP AX,64 ;Must only be 6 bits
|
||
MOV CL,1FH
|
||
JNB ERRJ
|
||
MOV BL,AL ;Save for second byte
|
||
SHR AL
|
||
SHR AL
|
||
SHR AL
|
||
OR AL,0D8H ;ESC opcode
|
||
CALL PUT
|
||
PUSH BX
|
||
CALL GETOP2
|
||
POP BX
|
||
AND BL,7 ;Low 3 bits of first operand
|
||
SHL BL
|
||
SHL BL
|
||
SHL BL
|
||
CMP AL,UNDEFID ;Check for memory operand
|
||
JZ ESCMEM
|
||
CMP AL,CONST ;Check for another immediate
|
||
JZ ESCIMM
|
||
MOV CL,20
|
||
ERRJ: JMP ERROR
|
||
|
||
ESCMEM:
|
||
OR BL,DL ;Combine mode with first operand
|
||
MOV AL,BL
|
||
JMP PUTADD
|
||
|
||
ESCIMM:
|
||
MOV CL,1EH
|
||
TEST [DLABEL],-1 ;See if second operand is fully defined
|
||
JNZ ERRJ
|
||
MOV AX,[DATA]
|
||
MOV CL,1FH
|
||
CMP AX,8 ;Must only be 3 bit value
|
||
JNB ERRJ
|
||
OR AL,BL ;Combine first and second operands
|
||
OR AL,0C0H ;Force "register" mode
|
||
JMP PUT
|
||
|
||
GRP20:
|
||
MOV CH,AL
|
||
MOV CL,1
|
||
CALL MROPS
|
||
MOV CL,0F6H
|
||
CALL IMMED
|
||
MOV CH,0A8H
|
||
JMP AIMM
|
||
GRP21:
|
||
CALL GETOP
|
||
CMP AL,SREG
|
||
MOV CL,28
|
||
JNZ ERRJ
|
||
MOV CH,26H
|
||
PACKREG:
|
||
MOV AL,DL
|
||
ADD AL,AL
|
||
ADD AL,AL
|
||
ADD AL,AL
|
||
OR AL,CH
|
||
JMP PUT
|
||
GRP22:
|
||
CALL GETOP
|
||
MOV CX,8F00H
|
||
CMP AL,UNDEFID
|
||
JNZ $+5
|
||
JMP PMEM
|
||
MOV CH,58H
|
||
CMP AL,XREG
|
||
JNZ $+5
|
||
JMP PXREG
|
||
MOV CH,7
|
||
CMP AL,SREG
|
||
JZ PACKREG
|
||
MOV CL,20
|
||
ERR11: JMP ERROR
|
||
GRP23:
|
||
MOV [DATSIZ],AL
|
||
GETDAT:
|
||
CALL GETSYM
|
||
MOV AL,2
|
||
CALL VAL1
|
||
MOV AL,[SYM]
|
||
CMP AL,','
|
||
MOV AL,[DATSIZ]
|
||
JNZ ENDDAT
|
||
CALL SAVDAT
|
||
JP GETDAT
|
||
ENDDAT:
|
||
CMP AL,2
|
||
JNZ SAVDAT
|
||
MOV BX,[DATA]
|
||
LAHF
|
||
OR BL,080H
|
||
SAHF
|
||
MOV [DATA],BX
|
||
SAVDAT:
|
||
OR AL,AL
|
||
JZ $+5
|
||
JMP PUTBYT
|
||
JMP PUTWOR
|
||
IF:
|
||
OR BX,BX
|
||
JZ SKIPCD
|
||
INC B,[IFFLG]
|
||
RET
|
||
|
||
SKIPCD:
|
||
INC B,[CHKLAB]
|
||
SKIPLP:
|
||
XOR AL,AL
|
||
CALL NEXLIN
|
||
CALL NEXTCHR
|
||
CMP AL,1AH
|
||
JZ END
|
||
CALL GETLAB
|
||
JC SKIPLP
|
||
MOV DI,LENID
|
||
MOV SI,IFEND
|
||
MOV CH,0
|
||
MOV CL,[DI]
|
||
INC CL
|
||
REPE
|
||
CMPB
|
||
JZ ENDCOND
|
||
MOV DI,LENID
|
||
MOV SI,IFNEST
|
||
MOV CL,[DI]
|
||
INC CL
|
||
REPE
|
||
CMPB
|
||
JNZ SKIPLP
|
||
INC B,[CHKLAB]
|
||
JP SKIPLP
|
||
|
||
ENDCOND:
|
||
DEC B,[CHKLAB]
|
||
JNZ SKIPLP
|
||
RET
|
||
|
||
ENDIF:
|
||
MOV AL,[IFFLG]
|
||
MOV CL,36
|
||
DEC AL
|
||
JS ERRJMP
|
||
MOV [IFFLG],AL
|
||
RET
|
||
|
||
ERRJMP: JMP ERROR
|
||
|
||
;*********************************************************************
|
||
;
|
||
; PASS 2
|
||
;
|
||
;*********************************************************************
|
||
|
||
END:
|
||
MOV DL,4
|
||
WREND:
|
||
MOV CH,0FFH
|
||
MOV AL,CH
|
||
CALL GEN
|
||
DEC DL
|
||
JNZ WREND
|
||
MOV [BUFPT],SRCBUF
|
||
MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY
|
||
MOV [LSTPNT],LSTBUF
|
||
MOV [HEXPNT],HEXBUF
|
||
XOR AX,AX
|
||
MOV [ERRCNT],AX
|
||
MOV [PC],AX
|
||
MOV [LINE],AX ;Current line number
|
||
MOV [HEXADD],OBJECT
|
||
MOV DX,FCB
|
||
MOV AH,OPEN
|
||
INT 33 ;Re-open source file
|
||
XOR AX,AX
|
||
MOV [FCB+12],AX ;Set CURRENT BLOCK to zero
|
||
MOV [FCB+20H],AL ;Set NEXT RECORD field to zero
|
||
MOV [FCB+14],BUFSIZ
|
||
MOV [COUNT],AL
|
||
MOV CH,1
|
||
MOV SI,START
|
||
FIXLINE:
|
||
MOV DI,START ;Store code over used up intermediate code
|
||
XOR AL,AL
|
||
MOV [SPC],AL ;No "special" yet (ORG, PUT, DS)
|
||
MOV [ERR],AL ;No second pass errors yet
|
||
NEXBT:
|
||
SHL CL ;Shift out last bit of previous code
|
||
DEC CH ;Still have codes left?
|
||
JNZ TESTTYP
|
||
LODB ;Get next flag byte
|
||
MOV CL,AL
|
||
MOV CH,4
|
||
TESTTYP:
|
||
SHL CL ;Set flags based on two bits
|
||
JO FIXUP
|
||
LODB
|
||
JC EMARK
|
||
OBJBT:
|
||
STOB
|
||
JP NEXBT
|
||
|
||
FIXUP:
|
||
;Either a word or byte fixup is needed from a forward reference
|
||
LODW ;Get pointer to symbol
|
||
XCHG AX,BX
|
||
LODW ;Get constant part
|
||
ADD AX,[BX+1] ;Add symbol value to constant part
|
||
CMP B,[BX],0 ;See if symbol got defined
|
||
JNZ HAVDEF
|
||
MOV B,[ERR],100 ;Undefined - flag error
|
||
XOR AX,AX
|
||
HAVDEF:
|
||
OR CL,CL ;See if word or byte fixup
|
||
JS DEFBYT
|
||
STOW
|
||
JP NEXBT
|
||
|
||
DEFBYT:
|
||
MOV DX,AX
|
||
CBW ;Extend sign
|
||
CMP AX,DX ;See if in range +127 to -128
|
||
JZ OBJBT ;If so, it's always OK
|
||
NOT AH ;Check for range +255 to -256
|
||
CMP AH,DH
|
||
JNZ RNGERR ;Must always be in this range
|
||
;Check for short jump. If so, we're out of range; otherwise we're OK
|
||
CMP DI,START+1 ;Only one other byte on line?
|
||
JNZ OBJBT ;Can't be short jump if not
|
||
MOV AL,[START] ;Get the first byte of this line
|
||
CMP AL,0EBH ;Direct short jump?
|
||
JZ RNGERR
|
||
AND AL,0FCH
|
||
CMP AL,0E0H ;LOOP or JCXZ instruction?
|
||
JZ RNGERR
|
||
AND AL,0F0H
|
||
CMP AL,70H ;Conditional jump?
|
||
MOV AL,DL ;Get code byte in AL
|
||
JNZ OBJBT ;If not, we're OK
|
||
RNGERR:
|
||
MOV B,[ERR],101 ;Value out of range
|
||
JP OBJBT
|
||
|
||
FINIJ: JMP FINI
|
||
|
||
EMARK:
|
||
CMP AL,-1 ;End of file?
|
||
JZ FINIJ
|
||
CMP AL,-10 ;Special item?
|
||
JA SPEND
|
||
PUSH CX
|
||
PUSH SI
|
||
PUSH AX ;Save error code
|
||
MOV AH,[LSTDEV]
|
||
AND AH,0FEH ;Reset error indicator
|
||
OR AL,[ERR] ;See if any errors on this line
|
||
JZ NOERR
|
||
OR AH,1 ;Send line to console if error occured
|
||
NOERR:
|
||
MOV [LSTDEV],AH
|
||
MOV CX,DI
|
||
CALL STRTLIN ;Print address of line
|
||
MOV SI,START
|
||
SUB CX,SI ;Get count of bytes of code
|
||
JZ SHOLIN
|
||
CODLP:
|
||
LODB
|
||
CALL SAVCD ;Ouput code to HEX and PRN files
|
||
LOOP CODLP
|
||
SHOLIN:
|
||
MOV AL,0
|
||
XCHG AL,[COUNT]
|
||
MOV CX,7 ;Allow 7 bytes of code per line
|
||
SUB CL,AL
|
||
MOV AL,' '
|
||
JZ NOFIL
|
||
BLNK: ;Put in 3 blanks for each byte not present
|
||
CALL LIST
|
||
CALL LIST
|
||
CALL LIST
|
||
LOOP BLNK
|
||
NOFIL:
|
||
CALL OUTLIN
|
||
POP AX ;Restore error code
|
||
CALL REPERR
|
||
MOV AL,[ERR]
|
||
CALL REPERR
|
||
POP SI
|
||
POP CX
|
||
MOV AL,[SPC] ;Any special funtion?
|
||
OR AL,AL
|
||
JNZ SPCFUN
|
||
JMP FIXLINE
|
||
|
||
SPEND:
|
||
MOV [SPC],AL ;Record special function
|
||
LODW ;Get it's data
|
||
MOV [DATA],AX
|
||
JMP NEXBT
|
||
|
||
SPCFUN:
|
||
MOV DX,[DATA]
|
||
CMP AL,-2
|
||
JZ DORG
|
||
CMP AL,-3
|
||
JZ DPUT
|
||
DDS:
|
||
;Handle DS pseudo-op
|
||
ADD [PC],DX
|
||
ADD [HEXADD],DX
|
||
JMP FIXLINE
|
||
|
||
DORG:
|
||
;Handle ORG pseudo-op
|
||
MOV [PC],DX
|
||
JMP FIXLINE
|
||
|
||
DPUT:
|
||
;Handle PUT pseudo-op
|
||
MOV [HEXADD],DX
|
||
JMP FIXLINE
|
||
|
||
OUTLIN:
|
||
;Copy the source line to the ouput device. Line will be preceded by
|
||
;assembler-generated line number. This routine may be called several times
|
||
;on one line (once for each line of object code bytes), so it sets a flag
|
||
;so the line will only be output on the first call.
|
||
MOV AL,-1
|
||
XCHG AL,[LINFLG]
|
||
OR AL,AL
|
||
JNZ CRLF ;Output line only if first time
|
||
MOV AX,[LINE]
|
||
INC AX
|
||
MOV [LINE],AX
|
||
MOV BH,0 ;No leading zero suppression
|
||
CALL OUT10
|
||
MOV AL," "
|
||
CALL LIST
|
||
MOV AL,[LSTFCB]
|
||
CMP AL,'Z'
|
||
JZ CRLF ;Don't call NEXTCHR if listing suppressed
|
||
PUSH SI ;Save the only register destroyed by NEXTCHR
|
||
OUTLN:
|
||
CALL NEXTCHR
|
||
CALL LIST
|
||
CMP AL,10 ;Output until linefeed found
|
||
JNZ OUTLN
|
||
POP SI
|
||
RET
|
||
|
||
PRTCNT:
|
||
MOV AX,[ERRCNT]
|
||
MOV BX,ERCNTM
|
||
PRNT10:
|
||
PUSH AX
|
||
CALL PRINT
|
||
POP AX
|
||
MOV BH,"0"-" " ;Enable leading zero suppression
|
||
CALL OUT10
|
||
CRLF:
|
||
MOV AL,13
|
||
CALL LIST
|
||
MOV AL,10
|
||
JP LIST
|
||
|
||
OUT10:
|
||
XOR DX,DX
|
||
MOV DI,10000
|
||
DIV AX,DI
|
||
OR AL,AL ;>10,000?
|
||
JNZ LEAD
|
||
SUB AL,"0"-" " ;Convert leading zero to blank
|
||
LEAD:
|
||
ADD AL,"0"
|
||
CALL LIST
|
||
XCHG AX,DX
|
||
MOV BL,100
|
||
DIV AL,BL
|
||
MOV BL,AH
|
||
CALL HIDIG ;Convert to decimal and print 1000s digit
|
||
CALL DIGIT ;Print 100s digit
|
||
MOV AL,BL
|
||
CALL HIDIG ;Convert to decimal and print 10s digit
|
||
MOV BH,0 ;Ensure leading zero suppression is off
|
||
JP DIGIT
|
||
|
||
HIDIG:
|
||
AAM ;Convert binary to unpacked BCD
|
||
OR AX,3030H ;Add "0" bias
|
||
DIGIT:
|
||
XCHG AL,AH
|
||
CMP AL,"0"
|
||
JZ SUPZ
|
||
MOV BH,0 ;Turn off zero suppression if not zero
|
||
SUPZ:
|
||
SUB AL,BH ;Convert leading zeros to blanks
|
||
JP LIST
|
||
|
||
STRTLIN:
|
||
MOV B,[LINFLG],0
|
||
MOV BX,[PC]
|
||
MOV AL,BH
|
||
CALL PHEX
|
||
MOV AL,BL
|
||
PHEXB:
|
||
CALL PHEX
|
||
MOV AL,' '
|
||
LIST:
|
||
PUSH AX
|
||
PUSH DX
|
||
AND AL,7FH
|
||
MOV DL,AL
|
||
TEST B,[LSTDEV],3 ;See if output goes to console
|
||
JZ PRNCHK
|
||
MOV AH,2
|
||
INT 33 ;Output to console
|
||
PRNCHK:
|
||
TEST B,[LSTDEV],4 ;See if output goes to printer
|
||
JZ FILCHK
|
||
MOV AH,5
|
||
INT 33 ;Output to printer
|
||
FILCHK:
|
||
MOV AL,DL
|
||
POP DX
|
||
TEST B,[LSTDEV],80H ;See if output goes to a file
|
||
JZ LISTRET
|
||
CALL WRTBUF
|
||
LISTRET:
|
||
POP AX
|
||
RET
|
||
|
||
WRTBUF:
|
||
PUSH DI
|
||
MOV DI,[LSTPNT]
|
||
STOB
|
||
CMP DI,LSTBUF+LSTBUFSIZ
|
||
JNZ SAVPT
|
||
PUSH AX
|
||
PUSH CX
|
||
PUSH DX
|
||
CALL FLUSHBUF
|
||
POP DX
|
||
POP CX
|
||
POP AX
|
||
SAVPT:
|
||
MOV [LSTPNT],DI
|
||
POP DI
|
||
RET
|
||
|
||
PHEX:
|
||
PUSH AX
|
||
CALL UHALF
|
||
CALL LIST
|
||
POP AX
|
||
CALL LHALF
|
||
JP LIST
|
||
|
||
FINI:
|
||
OR B,[LSTDEV],1
|
||
CALL PRTCNT
|
||
MOV BX,SYMSIZE
|
||
MOV AX,[6]
|
||
SUB AX,[HEAP] ;Size of symbol table
|
||
CALL PRNT10
|
||
MOV BX,FRESIZE
|
||
MOV AX,[HEAP]
|
||
SUB AX,[CODE] ;Free space remaining
|
||
CALL PRNT10
|
||
AND B,[LSTDEV],0FEH
|
||
MOV AL,[HEXFCB]
|
||
CMP AL,'Z'
|
||
JZ SYMDMP
|
||
MOV AL,[HEXCNT]
|
||
CMP AL,-5
|
||
JZ L0012
|
||
CALL ENHEXL
|
||
L0012:
|
||
MOV AL,':'
|
||
CALL PUTCHR
|
||
MOV CH,10
|
||
HEXEND:
|
||
PUSH CX
|
||
MOV AL,'0'
|
||
CALL PUTCHR
|
||
POP CX
|
||
DEC CH
|
||
JNZ HEXEND
|
||
MOV AL,13
|
||
CALL PUTCHR
|
||
MOV AL,10
|
||
CALL PUTCHR
|
||
MOV AL,1AH
|
||
CALL PUTCHR
|
||
CALL WRTHEX ;Flush HEX file buffer
|
||
MOV DX,HEXFCB
|
||
MOV AH,CLOSE
|
||
INT 33
|
||
SYMDMP:
|
||
MOV AL,[SYMFLG]
|
||
CMP AL,'S'
|
||
JNZ ENDSYM
|
||
MOV AL,[LSTDEV]
|
||
OR AL,AL ;Any output device for symbol table dump?
|
||
JNZ DOSYMTAB
|
||
OR AL,1 ;If not, send it to console
|
||
MOV [LSTDEV],AL
|
||
DOSYMTAB:
|
||
MOV BX,SYMMES
|
||
CALL PRINT
|
||
MOV DX,[BASE]
|
||
MOV AL,DH
|
||
OR AL,DL
|
||
JZ ENDSYM
|
||
MOV B,[SYMLIN],SYMWID ;No symbols on this line yet
|
||
MOV BX,[HEAP]
|
||
MOV SP,BX ;Need maximum stack for recursive tree walk
|
||
CALL NODE
|
||
ENDSYM:
|
||
TEST B,[LSTDEV],80H ;Print listing to file?
|
||
JZ EXIT
|
||
MOV AL,1AH
|
||
CALL WRTBUF ;Write end-of-file mark
|
||
MOV DI,[LSTPNT]
|
||
CALL FLUSHBUF
|
||
MOV AH,CLOSE
|
||
INT 33
|
||
EXIT: JMP 0
|
||
|
||
NODE:
|
||
XCHG DX,BX
|
||
PUSH BX
|
||
MOV DL,[BX]
|
||
MOV DH,0
|
||
INC BX
|
||
ADD BX,DX
|
||
MOV DX,[BX]
|
||
OR DX,DX
|
||
JZ L0014
|
||
CALL NODE
|
||
L0014:
|
||
POP BX
|
||
MOV AL,[BX]
|
||
INC BX
|
||
MOV CH,AL
|
||
ADD AL,24
|
||
SHR AL
|
||
SHR AL
|
||
SHR AL
|
||
MOV CL,AL
|
||
INC CL ;Invert last bit
|
||
AND CL,1 ;Number of extra tabs needed (0 or 1)
|
||
SHR AL ;Number of positions wide this symbol needs
|
||
SUB [SYMLIN],AL
|
||
JNC WRTSYM ;Will it fit?
|
||
SUB AL,SYMWID
|
||
NEG AL
|
||
MOV [SYMLIN],AL
|
||
CALL CRLF ;Start new line if not
|
||
WRTSYM:
|
||
MOV AL,[BX]
|
||
INC BX
|
||
CALL LIST
|
||
DEC CH
|
||
JNZ WRTSYM
|
||
INC CL
|
||
TABVAL:
|
||
MOV AL,9
|
||
CALL LIST
|
||
LOOP TABVAL
|
||
INC BX
|
||
INC BX
|
||
PUSH BX
|
||
MOV AL,[BX+4]
|
||
CALL PHEX
|
||
MOV AL,[BX+3]
|
||
CALL PHEX
|
||
CMP B,[SYMLIN],0 ;Will any more fit on line?
|
||
JZ NEXSYMLIN
|
||
MOV AL,9
|
||
CALL LIST
|
||
JP RIGHTSON
|
||
NEXSYMLIN:
|
||
CALL CRLF
|
||
MOV B,[SYMLIN],SYMWID
|
||
RIGHTSON:
|
||
POP BX
|
||
MOV DX,[BX]
|
||
OR DX,DX
|
||
JNZ NODE
|
||
RET
|
||
|
||
SAVCD:
|
||
MOV [PREV],AL
|
||
PUSH BX
|
||
PUSH CX
|
||
PUSH AX
|
||
PUSH DX
|
||
CALL CODBYT
|
||
POP DX
|
||
MOV BX,COUNT
|
||
INC B,[BX]
|
||
MOV AL,[BX]
|
||
CMP AL,8
|
||
JNZ NOEXT
|
||
MOV B,[BX],1
|
||
CALL OUTLIN
|
||
MOV AL,' '
|
||
MOV CH,5
|
||
TAB:
|
||
CALL LIST
|
||
DEC CH
|
||
JNZ TAB
|
||
NOEXT:
|
||
POP AX
|
||
CALL PHEXB
|
||
POP CX
|
||
INC [PC]
|
||
INC [HEXADD]
|
||
POP BX
|
||
RET
|
||
|
||
REPERR:
|
||
OR AL,AL ;Did an error occur?
|
||
JZ RET
|
||
INC [ERRCNT]
|
||
PUSH AX
|
||
MOV BX,ERRMES ;Print "ERROR"
|
||
CALL PRINT
|
||
POP AX
|
||
;We have error number in AL. See if there's an error message for it
|
||
MOV DI,ERRTAB
|
||
MOV BL,80H
|
||
ERRLOOK:
|
||
SCASB ;Do we have the error message
|
||
JBE HAVMES ;Quit looking if we have it or passed it
|
||
XCHG AX,BX ;Put 80H in AL to look for end of this message
|
||
NEXTMES:
|
||
SCASB ;Look for high bit set in message
|
||
JA NEXTMES ; which means we've reached the end
|
||
XCHG AX,BX ;Restore error number to AL
|
||
JMPS ERRLOOK ;Keep looking
|
||
|
||
HAVMES:
|
||
MOV BX,DI ;Put address of message in BX
|
||
JZ PRNERR ;Do we have a message for this error?
|
||
CALL PHEX ;If not, just print error number
|
||
JMP CRLF
|
||
|
||
PRNERR:
|
||
CALL PRINT
|
||
JMP CRLF
|
||
|
||
PRINT:
|
||
MOV AL,[BX]
|
||
CALL LIST
|
||
OR AL,AL
|
||
JS RET
|
||
INC BX
|
||
JP PRINT
|
||
|
||
OUTA:
|
||
MOV DL,AL
|
||
OUT:
|
||
AND DL,7FH
|
||
MOV CL,2
|
||
SYSTEM:
|
||
CALL 5
|
||
RET
|
||
|
||
CODBYT:
|
||
CMP B,[HEXFCB],"Z"
|
||
JZ RET
|
||
PUSH AX
|
||
MOV DX,[LASTAD]
|
||
MOV BX,[HEXADD]
|
||
MOV [LASTAD],BX
|
||
INC DX
|
||
MOV AL,[HEXCNT]
|
||
CMP AL,-5
|
||
JZ NEWLIN
|
||
CMP BX,DX
|
||
JZ AFHEX
|
||
CALL ENHEXL
|
||
NEWLIN:
|
||
MOV AL,':'
|
||
CALL PUTCHR
|
||
MOV AL,-4
|
||
MOV [HEXCNT],AL
|
||
XOR AL,AL
|
||
MOV [CHKSUM],AL
|
||
MOV BX,[HEXPNT]
|
||
MOV [HEXLEN],BX
|
||
CALL HEXBYT
|
||
MOV AL,[HEXADD+1]
|
||
CALL HEXBYT
|
||
MOV AL,[HEXADD]
|
||
CALL HEXBYT
|
||
XOR AL,AL
|
||
CALL HEXBYT
|
||
AFHEX:
|
||
POP AX
|
||
HEXBYT:
|
||
MOV CH,AL
|
||
MOV BX,CHKSUM
|
||
ADD AL,[BX]
|
||
MOV [BX],AL
|
||
MOV AL,CH
|
||
CALL UHALF
|
||
CALL PUTCHR
|
||
MOV AL,CH
|
||
CALL LHALF
|
||
CALL PUTCHR
|
||
MOV BX,HEXCNT
|
||
INC B,[BX]
|
||
MOV AL,[BX]
|
||
CMP AL,26
|
||
JNZ RET
|
||
ENHEXL:
|
||
MOV DI,[HEXLEN]
|
||
MOV CH,AL
|
||
CALL UHALF
|
||
STOB
|
||
MOV AL,CH
|
||
CALL LHALF
|
||
STOB
|
||
MOV AL,-6
|
||
MOV [HEXCNT],AL
|
||
MOV AL,[CHKSUM]
|
||
ADD AL,CH
|
||
NEG AL
|
||
CALL HEXBYT
|
||
MOV AL,13
|
||
CALL PUTCHR
|
||
MOV AL,10
|
||
CALL PUTCHR
|
||
WRTHEX:
|
||
;Write out the line
|
||
MOV DX,HEXBUF
|
||
MOV [HEXPNT],DX
|
||
MOV AH,SETDMA
|
||
INT 33
|
||
SUB DI,DX ;Length of buffer
|
||
MOV CX,DI
|
||
MOV DX,HEXFCB
|
||
MOV AH,BLKWRT
|
||
INT 33
|
||
OR AL,AL
|
||
JNZ DSKFUL
|
||
RET
|
||
|
||
PUTCHR:
|
||
MOV DI,[HEXPNT]
|
||
STOB
|
||
MOV [HEXPNT],DI
|
||
RET
|
||
|
||
FLUSHBUF:
|
||
MOV CX,DI
|
||
MOV DX,LSTBUF
|
||
MOV DI,DX
|
||
SUB CX,DX
|
||
JZ RET ;Buffer empty?
|
||
MOV AH,SETDMA
|
||
INT 33
|
||
MOV DX,LSTFCB
|
||
MOV AH,BLKWRT
|
||
INT 33
|
||
OR AL,AL
|
||
JZ RET
|
||
DSKFUL:
|
||
MOV BX,WRTERR
|
||
JMP PRERR
|
||
|
||
UHALF:
|
||
RCR AL
|
||
RCR AL
|
||
RCR AL
|
||
RCR AL
|
||
LHALF:
|
||
AND AL,0FH
|
||
OR AL,30H
|
||
CMP AL,'9'+1
|
||
JC RET
|
||
ADD AL,7
|
||
RET
|
||
|
||
NONE: DB 0
|
||
|
||
; 8086 MNEMONIC TABLE
|
||
|
||
; This table is actually a sequence of subtables, each starting with a label.
|
||
; The label signifies which mnemonics the subtable applies to--A3, for example,
|
||
; means all 3-letter mnemonics beginning with A.
|
||
|
||
A3:
|
||
DB 7
|
||
DB 'dd'
|
||
DW GRP7
|
||
DB 2
|
||
DB 'nd'
|
||
DW GRP13
|
||
DB 22H
|
||
DB 'dc'
|
||
DW GRP7
|
||
DB 12H
|
||
DB 'aa'
|
||
DW PUT
|
||
DB 37H
|
||
DB 'as'
|
||
DW PUT
|
||
DB 3FH
|
||
DB 'am'
|
||
DW GRP11
|
||
DB 0D4H
|
||
DB 'ad'
|
||
DW GRP11
|
||
DB 0D5H
|
||
A5:
|
||
DB 1
|
||
DB 'lign'
|
||
DW ALIGN
|
||
DB 0
|
||
C3:
|
||
DB 7
|
||
DB 'mp'
|
||
DW GRP7
|
||
DB 3AH
|
||
DB 'lc'
|
||
DW PUT
|
||
DB 0F8H
|
||
DB 'ld'
|
||
DW PUT
|
||
DB 0FCH
|
||
DB 'li'
|
||
DW PUT
|
||
DB 0FAH
|
||
DB 'mc'
|
||
DW PUT
|
||
DB 0F5H
|
||
DB 'bw'
|
||
DW PUT
|
||
DB 98H
|
||
DB 'wd'
|
||
DW PUT
|
||
DB 99H
|
||
C4:
|
||
DB 3
|
||
DB 'all'
|
||
DW GRP14
|
||
DB 9AH
|
||
DB 'mpb'
|
||
DW PUT
|
||
DB 0A6H
|
||
DB 'mpw'
|
||
DW PUT
|
||
DB 0A7H
|
||
C5:
|
||
DB 2
|
||
DB 'mpsb'
|
||
DW PUT
|
||
DB 0A6H
|
||
DB 'mpsw'
|
||
DW PUT
|
||
DB 0A7H
|
||
D2:
|
||
DB 5
|
||
DB 'b'
|
||
DW GRP23
|
||
DB 1
|
||
DB 'w'
|
||
DW GRP23
|
||
DB 0
|
||
DB 'm'
|
||
DW GRP23
|
||
DB 2
|
||
DB 's'
|
||
DW GRP5
|
||
DB 1
|
||
DB 'i'
|
||
DW PUT
|
||
DB 0FAH
|
||
D3:
|
||
DB 4
|
||
DB 'ec'
|
||
DW GRP8
|
||
DB 49H
|
||
DB 'iv'
|
||
DW GRP10
|
||
DB 30H
|
||
DB 'aa'
|
||
DW PUT
|
||
DB 27H
|
||
DB 'as'
|
||
DW PUT
|
||
DB 2FH
|
||
D4:
|
||
DB 1
|
||
DB 'own'
|
||
DW PUT
|
||
DB 0FDH
|
||
E2:
|
||
DB 1
|
||
DB 'i'
|
||
DW PUT
|
||
DB 0FBH
|
||
E3:
|
||
DB 3
|
||
DB 'qu'
|
||
DW GRP5
|
||
DB 2
|
||
DB 'sc'
|
||
DW GRP19
|
||
DB 0D8H
|
||
DB 'nd'
|
||
DW END
|
||
DB 0
|
||
E5:
|
||
DB 1
|
||
DB 'ndif'
|
||
DW ENDIF
|
||
DB 0
|
||
H3:
|
||
DB 1
|
||
DB 'lt'
|
||
DW PUT
|
||
DB 0F4H
|
||
H4:
|
||
DB 1
|
||
DB 'alt'
|
||
DW PUT
|
||
DB 0F4H
|
||
I2:
|
||
DB 2
|
||
DB 'n'
|
||
DW GRP4
|
||
DB 0E4H
|
||
DB 'f'
|
||
DW GRP5
|
||
DB 4
|
||
I3:
|
||
DB 4
|
||
DB 'nc'
|
||
DW GRP8
|
||
DB 41H
|
||
DB 'nb'
|
||
DW GRP4
|
||
DB 0E4H
|
||
DB 'nw'
|
||
DW GRP4
|
||
DB 0E5H
|
||
DB 'nt'
|
||
DW GRP18
|
||
DB 0CCH
|
||
I4:
|
||
DB 4
|
||
DB 'mul'
|
||
DW GRP10
|
||
DB 28H
|
||
DB 'div'
|
||
DW GRP10
|
||
DB 38H
|
||
DB 'ret'
|
||
DW PUT
|
||
DB 0CFH
|
||
DB 'nto'
|
||
DW PUT
|
||
DB 0CEH
|
||
J2:
|
||
DB 10
|
||
DB 'p'
|
||
DW GRP17
|
||
DB 0EBH
|
||
DB 'z'
|
||
DW GRP17
|
||
DB 74H
|
||
DB 'e'
|
||
DW GRP17
|
||
DB 74H
|
||
DB 'l'
|
||
DW GRP17
|
||
DB 7CH
|
||
DB 'b'
|
||
DW GRP17
|
||
DB 72H
|
||
DB 'a'
|
||
DW GRP17
|
||
DB 77H
|
||
DB 'g'
|
||
DW GRP17
|
||
DB 7FH
|
||
DB 'o'
|
||
DW GRP17
|
||
DB 70H
|
||
DB 's'
|
||
DW GRP17
|
||
DB 78H
|
||
DB 'c'
|
||
DW GRP17
|
||
DB 72H
|
||
J3:
|
||
DB 17
|
||
DB 'mp'
|
||
DW GRP14
|
||
DB 0EAH
|
||
DB 'nz'
|
||
DW GRP17
|
||
DB 75H
|
||
DB 'ne'
|
||
DW GRP17
|
||
DB 75H
|
||
DB 'nl'
|
||
DW GRP17
|
||
DB 7DH
|
||
DB 'ge'
|
||
DW GRP17
|
||
DB 7DH
|
||
DB 'nb'
|
||
DW GRP17
|
||
DB 73H
|
||
DB 'ae'
|
||
DW GRP17
|
||
DB 73H
|
||
DB 'nc'
|
||
DW GRP17
|
||
DB 73H
|
||
DB 'ng'
|
||
DW GRP17
|
||
DB 7EH
|
||
DB 'le'
|
||
DW GRP17
|
||
DB 7EH
|
||
DB 'na'
|
||
DW GRP17
|
||
DB 76H
|
||
DB 'be'
|
||
DW GRP17
|
||
DB 76H
|
||
DB 'pe'
|
||
DW GRP17
|
||
DB 7AH
|
||
DB 'np'
|
||
DW GRP17
|
||
DB 7BH
|
||
DB 'po'
|
||
DW GRP17
|
||
DB 7BH
|
||
DB 'no'
|
||
DW GRP17
|
||
DB 71H
|
||
DB 'ns'
|
||
DW GRP17
|
||
DB 79H
|
||
J4:
|
||
DB 6
|
||
DB 'mps'
|
||
DW GRP17
|
||
DB 0EBH
|
||
DB 'cxz'
|
||
DW GRP17
|
||
DB 0E3H
|
||
DB 'nge'
|
||
DW GRP17
|
||
DB 7CH
|
||
DB 'nae'
|
||
DW GRP17
|
||
DB 72H
|
||
DB 'nbe'
|
||
DW GRP17
|
||
DB 77H
|
||
DB 'nle'
|
||
DW GRP17
|
||
DB 7FH
|
||
L3:
|
||
DB 3
|
||
DB 'ea'
|
||
DW GRP6
|
||
DB 8DH
|
||
DB 'ds'
|
||
DW GRP6
|
||
DB 0C5H
|
||
DB 'es'
|
||
DW GRP6
|
||
DB 0C4H
|
||
L4:
|
||
DB 5
|
||
DB 'oop'
|
||
DW GRP17
|
||
DB 0E2H
|
||
DB 'odb'
|
||
DW PUT
|
||
DB 0ACH
|
||
DB 'odw'
|
||
DW PUT
|
||
DB 0ADH
|
||
DB 'ahf'
|
||
DW PUT
|
||
DB 9FH
|
||
DB 'ock'
|
||
DW PUT
|
||
DB 0F0H
|
||
L5:
|
||
DB 4
|
||
DB 'oope'
|
||
DW GRP17
|
||
DB 0E1H
|
||
DB 'oopz'
|
||
DW GRP17
|
||
DB 0E1H
|
||
DB 'odsb'
|
||
DW PUT
|
||
DB 0ACH
|
||
DB 'odsw'
|
||
DW PUT
|
||
DB 0ADH
|
||
L6:
|
||
DB 2
|
||
DB 'oopne'
|
||
DW GRP17
|
||
DB 0E0H
|
||
DB 'oopnz'
|
||
DW GRP17
|
||
DB 0E0H
|
||
M3:
|
||
DB 2
|
||
DB 'ov'
|
||
DW GRP1
|
||
DB 88H
|
||
DB 'ul'
|
||
DW GRP10
|
||
DB 20H
|
||
M4:
|
||
DB 2
|
||
DB 'ovb'
|
||
DW PUT
|
||
DB 0A4H
|
||
DB 'ovw'
|
||
DW PUT
|
||
DB 0A5H
|
||
M5:
|
||
DB 2
|
||
DB 'ovsb'
|
||
DW PUT
|
||
DB 0A4H
|
||
DB 'ovsw'
|
||
DW PUT
|
||
DB 0A5H
|
||
N3:
|
||
DB 3
|
||
DB 'ot'
|
||
DW GRP9
|
||
DB 10H
|
||
DB 'eg'
|
||
DW GRP9
|
||
DB 18H
|
||
DB 'op'
|
||
DW PUT
|
||
DB 90H
|
||
O2:
|
||
DB 1
|
||
DB 'r'
|
||
DW GRP13
|
||
DB 0AH
|
||
O3:
|
||
DB 2
|
||
DB 'ut'
|
||
DW GRP4
|
||
DB 0E6H
|
||
DB 'rg'
|
||
DW GRP5
|
||
DB 0
|
||
O4:
|
||
DB 2
|
||
DB 'utb'
|
||
DW GRP4
|
||
DB 0E6H
|
||
DB 'utw'
|
||
DW GRP4
|
||
DB 0E7H
|
||
P3:
|
||
DB 2
|
||
DB 'op'
|
||
DW GRP22
|
||
DB 8FH
|
||
DB 'ut'
|
||
DW GRP5
|
||
DB 3
|
||
P4:
|
||
DB 2
|
||
DB 'ush'
|
||
DW GRP2
|
||
DB 0FFH
|
||
DB 'opf'
|
||
DW PUT
|
||
DB 9DH
|
||
P5:
|
||
DB 1
|
||
DB 'ushf'
|
||
DW PUT
|
||
DB 9CH
|
||
R3:
|
||
DB 6
|
||
DB 'et'
|
||
DW GRP16
|
||
DB 0C3H
|
||
DB 'ep'
|
||
DW PUT
|
||
DB 0F3H
|
||
DB 'ol'
|
||
DW GRP12
|
||
DB 0
|
||
DB 'or'
|
||
DW GRP12
|
||
DB 8
|
||
DB 'cl'
|
||
DW GRP12
|
||
DB 10H
|
||
DB 'cr'
|
||
DW GRP12
|
||
DB 18H
|
||
R4:
|
||
DB 2
|
||
DB 'epz'
|
||
DW PUT
|
||
DB 0F3H
|
||
DB 'epe'
|
||
DW PUT
|
||
DB 0F3H
|
||
R5:
|
||
DB 2
|
||
DB 'epnz'
|
||
DW PUT
|
||
DB 0F2H
|
||
DB 'epne'
|
||
DW PUT
|
||
DB 0F2H
|
||
S3:
|
||
DB 11
|
||
DB 'ub'
|
||
DW GRP7
|
||
DB 2AH
|
||
DB 'bb'
|
||
DW GRP7
|
||
DB 1AH
|
||
DB 'bc'
|
||
DW GRP7
|
||
DB 1AH
|
||
DB 'tc'
|
||
DW PUT
|
||
DB 0F9H
|
||
DB 'td'
|
||
DW PUT
|
||
DB 0FDH
|
||
DB 'ti'
|
||
DW PUT
|
||
DB 0FBH
|
||
DB 'hl'
|
||
DW GRP12
|
||
DB 20H
|
||
DB 'hr'
|
||
DW GRP12
|
||
DB 28H
|
||
DB 'al'
|
||
DW GRP12
|
||
DB 20H
|
||
DB 'ar'
|
||
DW GRP12
|
||
DB 38H
|
||
DB 'eg'
|
||
DW GRP21
|
||
DB 26H
|
||
S4:
|
||
DB 5
|
||
DB 'cab'
|
||
DW PUT
|
||
DB 0AEH
|
||
DB 'caw'
|
||
DW PUT
|
||
DB 0AFH
|
||
DB 'tob'
|
||
DW PUT
|
||
DB 0AAH
|
||
DB 'tow'
|
||
DW PUT
|
||
DB 0ABH
|
||
DB 'ahf'
|
||
DW PUT
|
||
DB 9EH
|
||
S5:
|
||
DB 4
|
||
DB 'casb'
|
||
DW PUT
|
||
DB 0AEH
|
||
DB 'casw'
|
||
DW PUT
|
||
DB 0AFH
|
||
DB 'tosb'
|
||
DW PUT
|
||
DB 0AAH
|
||
DB 'tosw'
|
||
DW PUT
|
||
DB 0ABH
|
||
T4:
|
||
DB 1
|
||
DB 'est'
|
||
DW GRP20
|
||
DB 84H
|
||
U2:
|
||
DB 1
|
||
DB 'p'
|
||
DW PUT
|
||
DB 0FCH
|
||
W4:
|
||
DB 1
|
||
DB 'ait'
|
||
DW PUT
|
||
DB 9BH
|
||
X3:
|
||
DB 1
|
||
DB 'or'
|
||
DW GRP13
|
||
DB 32H
|
||
X4:
|
||
DB 2
|
||
DB 'chg'
|
||
DW GRP3
|
||
DB 86H
|
||
DB 'lat'
|
||
DW PUT
|
||
DB 0D7H
|
||
|
||
|
||
; 8087 MNEMONIC TABLE
|
||
; Similar to 8086 table above, except NOT distinguished by opcode length
|
||
|
||
XM1: ;F2XM1
|
||
DB 1 ;One opcode
|
||
DM "xm1"
|
||
DB 1,0F0H
|
||
|
||
NDPA:
|
||
DB 3
|
||
DM "dd"
|
||
DB 6+ARITH,0C1H
|
||
DM "ddp"
|
||
DB NEEDOP+STACKOP,0
|
||
DM "bs"
|
||
DB 1,0E1H
|
||
|
||
NDPB:
|
||
DB 2
|
||
DM "ld"
|
||
DB 7+NEEDOP+MEMORY,20H
|
||
DM "stp"
|
||
DB 7+NEEDOP+MEMORY,30H
|
||
|
||
NDPC:
|
||
DB 5
|
||
DM "om"
|
||
DB 0+ONEREG+REAL,0D1H
|
||
DM "omp"
|
||
DB 0+ONEREG+REAL,0D9H
|
||
DM "hs"
|
||
DB 1,0E0H
|
||
DM "ompp"
|
||
DB 6,0D9H
|
||
DM "lex"
|
||
DB 3,0E2H
|
||
|
||
NDPD:
|
||
DB 6
|
||
DM "iv"
|
||
DB 6+ARITH,0F1H
|
||
DM "ivp"
|
||
DB NEEDOP+STACKOP,30H
|
||
DM "ivr"
|
||
DB 6+ARITH,0F9H
|
||
DM "ivrp"
|
||
DB NEEDOP+STACKOP,38H
|
||
DM "ecstp"
|
||
DB 1,0F6H
|
||
DM "isi"
|
||
DB 3,0E1H
|
||
|
||
NDPE:
|
||
DB 1
|
||
DM "ni"
|
||
DB 3,0E0H
|
||
|
||
NDPF:
|
||
DB 1
|
||
DM "ree"
|
||
DB 5+NEEDOP+ONEREG,0
|
||
|
||
NDPI:
|
||
DB 13
|
||
DM "add"
|
||
DB 2+NEEDOP+INTEGER,0
|
||
DM "ld"
|
||
DB 3+NEEDOP+INTEGER+EXTENDED,0
|
||
DM "sub"
|
||
DB 2+NEEDOP+INTEGER,20H
|
||
DM "stp"
|
||
DB 3+NEEDOP+INTEGER+EXTENDED,18H
|
||
DM "st"
|
||
DB 3+NEEDOP+INTEGER,10H
|
||
DM "mul"
|
||
DB 2+NEEDOP+INTEGER,8
|
||
DM "div"
|
||
DB 2+NEEDOP+INTEGER,30H
|
||
DM "subr"
|
||
DB 2+NEEDOP+INTEGER,28H
|
||
DM "divr"
|
||
DB 2+NEEDOP+INTEGER,38H
|
||
DM "com"
|
||
DB 2+NEEDOP+INTEGER,10H
|
||
DM "comp"
|
||
DB 2+NEEDOP+INTEGER,18H
|
||
DM "ncstp"
|
||
DB 1,0F7H
|
||
DM "nit"
|
||
DB 3,0E3H
|
||
|
||
NDPL:
|
||
DB 10
|
||
DM "d"
|
||
DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0
|
||
DM "dz"
|
||
DB 1,0EEH
|
||
DM "d1"
|
||
DB 1,0E8H
|
||
DM "dpi"
|
||
DB 1,0EBH
|
||
DM "dl2t"
|
||
DB 1,0E9H
|
||
DM "dl2e"
|
||
DB 1,0EAH
|
||
DM "dlg2"
|
||
DB 1,0ECH
|
||
DM "dln2"
|
||
DB 1,0EDH
|
||
DM "dcw"
|
||
DB 1+NEEDOP+MEMORY,28H
|
||
DM "denv"
|
||
DB 1+NEEDOP+MEMORY,20H
|
||
|
||
NDPM:
|
||
DB 2
|
||
DM "ul"
|
||
DB 6+ARITH,0C9H
|
||
DM "ulp"
|
||
DB NEEDOP+STACKOP,8
|
||
|
||
NDPO:
|
||
DB 1
|
||
DM "p"
|
||
DB NEEDOP+1,0 ;Flag special handling
|
||
|
||
NDPN:
|
||
DB 1
|
||
DM "op"
|
||
DB 1,0D0H
|
||
|
||
NDPP:
|
||
DB 3
|
||
DM "rem"
|
||
DB 1,0F8H
|
||
DM "tan"
|
||
DB 1,0F2H
|
||
DM "atan"
|
||
DB 1,0F3H
|
||
|
||
NDPR:
|
||
DB 2
|
||
DM "ndint"
|
||
DB 1,0FCH
|
||
DM "stor"
|
||
DB 5+NEEDOP+MEMORY,20H
|
||
|
||
NDPS:
|
||
DB 12
|
||
DM "t"
|
||
DB 5+NEEDOP+ONEREG+REAL,0D0H
|
||
DM "tp"
|
||
DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H
|
||
DM "ub"
|
||
DB 6+ARITH,0E1H
|
||
DM "ubp"
|
||
DB NEEDOP+STACKOP,0E0H
|
||
DM "ubr"
|
||
DB 6+ARITH,0E9H
|
||
DM "ubrp"
|
||
DB NEEDOP+STACKOP,0E8H
|
||
DM "qrt"
|
||
DB 1,0FAH
|
||
DM "cale"
|
||
DB 1,0FDH
|
||
DM "ave"
|
||
DB 5+NEEDOP+MEMORY,30H
|
||
DM "tcw"
|
||
DB 1+NEEDOP+MEMORY,38H
|
||
DM "tenv"
|
||
DB 1+NEEDOP+MEMORY,30H
|
||
DM "tsw"
|
||
DB 5+NEEDOP+MEMORY,38H
|
||
|
||
NDPT:
|
||
DB 1
|
||
DM "st"
|
||
DB 1,0E4H
|
||
|
||
NDPW:
|
||
DB 1
|
||
DM "ait"
|
||
DB NEEDOP,0 ;Flag special handling
|
||
|
||
NDPX:
|
||
DB 3
|
||
DM "ch"
|
||
DB 1+ONEREG,0C9H
|
||
DM "am"
|
||
DB 1,0E5H
|
||
DM "tract"
|
||
DB 1,0F4H
|
||
|
||
NDPY:
|
||
DB 2
|
||
DM "l2x"
|
||
DB 1,0F1H
|
||
DM "l2xp1"
|
||
DB 1,0F9H
|
||
|
||
|
||
OPTAB:
|
||
; Table of pointers to mnemonics. For each letter of the alphabet (the
|
||
; starting letter of the mnemonic), there are 5 entries. Each entry
|
||
; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters
|
||
; long, respectively. If there are no mnemonics for a given combination
|
||
; of first letter and length (such as A-2), then the corresponding entry
|
||
; points to NONE. Otherwise, it points to a place in the mnemonic table
|
||
; for that type.
|
||
|
||
; This table only needs to be modified if a mnemonic is added to a group
|
||
; previously marked NONE. Change the NONE to a label made up of the first
|
||
; letter of the mnemonic and its length, then add a new subsection to
|
||
; the mnemonic table in alphabetical order.
|
||
|
||
DW NONE
|
||
DW A3
|
||
DW NONE
|
||
DW A5
|
||
DW NONE
|
||
DW NONE ;B
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;C
|
||
DW C3
|
||
DW C4
|
||
DW C5
|
||
DW NONE
|
||
DW D2 ;D
|
||
DW D3
|
||
DW D4
|
||
DW NONE
|
||
DW NONE
|
||
DW E2 ;E
|
||
DW E3
|
||
DW NONE
|
||
DW E5
|
||
DW NONE
|
||
DW NONE ;F
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;G
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;H
|
||
DW H3
|
||
DW H4
|
||
DW NONE
|
||
DW NONE
|
||
DW I2 ;I
|
||
DW I3
|
||
DW I4
|
||
DW NONE
|
||
DW NONE
|
||
DW J2 ;J
|
||
DW J3
|
||
DW J4
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;K
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;L
|
||
DW L3
|
||
DW L4
|
||
DW L5
|
||
DW L6
|
||
DW NONE ;M
|
||
DW M3
|
||
DW M4
|
||
DW M5
|
||
DW NONE
|
||
DW NONE ;N
|
||
DW N3
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW O2 ;O
|
||
DW O3
|
||
DW O4
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;P
|
||
DW P3
|
||
DW P4
|
||
DW P5
|
||
DW NONE
|
||
DW NONE ;Q
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;R
|
||
DW R3
|
||
DW R4
|
||
DW R5
|
||
DW NONE
|
||
DW NONE ;S
|
||
DW S3
|
||
DW S4
|
||
DW S5
|
||
DW NONE
|
||
DW NONE ;T
|
||
DW NONE
|
||
DW T4
|
||
DW NONE
|
||
DW NONE
|
||
DW U2 ;U
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;V
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;W
|
||
DW NONE
|
||
DW W4
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;X
|
||
DW X3
|
||
DW X4
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;Y
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE ;Z
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
DW NONE
|
||
|
||
NDPTAB:
|
||
;Lookup table for 8087 mnemonics. There is one entry for each letter of the
|
||
;alphabet
|
||
DW NDPA
|
||
DW NDPB
|
||
DW NDPC
|
||
DW NDPD
|
||
DW NDPE
|
||
DW NDPF
|
||
DW NONE ;G
|
||
DW NONE ;H
|
||
DW NDPI
|
||
DW NONE ;J
|
||
DW NONE ;K
|
||
DW NDPL
|
||
DW NDPM
|
||
DW NDPN
|
||
DW NDPO
|
||
DW NDPP
|
||
DW NONE ;Q
|
||
DW NDPR
|
||
DW NDPS
|
||
DW NDPT
|
||
DW NONE ;U
|
||
DW NONE ;V
|
||
DW NDPW
|
||
DW NDPX
|
||
DW NDPY
|
||
DW NONE ;Z
|
||
|
||
;Error message table
|
||
|
||
ERRTAB:
|
||
DM 1,"Register not allowed in immediate value"
|
||
DM 2,"Index or base register must be BP, BX, SI, or DI"
|
||
DM 3,"Only one base register (BX, BP) allowed"
|
||
DM 4,"Only one index register (SI or DI) allowed"
|
||
DM 5,"Only addition allowed on register or undefined label"
|
||
DM 6,"Only one undefined label per expression allowed"
|
||
DM 7,"Illegal digit in hexadecimal number"
|
||
DM 8,"Illegal digit in decimal number"
|
||
DM 10,"Illegal character in label or opcode"
|
||
DM 11,"Label defined twice"
|
||
DM 12,"Opcode not recognized"
|
||
DM 20,"Invalid operand"
|
||
DM 21,'"," and second operand expected'
|
||
DM 22,"Register mismatch"
|
||
DM 23,"Immediate operand not allowed"
|
||
DM 24,'"]" expected'
|
||
DM 25,"Two memory operands not allowed"
|
||
DM 26,"Destination must not be immediate value"
|
||
DM 27,"Both operands must not be registers"
|
||
DM 28,"Operand must be segment register"
|
||
DM 29,"First operand must be register"
|
||
DM 30,"Undefined label not allowed"
|
||
DM 31,"Value out of range"
|
||
DM 32,"Missing or illegal operand size flag"
|
||
DM 33,"Must have label on same line"
|
||
DM 35,"Zero-length string illegal"
|
||
DM 36,"ENDIF without IF"
|
||
DM 37,"One-character strings only"
|
||
DM 38,"Illegal expression"
|
||
DM 39,"End of string not found"
|
||
DM 100,"Undefined label"
|
||
DM 101,"Value out of range (forward)"
|
||
DB 255
|
||
|
||
ERRMES: DM '***** ERROR: '
|
||
NOSPAC: DB 13,10,'File creation error',13,10,"$"
|
||
NOMEM: DB 13,10,'Insufficient memory',13,10,'$'
|
||
NOFILE: DB 13,10,'File not found',13,10,'$'
|
||
WRTERR: DB 13,10,'Disk full',13,10,'$'
|
||
BADDSK: DB 13,10,'Bad disk specifier',13,10,'$'
|
||
ERCNTM: DM 13,10,13,10,'Error Count ='
|
||
SYMSIZE DM 13,10,'Symbol Table size = '
|
||
FRESIZE DM 'Free space = '
|
||
SYMMES: DM 13,10,'Symbol Table',13,10,13,10
|
||
EXTEND: DB 'ASM',0,0
|
||
IFEND: DB 5,'endif'
|
||
IFNEST: DB 2,'if'
|
||
RETSTR: DM 'ret'
|
||
HEXFCB: DB 0,' HEX',0,0,0,0
|
||
DS 16
|
||
DB 0,0,0,0,0
|
||
LSTFCB: DB 0,' PRN',0,0,0,0
|
||
DS 16
|
||
DB 0,0,0,0,0
|
||
PC: DS 2
|
||
OLDPC: DS 2
|
||
LABPT: DS 2
|
||
FLAG: DS 1
|
||
MAXFLG: DS 1
|
||
ADDR: DS 2
|
||
ALABEL: DS 2
|
||
DATA: DS 2
|
||
DLABEL: DS 2
|
||
CON: DS 2
|
||
UNDEF: DS 2
|
||
LENID: DS 1
|
||
ID: DS 80
|
||
CHR: DS 1
|
||
SYM: DS 1
|
||
BASE: DS 2
|
||
HEAP: DS 2
|
||
SYMFLG: DS 1
|
||
SYMLIN: DS 1
|
||
CODE: DS 2
|
||
DATSIZ: DS 1
|
||
RELOC: DS 1
|
||
BCOUNT: DS 1
|
||
COUNT: DS 1
|
||
ERR: DS 1
|
||
LINE: DS 2
|
||
HEXLEN: DS 2
|
||
HEXADD: DS 2
|
||
LASTAD: DS 2
|
||
HEXCNT: DS 1
|
||
CHKSUM: DS 1
|
||
LINFLG: DS 1
|
||
PREV: DS 1
|
||
IFFLG: DS 1
|
||
CHKLAB: DS 1
|
||
ERRCNT: DS 2
|
||
LSTRET: DS 2
|
||
RETPT: DS 2
|
||
LSTDEV: DS 2
|
||
SPC: DS 1
|
||
NOWAIT: DS 1
|
||
IX: DS 2
|
||
IY: DS 2
|
||
HEXPNT: DS 2
|
||
LSTPNT: DS 2
|
||
HEXBUF: DS HEXBUFSIZ
|
||
LSTBUF: DS LSTBUFSIZ
|
||
BUFPT: DS 2
|
||
SRCBUF: DS BUFSIZ
|
||
DS 100H
|
||
ALIGN
|
||
STACK: EQU $
|
||
START: EQU $
|
||
|