* * GET HERE WHEN END PSEUDO-OP IS FOUND OR WHEN END OF FILE * OCCURS IN SOURCE STATEMENTS. CONTROL IS SET FOR EITHER * PASS 2 OR ASSEMBLEY TERMINATES IF FINISHED. * EASS0 POP H GET RID OF GTLIN'S RETURN ADDRESS EASS CALL CPYCL CLOSE ALL COPY FILES MVI D,0 REWIND IN-FILE LDA INUM CALL SYS DB SPAOP CALL ERR0 LXI H,'0'*256+'0' SET LINO TO '0000' SHLD LINO SHLD LINO+2 LXI H,PASI PASS INDICATOR MOV A,M CPI 1 JZ EASS1 END OF PASS 2? JNC SYM7 IN PASS 3? * * SET UP FOR PASS 2 * INR M SET FOR PASS 2 MVI A,0 RESET IFFLG STA IFFLG CALL OUTLF OUTPUT A LINEFEED TO CONSOLE CALL ORDER ORDER THE SYM TAB JMP ASM3 * * * DONE WITH PASS 2 * EASS1 LDA BNUM IS THERE A BINARY FILE? INR A JZ EASS2 NO-SKIP AHEAD CALL UPDATE YES-MAKE SURE IT IS UPDATED LDA XQFLG XEQ ADDRESS? ORA A JZ EASS2 NO-SKIP AHEAD LXI D,XQADR POINT TO ADDRESS LXI B,2 TWO BYTES LDA BNUM CALL SYS DB WBLOP CALL ERR0 * EASS2 CALL OUTCR OUTPUT A CRLF TO CONSOLE LDA LNUM CALL NEWPAGE FORMFEED LDA SNUM IS THERE A SYMBOL FILE? INR A JZ DONE NO-DONE LXI H,PASI INR M YES-SET FOR PASS 3 * * OUTPUT SYMBOL TABLE * LDA POFLG PAGNATION WANTED? CPI '+' JNZ SYMP2 NO MVI A,1 YES-RESET COUNT OF LINES ON PAGE STA PGCNT * SYMP2 XRA A SYMP3 STA SCNT SET LINE COUNT LXI H,SYMAD GET SYMBOL TABLE ADDRESS MOV D,H MOV E,L SYM1 LXI B,LLAB-1 PROCESS SYMBOLS IN ALPHABETICAL ORDER MOV A,M FETCH CHARACTER ORA A CHECK FOR END OF TABLE JZ SYM3 DAD B XCHG DAD B XCHG INR C SYMBOL CHARACTER COUNT CALL COMO COMPARE SYMBOLS, CLEAR CARRY IF NEW LOW SYMBOL INX H INX D LXI B,LLAB+2 JC SYM2 JUMP IF LARGE SYMBOL MOV D,H SET NEW LOW (ALPHABETICALLY) SYMBOL MOV E,L SYM2 DAD B JMP SYM1 SYM3 XCHG MOV A,M DCR A JM SYMDONE INR A SHLD SYMSAV CALL SYMOT LDA XOFLG CROSS REFERENCE WANTED? CPI '+' JZ ASM3 YES * * OUTPUT SYMBOL TABLE * LDA SLNSZ GET SYMLIST MAX LINE SIZE MOV B,A LDA SCNT GET LINE COUNT INR A CMP B LINE FILLED? SYM7 LHLD SYMSAV MVI M,-1 DELETE SYMBOL JC SYMP3 CALL SOUT IF LINE FULL OUTPUT IT CALL PAUSE PAUSE/EXIT ON SPACEBAR/MODE SELECT JMP SYMP2 * * SYMOT MVI C,LLAB SYM4 MOV B,A ORA A JNZ SYM5 MVI B,' ' GET A BLANK * SYM5 CALL OUT8 INX H MOV A,M GET A SYMBOL DCR C JNZ SYM4 MVI C,3 CALL BLKO MOV D,M INX H MOV E,M PUSH H CALL ADOUT POP D MVI C,5 CALL BLKO RET . * SYMDONE CALL SOUT MAKE SURE LAST UPDATE IS OUTPUT LDA SNUM CALL NEWPAGE MOVE TO NEW PAGE JMP DONE * ********** * * OUTCR MVI B,CR OUTPUT A CRLF TO CONSOLE CALL OUTER DO THE CR,THEN FALL THROUGH TO LF OUTLF MVI B,LF OUTPUT A LINEFEED TO CONSOLE OUTER MVI A,1 CALL WB CALL ERR0 RET . * **************************************** * * * THIS ROUTINE SCANS THROUGH A CHARACTER STRING UNTIL * THE FIRST NON BLANK CHARACTER IS FOUND * * ON RETURN CARRY = 1 INDICATES A CR AS FIRST NON BLANK CHR * SBLK LHLD PNTR FETCH ADDRESS SBL1 MOV A,M FETCH CHARACTER INX H CPI ' ' JZ SBL1 DCX H SHLD PNTR RET * **************************************** * * THE FOLLOWING IS ADDED FOR "COPY" STMNTS TO ALLOW * COPYING FROM SOURCE FILES. GLENN S. TENNEY 77-02-15 * CPYPO EQU $ POP ONE FILE FROM COPY STACK LXI D,CPYSS+1 FROM ADDR LXI H,CPYSS TO ADDR MVI B,CPYNN-1 LENGTH CALL MOVL MOVE FM LEFT SIDE MVI M,0FFH FLAG AS END OF CPY STACK LHLD NAMPTR MOVE TITLE NAME POINTER LXI D,-18 DAD D SHLD NAMPTR RET . COPY NOW POPPED * MOVL LDAX D GET BYTE TO MOVE FROM RIGHT MOV M,A MOVE IT INX D NEXT SENDING FIELD INX H NEXT RCV FIELD DCR B DROP COUNT JNZ MOVL NOT DONE YET RET . MOVE FM LEFT ALL DONE * * MOVR LDAX D GET CHAR TO MOVE FM RIGHT MOV M,A MOVE ONE CHAR DCX D NEXT SENDING FIELD DCX H NEXT RCV FIELD DCR B DROP COUNT JNZ MOVR NOT DONE YET RET . MOVE FM RIGHT ALL DONE * * CPY EQU $ THIS HANDLES THE "COPY" PSUEDO LDA CPYSS+CPYNN-1 GET LAST CPY FILE IN STACK CPI 0FFH IS THERE ROOM FOR ANOTHER JNZ ERRV NO--SHOW VALUE ERROR CALL SBLK SCAN TO NON BLANK JC ERRS INVALID IF NO NAME DCX H DROP BACK TO NAME-1 CALL NAME PROCESS NAME AND OPEN IT MOV C,A SAVE FILE NUMBER MVI B,CPYNN-1 LENGTH LXI D,CPYSS+CPYNN-2 SENDING FIELD LXI H,CPYSS+CPYNN-1 RCV FIELD CALL MOVR MOVE FROM RIGHT MOV M,C POST NEW FILE NUMBER LDA PASI PASS 1 OR 2 ORA A RZ . RET IF PASS ONE JMP COMNT PASS TWO=COMMENT * * **************************************** * CLER MVI M,' ' INX H CMP L JNZ CLER RET . * * ZBUF XRA A GET THE ZERO LXI D,ABUF+35 MVI B,35 ZBU1 DCX D STAX D DCR B JNZ ZBU1 RET * * SEAR LDAX D FETCH CHAR CMP M JNZ INCA INX H INX D DCR C JNZ SEAR RET . GOT IT * INCA MOV A,C ADD E MOV E,A JNC INCA1 INR D INCA1 INR C RESET ZERO FLAG RET * * BLKO CALL BLK1 DCR C JNZ BLKO RET * BLK1 MVI B,' ' JMP OUT8 * * COMO ORA A CLEAR CARRY FLAG CO1 LDAX D SBB M JZ CO2 CO2 DCX D DCX H DCR C JNZ CO1 RET * * RMOV LDAX D DCX D CMP C RZ MOV M,A DCX H JMP RMOV * * * * ADEC LXI H,0 ADE1 LDAX B ORA A RZ MOV D,H MOV E,L DAD H DAD H DAD D DAD H SUI 48 CPI 10 CMC RC MOV E,A MVI D,0 DAD D INX B JMP ADE1 * * AHEX LXI H,0 AHE1 LDAX B CALL MAP MAP FROM LOWER TO UPPER CASE ORA A RZ DAD H DAD H DAD H DAD H CALL AHS1 CPI 10H CMC RC ADD L MOV L,A INX B JMP AHE1 * * AHS1 SUI 48 CPI 10 RC SUI 7 CPI 10 RNC MVI A,-1 RET * * AOCT LXI H,0 AOC1 LDAX B ORA A RZ DAD H DAD H DAD H SUI '0' CPI 8 CMC RC ADD L MOV L,A INX B JMP AOC1 * * ABIN LXI H,0 ABI1 LDAX B ORA A RZ . DAD H SUI '0' CPI 2 CMC . RC . ADD L MOV L,A INX B JMP ABI1 * BINH LXI H,HCON BINH0 MOV B,A RAR RAR RAR RAR CALL BIN1 MOV M,A INX H MOV A,B CALL BIN1 MOV M,A RET * * BIN1 ANI 0FH ADI 48 CPI 58 RC ADI 7 RET * * ADOUT MOV A,D RAL MOV C,A MOV A,D CALL DUMO MOV A,C RAR MOV A,E * * DUMO CALL BINH LXI H,HCON MOV B,M CALL OUT8 INX H MOV B,M * * OUT8 LDA SNUM PUSH H PUSH D PUSH B LHLD SBPTR PLACE BYTE IN SBUF MOV M,B INX H SHLD SBPTR POP B POP D POP H RET * **************************************** * * * THIS ROUTINE CHECKS THE LEGAL OPCODES IN BOTH PASS 1 AND * PASS 2. IN PASS 1 THE PROGRAM COUNTER IS INCREMENTED BY * THE CORRECT NUMBER OF BYTES. AN ADDRESS IS ALSO SET SO * THAT AN INDEXED JUMP CAN BE MADE TO PROCESS THE OPCODE * FOR PASS2. * * OPCD CALL SOPC SEARCH OPTAB FOR MATCH OF OPBUF LDA IFFLG IF FLAG SET? ORA A JNZ OPCD1 YES-CHECK FOR IF OR ENDF PSEUDO-OPS * LHLD ASPC GET PC LDAX D GET TYPE ANI 3 MASK FOR BYTE COUNT ADD L ADD TO PC MOV L,A MVI A,0 ADC H MOV H,A SHLD ASPC STORE NEW PC * LDA PASI PASS 1? ORA A JNZ OPCD2 NO-CONTINUE LDAX D GET TYPE/BYTE COUNT ANI 0DCH IS IT A PSEUDO OP (TYPE=0)? RNZ . NO-DON'T PROCCESS OPS IN PASS 1 * OPCD2 LDAX D GET TYPE ANI 0FCH MASK OUT BYTE COUNT RRC . ROTATE TO GET TABLE ADDRESS RRC . LXI H,OPTJT ADD TO OP TYPE JUMP TABLE BASE ADD L MOV L,A INX D LDAX D GET VALUE (BINARY OF OPCODE) STA TEMP SAVE VALUE PCHL . DO INDEXED JUMP TO TYPE HANDLERS * * * IF FLAG SET, CHECK FOR IF OR ENDF * OPCD1 LDAX D GET TYPE ORA A JNZ IFLTS NOT-PSEUDO, GO CHECK FOR IF LIST FLAG INX D LDAX D GET OPCODE VALUE CPI IFCOD IF PSEUDO OP? JZ IFPRC YES CPI EFCOD ENDF PSEUDO OP? JZ ENDIF YES JMP IFLTS NEITHER-CHECK FOR IF LIST FLAG * ********** * * * SEARCH OPCODE TABLE * (OPBUF IS AT END OF OPTAB SO THAT IF) * (BAD OPCODE IS USED, WILL MATCH ON ITSELF) * (THIS SAVES TEST FOR END IN LOOP FOR SPEED) * SOPC LXI H,OPBUF COPY ABUF INTO OPBUF LXI D,ABUF LXI B,ABUF+4 IS OPCOD LENGTH LESS THAN 4? LDAX B ORA A JZ SOPC4 YES-SKIP AHEAD POP PSW NO-OPCODE ERROR,GET RID OR RET ADR JMP OERR * * SOPC4 LDAX D ORA A JZ SOPC5 DONE COPY CALL MAP MOV M,A INX D INX H JMP SOPC4 * * SOPC5 MVI M,' ' ENDFILL OPBUF WITH BLANKS INX H MVI M,' ' INX H MVI M,' ' MVI A,57H SET OPBUFS TYPE TO 57-OPCODE ERROR STA OPBUF+4 IN CASE IT IS FIRST MATCH * * HASH * LXI H,OPBUF MOV A,M INX H XRA M INX H XRA M INX H XRA M ANI 1FH * * SET TO PROPER GROUP * LXI D,OPHSH ADD A MOV L,A MVI H,0 DAD D XCHG . LDAX D MOV L,A INX D LDAX D MOV H,A * * START LINEAR SEARCH * MVI B,4 SOPC1 LXI D,OPBUF MOV C,B SOPC2 LDAX D CMP M JNZ SOPC3 NON-MATCH INX H INX D DCR C JNZ SOPC2 * MATCH XCHG . RET . * * * NON-MATCH * SOPC3 MOV E,C ADD OVER REMAINDER OF ENTRY INR E INR E MVI D,0 DAD D JMP SOPC1 GO CHECK NEXT ENTRY * * * OPCODE HASH TABLE * OPHSH DW HASH0 DW HASH1 DW HASH2 DW HASH3 DW HASH4 DW HASH5 DW HASH6 DW HASH7 DW HASH8 DW HASH9 DW OPBUF NO HASH TO HERE DW HASHB DW HASHC DW HASHD DW HASHE DW HASHF DW HAS10 DW HAS11 DW HAS12 DW HAS13 DW HAS14 DW HAS15 DW HAS16 DW HAS17 DW HAS18 DW HAS19 DW HAS1A DW OPBUF NO HASH TO HERE DW HAS1C DW HAS1D DW HAS1E DW HAS1F WHEW..THAT WAS BORING TO TYPE * * * OPCODE TYPE JUMP TABLE * OTJLN EQU 24 LENGTH OF OPTJT BNDC2 EQU >$ 256 BOUNDRY CHECK BNDC3 EQU BNDC2+OTJLN-1 * IF 0-$ ENDF * OPTJT JMP PSEU JMP ASTO JMP TYP2 JMP TYP3 JMP TYP4 JMP TYP5 JMP TYP6 JMP ERRO NO MATCH TILL OPBUF FOUND * **************************************** * * * OPCODE ERROR * OERR LXI B,3 LEAVE 3 BYTES FOR PATCH LHLD ASPC DAD B SHLD ASPC JMP ERRO * * * LABEL ERROR * LERR LXI B,3 LEAVE 3 BYTES FOR PATCH LHLD ASPC DAD B SHLD ASPC JMP ERRL * * PSEU LXI H,ABUF+4 SET BUFFER ADDRESS MOV A,M FETCH CHARACTER AFTER OPCODE ORA A SHOULD BE A ZERO JNZ OERR LDAX D CPI 15 JZ ENDIF CPI 14 JZ IFPRC LDA IFFLG ORA A JNZ IFLTS IGNORE IF IF FLAG SET LDA PASI PASS INDICATOR ORA A JZ PSU1 JMP PSU2 * **************************************** * * * THIS ROUTINE IS USED TO PROCESS LABELS * * IT CHECKS WHETHER A LABEL IS IN THE SYMBOL TABLE OR NOT * ON RETURN Z=1 MEANS A MATCH WAS FOUND AND H,L CONTAIN THE * ASSOCIATED WITH THE LABEL. OTHERWISE D,E POINT TO THE NEX * LOCATION IN THE TABLE. THE REGISTER NAMES A,B,C,D,E,H,L,M * ARE PREDEFINED BY THE SYSTEM AND NEED NOT BE ENTERED BY T * ON RETURN C=1 INDICATES A LABEL ERROR * SLAB MOV D,A SAVE CHARACTER LDA IFFLG IF FLAG SET? ORA A MOV A,D JNZ SLAB2 YES-JUST SKIM OVER LABLE AND RETURN CPI 'A' CHECK FOR LEGAL CHARACTER RC . RETURN IF ILLEGAL CHARACTER CPI 'z'+1 CHECK FOR ILLEGAL CHARACTER CMC RC . ILLEGAL CHARACTER LXI D,ABUF CALL ALPS PLACE SYMBOL IN BUFFER LXI H,ABUF SET BUFFER ADDRESS LDA PASI GET PASS INDICATOR CPI 2 INR A RESET ZERO FLAG RNC DCR B CHECK IF ONE CHARACTER JNZ SLA1 * * CHECK IF PREDEFINED REGISTER NAME * MOV A,M FETCH CHARACTER CALL MAP UPSHIFT CPI 'M'+1 JNC SLA1 NOT 'A'-'M' SUI 'A' CONVERT INTO TABLE INDEX LXI H,RTAB ADD L (ONLY NEED 8-BIT ADD, RTAB CROSSES NO BOUNDRIES) MOV L,A INDEX INTO TABLE * MOV A,M GET VALUE FROM TABLE ORA A IS IT -1? JM SLA1 YES-NOT REGISTER VALUE MOV L,A NO-IS REGISTER VALUE MVI H,0 MOVE VALUE INTO HL XRA A RESET CARRY, SET ZERO FLAGS RET * * * CHECK SYMBOL TABLE FOR LABEL * * (LOOP NOT USED IN SRCH TO SAVE TIME) * (ABUF COPIED TO END TO SAVE TIME) * (IE-NO NEED TO CHECK FOR END IN LOOP) * SLA1 LXI D,ABUF COPY ABUF TO END OF SYMTAB LHLD STEND MVI C,5 * SLA2 LDAX D MOV M,A INX H INX D DCR C JNZ SLA2 * LDA PASI SPECIAL SEARCH IN PASS 2 CPI 1 JNZ SLA22 * LDA ABUF GET FIRST CHAR OF SYM CPI 'Z'+1 LOWER CASE? JC SLA21 SUI 32 UPSHIFT * SLA21 SUI 65 REL TO ZERO MOV L,A MVI H,0 DAD H *2 LXI D,HASHT ADDR OF HASH TABLE DAD D INDEX IN MOV A,M GET ADDR OF A GROUP OF SYMBOLS INX H MOV H,M MOV L,A JMP SRCH * SLA22 LXI H,SYMAD POINT TO START OF SYMTAB JMP SRCH SEARCH THROUGH IT * * SRCH0 DAD B ADD TO NEXT ENTRY OF SYMTAB SRCH LXI D,ABUF POINT TO LABLE LOOKING FOR LDAX D CMP M JZ SRCH1 MATCH 1ST LETTER LXI B,LLAB+2 JMP SRCH0 * * SRCH1 INX H INX D LDAX D CMP M JZ SRCH2 MATCH 2ND LETTER LXI B,LLAB+2-1 JMP SRCH0 * * SRCH2 INX H INX D LDAX D CMP M JZ SRCH3 MATCH 3RD LETTER LXI B,LLAB+2-2 JMP SRCH0 * * SRCH3 INX H INX D LDAX D CMP M JZ SRCH4 MATCH 4TH LETTERR LXI B,LLAB+2-3 JMP SRCH0 * * SRCH4 INX H INX D LDAX D CMP M JZ SRCH5 MATCH 5TH LETTER LXI B,LLAB+2-4 JMP SRCH0 * * SRCH5 LDA STEND+1 PAST END OF TABLE? CMP H JC NMTCH YES JNZ MATCH LDA STEND CMP L JC NMTCH YES * MATCH XCHG LHLD STEND REMARK END OF SYMTAB WITH A ZERO MVI M,0 INX D LDAX D GET VALUE MOV H,A INX D LDAX D MOV L,A XRA A SET ZERO (MATCH) FLAG RET * * * NO MATCH * NMTCH LHLD STEND REMARK END OF SYMTAB WITH A ZERO MVI M,0 XCHG . SET DE TO POINT TO END OF SYMTAB XRA A RESET CARRY FLAG (NO ERROR) INR A RESET ZERO FLAG (NO MATCH) RET . * * * SCAN OVER LABEL AND IGNORE IT * SLAB2 CPI ' '+1 END OF LABEL? INX H MOV A,M JNC SLAB2 NOT YET DCX H NOW SHLD PNTR CMC . RESET CARRY (ERROR) FLAG RET . * * **************************************** * * * THIS ROUTINE SCANS THE INPUT LINE AND PLACES THE OPCODES * AND LABELS IN THE BUFFER. THE SCAN TERMINATES WHEN A * CHARACTER OTHER THAN 0-9 OR A-Z IS FOUND * ALPS MVI B,0 SET COUNT ALP1 STAX D STORE CHARACTER IN BUFFER INR B INCREMENT COUNT MOV A,B FETCH COUNT CPI 34 MAXIMUM BUFFER SIZE RNC . BUFFER FILLED INX D INCREMENT BUFFER INX H INCREMENT INPUT ADDRESS SHLD PNTR SAVE LINE POINTER MOV A,M FETCH CHARACTER CPI '0' CHECK FOR LEGAL CHARACTERS RC CPI '9'+1 JC ALP1 CPI 'A' RC CPI 'z'+1 JC ALP1 RET * **************************************** * * THIS ROUTINE IS USED TO SCAN THROUGH THE INPUT LINE TO * FETCH THE VALUE OF THE OPERAND FIELD. ON RETURN THE VALUE * OF THE OPERAND IS CONTAINED IN REGISTERS H,L. * ASBL CALL SBLK GET FIRST ARGUMENT ASCN LHLD PNTR GET LINE POINTER XRA A STA GTLT MOV A,M GET FIRST CHARACTER LXI H,0 SHLD OPRD INITIALIZE OPERAND INR L MOV H,A SHLD OPRI INITIALIZE OPERAND INDICATOR * NXT1 LHLD PNTR FETCH SCAN POINTER DCX H CALL ZBUF CLEAR BUFFER STA SIGN ZERO SIGN INDICATOR * NXT2 INX H INCREMENT POINTER MOV A,M FETCH NEXT CHARACTER CPI '<' JNZ NXT1A STA GTLT JMP NXT2 * * NXT1A CPI '>' JNZ NXT1B STA GTLT JMP NXT2 * NXT1B CPI ' '+1 JC SEND JUMP IF CR OR BLANK CPI ',' FIELD SEPARATOR JZ SEND * * CHECK FOR OPERATORS * CPI '+' CHECK FOR PLUS JZ NXT3 INR B CPI '-' CHECK FOR MINUS JZ NXT3 INR B CPI '*' JZ NXT3 INR B CPI '/' JNZ NXT4 * NXT3 MOV A,B STA SIGN LDA OPRI FETCH OPERAND INDICATOR CPI 2 CHECK FOR TWO OPERATORS JZ ERRS SYNTAX ERROR MVI A,2 STA OPRI SET INDICATOR JMP NXT2 * * * CHECK FOR OPERANDS * NXT4 MOV C,A SAVE CHARACTER LDA OPRI GET INDICATOR ORA A CHECK FOR TWO OPERANDS JZ ERRS SYNTAX ERROR MOV A,C CPI '$' LC EXPRESSION JNZ ASC3 INX H INCREMENT POINTER SHLD PNTR SAVE POINTER LHLD ASPC FETCH LOCATION COUNTER JMP AVAL * * * CHECK FOR ASCII CHARACTERS * ASC3 CPI '''' CHECK FOR SINGLE QUOTE JNZ ASC5 JUMP IF NOT QUOTE LXI D,0 GET A ZERO MVI C,3 CHARACTER COUNT * ASC4 INX H INCREMENT POINTER SHLD PNTR SAVE MOV A,M FETCH NEXT CHARACTER CPI CR IS IT A CR JZ ERRA ARGUMENT ERROR CPI '''' IS IT A QUOTE JNZ SSTR INX H INCREMENT POINTER SHLD PNTR SAVE MOV A,M FETCH NEXT CHARACTER CPI '''' CHECK FOR 2 QUOTES IN A ROW JNZ AVAL+1 TERMINAL QUOTE * SSTR DCR C CHECK COUNT JZ ERRA TOO MANY CHARACTERS MOV D,E MOV E,A SET CHARACTER IN BUFFER JMP ASC4 * * ASC5 CPI '0' CHECK FOR NUMERIC JC ERRA ILLEGAL CHARACTER CPI '9'+1 JNC ALAB CALL NUMS GET NUMERIC VALUE JC ERRA ARGUMENT ERROR * AVAL XCHG LHLD OPRD XRA A GET A ZERO STA OPRI STORE IN OPERAND INDICATOR LDA SIGN GET SIGN INDICATOR CPI 1 JZ ASUB JNC AMULT DAD D FORM RESULT * ASC7 SHLD OPRD SAVE RESULT JMP NXT1 * * * SUBTRACT * ASUB MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A JMP ASC7 * * * MULTIPLY * AMULT MOV B,D MOV C,E XCHG LXI H,0 CPI 3 JZ ADIV CALL MULT JMP ASC7 * * MULT MVI A,16 MULT1 DAD H XCHG DAD H XCHG JNC MULT2 DAD B MULT2 DCR A JNZ MULT1 RET * * * DIVIDE * ADIV MOV A,B ORA C JZ ASC7 DIVIDE BY ZERO CALL DIV XCHG JMP ASC7 * * DIV MVI A,16 SET BIT COUNT DIV1 STA SCNT DAD H ROTATE BUFFER XCHG DAD H ROTATE DIVIDEND XCHG JNC DIV2 INX H * DIV2 MOV A,L SUB C MOV L,A MOV A,H SBB B MOV H,A INX D ASSUMED 1 IN QUOTIENT JNC DIV3 DAD B RESTORE DIVIDEND DCX D * DIV3 LDA SCNT GET BIT COUNT DCR A JNZ DIV1 RET * * ALAB CALL SLAB JZ AVAL JC ERRA ILLEGAL SYMBOL LDA PASI CPI 2 JC ERRU UNDEFINED SYMBOL * XCHG LHLD SYMSAV ADDRESS OF NEXT SYMBOL MVI C,LLAB CALL SEAR CHECK FOR REFERENCE JNZ SLA6 LXI H,SCNT GET LINE COUNT INR M LDA XLNSZ COMPARE WITH MAX XTAB LINE SIZE DCR A CMP M LINE FILLED JNC SLA4 MVI M,1 INITIALIZE COUNT CALL SOUT IF LINE FULL OUTPUT IT MVI C,LLAB+12 CALL BLKO * SLA4 LXI H,IBUF-5 MVI C,4 SLA5 MOV B,M CALL OUT8 OUTPUT LINE NUMBER INX H DCR C JNZ SLA5 CALL BLK1 SLA6 XRA A SET ZERO FLAG MVI H,0 SET SYMBOL VALUE JMP AVAL * * * GET HERE WHEN TERMINATION CHARACTER IS FOUND. BLANK,COMMA * CHECK FOR LEADING FIELD SEPARATOR * SEND LDA OPRI FETCH OPERAND INDICATOR ORA A SET FLAGS JNZ ERRS SYNTAX ERROR LHLD OPRD LDA GTLT GET GREATER LESS THAN FLAG CPI 3CH IS IT GREATER THAN JNZ SEN0 MOV L,H JMP SEN2 * * SEN0 CPI 3EH IS IT LESS THAN JNZ SEN1 * SEN2 MVI H,0 SET HIGH ORDER 0 SEN1 MOV A,H GET HIGH ORDER BYTE LXI D,TEMP SET ADDRESS ORA A RET * * * GET A NUMERIC VALUE WHICH IS EIGHER HEXADECIMAL OR DECIMA * ON RETURN CARRY SET INDICATES AN ERROR * NUMS CALL ALPS GET NUMERIC DCX D LDAX D GET LAST CHARACTER CALL MAP MAP FROM LOWER TO UPPER CASE LXI B,ABUF SET BUFFER ADDRESS CPI 'H' IS IT HEXADECIMAL JZ NUM2 CPI 'Q' IS IT OCTAL JZ NUM3 CPI 'O' IS IT OCTAL JZ NUM3 CPI 'B' BINARY? JZ NUM6 CPI 'D' IS IT DECIMAL JNZ ADEC * XRA A GET A ZERO STAX D CLEAR D FROM BUFFER JMP ADEC CONVERT DECIMAL VALUE * * NUM2 XRA A GET A ZERO STAX D CLEAR H FROM BUFFER JMP AHEX CONVERT HEX * * NUM3 XRA A STAX D JMP AOCT * * NUM6 XRA A STAX D JMP ABIN * * * PROCESS REGISTER ERROR * ERRR MVI A,'R' GET INDICATOR STA OBUF+18 SET IN OUTPUT BUFFER CALL UPERR INCREMENT ERROR COUNT LXI H,0 GET A 0 RET * * * PROCESS SYNTAX ERROR * ERRS MVI A,'S' GET INDICATOR STA OBUF+18 STORE IN OUTPUT BUFFER LDA PASI ORA A JZ ERRS1 CALL UPERR INCREMENT ERROR COUNT ERRS1 LXI H,0 GET A ZERO JMP SEN1 * * * PROCESS UNDEFINED SYMBOL ERROR * ERRU MVI A,'U' GET INDICATOR JMP ERRS+2 * * PROCESS VALUE ERROR * ERRV MVI A,'V' GET INDICATOR JMP ERRR+2 * * PROCESS MISSING LABEL ERROR * ERRM MVI A,'M' GET INDICATOR STA OBUF+18 STORE IN OUTPUT BUFFER CALL UPERR INCREMENT ERROR COUNT JMP LOUT DISPLAY ERROR * * PROCESS ARGUMENT ERROR * ERRA MVI A,'A' GET INDICATOR JMP ERRS+2 * * * PROCESS OPCODE ERROR * STORE 3 BYTES OF ZERO IN OBJECT CODE TO PROVIDE FOR A PA * ERRO MVI A,'O' GET INDICATOR STA OBUF+18 STORE IN OUTPUT BUFFER LDA PASI FETCH PASS INDICATOR ORA A WHICH PASS RZ . IF PASS 1 MVI C,3 NEED 3 BYTES ERO1 XRA A GET A ZERO CALL ASTO PUT IN LISTING AND MEMORY DCR C JNZ ERO1 CALL UPERR INCREMENT ERROR COUNT RET * * PROCESS LABEL ERROR * ERRL MVI A,'L' GET INDICATOR JMP ERRO+2 * * PROCESS DUPLICATE LABEL ERROR * ERRD MVI A,'D' GET ERROR INDICATOR STA OBUF+18 STORE IN OUTPUT BUFFER CALL LOUT DISPLAY ERROR CALL UPERR INCREMENT ERROR COUNT JMP OPC PROCESS OPCODE * * UPERR LDA PASI CPI 2 RZ . DON'T COUNT IF PASS 3 LXI H,ERCNT INR M RET . * ******************* * * * THIS ROUTINE IS USED TO FORMAT THE ASSEMBLY LISTING * FORMT LDA LFMT CHECK TO SEE IF FORMATTING DESIRED ORA A RZ . IF NOT-RETURN MVI C,0 LXI H,IBUF LINE ADDRESS MOV A,M GET FIRST CHARACTER CPI '*' COMMENT RZ CPI ';' COMMENT RZ . MVI B,2 CALL FRSUB FORMAT LINE RC INR B MORE FORMAT CALL FRSUB FORMAT LINE RC MVI D,2 JMP FRSUA * * FRSUB MVI D,1 FRSUA MOV A,B ADD D MOV B,A LDA TERMW SUI 2 JZ PDDER ZERO IS RIGHT ON JNC BOVER DCR B JMP PDDER * * BOVER MOV A,D GET VALUE OF D RAL ADD B MOV B,A PDDER MOV A,B ADI 5 MOV B,A * FRSU0 MOV E,D FRSU3 INR C INCREMENT CHARACTER COUNT MOV A,M GET NEXT CHARACTER CPI ' ' RC . RETURN IF CR INX H JNZ FRSU0 DCR E JNZ FRSU3 * FRSU1 INR C MOV A,M GET NEXT CHARACTER CPI ' ' LOOK FOR NON BLANK RC INX H JZ FRSU1 MOV A,C SUB B RNC DCX H DCX H MVI C,0 MOV M,C SET MOVE STOP MOV C,A * MOV L,C MVI H,0FFH MVI C,0 LXI D,IBUF+IBFLN END OF BUFFER ADDRESS DAD D XCHG CALL RMOV FORMAT LINE XCHG FRSU2 INX H MVI M,' ' REPLACE STOP WITH A BLANK MOV A,L CMP E JNZ FRSU2 INX H INX H MOV C,B RET * **************************************** * * * GET FILE NAME/UNIT FOR COPY PSEUDO * OPEN FILE AND RETURN # IN A * NAME INX H LXI D,NBUF TEMP NAME BUFFER XRA A STA FTEMP CLEAR TEMP HOLDER * MVI C,11 MAX CHR COUNT+1 NAMEB MOV A,M CPI ' '+1 CHK FOR BLNK / CR JC ZFIL YES--ALSO END OF NAME INX H CALL NAMEC JZ ERR7 > 8 CHR IN NAME JMP NAMEB * * NAMEC STAX D PUT CHR IN NBUF DCR C CHR COUNT RZ INX D RET * * ZFIL XRA A ZERO FILE NAME TO 11 CHARACTERS ZFIL2 CALL NAMEC JNZ ZFIL2 * SHLD NAMWK SAVE BUFR ADDRESS LXI D,NBUF CALL SAVNAME PUT NAME IN TITLE LXI D,NBUF POINT TO NAME LXI H,0 STATIC BUFFER CALL SYS OPEN UP DB OPEOP CALL ERROP LHLD NAMWK GET BUFR ADDRESS RET . WITH FILE NUMBER IN HAND * * **************************************** * * * THE FOLLOWING CODE IS USED TO ORDER THE SYMBOL TABLE * SO SEARCHING DURING PASS TWO WILL BE FASTER * ORDER LXI H,SYMAD INIT SOME POINTERS SHLD STP SYM TAB POINTER SHLD SPTR SEARCH POINTER XCHG LXI H,HASHT SHLD HASP HASH TABLE POINTER MVI C,26 LOOP 26 TIME TO INIT THE HASH TABLE ORD01 MOV M,E LOW INX H MOV M,D THE HIGH INX H DCR C JNZ ORD01 MVI A,'A'-1 STA CCHR CURRENT CHARACTER * * LOOP HERE TO ORDER ON EVERY LETTER OF THE ALPHABET * ORD02 LDA CCHR NEXT CHARACTER INR A STA CCHR CALL ORD1 DO A PASS FOR THE CURRENT CHARACTER LHLD SPTR TEST FOR END OF SYMBOL TBALE XCHG LHLD STEND CALL HDCMP HL-DE RZ . END OF TABLE, ALL DONE LDA CCHR CPI 'Z' HAVE WE DONE THEM ALL? RZ . YES, ALL DONE JMP ORD02 * * * THIS IS THE LOOP FOR EACH CHARACTER * ORD1 LHLD STP SYM TAB PTR XCHG LHLD HASP HASH TABLE POINTER MOV M,E PLACE CURRENT STP IN HASH TABLE INX H MOV M,D INX H SHLD HASP UPDATE HASH TABLE POINTER * * LOOP HERE TO DO EACH ENTRY IN THE SYM TAB * ORD03 CALL ORD2 DO ONE ENTRY LHLD SPTR XCHG LHLD STEND CALL HDCMP END OF SYM TAB? JNZ ORD03 NO, CONTINUE * * DONE WITH THIS CURRENT CHARACTRER, RESET FOR NEXT SEARCH AND * RETURN * LHLD STP SET SPTR TO STP SHLD SPTR RET * * * THIS PART DOES THE PROCESSING FOR EACH ENTRY IN * THE SYM TAB * ORD2 LHLD SPTR GET CHARACTER OF THIS ENTRY MOV A,M CPI 'Z'+1 LOWER CASE? JC ORD28 SUI 32 UP SHIFT ORD28 LXI H,CCHR CMP M FOUND? JNZ ORD05 NO, SEARCH * * MATCH FOUND * LHLD STP MVI C,7 * * THIS LOOP EXCHANGES TWO SYM TAB ENTRIES * ORD04 MOV A,M LHLD SPTR MOV B,M MOV M,A INX H SHLD SPTR LHLD STP MOV M,B INX H SHLD STP DCR C ALL 7 CHARACTERS JNZ ORD04 RET . DONE WITH THIS ONE * * MATCH NOT FOUND * ORD05 LHLD SPTR LXI D,7 DAD D SHLD SPTR MOVE TO NEXT ENTRY RET * * * HL-DE COMPARE * HDCMP MOV A,H CMP D RNZ MOV A,L CMP E RET * *