TITLE 'ASM MAIN MODULE' ; CP/M RESIDENT ASSEMBLER MAIN PROGRAM ; ; COPYRIGHT (C) 1976, 1977, 1978 ; DIGITAL RESEARCH ; BOX 579, PACIFIC GROVE ; CALIFORNIA, 93950 ; ; ORG 1BA0H ; MODULE ENTRY POINTS IOMOD EQU 200H ;IO MODULE SCMOD EQU 1100H ;SCANNER MODULE SYMOD EQU 1340H ;SYMBOL TABLE MODULE BMOD EQU 15A0H ;BINARY SEARCH MODULE OPMOD EQU 1860H ;OPERAND SCAN MODULE ; SETUP EQU IOMOD+3H ;FILE SETUP FOR EACH PASS PCON EQU IOMOD+12H ;WRITE CONSOLE BUFFER TO CR WOBUFF EQU IOMOD+15H ;WRITE PRINT BUFFER AND REINITIALIZE PERR EQU IOMOD+18H ;WRITE ERROR CHARACTER TO PRINT BUFFER DHEX EQU IOMOD+1BH ;SEND HEX CHARACTER TO MACHINE CODE FILE EOR EQU IOMOD+1EH ;END OF PROCESSING, CLOSE FILES AND TERMINATE ; INITS EQU SCMOD+3H ;INITIALIZE SCANNER MODULE SCAN EQU SCMOD+6H ;SCAN NEXT TOKEN ; INISY EQU SYMOD+3H ;INITIALIZE SYMBOL TABLE LOOKUP EQU SYMOD+6H ;LOOKUP SYMBOL IN ACCUMULATOR FOUND EQU SYMOD+9H ;FOUND IF NZ FLAG ENTER EQU SYMOD+0CH ;ENTER SYMBOL IN ACCUMULATOR SETTY EQU SYMOD+0FH ;SET TYPE FIELD GETTY EQU SYMOD+12H ;GET TYPE FIELD SETVAL EQU SYMOD+15H ;SET VALUE FIELD GETVAL EQU SYMOD+18H ;GET VALUE FIELD ; BGET EQU BMOD+6H ;BINARY SEARCH AND GET TYPE/VALUE PAIR ; OPAND EQU OPMOD+3H ;GET OPERAND VALUE TO 'EVALUE' MULF EQU OPMOD+6H ;MULT D,E BY H,L TO H,L DIVF EQU OPMOD+9H ;DIVIDE HL BY DE, RESULT TO DE ; ; ; COMMON EQUATES PBMAX EQU 120 ;MAX PRINT SIZE PBUFF EQU 10CH ;PRINT BUFFER PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER ; TOKEN EQU PBP+1 ;CURRENT TOKEN UDER SCAN VALUE EQU TOKEN+1 ;VALUE OF NUMBER IN BINARY ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH ACCUM EQU ACCLEN+1 ; EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS ; SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP SYMAX EQU SYTOP+2 ;MAX ADDRESS+1 ; PASS EQU SYMAX+2 ;CURRENT PASS NUMBER FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC SYBAS EQU ASPC+2 ;BASE OF SYMBOL TABLE SYADR EQU SYBAS+2 ;CURRENT SYMBOL ADDRESS ; ; GLOBAL EQUATES IDEN EQU 1 ;IDENTIFIER NUMB EQU 2 ;NUMBER STRNG EQU 3 ;STRING SPECL EQU 4 ;SPECIAL CHARACTER ; PLABT EQU 0001B ;PROGRAM LABEL DLABT EQU 0010B ;DATA LABEL EQUT EQU 0100B ;EQUATE SETT EQU 0101B ;SET MACT EQU 0110B ;MACRO ; EXTT EQU 1000B ;EXTERNAL REFT EQU 1011B ;REFER GLBT EQU 1100B ;GLOBAL ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED EOF EQU 1AH ;END OF FILE NBMAX EQU 16 ;STARTING POSITION OF PRINT LINE ; ; RT EQU 16 ;REGISTER TYPE PT EQU RT+1 ;PSEUDO OPERATION PENDIF EQU 5 ;PSEUDO OPERATOR 'ENDIF' OBASE EQU PT+1 O1 EQU OBASE+1 ;FIRST OPERATOR O15 EQU OBASE+15;LAST OPERATOR ; ; MAIN STATEMENT PROCESSING LOOP XRA A STA PASS ;SET TO PASS 0 INITIALLY CALL INISY ;INITIALIZE THE SYMBOL TABLE RESTART: ;PASS LOOP GOES FROM 0 TO 1 CALL INITS ;INITIALIZE THE SCANNER CALL SETUP ;SET UP THE INPUT FILE LXI H,0 SHLD SYLAB ;ASSUME NO STARTING LABEL SHLD FPC SHLD ASPC SHLD EPC ;END PC ; SCNEXT: ;SCAN THE NEXT INPUT ITEM CALL SCAN SCN0: LDA TOKEN CPI NUMB ;SKIP LEADING NUMBERS FROM LINE EDITORS JZ SCNEXT CPI SPECL ;MAY BE PROCESSOR TECH'S COMMENT JNZ SCN1 ; SPECIAL CHARACTER, CHECK FOR * LDA ACCUM CPI '*' JNZ CHEND ;END OF LINE IF NOT * ; * FOUND, NO PRECEDING LABEL ALLOWED CALL SETLA JNZ STERR ;ERROR IF LABEL JMP CHEN1 ;SCAN THE COMMENT OTHERWISE ; SCN1: ;NOT NUMBER OR SPECIAL CHARACTER, CHECK FOR IDENTIFIER CPI IDEN JNZ STERR ;ERROR IF NOT ; ; IDENTIFIER FOUND, MAY BE LABEL, OPCODE, OR MACRO CALL BGET ;BINARY SEARCH FIXED DATA JZ CHKPT ;CHECK FOR PSEUDO OR REAL OPERATOR ; ; BINARY SEARCH WAS UNSUCCESSFUL, CHECK FOR MACRO CALL LOOKUP CALL FOUND JNZ LFOUN ;NZ FLAG SET IF FOUND ; ; NOT FOUND, ENTER IT CALL ENTER ;THIS MUST BE PASS 0 LDA PASS ORA A CNZ ERRP ;PHASE ERROR IF NOT JMP SETSY ;SET SYLAB ; ; ITEM WAS FOUND, CHECK FOR MACRO LFOUN: CALL GETTY CPI MACT JNZ SETSY ; ; MACRO DEFINITION FOUND, EXPAND MACRO CALL ERRN ;NOT CURRENTLY IMPLEMENTED JMP CHEN1 ;SCANS TO END OF CURRENT LINE ; SETSY: ;LABEL FOUND - IS IT THE ONLY ONE? LHLD SYLAB MOV A,L ORA H CNZ ERRL ;LABEL ERROR IF NOT LHLD SYADR ;ADDRESS OF SYMBOL SHLD SYLAB ;MARK AS LABEL FOUND ; ; LABEL FOUND, SCAN OPTIONAL ':' CALL SCAN LDA TOKEN CPI SPECL JNZ SCN0 ;SKIP NEXT SCAN IF NOT SPECIAL LDA ACCUM CPI ':' JNZ SCN0 JMP SCNEXT ;TO IGNORE ':' ; ; BINARY SEARCH FOUND SYMBOL, CHECK FOR PSEUDO OR REAL OP CHKPT: CPI PT ;PSEUDO OPCODE? JNZ CHKOT ; ; PSEUDO OPCODE FOUND, BRANCH TO CASES MOV E,B ;B HAS PARTICULAR OPERATOR NUMBER MVI D,0 ;DOUBLE PRECISION VALUE TO D,E DCX D ;BIASED BY +1 LXI H,PTTAB ;BASE OF JUMP TABLE DAD D DAD D MOV E,M INX H MOV H,M MOV L,E PCHL ;JUMP INTO TABLE ; PTTAB: ;PSEUDO OPCODE JUMP TABLE DW SDB ;DB DW SDS ;DS DW SDW ;DW DW SEND ;END DW SENDIF ;ENDIF DW SENDM ;ENDM DW SEQU ;EQU DW SIF ;IF DW SMACRO ;MACRO DW SORG ;ORG DW SSET ;SET DW STITLE ;TITLE ; SDB: CALL FILAB ;SET LABEL FOR THIS LINE TO ASPC SDB0: CALL SCAN ;PAST DB TO NEXT ITEM LDA TOKEN ;LOOK FOR LONG STRING CPI STRNG JNZ SDBC ;SKIP IF NOT STRING LDA ACCLEN DCR A ;LENGTH 1 STRING? JZ SDBC ; LENGTH 0,2,... STRING MOV B,A INR B INR B ;BECOMES 1,3,... FOR 0,2,... LENGTHS LXI H,ACCUM ;ADDRESS CHARACTERS IN STRING SDB1: DCR B ;COUNT DOWN TO ZERO JZ SDB2 ;SCAN DELIMITER AT END OF STRING PUSH B ;SAVE COUNT MOV B,M ;GET CHARACTER INX H PUSH H ;SAVE ACCUM POINTER CALL FILHB ;SEND TO HEX FILE POP H POP B JMP SDB1 SDB2: CALL SCAN ;TO THE DELIMITER JMP SDB3 ; ; NOT A LONG STRING SDBC: CALL OPAND ;COMPUTE OPERAND LHLD EVALUE ;VALUE TO H,L MOV A,H ORA A ;HIGH ORDER MUST BE ZERO CNZ ERRD ;DATA ERROR MOV B,L ;GET LOW BYTE CALL FILHB SDB3: ;END OF ITEM - UPDATE ASPC CALL SETAS ;SET ASPC TO FPC CALL DELIM CPI ',' JZ SDB0 ;FOR ANOTHER ITEM JMP CHEND ;CHECK END OF LINE SYNTAX ; SDS: CALL FILAB ;HANDLE LABEL IF IT OCCURRED CALL PADD ;PRINT ADDRESS CALL EXP16 ;SCAN AND GET 16BIT OPERAND XCHG ;TO D,E LHLD ASPC ;CURRENT PSEUDO PC DAD D ;+EXPRESSION SHLD ASPC SHLD FPC ;NEXT TO FILL JMP CHEND ; SDW: CALL FILAB ;HANDLE OPTIONAL LABEL SDW0: CALL EXP16 ;GET 16BIT OPERAND PUSH H ;SAVE A COPY MOV B,L ;LOW BYTE FIRST CALL FILHB ;SEND LOW BYTE POP H ;RECLAIM A COPY MOV B,H ;HIGH BYTE NEXT CALL FILHB ;SEND HIGH BYTE CALL SETAS ;SET ASPC=FPC CALL DELIM ;CHECK DELIMITER SYNTAX CPI ',' JZ SDW0 ;GET MORE DATA JMP CHEND ; SEND: CALL FILAB CALL PADD ;WRITE LAST LOC LDA PBUFF CPI ' ' JNZ CHEND CALL EXP16 ;GET EXPRESSION IF IT'S THERE LDA PBUFF CPI ' ' JNZ SEND0 SHLD EPC ;EXPRESSION FOUND, STORE IT FOR LATER SEND0: MVI A,' ' STA PBUFF ;CLEAR ERROR, IF IT OCCURRED CALL SCAN ;CLEAR CR LDA TOKEN CPI SPECL JNZ STERR LDA ACCUM CPI LF JNZ STERR JMP ENDAS ;END OF ASSEMBLER ; SENDIF: JMP POEND ; SENDM: CALL ERRN JMP POEND ; SEQU: CALL SETLA JZ STERR ;MUST BE A LABEL LHLD ASPC ;HOLD TEMP ASPC PUSH H ;IN STACK CALL EXP16 ;GET 16BIT OPERAND SHLD ASPC ;VALUE OF EXPRESSION CALL FILAB CALL PADDR ;COMPUTED VALUE LXI H,PBUFF+6 ;SPACE AFTER VALUE MVI M,'=' POP H ;REAL ASPC SHLD ASPC ;CHANGE BACK JMP CHEND ; SIF: CALL FILAB ;IN CASE OF LABEL CALL EXP16 ;GET IF EXPRESSION LDA PBUFF CPI ' ' JNZ CHEND ;SKIP IF ERROR MOV A,L ;GET LSB RAR JC CHEND ;TRUE IF CARRY BIT SET ; ; SKIP TO EOF OR ENDIF SIF0: CALL SCAN LDA TOKEN CPI SPECL JNZ SIF1 LDA ACCUM CPI EOF MVI A,'B' ;BALANCE ERROR CZ PERR JZ ENDAS JMP SIF0 ;FOR ANOTHER SIF1: ;NOT A SPECIAL CHARACTER CPI IDEN JNZ SIF0 ;NOT AN IDENTIFIER CALL BGET ;LOOK FOR ENDIF JNZ SIF0 ;NOT FOUND CPI PT ;PSEUDO OP? JNZ SIF0 MOV A,B ;GET OPERATOR NUMBER CPI PENDIF ;ENDIF? JNZ SIF0 ;GET ANOTHER TOKEN JMP POEND ;OK, CHECK END OF LINE ; SMACRO: CALL ERRN JMP CHEND ; SORG: CALL EXP16 LDA PBUFF CPI ' ' JNZ CHEND ;SKIP ORG IF ERROR SHLD ASPC ;CHANGE PC SHLD FPC ;CHANGE NEXT TO FILL CALL FILAB ;IN CASE OF LABEL CALL PADD JMP CHEND ; SSET: CALL SETLA JZ STERR ;MUST BE LABELLED ; CALL GETTY CPI SETT CNZ ERRL ;LABEL ERROR MVI A,SETT CALL SETTY ;REPLACE TYPE WITH 'SET' CALL EXP16 ;GET THE EXPRESSION PUSH H ;SAVE IT CALL SETLA ;RE-ADDRESS LABEL POP H ;RECLAIM IT CALL SETVAL LXI H,0 SHLD SYLAB ;PREVENT LABEL PROCESSING JMP CHEND ; ; STITLE: CALL ERRN ;NOT IMPLEMENTED ; POEND: ;PSEUDO OPERATOR END - SCAN TO NEXT TOKEN CALL SCAN JMP CHEND ; ; NOT A PSEUDO OPCODE, CHECK FOR REAL OPCODE CHKOT: SUI O1 ;BASE OF OPCODES CPI O15 ;PAST LAST OPCODE? JNC STERR ;STATEMENT ERROR IF SO ; ; FOUND OPCODE, COMPUTE INDEX INTO TABLE AND JUMP TO CASE MOV E,A MVI D,0 LXI H,OPTAB DAD D DAD D MOV E,M INX H MOV H,M MOV L,E PCHL ;JUMP TO CASE ; OPTAB: ;OPCODE CATEGORIES DW SSIMP ;SIMPLE DW SLXI ;LXI DW SDAD ;DAD DW SPUSH ;PUSH/POP DW SJMP ;JMP/CALL DW SMOV ;MOV DW SMVI ;MVI DW SACCI ;ACCUM IMMEDIATE DW SLDAX ;LDAX/STAX DW SLHLD ;LHLD/SHLD/LDA/STA DW SACCR ;ACCUM-REGISTER DW SINC ;INC/DCR DW SINX ;INX/DCX DW SRST ;RESTART DW SIN ;IN/OUT ; SSIMP: ;SIMPLE OPERATION CODES CALL FILHB ;SEND HEX VALUE TO MACHINE CODE FILE CALL SCAN ;TO NEXT TOKEN JMP INCPC ; SLXI: ;LXI H,16B CALL SHDREG ;SCAN DOUBLE PRECISION REGISTER CALL CHCOM ;CHECK FOR COMMA FOLLOWING REGISTER CALL SETADR ;SCAN AND EMIT DOUBLE PRECISION OPERAND JMP INCPC ; SDAD: ;DAD B CALL SHDREG ;SCAN AND EMIT DOUBLE PRECISION REGISTER JMP INCPC ; SPUSH: ;PUSH B POP D CALL SHREG ;SCAN SINGLE PRECISION REGISTER TO A CPI 111000B ;MAY BE PSW JZ SPU0 ; NOT PSW, MUST BE B,D, OR H ANI 001000B ;LOW BIT MUST BE 0 CNZ ERRR ;REGISTER ERROR IF NOT SPU0: MOV A,C ;RECALL REGISTER AND MASK IN CASE OF ERROR ANI 110000B ORA B ;MASK IN OPCODE FOR PUSH OR POP JMP FILINC ;FILL HEX VALUE AND INCREMENT PC ; SJMP: ;JMP 16B/ CALL 16B CALL FILHB ;EMIT JMP OR CALL OPCODE CALL SETADR ;EMIT 16BIT OPERAND JMP INCPC ; SMOV: ;MOV A,B CALL SHREG ORA B ;MASK IN OPCODE MOV B,A ;SAVE IN B TEMPORARILY CALL CHCOM ;MUST BE COMMA SEPARATOR CALL EXP3 ;VALUE MUST BE 0-7 ORA B ;MASK IN OPCODE JMP FILINC ; SMVI: ;MVI A,8B CALL SHREG ORA B ;MASK IN OPCODE CALL FILHEX ;EMIT OPCODE CALL CHCOM ;SCAN COMMA CALL SETBYTE ;EMIT 8BIT VALUE JMP INCPC ; SACCI: ;ADI 8B CALL FILHB ;EMIT IMMEDIATE OPCODE CALL SETBYTE ;EMIT 8BIT OPERAND JMP INCPC ; SLDAX: ;LDAX B/STAX D CALL SHREG ANI 101000B ;MUST BE B OR D CNZ ERRR ;REGISTER ERROR IF NOT MOV A,C ;RECOVER REGISTER NUMBER ANI 010000B ;CHANGE TO B OR D IF ERROR ORA B ;MASK IN OPCODE JMP FILINC ;EMIT OPCODE ; SLHLD: ;LHLD 16B/ SHLD 16B/ LDA 16B/ STA 16B CALL FILHB ;EMIT OPCODE CALL SETADR ;EMIT OPERAND JMP INCPC ; SACCR: ;ADD B CALL EXP3 ;RIGHT ADJUSTED 3BIT VALUE FOR REGISTER ORA B ;MASK IN OPCODE JMP FILINC ; SINC: ;INR B/DCR D CALL SHREG ;GET REGISTER ORA B JMP FILINC ; SINX: ;INX H/DCX B CALL SHREG ANI 001000B ;MUST BE B D M OR SP CNZ ERRR ;REGISTER ERROR IF NOT MOV A,C ;RECOVER REGISTER ANI 110000B ;IN CASE OF ERROR ORA B ;MASK IN OPCODE JMP FILINC ; SRST: ;RESTART 4 CALL SHREG ;VALUE IS 0-7 ORA B ;OPCODE MASKED JMP FILINC ; SIN: ;IN 8B/OUT 8B CALL FILHB ;EMIT OPCODE CALL SETBYTE ;EMIT 8BIT OPERAND JMP INCPC ; FILINC: ;FILL HEX VALUE FROM A BEFORE INCREMENTING PC CALL FILHEX ; INCPC: ;CHANGE ASSEMBLER'S PSEUDO PROGRAM COUNTER CALL FILAB ;SET ANY LABELS WHICH OCCUR ON THE LINE CALL SETAS ;ASPC=FPC JMP CHEND ;END OF LINE SCAN ; ; ; UTILITY SUBROUTINES FOR OPERATION CODES ; DELIM: ;CHECK DELIMITER SYNTAX FOR DATA STATEMENTS LDA TOKEN CPI SPECL CNZ ERRD LDA ACCUM CPI ',' RZ CPI ';' RZ CPI CR CNZ ERRD RET ; EXP16: ;GET 16BIT VALUE TO H,L PUSH B CALL SCAN ;START SCANNING OPERAND FIELD CALL OPAND LHLD EVALUE ;VALUE TO H,L POP B RET ; EXP8: ;GET 8BIT VALUE TO REG A CALL EXP16 MOV A,H ORA A CNZ ERRV ;VALUE ERROR IF HIGH BYTE NOT ZERO MOV A,L RET ; EXP3: ;GET 3BIT VALUE TO REG A CALL EXP8 CPI 8 CNC ERRV ;VALUE ERROR IF >=8 ANI 111B ;REDUCE IF ERROR OCCURS RET ; SHREG: ;GET 3BIT VALUE AND SHIFT LEFT BY 3 CALL EXP3 RAL RAL RAL ANI 111000B MOV C,A ;COPY TO C RET ; SHDREG: ;GET DOUBLE REGISTER TO A CALL SHREG ANI 001000B ;CHECK FOR A,C,E, OR L CNZ ERRR ;REGISTER ERROR MOV A,C ;RECOVER REGISTER ANI 110000B ;FIX IT IF ERROR OCCURRED ORA B ;MASK OPCODE JMP FILHEX ;EMIT IT ; SETBYTE: ;EMIT 16BIT OPERAND CALL EXP8 JMP FILHEX ; SETADR: ;EMIT 16BIT OPERAND CALL EXP16 JMP FILADR ; CHCOM: ;CHECK FOR COMMA FOLLOWING EXPRESSION PUSH PSW PUSH B LDA TOKEN CPI SPECL JNZ COMER ; SPECIAL CHARACTER, CHECK FOR COMMA LDA ACCUM CPI ',' JZ COMRET ;RETURN IF COMMA FOUND COMER: ;COMMA ERROR MVI A,'C' CALL PERR COMRET: POP B POP PSW RET ; CHEND: ;END OF LINE CHECK CALL FILAB ;IN CASE OF A LABEL LDA TOKEN CPI SPECL JNZ STERR ;MUST BE A SPECIAL CHARACTER LDA ACCUM CPI CR ;CARRIAGE RETURN JNZ CHEN0 ; CARRIAGE RETURN FOUND, SCAN PICKS UP LF AND PUSHES LINE CALL SCAN JMP SCNEXT ; CHEN0: ;NOT CR, CHECK FOR COMMENT CPI ';' JNZ CHEN2 CALL FILAB ;IN CASE LABELLED EMPTY LINE ; CLEAR COMMENT TO END OF LINE CHEN1: CALL SCAN LDA TOKEN CPI SPECL JNZ CHEN1 LDA ACCUM CPI LF JZ SCNEXT CPI EOF JZ ENDAS ;END OF ASSEMBLY IF EOF CPI '!' JZ SCNEXT ;LOGICAL END OF LINE JMP CHEN1 ;NONE OF THE ABOVE ; ; NOT CR OR LF, MAY BE LOGICAL END OF LINE CHEN2: CPI '!' JZ SCNEXT CPI EOF JZ ENDAS ; ; STATEMENT ERROR IN OPERAND FIELD STERR: MVI A,'S' CALL PERR JMP CHEN1 ;TO DUMP LINE ; DIFF: ;COMPUTE DE-HL TO HL MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ENDAS: ;END OF ASSEMBLY FOR THIS PASS LXI H,PASS MOV A,M INR M ;PASS NUMBER INCREMENTED ORA A JZ RESTART CALL SCAN ;TO CLEAR LAST LINE FEED CALL PADD ;WRITE LAST ADDRESS LXI H,PBUFF+5 MVI M,CR ;SET TO CR FOR END OF MESSAGE LXI H,PBUFF+1 CALL PCON ;PRINT LAST ADDRESS ; ; COMPUTE REMAINING SPACE LHLD SYTOP XCHG LHLD SYBAS CALL DIFF ;DIFFERENCE TO H,L PUSH H ;SYTOP-SYBAS TO STACK LHLD SYMAX XCHG LHLD SYBAS CALL DIFF ;SYMAX-SYBAS TO H,L MOV E,H MVI D,0 ;DIVIDED BY 256 POP H ;SYTOP-SYBAS TO H,L CALL DIVF ;RESULT TO DE XCHG CALL PADDR ;PRINT H,L TO PBUFF LXI H,PBUFF+5 ;MESSAGE LXI D,EMSG ;END MESSAGE ENDA0: LDAX D ORA A ;ZERO? JZ ENDA1 MOV M,A INX H INX D JMP ENDA0 ; EMSG: DB 'H USE FACTOR',CR,0 ; ENDA1: LXI H,PBUFF+2 ;BEGINNING OF RATIO CALL PCON LHLD EPC SHLD FPC ;END PROGRAM COUNTER JMP EOR ; ; UTILITY SUBROUTINES COMDH: ;COMPARE D,E WITH H,L FOR EQUALITY (NZ FLAG IF NOT EQUAL) MOV A,D CMP H RNZ MOV A,E CMP L RET ; SETAS: ;ASPC=FPC LHLD FPC SHLD ASPC RET ; SETLA: ;SYADR=SYLAB, FOLLOWED BY CHECK FOR ZERO LHLD SYLAB SHLD SYADR CALL FOUND RET ; FILAB: ;FILL LABEL VALUE WITH CURRENT ASPC, IF LABEL FOUND CALL SETLA RZ ;RETURN IF NO LABEL DETECTED ; ; LABEL FOUND, MUST BE DEFINED ON PASS-1 LXI H,0 SHLD SYLAB ;TO MARK NEXT STATEMENT WITH NO LABEL LDA PASS ORA A JNZ FIL1 ; ; PASS 0 CALL GETTY PUSH PSW ;SAVE A COPY OF TYPE ANI 111B ;CHECK FOR UNDEFINED CNZ ERRL ;LABEL ERROR POP PSW ;RESTORE TYPE ORI PLABT ;SET TO LABEL TYPE CALL SETTY ;SET TYPE FIELD LHLD ASPC ;GET CURRENT PC CALL SETVAL ;PLACE INTO VALUE FIELD RET ; FIL1: ;CHECK FOR DEFINED VALUE CALL GETTY ANI 111B CZ ERRP ;PHASE ERROR ; GET VALUE AND COMPARE WITH ASPC CALL GETVAL ;TO H,L XCHG LHLD ASPC CALL COMDH CNZ ERRP ;PHASE ERROR IF NOT THE SAME RET ; FILHEX: ;WRITE HEX BYTE IN REGISTER A TO MACHINE CODE FILE IF PASS-1 MOV B,A FILHB: LDA PASS ORA A MOV A,B JZ FILHI ; ; PASS - 1, WRITE HEX AND PRINT DATA PUSH B ;SAVE A COPY CALL DHEX ;INTO MACHINE CODE FILE ; MAY BE COMPLETELY EMPTY LINE, SO CHECK ADDRESS LDA PBUFF+1 CPI ' ' LHLD ASPC CZ PADDR ;PRINT ADDRESS FIELD ; LDA NBP CPI NBMAX ;TRUNCATE CODE IF TOO MUCH ON THIS LINE POP B ;RECALL HEX DIGIT JNC FILHI ; ROOM FOR DIGIT ON THIS LINE MOV A,B CALL WHEXB ;WRITE HEX BYTE TO PRINT LINE FILHI: LHLD FPC INX H SHLD FPC ;READY FOR NEXT BYTE RET ; FILADR: ;EMIT DOUBLE PRECISION VALUE FROM H,L PUSH H ;SAVE A COPY MOV B,L CALL FILHB ;LOW BYTE EMITTED POP H ;RECOVER A COPY OF H,L MOV B,H JMP FILHB ;EMIT HIGH BYTE AND RETURN ; ; UTILITY FUNCTIONS FOR PRINTING HEX ADDRESSES AND DATA CHEX: ;CONVERT TO HEX ADI '0' CPI '0'+10 RC ADI 'A'-'0'-10 RET ; WHEXN: ;WRITE HEX NIBBLE CALL CHEX ;CONVERT TO ASCII FROM HEX LXI H,NBP MOV E,M ;NEXT POSITION TO PRINT MVI D,0 ;DOUBLE PRECISION INR M ;NBP=NBP+1 LXI H,PBUFF DAD D MOV M,A ;STORE IN PRINT BUFFER RET ; WHEXB: ;WRITE HEX BYTE TO PRINT BUFFER PUSH PSW RAR RAR RAR RAR ANI 0FH ;HIGH ORDER NIBBLE NORMALIZE IN A CALL WHEXN ;WRITE IT POP PSW ANI 0FH JMP WHEXN ;WRITE AND RETURN ; PADD: LHLD ASPC PADDR: ;PRINT ADDRESS FIELD OF PRINT LINE FROM H,L XCHG LXI H,NBP ;INITIALIZE NEXT TO FILL PUSH H ;SAVE A COPY OF NBP'S ADDRESS MVI M,1 MOV A,D ;PRINT HIGH BYTE PUSH D ;SAVE A COPY CALL WHEXB POP D MOV A,E CALL WHEXB POP H ;ADDRESSING NBP INR M ;SKIP A SPACE AFTER ADDRESS FIELD RET ; ERRR: ;EMIT REGISTER ERROR PUSH PSW PUSH B MVI A,'R' CALL PERR POP B POP PSW RET ; ERRV: ;EMIT VALUE ERROR PUSH PSW PUSH H MVI A,'V' CALL PERR POP H POP PSW RET ; ERRD: PUSH PSW MVI A,'D' ;DATA ERROR JMP ERR ; ERRP: PUSH PSW MVI A,'P' JMP ERR ; ERRL: PUSH PSW MVI A,'L' ;LABEL ERROR JMP ERR ; ERRN: PUSH PSW MVI A,'N' ;NOT IMPLEMENTED ; ERR: CALL PERR POP PSW RET ; SYLAB: DS 2 ;ADDRESS OF LINE LABEL EPC: DS 2 ;END PC VALUE NBP: DS 1 ;NEXT BYTE POSITION TO WRITE FOR MACHINE CODE END