* * * STARTING HERE IS THE SELF ASSEMBLER PROGRAM * THIS PROGRAM ASSEMBLES PROGRAMS WHICH ARE * IN THE FILE AREA * ASSM CALL VCHK CHECK FOR PARAMETER LDA ABUF+7 GET 2ND PARAMETER ORA A CHECK FOR PARAMETERS JNZ ASM4 LHLD BBUF FETCH 1ST PARAMETER SHLD BBUF+2 STORE INTO 2ND PARAMETER ASM4 LDA IBUF+4 FETCH INPUT CHARACTER CPI 'E' JZ ASM5 CPI 'S' JZ ASM5 CPI 'X' JZ ASM5 CPI ' ' JNZ WHAT ASM5 STA AERR SET ERROR SWITCH LDA IBUF+3 STA ASMTY SET ASSEMBLY TYPE XRA A GET A ZERO LHLD SYMADD MOV M,A SET SYMBOL TABLE TERMINATOR STA ALST SET LIST SWITCH STA PASI SET PASS INDICATOR ASM3 LHLD BBUF FETCH ORIGIN SHLD ASPC INITIALIZE PC LHLD BOFP GET START OF FILE SHLD APNT SAVE ADDRESS ASM1 LXI SP,AREA+18 LXI H,OBUF CLEAR STARTING ADDRESS MVI A,IBUF-IBUFP CALL CLER CLEAR BUFFER LDA ASMTY GET TYPE FLAG CPI 'I' USE I/O JZ ASM6 CALL MOVEL GET LINE FROM FILE JZ EASS JMP ASM7 ASM6 CALL IN8 ***** ASSI INPUT CALL *** ASM7 LDA PASI GET PASS INDICATOR ORA A SET FLAGS JNZ ASM2 JUMP IF PASS 2 CALL PAS1 JMP ASM1 ASM2 CALL PAS2 LXI H,OBUF OUTPUT BUFFER ADDRESS CALL AOUT OUTPUT LINE JMP ASM1 * * THIS ROUTINE IS USED TO OUTPUT THE LISTING FOR AN ASSEMBLY * IT CHECKS WHETHER ALL LINES ARE PRINTED OR ONLY THOSE * WITH ERRORS DEPENDING UPON THE ERROR SWITCH * AOUT LDA OBUF+18 CHECK FOR AN ERROR CPI ' ' JNZ AOU1 AOU2 LDA AERR GET ERROR SWITCH CPI 'E' ERRORS ONLY? RZ LDA ALST GET LIST CONTROL ORA A RNZ AOU1 LDA PASI CPI 2 RNC LDA LFMT ORA A FORMATTED OUTPUT CNZ FORMT LXI H,OBUF OUTPUT BUFFER ADDRESS CALL CRLF JMP SCRN OUTPUT THE LINE * * PASS 1 OF ASSEMBLER. USED TO FORM SYMBOL TABLE * PAS1 CALL ZBUF CLEAR BUFFER STA PASI SET FOR PASS 1 LXI H,IBUF INITIALIZE LINE POINTER SHLD PNTR SAVE ADDRESS MOV A,M FETCH CHARACTER CPI ' ' CHECK FOR A BLANK JZ OPC JUMP IF NO LABEL CPI '*' CHECK FOR COMMENT RZ RETURN IF COMMENT * * PROCESS LABEL * CALL SLAB GET AND CHECK LABEL JC LERR ERROR IN LABEL JZ ERRD DUPLICATE LABEL CALL LCHK CHECK CHARACTER AFTER LABEL JC LERR ERROR IN LABEL CALL MLAB1 STORE LABEL XCHG SHLD TABA SAVE TABLE ADDRESS FOR EQU LDA ASPC+1 FETCH PC (HIGH) MOV M,A STORE IN TABLE INX H LDA ASPC FETCH PC (LOW) MOV M,A STORE IN TABLE INX H MVI M,0 SET TABLE TERMINATOR * * PROCESS OPCODE * OPC CALL ZBUF ZERO WORKING BUFFER CALL SBLK SCAN TO OPCODE JC OERR FOUND CARRIAGE RETURN CALL ALPS PLACE OPCODE IN BUFFER CPI ' ' CHECK FOR BLANK AFTER OPCODE JC OPCD CR AFTER OPCODE JNZ OERR ERROR IF NO BLANK JMP OPCD CHECK OPCODE MLAB1 MVI C,LLAB LEBEL LENGTH LXI H,ABUF SET BUFFER ADDRESS MLAB MOV A,M FETCH NEXT CHARACTER STAX D STORE IN SYMBOL TABLE INX D INX H DCR C DECREMENT COUNT JNZ MLAB RET * THIS ROUTINE CHECKS THE CHARACTER AFTER A LABEL FOR A BLANK * OR A COLON* * LCHK LHLD PNTR MOV A,M GET CHARACTER AFTER LABEL CPI ' ' CHECK FOR A BLANK RZ RETURN IF A BLANK CPI ':' CHECK FOR A COLON RNZ INX H SHLD PNTR SAVE POINTER RET * * PROCESS ANY PSEUDO OPS THAT NEED TO BE IN PASS 1 * PSU1 CALL SBLK SCAN TO OPERAND LDAX D FETCH VALUE ORA A JZ ORG1 JM DAT21 CPI 2 JC EQU1 JZ RES1 CPI 8 JZ ASC1 CPI 5 RNC JPE EASS JUMP IF END * DO DW PSEUDO/OP ACO1 MVI C,2 2 BYTE INSTRUCTION XRA A GET A ZERO JMP OCN1 ADD VALUE TO PROGRAM COUNTER * DO ORG PSEUDO-OP ORG1 CALL ASCN GET OPERAND LDA OBUF+18 FETCH ERROR INDICATOR CPI ' ' CHECK FOR AN ERROR RNZ IF ERROR DON'T CHANGE PC SHLD ASPC STORE NEW ORIGIN LDA IBUF GET FIRST CHARACTER CPI ' ' CHECK FOR LABEL RZ NO LABEL JMP EQUS CHANGE LABEL VALUE * DO EQU PSEUDO-OP EQU1 CALL ASCN GET OPERAND LDA IBUF FETCH 1ST CHARACTER CPI ' ' CHECK FOR LABEL JZ ERRM MISSING LABEL EQUS XCHG LHLD TABA SYMBOL TABLE ADDRESS MOV M,D STORE LABEL VALUE INX H MOV M,E LDA OBUF+18 CPI ' ' RZ JMP AOU1 * DO DS PSEUDO-OP RES1 CALL ASCN GET OPERAND MOV B,H MOV C,L LDA OBUF+18 CPI ' ' JNZ AOU1 JMP RES21 ADD VALUE TO PROGRAM COUNTER * * DO DB PSEUDO-OP * DO ASC PSEUDO OP ASC1 MOV A,M GET FIRST CHARACTER CPI ASCR CARRIAGE RETURN RZ MOV D,A SAVE AS DELIMITER LXI B,0 SET BYTE COUNT TO 0 ASC11 INX H MOV A,M GET NEXT CHARACTER CPI ASCR CARRIAGE RETURN JZ RES21 UPDATE PC CMP D FOUND DELIMITER JZ RES21 INX B JMP ASC11 * * PERFORM PASS 2 OF THE ASSEMBLER * PAS2 LXI H,OBUF SET OUTPUT BUFFER ADDRESS LDA ASPC+1 FETCH PC (HIGH) CALL BINH+3 CONVERT FOR OUTPUT INX H LDA ASPC FETCH PC (LOW) CALL BINH+3 CONVERT FOR OUTPUT SHLD OIND SAVE OUTPUT ADDRESS CALL ZBUF CLEAR BUFFER LXI H,IBUF INITIALIZE LINE POINTER PABL SHLD PNTR SAVE POINTER MOV A,M FETCH FIRST CHARACTER CPI ' ' CHECK FOR LABEL JZ OPC GET OPCODE CPI '*' CHECK FOR COMMENT RZ RETURN IF COMMENT CALL SLAB SCAN OFF LABEL JC LERR ERROR IN LABEL CALL LCHK CHECK FOR A BLANK OR COLON JNZ LERR ERROR IF NOT A BLANK JMP OPC * * * * PROCESS PSEUDO OPS FOR PASS 2 PSU2 LDAX D ORA A JZ ORG2 JM DAT2 CPI 2 RC JZ RES2 CPI 8 JZ ASC2 CPI 5 JZ COM JNC LST JPE EASS * DO DW PSEUDO-OP ACO2 CALL TYS6 GET VALUE JMP ACO1 * DO DS PSEUDO-OP RES2 CALL ASBL GET OPERAND MOV B,H MOV C,L LHLD BBUF+2 FETCH STORAGE COUNTER DAD B ADD VALUE SHLD BBUF+2 SAVE RES21 XRA A GET A ZERO JMP OCN2 * DO DB PSEUDO-OP DAT2 CALL TYS5 GET OPERAND DAT21 XRA A GET A ZERO MVI C,1 BYTE COUNT JMP OCN1 * DO ORG PSEUDO-OP ORG2 CALL ASBL GET NEW ORIGIN LDA OBUF+18 GET ERROR INDICATOR CPI ' ' CHECK FOR AN ERROR RNZ DON'T MODIFY PC IF ERROR XCHG LHLD ASPC FETCH PC XCHG SHLD ASPC STORE NEW PC MOV A,L SUB E FORM DIFFERENCE OF ORIGINS MOV E,A MOV A,H SBB D MOV D,A LHLD BBUF+2 FETCH STORAGE POINTER DAD D MODIFY SHLD BBUF+2 SAVE RET * PROCESS LST AND NLST PSEUDO-OPS LST SUI 6 STA ALST SET LIST SWITCH RET * PROCESS COM PSEUDO-OP COM CALL ZBUF CLEAR BUFFER CALL SBLK SCAN TO ARGUMENT CALL SLAB CHECK LABEL JC ERRA ILLEGAL SYMBOL JNZ ERRU UNDEFINED SYMBOL * CHECK IF IN SYSTEM TABLE COM1 LXI D,SYSYM SHLD OPRD SAVE SYMBOL VALUE MVI B,LLAB CALL COMS JZ COM2 CALL MLAB1 STORE SYMBOL INX D INX D XRA A STAX D DCX D INR A CLEAR Z FLAG COM2 LHLD OPRD XCHG MOV M,E DCX H MOV M,D RET * DO ASC PSEUDO OP ASC2 CALL SBLK SCAN TO OPERAND JC ERRA FOUND CR MOV C,A SAVE DELIMITER INX H MOV A,M GET NEXT CHARACTER CPI ASCR JZ ERRA CMP C FOUND DELIMITER JZ ERRA MVI B,-7 ASC21 MOV A,M GET NEXT CHARACTER CPI ASCR JZ ASC23 CMP C FOUND DELIMITER JZ ASC23 SHLD PNTR LHLD ASPC INX H INCREMENT PROGRAM COUNTER SHLD ASPC SAVE PC INR B PUSH B CALL ASTO STORE OBJECT BYTE MOV A,L CPI OBUF15-OBUFP JNZ ASC22 CALL AOUT OUTPUT LINE POP B MVI B,0 PUSH B LXI H,2020H ASCII BLANKS SHLD OBUF SHLD OBUF+2 CLEAR ADDRESS MVI A,ASCR STA OBUF+16 PUT CR IN BUFFER LXI H,OBUF+3 SHLD OIND SET BUFFER POINTER ASC22 LHLD PNTR POP B INX H JMP ASC21 * GET HERE AT END OF SCAN ASC23 MOV A,B ORA A ANYTHING ON LINE RM JZ ASM1 LHLD OIND GET LAST CHARACTE R ON LINE INX H MVI M,ASCR PUT IN A CR RET * PROCESS 1 BYTE INSTRUCTIONS WITHOUT OPERANDS * * * PROCESS STAX AND LDAX INSTRUCTIONS * TYP2 CALL ASBL FETCH OPERAND CNZ ERRR ILLEGAL REGISTER MOV A,L GET LOW ORDER OPERAND ORA A SET FLAGS JZ TY31 OPERAND = 0 CPI 2 OPERAND = 2 CNZ ERRR ILLEGAL REGISTER JMP TY31 * * PROCESS PUSH,POP,INX,DCX,DAD INSTRUCTIONS * TYP3 CALL ASBL FETCH OPERAND CNZ ERRR ILLEGAL REGISTER MOV A,L GET LOW ORDER OPERAND RRC CHECK LOW ORDER BIT CC ERRR ILLEGAL REGISTER RAL RESTORE OPERAND CPI 8 CNC ERRR ILLEGAL REGISTER TY31 RLC MULTIPLY BY 8 RAL RAL TY32 MOV B,A LDAX D FETCH OPCODE BASE ADD B FORM OPCODE CPI 118 CHECK FOR MOV M,M CZ ERRR ILLEGAL REGISTER JMP ASTO * * PROCESS ACCUMULATOR, INR,DCR,MOV,RST INSTRUCTIONS * TYP4 CALL ASBL FETCH OPERAND CNZ ERRR ILLEGAL REGISTER MOV A,L GET LOW ORDER OPERAND CPI 8 CNC ERRR ILLEGAL REGISTER LDAX D FETCH OPCODE BASE CPI 64 CHECK FOR MOV INSTRUCTION JZ TY41 CPI 199 MOV A,L JZ TY31 RST INSTRUCTION JM TY32 ACCUMULATOR INSTRUCTION JMP TY31 INR,DCR * PROCESS MOV INSTRUCTION TY41 DAD H MULTIPLY OPERAND BY 8 DAD H DAD H ADD L FORM OPCODE STAX D SAVE OPCODE CALL MPNT INCREMENT POINTER CALL ASCN GET NEXT OPERAND CNZ ERRR ILLEGAL REGISTER MOV A,L FETCH LOW ORDER OPERAND CPI 8 CNC ERRR ILLEGAL REGISTER JMP TY32 * * PROCESS IMMEDIATE INSTRUCTIONS * IMMEDIATE BYTE CAN BE BETWEEN -256 AND +255 * MVI INSTRUCTION IS A SPECIAL CASE AND CONTAINS 2 ARGUMENTS * IN OPERAND TYP5 CPI 6 CHECK FOR MVI INSTRUCTION CZ TY56 CALL ASTO STORE OBJECT BYTE TYS5 CALL ASBL GET IMMEDIATE ARGUMENT INR A CPI 2 CHECK OPERAND FOR RANGE CNC ERRV OPERAND OUT OF RANGE MOV A,L JMP ASTO * * FETCH 1ST ARGUMENT FOR MVI AND LXI INSTRUCTIONS * TY56 CALL ASBL FETCH ARGUMENT CNZ ERRR ILLEGAL REGISTER MOV A,L GET LOW ORDER ARGUMENT CPI 8 CNC ERRR ILLEGAL REGISTER DAD H MULTIPLY BY 8 DAD H DAD H LDAX D FETCH OPCODE BASE ADD L FORM OPCODE MOV E,A SAVE OBJECT BYTE MPNT LHLD PNTR FETCH POINTER MOV A,M FETCH CHARACTER CPI ',' CHECK FOR COMMA INX H INCREMENT POINTER SHLD PNTR JNZ ERRS SYNTAX ERROR IF NO COMMA MOV A,E GET OBJECT BYTE RET * * PROCESS 3 BYTE INSTRUCTIONS * LXI INSTRUCTION IS A SPECIAL CASE * TYP6 CPI 1 CHECK FOR LXI INSTRUCTION JNZ TY6 JUMP IF NOT LXI CALL TY56 GET REGISTER ANI 8 CHECK FOR ILLEGAL REGISTER CNZ ERRR REGISTER ERROR MOV A,E GET OPCODE ANI 0F7H CLEAR BIT IN ERROR TY6 CALL ASTO STORE OBJECT BYTE TYS6 CALL ASBL FETCH OPERAND MOV A,L MOV D,H CALL ASTO STORE 2ND BYTE MOV A,D * * THIS ROUTINE IS USED TO STORE OBJECT CODE PRODUCED * BY THE ASSEMBLER DURING PASS 2 INTO MEMORY * ASTO LHLD BBUF+2 FETCH STORAGE ADDRESS MOV B,A LDA PASI CPI 2 RNC MOV A,B MOV M,A STORE OBJECT BYTE INX H INCREMENT LOCATION SHLD BBUF+2 LHLD OIND FETCH OUTPUT ADDRESS INX H INX H CALL BINH+3 CONVERT OBJECT BYTE SHLD OIND RET * * GET HERE WHEN END PSEUDO-OP IS FOUND OR WHEN END OF FILE * OCCURS IN SOURCE STATEMENTS. CONTROL IS SET FOR EIGHER PASS 2 * OR ASSEMBLEY TERMINATES IF FINISHED. * EASS LXI H,PASI PASS INDICATOR MOV A,M CPI 1 JZ EASS1 JNC SYM7 * SET UP FOR PASS 2 CALL CRLF INR M SET FOR PASS 2 JMP ASM3 EASS1 LDA SYMX SYMBOL TABLE? CPI 'E'+1 JC EOR INR M SET FOR PASS 3 * SYMPR CALL CRLF SYMP1 CALL CRLF XRA A SYMP2 STA SCNT SET LINE COUNT SYMB LHLD SYMADD GET SYMBOL TABLE ADDRESS SYM0 MOV D,H MOV E,L SYM1 LXI B,LLAB-1 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 COM0+2 INX H INX D LXI B,LLAB+2 JC SYM2 JUMP IF LARGE SYMBOL MOV D,H MOV E,L SYM2 DAD B JMP SYM1 SYM3 XCHG MOV A,M DCR A JM EOR INR A SHLD SYMSAV CALL SYMOT LDA SYMX SYMBOL INDICATOR CPI 'X' JZ ASM3 * OUTPUT SYMBOL TABLE LDA SCNT GET LINE COUNT INR A CPI 4 LINE FILLED? SYM7 LHLD SYMSAV MVI M,-1 DELETE SYMBOL JC SYMP2 JMP SYMP1 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 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 JMP BLKO * * * 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 CHARACTER * SBLK LHLD PNTR FETCH ADDRESS SBL1 MOV A,M FETCH CHARACTER CPI ' ' CHECK FOR A BLANK RNZ RETURN IF NON BLANK SBL2 INX H INCREMENT SHLD PNTR SAVE POINTER JMP SBL1 * * * THIS ROUTINE IS USED TO CHECK THE CONDITION CODE MNEMONICS * FOR CONDITIONAL JUMPS, CALLS, AND RETURNS. * COND LXI H,ABUF+1 SHLD ADDS MVI B,2 2 CHARACTERS