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