; Seattle Computer Products 8086 Assembler version 2.00 ; by Tim Paterson ; Runs on the 8086 under 86-DOS SYMWID: EQU 10 FCB: EQU 5CH BUFSIZ: EQU 128 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 DELETE: EQU 19 READ: EQU 20 SETDMA: EQU 26 MAKE: EQU 22 SEQWRT: EQU 21 ;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 ORG 100H PUT 100H JMP BEGIN CPYRHT: DB 'Copyright 1979 by Seattle Computer Products, Inc.' DB 13,10,13,10,'$' BEGIN: MOV SP,STACK MOV DX,HEADER MOV CL,PRINTMES CALL SYSTEM MOV DX,CPYRHT CALL SYSTEM MOV AL,[FCB+17] MOV [SYMFLG],AL ;Save symbol table request flag MOV BX,FCB+9 ;Point to file extension MOV AL,[BX] ;Get source drive letter CALL CHKDSK ;Valid drive? OR AL,AL JZ DEFAULT ;If no extension, use existing drive spec MOV [FCB],AL DEFAULT: INC BX MOV AL,[BX] ;Get HEX file drive letter CMP AL,'Z' ;Suppress HEX file? JZ L0000 CALL CHKDSK L0000: MOV [HEXFCB],AL INC BX MOV AL,[BX] ;Get PRN file drive letter CMP AL,'Z' ;Suppress PRN file? JZ NOPRN CMP AL,'X' ;PRN file to console? JZ NOPRN CALL CHKDSK NOPRN: MOV [LSTFCB],AL CALL ADDEXT MOV DX,FCB MOV CL,OPEN CALL SYSTEM MOV BX,NOFILE INC AL JNZ $+5 JMP PRERR XOR AL,AL MOV [FCB+32],AL ;Zero Next Record field MOV DX,HEXFCB CALL MAKFIL MOV DX,LSTFCB CALL MAKFIL MOV BX,0FFH XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] MOV BX,START+1 ;POINTER TO NEXT BYTE OF INTERMEDIATE CODE MOV [CODE],BX MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE MOV BX,0 MOV [PC],BX ;DEFAULT PROGRAM COUNTER MOV [BASE],BX ;POINTER TO ROOT OF ID TREE=NIL MOV [RETPT],BX ;Pointer to last RET record DEC BX MOV [LSTRET],BX ;Location of last RET MOV BX,[6] ;HL=END OF MEMORY MOV [HEAP],BX ;BACK END OF SYMBOL TABLE SPACE MOV AL,4 MOV [BCOUNT],AL ;CODE BYTES PER RELOCATION BYTE XOR AL,AL MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF MOV [CHKLAB],AL ;LOOKUP ALL LABELS ;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: 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: XCHG DX,BX MOV CL,PRINTMES CALL SYSTEM JMP 0 MAKFIL: MOV SI,DX LODB ;Get drive select byte CMP AL,20H ;If not valid, don't make file JNC RET PUSH DX INC DX MOV BX,FCB+1 MOV CX,8 UP MOV SI,BX MOV DI,DX REP MOVB ;Copy source file name MOV DX,DI MOV BX,SI POP DX MOV CL,DELETE CALL SYSTEM MOV CL,MAKE CALL SYSTEM MOV BX,NOSPAC INC AL ;Success? JZ PRERR MOV CL,OPEN JMP SYSTEM ADDEXT: MOV DX,FCB+9 MOV BX,EXTEND ;Set extension to ASM MOV CX,7 UP MOV SI,BX MOV DI,DX REP MOVB MOV DX,DI MOV BX,SI RET CHKDSK: SUB AL,' ' ;If not present, set zero flag JZ RET SUB AL,20H JZ DSKERR ;Must be in range A-W CMP AL,'X'-'@' JC RET DSKERR: MOV BX,BADDSK JP PRERR ERROR: MOV AL,CL JMP ENDLIN NEXTCHR: XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] INC BL JNZ GETCH ;Buffer empty so refill it MOV DX,80H MOV CL,SETDMA CALL SYSTEM XCHG DX,BX MOV DX,FCB MOV CL,READ CALL SYSTEM OR AL,AL MOV AL,1AH ;Possibly signal End of File JNZ NOMOD ;If nothing read GETCH: MOV AL,[BX] NOMOD: XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] MOV [CHR],AL RET MROPS: 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? RCR SI TEST CL,1 ;Check if register-to-register operation OK RCL SI 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 RCR SI TEST CL,8 ;Check if segment register OK RCL SI 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 AND CH,0FDH ;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: 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 BX,[CON] ;Defined part MOV [DATA],BX MOV BX,[UNDEF] ;Undefined part MOV [DLABEL],BX MOV DL,CH MOV DH,CONST MOV AL,DH RET NREG: PUSH DX CALL GETSYM POP DX MOV AL,DH RET MEM: CALL GETSYM MOV AL,1 CALL GETVAL MOV AL,[SYM] CMP AL,']' MOV CL,24 JNZ ERR1 CALL GETSYM MOV BX,[CON] MOV [ADDR],BX MOV BX,[UNDEF] MOV [ALABEL],BX MOV DL,CH MOV DH,UNDEFID MOV AL,DH RET FLG: CALL GETSYM CMP AL,',' JZ GETOP JP GETOP1 GETVAL: LAHF XCHG AX,BP SAHF PUSH BX MOV BX,0 MOV [CON],BX MOV [UNDEF],BX POP BX MOV AL,[SYM] CMP AL,'+' JZ PLSMNS CMP AL,'-' JZ PLSMNS MOV CH,'+' PUSH CX JP OPERATE PLSMNS: LAHF XCHG AH,AL PUSH AX XCHG AH,AL LAHF XCHG AX,BP SAHF LAHF OR AL,4 ;Flag that a sign was found SAHF LAHF XCHG AX,BP SAHF CALL GETSYM OPERATE: CMP AL,CONST JNZ $+5 JMP CVAL CMP AL,UNDEFID JNZ $+5 JMP UVAL CMP AL,'"' JNZ $+5 STRINGJ:JMP STRING CMP AL,"'" JZ STRINGJ CMP AL,XREG ;Only 16-bit register may index MOV CL,20 JNZ ERR2 LAHF XCHG AX,BP SAHF RCR SI TEST AL,1 ;Check to see if indexing is OK RCL SI MOV CL,1 JZ ERR2 LAHF XCHG AX,BP SAHF MOV AL,DL MOV CL,3 CMP AL,3 ;Check for BX JZ BXJ SUB AL,5 ;Check for BP JZ BPJ DEC AL ;Check for SI MOV CL,4 JZ SIJ DEC AL ;Check for DI JZ DIJ MOV CL,2 ;Invalid base/index register ERR2: JMP ERROR DIJ: LAHF XCHG AX,BP SAHF RCR SI TEST AL,10H ;Check if already seen index register RCL SI JNZ ERR2 OR AL,30H ;Flag seeing index register DI JP LPCHK SIJ: LAHF XCHG AX,BP SAHF RCR SI TEST AL,010H ;Check if already seen index register RCL SI JNZ ERR2 LAHF OR AL,010H ;Flag seeing index register SI SAHF JP LPCHK BXJ: LAHF XCHG AX,BP SAHF RCR SI TEST AL,080H ;Check if already seen base register RCL SI JNZ ERR2 LAHF OR AL,080H ;Flag seeing base register BX SAHF JP LPCHK BPJ: LAHF XCHG AX,BP SAHF RCR SI TEST AL,080H ;Check if already seen base register RCL SI JNZ ERR2 OR AL,0C0H ;Flag seeing base register BP LPCHK: LAHF XCHG AX,BP SAHF POP AX ;Get operator XCHG AH,AL SAHF CMP AL,'-' ;Can't subtract a register MOV CL,5 JZ ERR2 NEXTER: LAHF XCHG AX,BP SAHF LAHF OR AL,4 ;Flag that a term was processed SAHF LAHF XCHG AX,BP SAHF CALL GETSYM CMP AL,'+' JNZ $+5 PJ: JMP PLSMNS CMP AL,'-' JZ PJ LAHF XCHG AX,BP SAHF MOV CH,0 RCR SI TEST AL,010H ;Test INDEX bit RCL SI RCL AL ;BASE bit (zero flag not affected) JZ NOIND ;Jump if not indexed, with BASE bit in carry CMC RCL CH RCL AL ;BP bit RCL CH RCL AL ;DI bit RCL CH ;The low 3 bits now have indexing mode MODE: MOV BX,[UNDEF] MOV AL,BH OR AL,BL LAHF OR CH,080H ;If undefined label, force 16-bit displacement SAHF JNZ RET MOV BX,[CON] CALL SIGNEXT ;Check if 8-bit with sign extended JNZ RET ;If not, use 16-bit displacement LAHF AND CH,07FH ;Reset 16-bit displacement SAHF LAHF OR CH,040H ;Set 8-bit displacement SAHF MOV AL,BH OR AL,BL JNZ RET ;Use it if not zero displacement MOV AL,CH AND AL,7 ;Specify no displacement MOV CH,AL CMP AL,6 ;Check for BP+0 addressing mode JNZ RET LAHF OR CH,040H ;If BP+0, use 8-bit displacement SAHF RET SIGNEXT: MOV AL,BH OR AL,AL JZ HIZERO INC AL JNZ RET HIZERO: MOV AL,BL XOR AL,BH AND AL,80H RET NOIND: MOV CH,6 ;Try direct address mode JNC RET ;If no base register, that's right RCL AL ;Check BP bit JC MODE INC CH ;If not, must be BX JP MODE CVAL: MOV BX,[CON] POP AX XCHG AH,AL SAHF CMP AL,'-' JNZ ADDCON SBB BX,DX SETCON: MOV [CON],BX JMP NEXTER ADDCON: LAHF ADD BX,DX RCR SI SAHF RCL SI JP SETCON UVAL: LAHF XCHG AX,BP SAHF MOV CL,6 RCR SI TEST AL,008H ;Check if undefined label has been seen RCL SI JNZ ERR30 LAHF OR AL,008H ;Flag seeing undefined label XCHG AX,BP SAHF MOV [UNDEF],BX POP AX XCHG AH,AL SAHF CMP AL,'+' ;Undefined label may only be added MOV CL,5 ERR30: JNZ ERR3 JMP NEXTER GETSYM: CALL GETSY MOV AL,[SYM] RET SCANB: MOV AL,[CHR] SCANT: CMP AL,' ' JZ NEXB CMP AL,9 JNZ RET NEXB: CALL NEXTCHR JP SCANT DOLLAR: MOV DX,[OLDPC] MOV AL,CONST MOV [SYM],AL NEXTCHJ: JMP NEXTCHR GETSY: CALL SCANB CMP AL,'$' JZ DOLLAR MOV [SYM],AL OR AL,20H CMP AL,'z'+1 JNC NEXTCHJ CMP AL,'a' JC $+5 JMP LETTER CMP AL,'9'+1 JNC NEXTCHJ CMP AL,'0' JC NEXTCHJ MOV BX,SYM MOV B,[BX],CONST CALL READID LAHF DEC BX SAHF 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 ERR3: 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 STRING: MOV CH,AL MOV AL,[CHR] CMP AL,CH MOV CL,35 MOV DL,AL MOV DH,0 JNZ L0003 CALL ZERLEN L0003: CALL GETCHR LAHF XCHG AX,BP SAHF MOV CL,37 TEST AL,002H JZ ERR3 TEST AL,004H MOV CL,38 JNZ ERR3 LAHF XCHG AX,BP SAHF STRGDAT: MOV AL,DL CMP AL,EOL MOV CL,39 JZ ERR3 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 ERR3 RET GETCHR: CALL NEXTCHR CMP AL,CH JNZ RET CALL NEXTCHR CMP AL,CH JZ RET POP BX JMP CVAL 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 LAHF INC BX SAHF CALL NEXTCHR CMP AL,'0' JC NOMORE OR AL,20H CMP AL,'z'+1 JNC NOMORE CMP AL,'9'+1 JC MOREID CMP AL,'a' JNC MOREID NOMORE: MOV CL,AL MOV AL,CH MOV [LENID],AL OR AL,AL MOV AL,CL RET LETTER: CALL READID MOV AL,CH DEC AL JNZ NOFLG MOV AL,[ID] CMP AL,'l' MOV CL,0 MOV DX,LONG JZ BWFLAG CMP AL,'b' MOV DX,FLAG JZ BWFLAG CMP AL,'w' MOV CL,1 JZ BWFLAG XOR AL,AL NOFLG: DEC AL PUSH BX JNZ L0004 CALL REGCHK L0004: POP BX MOV AL,DH JZ SYMSAV CALL LOOKRET SYMSAV: MOV [SYM],AL RET BWFLAG: XCHG DX,BX MOV AL,[BX] INC AL MOV [BX],CL MOV CL,32 JZ $+5 JMP ERROR MOV AL,5 JP SYMSAV REGCHK: MOV BX,ID MOV CL,[BX] LAHF INC BX SAHF MOV AL,[BX] MOV BX,REGTAB MOV DH,XREG MOV DL,0 CMP AL,'x' JZ SCANREG MOV DH,REG CMP AL,'l' JZ SCANREG MOV DL,4 CMP AL,'h' JZ SCANREG MOV DH,SREG MOV DL,0 MOV BX,SEGTAB CMP AL,'s' JZ SCANREG MOV DH,XREG CMP AL,'p' JZ PREG CMP AL,'i' JNZ RET MOV DL,6 MOV AL,CL CMP AL,'s' JZ RET INC DL CMP AL,'d' RET PREG: MOV DL,4 MOV AL,CL CMP AL,'s' JZ RET INC DL CMP AL,'b' RET SCANREG: MOV AL,CL MOV CX,4 UP MOV DI,BX REPNZ SCAB MOV BX,DI JNZ RET MOV AL,CL ADD AL,DL MOV DL,AL XOR AL,AL RET REGTAB: DB 'bdca' SEGTAB: DB 'dsce' LOOK: MOV CH,[BX] LAHF INC BX SAHF MOV DX,ID CALL CPSLP JZ RET XOR AL,80H MOV CL,AL LAHF DEC BX SAHF MOV AL,[BX] XOR AL,80H CMP AL,CL JNC SMALL INC CH INC CH SMALL: MOV DL,CH MOV DH,0 LAHF ADD BX,DX RCR SI SAHF RCL SI MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] MOV AL,DH OR AL,DL STC JZ RET XCHG DX,BX JP LOOK LOOKRET: MOV AL,CH CMP AL,3 ;RET has 3 letters JNZ LOOKUP LAHF DEC BX SAHF LAHF OR B,[BX],080H SAHF MOV DX,RETSTR+2 CHKRET: MOV SI,DX LODB CMP AL,[BX] JNZ LOOKIT LAHF DEC BX SAHF LAHF DEC DX SAHF DEC CH JNZ CHKRET MOV DX,[LSTRET] MOV AL,DL AND AL,DH INC AL JZ ALLRET MOV BX,[PC] SBB BX,DX CALL SIGNEXT MOV AL,1 JZ RET ALLRET: MOV BX,[RETPT] MOV AL,BH OR AL,BL MOV AL,0 JNZ RET MOV BX,[HEAP] LAHF DEC BX SAHF LAHF DEC BX SAHF LAHF DEC BX SAHF MOV [HEAP],BX XOR AL,AL MOV [BX],AL MOV [RETPT],BX RET LOOKUP: LAHF DEC BX SAHF LAHF OR B,[BX],080H SAHF LOOKIT: MOV BX,[BASE] MOV AL,BH OR AL,BL JZ EMPTY CALL LOOK JC ENTER MOV DX,4 LAHF ADD BX,DX RCR SI SAHF RCL SI MOV AL,[BX] OR AL,AL JZ RET LAHF INC BX SAHF MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] RET ENTER: PUSH BX ;Save pointer to link field CALL CREATE ;Add the node POP SI XCHG SI,BX PUSH SI MOV [BX],DH ;Link new node LAHF DEC BX SAHF MOV [BX],DL POP BX RET ;Zero was set by CREATE EMPTY: CALL CREATE MOV [BASE],DX RET CREATE: MOV AL,[LENID] ADD AL,8 ;Storage needed for the node MOV BX,[HEAP] MOV DL,AL MOV DH,0 SBB BX,DX ;Heap grows downward MOV [HEAP],BX XCHG DX,BX MOV BX,[CODE] ;Check to make sure there's enough SBB BX,DX JB $+5 JMP ABORT PUSH DX MOV BX,LENID MOV CL,[BX] INC CL MOV CH,0 UP MOV SI,BX MOV DI,DX REP MOVB ;Move identifier and length into node MOV DX,DI MOV BX,SI MOV CH,4 XCHG DX,BX NILIFY: MOV [BX],CL ;Zero left and right links INC BX DEC CH JNZ NILIFY XOR AL,AL ;Set zero flag MOV [BX],AL ;Zero defined flag POP DX ;Restore pointer to node RET CPSLP: MOV SI,DX LODB CMP AL,[BX] LAHF INC DX INC BX SAHF JNZ RET DEC CH JNZ CPSLP RET GETLAB: MOV BX,0 MOV [LABPT],BX MOV AL,-1 MOV [FLAG],AL MOV [LONG],AL MOV DH,0 MOV AL,[CHR] CMP AL,' '+1 JC NOT1 LAHF OR DH,001H SAHF NOT1: CALL GETLET JC RET CMP AL,':' JNZ LABCHK CALL NEXTCHR JP LABEL LABCHK: OR AL,AL RCR SI TEST DH,001H RCL SI 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 LAHF INC BX SAHF MOV [BX],DL MOV [LABPT],BX LAHF INC BX SAHF MOV [BX],DH JMP GETLET ERR5: JMP ERROR ASMLIN: MOV BX,[PC] MOV [OLDPC],BX CALL GETLAB JNC $+5 JMP ENDLN MOV BX,LENID MOV AL,[BX] MOV CL,12 SUB AL,2 MOV CH,AL JC ERR5 CMP AL,5 JNC ERR5 LAHF INC BX SAHF 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 LAHF ADD BX,DX RCR SI SAHF RCL SI MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] XCHG DX,BX INC CH MOV CL,CH MOV AL,[BX] LAHF INC BX SAHF OR AL,AL JZ OPERR FINDOP: MOV CH,CL LAHF XCHG AX,BP SAHF MOV DX,ID+1 CALL CPSLP JZ HAVOP MOV DH,0 MOV DL,CH INC DL INC DL LAHF ADD BX,DX RCR SI SAHF RCL SI LAHF XCHG AX,BP SAHF DEC AL JNZ FINDOP OPERR: MOV CL,12 JMP ERROR HAVOP: MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] LAHF INC BX SAHF MOV AL,[BX] ;Get opcode XCHG DX,BX JMP BX GRP1: MOV CX,8A09H CALL MROPS MOV CX,0C6H MOV AL,BH CMP AL,UNDEFID JNZ L0006 CALL STIMM L0006: AND AL,1 JZ BYTIMM MOV AL,0B8H OR AL,BL CALL PUT JMP PUTWOR BYTIMM: MOV AL,0B0H OR AL,BL CALL PUT PUTBJ: JMP PUTBYT IMMED: MOV AL,BH CMP AL,UNDEFID JZ STIMM MOV AL,BL OR AL,AL JZ RET MOV AL,BH CALL IMM OR AL,0C0H CALL PUT FINIMM: MOV AL,CL POP CX RCR SI TEST AL,001H RCL SI JZ PUTBJ CMP AL,83H JZ PUTBJ JMP PUTWOR STIMM: MOV AL,[FLAG] CALL IMM CALL PUTADD JP FINIMM IMM: AND AL,1 OR AL,CL MOV CL,AL CALL PUT MOV AL,CH AND AL,38H OR AL,BL RET PUT: PUSH BX PUSH CX MOV CH,0 ;Flag as pure code CALL GEN POP CX POP BX RET GEN: 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] PUSH BX POP [IY] LAHF INC BX SAHF MOV [CODE],BX RET PUTINC: PUSH BX MOV BX,[PC] LAHF INC BX SAHF MOV [PC],BX JP PUTCD1 PUTCD: PUSH BX PUTCD1: MOV BX,[CODE] MOV [BX],AL LAHF INC BX SAHF MOV [CODE],BX POP BX RET PUTWOR: PUSH CX MOV CH,80H PUSH DX PUSH BX JP PUTBW PUTBYT: PUSH CX MOV CH,40H PUSH DX PUSH BX MOV BX,[DLABEL] MOV AL,BH OR AL,BL JNZ PUTBW MOV BX,[DATA] OR AL,BH JZ PUTBW INC BH JZ PUTBW MOV CL,31 JMP ERROR PUTBW: MOV DX,[DLABEL] MOV BX,[DATA] PUTCHK: MOV AL,DH OR AL,DL JZ NOUNDEF MOV AL,DL CALL PUTCD MOV AL,DH CALL PUTCD MOV AL,BL CALL PUTINC MOV AL,BH RCR SI TEST CH,080H RCL SI JZ SMPUT CALL GEN JP PRET SMPUT: CALL PUTCD CALL GEN1 PRET: POP BX POP DX POP CX RET NOUNDEF: MOV AL,BL MOV CL,BH PUSH CX MOV CH,0 CALL GEN POP CX MOV AL,CL RCR SI TEST CH,080H RCL SI MOV CH,0 JZ PRETJ CALL GEN PRETJ: JP PRET PUTADD: PUSH CX PUSH DX PUSH BX MOV CH,0 MOV CL,AL CALL GEN ;Save the addressing mode as pure code MOV AL,CL MOV CH,80H AND AL,0C7H CMP AL,6 JZ TWOBT ;Direct address? AND AL,0C0H JZ PRET ;Indirect through reg, no displacement? CMP AL,0C0H JZ PRET ;Register to register operation? MOV CH,AL ;Save whether one- or two-byte displacement TWOBT: MOV BX,[ADDR] MOV DX,[ALABEL] JP PUTCHK GRP2: CALL GETOP MOV CX,0FF30H CMP AL,UNDEFID JZ PMEM MOV CH,50H CMP AL,XREG JZ PXREG MOV CH,6 CMP AL,SREG JNZ $+5 JMP PACKREG MOV CL,20 JMP ERROR PMEM: MOV AL,CH CALL PUT MOV AL,CL OR AL,DL JMP PUTADD PXREG: MOV AL,CH OR AL,DL JMP PUT GRP3: CALL GETOP PUSH DX CALL GETOP2 POP BX MOV CX,8614H MOV AL,SREG CMP AL,BH JZ ERR6 CMP AL,DH JZ ERR6 MOV AL,CONST CMP AL,BH JZ ERR6 CMP AL,DH JZ ERR6 MOV AL,UNDEFID CMP AL,BH JZ EXMEM CMP AL,DH JZ EXMEM1 MOV AL,BH CMP AL,DH MOV CL,22 JNZ ERR6 CMP AL,XREG JZ L0008 CALL RR1 L0008: ;RR1 never returns MOV AL,BL OR AL,AL JZ EXACC XCHG DX,BX MOV AL,BL OR AL,AL MOV AL,BH JZ EXACC CALL RR1 EXACC: MOV AL,90H OR AL,DL JMP PUT EXMEM: XCHG DX,BX EXMEM1: CMP AL,BH JZ ERR6 MOV CL,1 ;Flag word as OK CALL NOTAC ;NOTAC never returns ERR6: JMP ERROR GRP4: LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL GETOP POP CX CMP AL,CONST JZ FIXED SUB AL,XREG DEC DL DEC DL OR AL,DL MOV CL,20 JNZ ERR6 MOV AL,CH OR AL,8 JMP PUT FIXED: MOV AL,CH CALL PUT JMP PUTBYT GRP5: LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL GETOP CMP AL,CONST JNZ ERR6 MOV BX,[DLABEL] MOV AL,BH OR AL,BL MOV CL,30 JNZ ERR6 MOV BX,[DATA] POP AX XCHG AH,AL SAHF OR AL,AL JZ ORG DEC AL JZ DSJ DEC AL JZ EQU DEC AL JZ $+5 JMP IF PUTOP: MOV AL,-3 JP NEWLOC ALIGN: MOV AL,[PC] AND AL,1 JZ RET MOV BX,1 DSJ: XCHG DX,BX MOV BX,[PC] LAHF ADD BX,DX RCR SI SAHF RCL SI MOV [PC],BX XCHG DX,BX MOV AL,-4 JP NEWLOC EQU: XCHG DX,BX MOV BX,[LABPT] MOV AL,BH OR AL,BL MOV CL,34 JZ ERR7 MOV [BX],DL LAHF INC BX SAHF MOV [BX],DH RET ORG: MOV [PC],BX MOV AL,-2 NEWLOC: CALL PUTCD MOV AL,BL CALL PUTCD MOV AL,BH CALL PUTCD MOV CH,0C0H JMP GEN1 GRP6: MOV CH,AL MOV CL,4 CALL MROPS MOV CL,23 ERR7: JMP ERROR GRP7: MOV CH,AL MOV CL,1 CALL MROPS MOV CL,80H MOV DX,[DLABEL] MOV AL,DH OR AL,DL JNZ ACCJ XCHG DX,BX MOV BX,[DATA] CALL SIGNEXT XCHG DX,BX JNZ ACCJ LAHF OR CL,002H SAHF ACCJ: JMP ACCIMM GRP8: MOV CL,AL MOV CH,0FEH JP ONEOP GRP9: MOV CL,AL MOV CH,0F6H ONEOP: PUSH CX CALL GETOP ONE: MOV CL,26 CMP AL,CONST JZ ERR7 CMP AL,SREG MOV CL,22 JZ ERR7 POP CX CMP AL,UNDEFID JZ MOP AND AL,1 JZ ROP RCR SI TEST CL,001H RCL SI JZ ROP MOV AL,CL AND AL,0F8H OR AL,DL JMP PUT MOP: MOV AL,[FLAG] AND AL,1 OR AL,CH CALL PUT MOV AL,CL AND AL,38H OR AL,DL JMP PUTADD ROP: OR AL,CH CALL PUT MOV AL,CL AND AL,38H OR AL,0C0H OR AL,DL JMP PUT GRP10: MOV CL,AL MOV CH,0F6H PUSH CX CALL GETOP MOV CL,20 MOV AL,DL OR AL,AL JNZ ERRJ1 MOV AL,DH CMP AL,XREG JZ G10 CMP AL,REG ERRJ1: JNZ ERR8 G10: LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL GETOP POP AX XCHG AH,AL SAHF AND AL,1 MOV [FLAG],AL MOV AL,DH ONEJ: JP ONE GRP11: CALL PUT MOV AL,0AH JMP PUT GRP12: MOV CL,AL MOV CH,0D0H PUSH CX CALL GETOP MOV AL,[SYM] CMP AL,',' MOV AL,DH JNZ ONEJ PUSH DX CALL GETOP SUB AL,REG MOV CL,20 DEC DL OR AL,DL JNZ ERR8 POP DX MOV AL,DH POP CX LAHF OR CH,002H SAHF PUSH CX JMP ONE GRP13: MOV CH,AL MOV CL,1 CALL MROPS MOV CL,80H ACCIMM: CALL IMMED OR CH,004H AND CH,0FDH AIMM: MOV AL,BH AND AL,1 LAHF XCHG AH,AL PUSH AX XCHG AH,AL OR AL,CH CALL PUT POP AX XCHG AH,AL SAHF JNZ $+5 JMP PUTBYT JMP PUTWOR ERR8: JMP ERROR GRP14: LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL GETOP CMP AL,CONST JZ DIRECT MOV CL,20 CMP AL,REG JZ ERR8 CMP AL,SREG JZ ERR8 CMP AL,XREG JNZ NOTRG OR DL,040H OR DL,080H NOTRG: MOV AL,0FFH CALL PUT POP AX XCHG AH,AL SAHF AND AL,38H OR AL,DL MOV CH,AL MOV AL,[LONG] OR AL,AL MOV AL,CH JZ PUTADDJ AND AL,0F7H PUTADDJ: JMP PUTADD DIRECT: MOV AL,[SYM] CMP AL,',' JZ LONGJ POP AX XCHG AH,AL SAHF DEC AL CMP AL,0E9H JZ GOTOP MOV AL,0E8H GOTOP: CALL PUT MOV BX,[DATA] MOV DX,[PC] INC DX INC DX SUB BX,DX MOV [DATA],BX JMP PUTWOR LONGJ: POP AX XCHG AH,AL SAHF CALL PUT CALL PUTWOR CALL GETOP MOV CL,20 CMP AL,CONST JNZ ERR8 JMP PUTWOR GRP16: LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL GETSYM CMP AL,5 JZ LONGR CMP AL,EOL JZ NODEC CMP AL,';' JZ NODEC GETSP: CALL GETOP1 POP CX CMP AL,CONST MOV CL,20 JNZ ERR9 MOV AL,CH AND AL,0FEH CALL PUT JMP PUTWOR LONGR: MOV AL,[LONG] OR AL,AL JNZ NOTLON POP AX XCHG AH,AL SAHF OR AL,8 LAHF XCHG AH,AL PUSH AX XCHG AH,AL NOTLON: CALL GETSYM CMP AL,EOL JZ DORET CMP AL,';' JZ DORET CMP AL,',' JNZ L0011 CALL GETSYM L0011: JP GETSP NODEC: MOV BX,[PC] MOV [LSTRET],BX XCHG DX,BX MOV BX,[RETPT] MOV AL,BH OR AL,BL JZ DORET MOV B,[BX],1 LAHF INC BX SAHF MOV [BX],DL LAHF INC BX SAHF MOV [BX],DH MOV BX,0 MOV [RETPT],BX DORET: POP AX XCHG AH,AL SAHF JMP PUT GRP17: CALL PUT CALL GETOP CMP AL,CONST MOV CL,20 ERR9: JNZ ERR10 MOV BX,[DATA] MOV DX,[PC] LAHF INC DX SAHF SBB BX,DX MOV [DATA],BX CALL PUTBYT MOV BX,[DLABEL] MOV AL,BH OR AL,BL JNZ RET MOV BX,[DATA] CALL SIGNEXT JZ RET MOV CL,31 ERR10: JMP ERROR RET GRP18: CALL GETOP CMP AL,CONST MOV CL,20 JNZ ERR10 MOV BX,[DLABEL] MOV AL,BH OR AL,BL JNZ GENINT MOV BX,[DATA] MOV DX,3 SBB BX,DX JNZ GENINT MOV AL,0CCH JMP PUT GENINT: MOV AL,0CDH CALL PUT JMP PUTBYT GRP19: ;ESC opcode MOV CX,0D800H JMP ONEOP 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 ERR10 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: MOV AL,BH OR AL,BL MOV AL,1 JZ SKIPCD MOV [IFFLG],AL RET SKIPCD: MOV [CHKLAB],AL SKIPLP: XOR AL,AL CALL NEXLIN CALL NEXTCHR CMP AL,1AH JZ END CALL GETLAB JC SKIPLP MOV BX,LENID MOV DX,IFEND MOV CH,[BX] INC CH CALL CPSLP JNZ SKIPLP XOR AL,AL MOV [CHKLAB],AL RET ENDIF: MOV BX,IFFLG MOV AL,[BX] MOV B,[BX],0 MOV CL,36 OR AL,AL JZ ERR11 RET ;********************************************************************* ; ; PASS 2 ; ;********************************************************************* END: MOV CL,4 WREND: MOV CH,0FFH MOV AL,CH CALL GEN DEC CL JNZ WREND MOV AL,[LSTFCB] CMP AL,'Z' JZ NOREOPN CALL ADDEXT MOV DX,FCB MOV CL,OPEN CALL SYSTEM MOV BX,0FFH XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] NOREOPN: MOV AL,-5 MOV [HEXCNT],AL ;FLAG HEX BUFFER AS EMPTY MOV [SKPFLG],AL MOV BX,HEXBUF MOV [HEXPNT],BX MOV BX,LSTBUF MOV [LSTPNT],BX MOV BX,0 MOV [ERRCNT],BX MOV [PC],BX MOV BX,OBJECT MOV [HEXADD],BX XOR AL,AL MOV [FCB+20H],AL ;Set NEXT RECORD field to zero MOV [COUNT],AL CALL STRTLIN MOV BX,START NEXBT: MOV CH,4 MOV CL,[BX] ;Get flag byte LAHF INC BX ;Point to code SAHF CDLP: RCL CL ;Get high bit JC TESTTYP ;Word fixup or special RCL CL JNC $+5 JMP DEFBYT ;Byte fixup MOV AL,[BX] OBJBT: CALL SAVCD NEXCD: INC BX DEC CH ;Still have codes left? JNZ CDLP JP NEXBT TESTTYP: RCL CL JC $+5 JMP DEFWRD MOV AL,[BX] CMP AL,-10 JC $+5 JMP SPCFUN PUSH CX PUSH BX MOV BX,COUNT MOV AL,6 SUB AL,[BX] MOV B,[BX],0 MOV CH,AL MOV AL,' ' JZ NOFIL BLNK: ;Put in 3 blanks for each byte not present CALL LIST CALL LIST CALL LIST DEC CH JNZ BLNK NOFIL: CALL OUTLIN POP BX MOV AL,[BX] PUSH BX CALL REPERR MOV AL,[ERR] CALL REPERR CALL STRTLIN POP BX POP CX JP NEXCD OUTLIN: CALL LIST MOV AL,[LSTFCB] CMP AL,'Z' JZ RET MOV BX,LINFLG MOV AL,[BX] MOV B,[BX],-1 OR AL,AL JNZ CRLF ;Output line only if first time OUTLN: CALL NEXTCHR CALL LIST CMP AL,10 ;Output until linefeed found JNZ OUTLN RET PRTCNT: MOV BX,ERCNTM CALL PRINT MOV BX,[ERRCNT] CALL CONV10 CALL PRNT10 CRLF: MOV AL,13 CALL LIST MOV AL,10 JMP LIST DEFBYT: CALL FIXUP XCHG DX,BX CALL SIGNEXT ;See if in range +127 to -128 XCHG DX,BX JZ OBJBTE ;If so, it's always OK MOV AL,DH OR AL,AL ;Check for range +255 to -256 JZ CHKJMP INC AL JZ CHKJMP RNGERR: MOV AL,101 ;Value out of range MOV [ERR],AL OBJBTE: MOV AL,DL JMP OBJBT CHKJMP: ;Check for short jump. If so, we're out of range; otherwise we're OK MOV AL,[COUNT] DEC AL ;Only one other byte on line? JNZ OBJBTE ;Can't be short jump if not MOV AL,[PREV] ;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? JZ RNGERR JP OBJBTE DEFWRD: CALL FIXUP MOV AL,DL CALL SAVCD MOV AL,DH JMP OBJBT FIXUP: PUSH CX MOV DL,[BX] ;Get pointer to symbol LAHF INC BX SAHF MOV DH,[BX] LAHF INC BX SAHF XCHG DX,BX MOV AL,[BX] ;Whether symbol was defined LAHF INC BX SAHF MOV CL,[BX] ;Get symbol value LAHF INC BX SAHF MOV CH,[BX] XCHG DX,BX MOV DL,[BX] ;Get constant part LAHF INC BX SAHF MOV DH,[BX] XCHG DX,BX LAHF ADD BX,CX ;Add symbol value to constant part RCR SI SAHF RCL SI POP CX XCHG DX,BX OR AL,AL ;See if symbol got defined JNZ RET MOV AL,100 ;Undefined - flag error MOV [ERR],AL MOV DX,0 RET STRTLIN: XOR AL,AL MOV [ERR],AL MOV [LINFLG],AL MOV BX,[PC] MOV AL,BH CALL PHEX MOV AL,BL PHEXB: CALL PHEX MOV AL,' ' LIST: LAHF XCHG AH,AL PUSH AX XCHG AH,AL MOV AL,[LSTFCB] CMP AL,'Z' JZ OUTRET CMP AL,'X' JZ LSTCON POP AX XCHG AH,AL SAHF LAHF XCHG AH,AL PUSH AX XCHG AH,AL AND AL,7FH PUSH BX MOV BX,[LSTPNT] MOV [BX],AL CALL INCBUF MOV [LSTPNT],BX JNZ HAVSPC MOV BX,LSTBUF MOV [LSTPNT],BX PUSH DX XCHG DX,BX PUSH CX MOV CL,SETDMA CALL 5 MOV DX,LSTFCB MOV CL,SEQWRT CALL 5 POP CX POP DX HAVSPC: POP BX OUTRET: POP AX XCHG AH,AL SAHF RET LSTCON: POP AX XCHG AH,AL SAHF LAHF XCHG AH,AL PUSH AX XCHG AH,AL CALL OUTA POP AX XCHG AH,AL SAHF RET PHEX: MOV CH,AL CALL UHALF CALL LIST MOV AL,CH CALL LHALF JMP LIST SPCFUN: INC AL ;End of file? JZ FINI LAHF INC BX SAHF MOV DL,[BX] ;Get address LAHF INC BX SAHF MOV DH,[BX] PUSH BX INC AL ;ORG? JZ DORG INC AL ;PUT? JZ DPUT DDS: ;Handle DS pseudo-op MOV BX,[PC] LAHF ADD BX,DX RCR SI SAHF RCL SI MOV [PC],BX MOV BX,[HEXADD] LAHF ADD BX,DX RCR SI SAHF RCL SI MOV [HEXADD],BX JP SPEND DPUT: ;Handle PUT pseudo-op MOV [HEXADD],DX JP SPEND DORG: ;Handle ORG pseudo-op MOV [PC],DX SPEND: POP BX JMP NEXCD FINI: CALL PRTCNT 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 CALL HEXCRLF JZ L0013 CALL HEXEOF L0013: CALL HEXEOF MOV CL,CLOSE MOV DX,HEXFCB CALL SYSTEM SYMDMP: MOV AL,[SYMFLG] CMP AL,'S' JNZ ENDSYM MOV BX,SYMMES CALL PRINT MOV DX,[BASE] MOV AL,DH OR AL,DL JZ EXIT MOV BX,[HEAP] MOV SP,BX CALL NODE ENDSYM: MOV AL,[LSTFCB] CMP AL,'X' JZ EXIT CMP AL,'Z' JZ ERRCON ;Print error count to console CALL LSTEOF MOV DX,LSTFCB MOV CL,CLOSE CALL 5 ERRCON: MOV AL,'X' MOV [LSTFCB],AL CALL PRTCNT EXIT: JMP 0 RET LSTEOF: MOV AX,[LSTPNT] CMP AX,LSTBUF JZ RET MOV AL,1AH CALL LIST JP LSTEOF NODE: XCHG DX,BX PUSH BX MOV DL,[BX] MOV DH,0 LAHF INC BX SAHF LAHF ADD BX,DX RCR SI SAHF RCL SI MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] MOV AL,DL OR AL,DH JZ L0014 CALL NODE L0014: POP BX MOV CH,[BX] LAHF INC BX SAHF MOV AL,SYMWID SUB AL,CH JNC LENOK MOV AL,1 LENOK: MOV DH,AL WRTSYM: MOV AL,[BX] LAHF INC BX SAHF CALL LIST DEC CH JNZ WRTSYM MOV CH,DH INC CH MOV AL,' ' OUTB: CALL LIST DEC CH JNZ OUTB LAHF INC BX SAHF LAHF INC BX SAHF PUSH BX LAHF INC BX SAHF LAHF INC BX SAHF LAHF INC BX SAHF LAHF INC BX SAHF MOV AL,[BX] CALL PHEX LAHF DEC BX SAHF MOV AL,[BX] CALL PHEX CALL CRLF POP BX MOV DL,[BX] LAHF INC BX SAHF MOV DH,[BX] MOV AL,DH OR AL,DL JNZ NODE RET CONV10: MOV CH,16 MOV DX,0 CONVLP: LAHF ADD BX,BX RCR SI SAHF RCL SI MOV AL,DL ADC AL,AL DAA MOV DL,AL MOV AL,DH ADC AL,AL DAA MOV DH,AL RCL CL DEC CH JNZ CONVLP RET PRNT10: XCHG DX,BX MOV CH,'0'-' ' ;Enable leading zero suppression MOV AL,CL CALL LODIG MOV AL,BH CALL HIDIG MOV AL,BH CALL LODIG MOV AL,BL CALL HIDIG MOV AL,BL MOV CH,0 ;Don't suppress last digit LODIG: CALL LHALF DIGIT: CMP AL,'0' JZ SUPZ MOV CH,0 ;Turn off zero suppression if not zero SUPZ: SUB AL,CH ;Convert leading zeros to blanks JMP LIST HIDIG: CALL UHALF JP DIGIT HEXEOF: MOV AL,1AH CALL PUTCHR JNZ HEXEOF RET SAVCD: MOV [PREV],AL PUSH BX PUSH CX LAHF XCHG AH,AL PUSH AX XCHG AH,AL PUSH DX CALL CODBYT POP DX MOV BX,COUNT INC B,[BX] MOV AL,[BX] CMP AL,7 JNZ NOEXT MOV B,[BX],1 MOV AL,' ' CALL OUTLIN MOV AL,' ' MOV CH,5 TAB: CALL LIST DEC CH JNZ TAB NOEXT: POP AX XCHG AH,AL SAHF CALL PHEXB POP CX MOV BX,[PC] LAHF INC BX SAHF MOV [PC],BX MOV BX,[HEXADD] LAHF INC BX SAHF MOV [HEXADD],BX POP BX RET REPERR: OR AL,AL JZ RET LAHF XCHG AH,AL PUSH AX XCHG AH,AL MOV BX,ERRMES CALL PRINT POP AX XCHG AH,AL SAHF CALL PHEX MOV BX,ENDMES CALL PRINT MOV BX,[ERRCNT] LAHF INC BX SAHF MOV [ERRCNT],BX RET PRINT: MOV AL,[BX] CALL LIST OR AL,AL JS RET LAHF INC BX SAHF JP PRINT OUTA: MOV DL,AL MOV CL,2 SYSTEM: PUSH CX PUSH DX PUSH BX CALL 5 POP BX POP DX POP CX RET CODBYT: LAHF XCHG AH,AL PUSH AX XCHG AH,AL MOV AL,[HEXFCB] CMP AL,'Z' JNZ $+5 JMP OUTRET MOV DX,[LASTAD] MOV BX,[HEXADD] MOV [LASTAD],BX LAHF INC DX SAHF MOV AL,[HEXCNT] CMP AL,-5 JZ NEWLIN OR AL,AL SBB 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 XCHG AH,AL SAHF 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 BX,[HEXLEN] MOV CH,AL CALL UHALF MOV [BX],AL CALL INCBUF MOV AL,CH CALL LHALF MOV [BX],AL MOV AL,-6 MOV [HEXCNT],AL MOV AL,[CHKSUM] ADD AL,CH NEG AL CALL HEXBYT HEXCRLF: MOV AL,13 CALL PUTCHR MOV AL,10 PUTCHR: MOV BX,[HEXPNT] MOV [BX],AL CALL INCBUF MOV [HEXPNT],BX JNZ RET PUSH BX MOV BX,SKPFLG MOV AL,[BX] MOV B,[BX],0 ;Buffer filled, don't skip next time POP BX OR AL,AL ;Both buffers filled? JNZ RET MOV CL,SETDMA XCHG DX,BX CALL SYSTEM MOV DX,HEXFCB MOV CL,SEQWRT CALL SYSTEM XCHG DX,BX OR AL,AL JZ RET 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 INCBUF: INC BX CMP BX,HEXBUF+BUFSIZ JZ RET CMP BX,LSTBUF+BUFSIZ JZ RET CMP BX,HEXBUF+BUFSIZ+BUFSIZ JNZ RET MOV BX,HEXBUF ;Wrap back to first buffer RET NONE: DB 0 ; 8086 MNEMONIC TABLE 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 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 5 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 2 DB 'oope' DW GRP17 DB 0E1H DB 'oopz' DW GRP17 DB 0E1H 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 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 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 OPTAB: 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 NONE 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 NONE 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 NONE 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 HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.00' DB 13,10,'$' ERRMES: DM '***** ERROR no. ' NOSPAC: DB 13,10,'No directory space',13,10,24H ENDMES: DM 'H',13,10 NOMEM: DB 13,10,'Insufficient memory',13,10,'$' NOFILE: DB 13,10,'File not found',13,10,'$' WRTERR: DB 13,10,'Disk write error',13,10,'$' BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' ERCNTM: DM 13,10,13,10,'Error Count =' SYMMES: DM 13,10,'Symbol Table',13,10,13,10 EXTEND: DB 'ASM',0,0,0,0 IFEND: DB 5,'endif' RETSTR: DM 'ret' HEXFCB: DB 0,' HEX',0,0,0,0 DS 16 DB 0 LSTFCB: DB 0,' PRN',0,0,0,0 DS 16 DB 0 PC: DS 2 OLDPC: DS 2 LABPT: DS 2 FLAG: DS 1 LONG: DS 1 ADDR: DS 2 ALABEL: DS 2 DATA: DS 2 DLABEL: DS 2 CON: DS 2 UNDEF: DS 2 LENID: DS 1 ID: DS 80 CHR: DS 1 SYM: DS 1 BASE: DS 2 HEAP: DS 2 SYMFLG: DS 1 CODE: DS 2 DATSIZ: DS 1 RELOC: DS 1 BCOUNT: DS 1 COUNT: DS 1 ERR: DS 1 HEXPNT: DS 2 HEXLEN: DS 2 HEXADD: DS 2 LASTAD: DS 2 HEXCNT: DS 1 CHKSUM: DS 1 SKPFLG: DS 1 LINFLG: DS 1 PREV: DS 1 IFFLG: DS 1 CHKLAB: DS 1 LSTPNT: DS 2 ERRCNT: DS 2 LSTRET: DS 2 RETPT: DS 2 HEXBUF: DS BUFSIZ+BUFSIZ LSTBUF: DS BUFSIZ BC: DS 2 DE: DS 2 HL: DS 2 IX: DS 2 IY: DS 2 DS 50 STACK: EQU $ START: EQU $