;-----------------------------------------------; ; Z80 RESIDENT ASSEMBLER ; ;-----------------------------------------------; ; ; ; (C) COPYRIGHT 1977 ; ; LEHMAN CONSULTING SERVICES ; ; ; ; ALL RIGHTS RESERVED ; ; ; ;-----------------------------------------------; ; ; ; MAIN ASSEMBLER MODULE ; ; ; ;-----------------------------------------------; ; ; ; REV 0 14-JULY-1977 MGL ; ; REV 1 20-OCT-77 MGL ; ; ; ;-----------------------------------------------; ; ; ORG 100H ;MAIN MODULE ; JMP Z80ASM ;CP/M ENTRY POINT BRANCH ; ; EJECT ;-----------------------------------------------; ; ; ; CPMUTIL LINKAGE ; ; ; ;-----------------------------------------------; ; ORG 103H ;JUMP TABLE BASE ADDRESS ; ; ; FOR AN EXPLANATION OF THESE ROUTINES SEE CPMUTIL ASSEMBLY ; ; WLINE DS 3 WMSG DS 3 DSKSEL DS 3 OPNFIL DS 3 CLSFIL DS 3 DELFIL DS 3 DREAD DS 3 DWRITE DS 3 CREFIL DS 3 DMASET DS 3 MOVE DS 3 CMPCHR DS 3 CMPHD DS 3 MUL16 DS 3 GNB DS 3 WNB DS 3 GNB2 DS 3 WNB2 DS 3 CNV2HX DS 3 ; ; ; CPMUTIL DATA AREA - FOR MORE DETAIL SEE CPMUTIL LISTING ; ; FCB1 DS 33 FCB2 DS 33 IBP DS 2 IBP2 DS 1 OBP DS 1 OBP2 DS 1 IBUF DS 2 OBUF DS 2 IBUF2 DS 2 OBUF2 DS 2 INBUF DS 1024 OUTBUF DS 128 INBUF2 DS 128 OUTBF2 DS 128 ; ; EJECT ;-----------------------------------------------; ; Z80SUBS LINKAGE AREA ; ;-----------------------------------------------; ; ORG 980H ; ; FOR A MORE DETAILED DESCRIPTION OF THESE FIELDS SEE Z80SUBS LISTING ; HDRBUF DS 16 REC DS 80 PC DS 2 OBJ DS 32 OBJCNT DS 1 LEN DS 1 VAL DS 2 INST DS 80 EOM DS 1 PTR1 DS 2 PASSNO DS 1 IDBUF DS 16 INTBUF DS 2 CURLNE DS 1 LEN2 DS 2 LBLADR DS 2 EQUFLG DS 1 EQUVAL DS 2 ENDADR DS 2 EFLG DS 1 OPCODE DS 2 SAVVAL DS 2 LFLAG DS 1 HFLAG DS 1 ERRFLG DS 1 TEMP DS 2 MULT DS 2 SYMPTR DS 2 SYMPT DS 2 UFLAG DS 1 EVFLGS DS 1 ;FLAGS FROM LAST SYMLUK EVFLAGS EQU EVFLGS ; ; ; Z80SUBS JUMP TABLE ; EVAL DS 3 ID DS 3 INT DS 3 SETUP DS 3 SYMENT DS 3 SYMLUK DS 3 GNR DS 3 GNC DS 3 BACKUP DS 3 ; ; EJECT ; ; LOCAL DATA AREA FOR ASSEMBLER ; ORG 0E80H SYMAREA DS 15 ;AREA FOR SYMBOL TABLE BUILD SYMADR DS 2 ;ADDRESS OF VALUE LOW FIELD FOR LAST SYMENT OLDADR DW -1 ;LAST ADDR OF WOBJ OBJADR DS 2 PAGENO DS 1 ; RNAME EQU 20H ;FLAG BIT - REGISTER NAME RPNAME EQU 80H ;FLAG BIT - REGISTER PAIR NAME ; ; MAXLNE EQU 55 ;LINES PER PAGE ;:::::::::::::::::::::::::::::::::::::::::::::::; ; ; ; SYMBOL TABLE ADDRESS EQUATES ; ; ; ;:::::::::::::::::::::::::::::::::::::::::::::::; ; SYMBEG EQU 1F80H ;POINTER TO FIRST USABLE ENTRY SYMCND EQU SYMBEG+2 ;POINTER TO COND CODE TABLE SYM EQU SYMCND+2 ;ACTUAL BEGINING ADDRESS FOR SEARCHES ; ; ; ; ; EJECT ;-----------------------------------------------; ; ; ; Z 8 0 A S M - RESIDENT Z80 ASSEMBLER ; ; ; ; WRITTEN IN 8080 ASSEMBLY LANGUAGE ; ; TO BE ASSEMBLED BY THE CP/M ASSEMBLER ; ; ; ; AUTHOR: MICHAEL G. LEHMAN ; ; ; ;-----------------------------------------------; ; ; Z80ASM EQU $ ; ; INIT FIELDS AND SETUP FILES ; LXI SP,STACK+128 JMP STACK+128 VSNMSG DB 13,10,10,'ZILOG/MOSTEK Z-80 ASSEMBLER VERSION 2.0' DB 13,10,'(C) 1977 LCS',13,10,'$' STACK DS 128 LXI D,VSNMSG ! CALL WMSG ;DISPLAY ON CONSOLE LXI H,SYM ;GET ADDRESS OF SYMBOL TABLE SHLD SYMPT ! LHLD SYMBEG ! SHLD SYMPTR ;SET UP POINTERS CALL SETUP ;PROCESS FILE NAME, PARAMETERS, ETC. MVI A,MAXLNE+1 ! STA CURLNE ;SET UP FOR HEAD OF FORM ON FIRST PRINT XRA A ! STA PASSNO ;INDICATE PASS 1 LXI H,0 ! SHLD PC ;SET UP DEFAULT PROGRAM ORIGIN ; ; ; MAIN LOOP - READ A SOURCE RECORD ; PROCESS LABEL AND OPCODE ; PRINT LINE (UNLESS OPTION=N) ; OUTPUT HEX (IF NECESSARY) ; BACK TO MAIN LOOP FOR NEXT RECORD ; ; NEXT EQU $ XRA A ! STA LEN ! STA EFLG ! STA EQUFLG ! LXI H,0 ! SHLD LEN2 ;INIT LENGTH & FLGS MVI A,' ' ! STA ERRFLG ;FOR THIS RECORD CALL GNR ;GET NEXT RECORD CPI 1AH ! JZ S321 ;BRANCH IF EOF LDA REC ;GET COL 1 CPI 09H ! JZ S12 ;BRANCH IF TAB CPI 0DH ! JZ ENDSTMT ;IGNORE NULL LINE CPI ' ' ! JZ S12 ;BRANCH IF NO LABEL CPI ';' ! JZ ENDSTMT ;IF COMMENT THEN IGNORE CALL ID ! CALL GNC ! CPI ':' ! JZ S9 ! CALL BACKUP S9 EQU $ LDA PASSNO ! ORA A ! JNZ S12 ;BRANCH IF PASS 2 ; ; CALCULATE LENGTH OF SYMBOL AND BUILD ENTRY ; MVI B,0 ;LENGTH + FLAGS ! LXI H,IDBUF LXI D,SYMAREA+1 S10 EQU $ MOV A,M ! CPI ' ' ! JZ S10A STAX D ! INX H ! INX D ! INR B ! JMP S10 S10A EQU $ ;SYMBOL COLLECTED MOV A,B ! CPI 0CH ! JC S10B ;BRANCH IF LEN < 12 (I.E. OK) MVI A,'L' ! STA ERRFLG ! JMP ENDSTMT ;ELSE LABEL ERROR S10B EQU $ ADI 4 ! STA SYMAREA ;ADD 4 FOR OVERHEAD XCHG ;SWITCH REGISTERS LDA PC ! MOV M,A ! INX H ;MOVE IN PC AS VALUE LDA PC+1 ! MOV M,A ! INX H ! MVI M,0 ;AND SET TYPE =0 LXI H,IDBUF ! CALL SYMLUK ! JNZ S11 ;BRANCH IF NOT ALREADY THERE MVI A,'M' ! STA ERRFLG ! JMP ENDSTMT ;ELSE MULTI DEFINED ERROR S11 EQU $ LXI H,SYMAREA ! CALL SYMENT ;ENTER SYMBOL INTO TABLE SHLD SYMADR ;SAVE ADDRESS FOR EQU ; ; ; NOW PROCESS OPCODE ; ; S12 EQU $ CALL ID LDA IDBUF ! CPI ' ' ! JZ ENDSTMT ;BRANCH IF NO OPCODE (COMMENT) LXI H,IDBUF ! CALL SYMLUK ! JZ S16 ;BRANCH IF FOUND MVI A,'O' ! STA ERRFLG ! JMP ENDSTMT ;ERROR IF UNDEFINED OPCODE S16 EQU $ MOV A,M ! STA OPCODE ! INX H ! MOV A,M ! STA OPCODE+1 ;SAVE OPCODE INX H ! MOV A,M ;GET TYPE BYTE DCR A ! ADD A ;-1 AND DOUBLE FOR TABLE INDEX MOV E,A ! MVI D,0 ! LXI H,TYPTBL ! DAD D MOV E,M ! INX H ! MOV D,M ! XCHG PCHL ;DISPATCH TO PROPER INSTRUCTION TYPE ; ; EJECT ;-----------------------------------------------; ; ; ; INSTRUCTION CLASS DISPATCH TABLE ; ; ; ;-----------------------------------------------; ; TYPTBL EQU $ DW S18 ;CLASS 1 - OPCODE ONLY DW S24 ;CLASS 2 - ROTATES DW S42 ;CLASS 3 - JUMPS (NON RELATIVE) CALLS DW S62 ;CLASS 4 - RELATIVE JUMPS (JR AND DJNZ) DW S73 ;CLASS 5 - RST DW S77 ;CLASS 6 - ARITHMETIC INSTRUCTIONS DW S97 ;CLASS 7 - I/O DW S116 ;CLASS 8 - LD INSTRUCTIONS DW S220 ;CLASS 9 - PUSH,POP DW S228 ;CLASS 10- EXCHANGE (EX) DW S243 ;CLASS 11- RETURNS DW S250 ;CLASS 12- BIT,SET,RES DW S268 ;CLASS 13- INC,DEC DW S301 ;CLASS 14- PSEUDO OPERATORS ; ; EJECT ; ; CLASS 1 - OPCODE ONLY ; S18 EQU $ MVI A,1 ! STA LEN LDA OPCODE ! STA INST LDA OPCODE+1 ! ORA A ! JZ ENDSTMT ;BRANCH IF ONLY 1 BYTE MVI A,2 ! STA LEN LDA OPCODE+1 ! STA INST+1 JMP ENDSTMT ; ; EJECT ; ; CLASS 2 - ROTATES ; S24 EQU $ CALL GNC ! CPI '(' ! JZ S30 ;BRANCH IF () FORM CALL BACKUP ! CALL ID ! LXI H,IDBUF ! CALL SYMLUK ! JZ S27 MVI A,'U' ! STA ERRFLG ! JMP ENDSTMT ;BRANCH IF UNDEFINED OPERAND S27 EQU $ LDA IDBUF ! CPI 'A' ! JZ S41 ;BRANCH IF A REGISTER MVI A,0CBH ! STA INST LDA OPCODE ! MOV B,A ! MOV A,M ! ORA B ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; S30 EQU $ CALL GNC ! CALL GNC ! CPI 'L' ! JZ S40 ;BRANCH IF (HL) CPI 'Y' ! JZ S38 ;BRANCH IF (IY) MVI A,0DDH ! STA INST S33 EQU $ MVI A,0CBH ! STA INST+1 LDA OPCODE ! ADI 6 ! STA INST+3 CALL GNC ;BYPASS + CALL EVAL LDA VAL ! STA INST+2 MVI A,4 ! STA LEN JMP ENDSTMT S38 EQU $ MVI A,0FDH ! STA INST ! JMP S33 ;DO IX AND IY SIMILARLY ; S40 EQU $ MVI A,0CBH ! STA INST ! LDA OPCODE ! ADI 6 ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; S41 EQU $ ;COMPATIBILITY WITH RRA, ETC LDA OPCODE ! ORI 7 ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; ; ; EJECT ; ; CLASS 3 - JUMPS - CALLS ; S42 EQU $ CALL GNC CPI '(' ! JZ S53 ;BRANCH IF () FORM LHLD PTR1 ! MOV A,M ! CPI ',' ! JZ S49 ;BRANCH IF CONDITIONAL TYPE INX H ! MOV A,M ! CPI ',' ! JZ S49 LDA OPCODE ! STA INST ! MVI A,3 ! STA LEN CALL BACKUP S46 EQU $ CALL EVAL LHLD VAL ! SHLD INST+1 ! JMP ENDSTMT ; S49 EQU $ ;PROCESS CONDITIONAL JUMPS, CALLS LDA OPCODE ! ANI 0C6H ! STA INST ! MVI A,3 ! STA LEN LHLD SYMCND ! SHLD SYMPT ;SO NO CONFLICTS WITH REGISTER NAMES CALL BACKUP ! CALL EVAL ! LDA VAL ! RLC ! RLC ! RLC ! ANI 38H LXI H,SYM ! SHLD SYMPT ;PUT IT BACK THE WAY IT WAS MOV B,A ! LDA INST ! ORA B ! STA INST MVI A,3 ! STA LEN JMP S46 ;NOW GO PROCESS LIKE NON CONDITIONAL ; S53 EQU $ ;PROCESS () FORM CALL GNC ! CALL GNC ;GET REGISTER TYPE CPI 'L' ! JZ S58 ;BRANCH IF (HL) CPI 'Y' ! JZ S60 MVI A,0DDH ! STA INST S56 EQU $ MVI A,0E9H ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; S58 EQU $ MVI A,0E9H ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; S60 EQU $ MVI A,0FDH ! STA INST ! JMP S56 ; ; EJECT ; ; CLASS 4 - RELATIVE JUMPS (JR AND DJNZ) ; ; S62 EQU $ CALL GNC LHLD PTR1 ! MOV A,M ! CPI ',' ! JZ S68 INX H ! MOV A,M ! CPI ',' ! JZ S68 ;BRANCH IF CONDITIONAL LDA OPCODE ! STA INST ! MVI A,2 ! STA LEN CALL BACKUP ! CALL EVAL ! LDA VAL ! DCR A ! DCR A ! STA INST+1 JMP ENDSTMT ; S68 EQU $ LHLD SYMCND ! SHLD SYMPT ;SO NOT CONFLICT WITH REG NAMES CALL BACKUP ! CALL EVAL ! LDA VAL ! RLC ! RLC ! RLC ! ANI 38H LXI H,SYM ! SHLD SYMPT ;PUT IT BACK ADI 20H ! STA INST ! MVI A,2 ! STA LEN CALL EVAL ! LDA VAL ! DCR A ! DCR A ! STA INST+1 ! JMP ENDSTMT ; ; EJECT ; ; ; CLASS 5 - RESTARTS ; ; S73 EQU $ CALL EVAL ! LDA VAL ! ANI 38H ! ORI 0C7H ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; ; CLASS 6 - ARITHMETIC OPCODES ; ; ADD,SUB,ADC,SBC,AND,OR,XOR,CP ; ; S77 EQU $ CALL GNC ! CPI '(' ! JZ S85 ;BRANCH IF () FORM LHLD PTR1 ! INX H ! MOV A,M ! CPI ',' ! JZ S96A ;BR IF REG PAIR CALL BACKUP ! CALL EVAL ! LDA EVFLGS ! ANI RNAME ! JNZ S84 LDA OPCODE ! ADI 0C6H ! STA INST ! LDA VAL ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; ; PROCESS REGISTER NAME ; S84 EQU $ LDA OPCODE ! ADI 80H ! MOV B,A ! LDA VAL ! ADD B ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; S85 EQU $ CALL GNC ! CALL GNC ! CPI 'L' ! JZ S95 CPI 'Y' ! JZ S93 MVI A,0DDH ! STA INST S88 EQU $ LDA OPCODE ! ADI 86H ! STA INST+1 MVI A,3 ! STA LEN CALL GNC CALL EVAL ! LDA VAL ! STA INST+2 ! JMP ENDSTMT ; S93 EQU $ MVI A,0FDH ! STA INST ! JMP S88 ; S95 EQU $ LDA OPCODE ! ADI 86H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; ; ; PROCESS REGISTER PAIR ADD,SUB,ADC,SBC ; S96A EQU $ CALL BACKUP ! CALL EVAL LDA VAL ! CPI 0FFH ;IX ! JZ S96H ! CPI 0FEH ;IY ! JZ S96J LDA OPCODE+1 ! CPI 9 ! JZ S96F MVI A,0EDH ! STA INST ! MVI A,2 ! STA LEN CALL EVAL LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE+1 ! ADD B STA INST+1 ! JMP ENDSTMT ; S96F EQU $ CALL EVAL LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE+1 ! ADD B STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S96H EQU $ MVI A,0DDH ! STA INST JMP S96K ; S96J EQU $ MVI A,0FDH ! STA INST S96K EQU $ CALL EVAL LDA VAL ! CPI 0FFH ! JNZ S96L ! CPI 0FEH ! JNZ S96L ! MVI A,4 ! STA VAL S96L EQU $ LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE+1 ! ADD B STA INST+1 ! MVI A,2 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; CLASS 7 - I/O INSTRUCTIONS ; ; S97 EQU $ LDA OPCODE ! CPI 0D3H ! JZ S107 ;BRANCH IF OUT OPCODE CALL GNC ! CPI 'A' ! JNZ S104 ;BRANCH IF 8080 TYPE I/O CALL GNC ! CALL GNC ! CALL EVAL ;GET PORT ADDRESS MVI A,0DBH ! STA INST ! LDA VAL ! STA INST+1 ! MVI A,2 ! STA LEN JMP ENDSTMT ; S104 EQU $ CALL BACKUP ! CALL EVAL ;GET REGISTER NAME MVI A,0EDH ! STA INST LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 40H ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; S107 EQU $ ;PROCESS OUT INSTRUCTION CALL GNC ! CALL GNC ! CPI 'C' ! JNZ S109 LHLD PTR1 ! MOV A,M ! CPI ')' ! JZ S112 S109 EQU $ CALL BACKUP ! CALL EVAL ;GET PORT NUMBER MVI A,0D3H ! STA INST ! LDA VAL ! STA INST+1 ! MVI A,2 ! STA LEN JMP ENDSTMT ; S112 EQU $ CALL GNC ! CALL GNC CALL EVAL MVI A,0EDH ! STA INST LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 41H ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; CLASS 8 - LD INSTRUCTIONS ; ; ; THE FOLLOWING ARE STRINGS WHICH ARE SPECIAL OPERAND FORMS ; LD1 DB 'A,I' LD2 DB 'A,R' LD3 DB 'I,A' LD4 DB 'R,A' LD5 DB 'SP,HL' LD6 DB 'SP,IX' LD7 DB 'SP,IY' ; S116 EQU $ CALL GNC ! CALL BACKUP ;POINT TO OPERAND FIELD LHLD PTR1 ;SET UP POINTER TO OPERAND FIELD LXI D,LD1 ! MVI B,3 ! CALL CMPCHR ! JZ S171 LXI D,LD2 ! MVI B,3 ! CALL CMPCHR ! JZ S173 LXI D,LD3 ! MVI B,3 ! CALL CMPCHR ! JZ S175 LXI D,LD4 ! MVI B,3 ! CALL CMPCHR ! JZ S177 LXI D,LD5 ! MVI B,5 ! CALL CMPCHR ! JZ S179 LXI D,LD6 ! MVI B,5 ! CALL CMPCHR ! JZ S181 LXI D,LD7 ! MVI B,5 ! CALL CMPCHR ! JZ S183 ;PROCESS SPECIAL OPRNDS ; CALL GNC CPI '(' ! JZ S185 ;BRANCH IF () FORM CALL BACKUP ! CALL EVAL LDA EVFLGS ! ANI RPNAME ! JNZ S147 ;BRANCH IF RPAIR NAME CALL GNC ! CPI '(' ! JZ S130 ;BRANCH IF () OPERAND LHLD VAL ! SHLD SAVVAL CALL BACKUP ! CALL EVAL ! LDA EVFLAGS ! ANI RNAME ! JNZ S128 ;> RNAME LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 6 ! STA INST LDA VAL ! STA INST+1 ! MVI A,2 ! STA LEN ! JMP ENDSTMT ;IMMED OPERAND ; S128 EQU $ ;PROCESS RNAME LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA VAL ! ADD B ADI 40H ;FOR R-R TYPE INST STA INST ! MVI A,1 ! STA LEN ;REG-REG OPERAND JMP ENDSTMT ; S130 EQU $ CALL GNC ! CALL GNC CPI 'L' ! JZ S138 CPI 'X' ! JZ S140 CPI 'Y' ! JZ S145 CALL BACKUP ! CALL BACKUP ! CALL EVAL LDA EVFLAGS ! ANI RPNAME ! JNZ S136 ;BRANCH IF REG PAIR MVI A,3AH ! STA INST ! LHLD VAL ! SHLD INST+1 MVI A,3 ! STA LEN ! JMP ENDSTMT ; S136 EQU $ LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ADI 0AH ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S138 EQU $ LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ADI 46H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S140 MVI A,0DDH ! STA INST S140A LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 46H ! STA INST+1 CALL GNC CALL EVAL ! LDA VAL ! STA INST+2 MVI A,3 ! STA LEN JMP ENDSTMT ; S145 EQU $ MVI A,0FDH ! STA INST ! JMP S140A ; S147 EQU $ CALL GNC ! CPI '(' ! JZ S159 LHLD VAL ! SHLD SAVVAL CALL BACKUP CALL EVAL LDA SAVVAL ! CPI 0FFH ! JZ S155 ! CPI 0FEH ! JZ S157 LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! INR A ! STA INST LHLD VAL ! SHLD INST+1 ! MVI A,3 ! STA LEN ! JMP ENDSTMT ; S155 EQU $ MVI A,0DDH ! STA INST S156 EQU $ MVI A,21H ! STA INST+1 ! MVI A,4 ! STA LEN LHLD VAL ! SHLD INST+2 JMP ENDSTMT ; S157 EQU $ MVI A,0FDH ! STA INST ! JMP S156 ; S159 EQU $ LHLD VAL ! SHLD SAVVAL CALL EVAL LDA SAVVAL ! CPI 4 ! JZ S165 CPI 0FFH ! JZ S167 CPI 0FEH ! JZ S169 MVI A,0EDH ! STA INST LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 4BH ! STA INST+1 LHLD VAL ! SHLD INST+2 ! MVI A,4 ! STA LEN JMP ENDSTMT ; S165 EQU $ MVI A,2AH ! STA INST ! LHLD VAL ! SHLD INST+1 ! MVI A,3 ! STA LEN JMP ENDSTMT ; S167 EQU $ MVI A,0DDH ! STA INST S168 MVI A,2AH ! STA INST+1 ! LHLD VAL ! SHLD INST+2 ! MVI A,4 ! STA LEN JMP ENDSTMT ; S169 EQU $ MVI A,0FDH ! STA INST ! JMP S168 ; S171 LXI H,57EDH S171A SHLD INST ! MVI A,2 ! STA LEN ! JMP ENDSTMT ; S173 LXI H,5FEDH ! JMP S171A ; S175 LXI H,47EDH ! JMP S171A ; S177 LXI H,4FEDH ! JMP S171A ; S179 MVI A,0F9H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S181 LXI H,0F9DDH ! JMP S171A ; S183 LXI H,0F9FDH ! JMP S171A ; S185 JMP S186 ; LD01 DB 'HL)' LD02 DB 'IX+' LD03 DB 'IY+' ; S186 LHLD PTR1 LXI D,LD01 ! MVI B,3 ! CALL CMPCHR ! JZ S204 LXI D,LD02 ! MVI B,3 ! CALL CMPCHR ! JZ S210A LXI D,LD03 ! MVI B,3 ! CALL CMPCHR ! JZ S210B CALL EVAL ! LHLD VAL ! SHLD SAVVAL LDA EVFLAGS ! ANI RPNAME ! JNZ S202 CALL GNC ;BYPASS COMMA CALL EVAL ! LDA EVFLAGS ! ANI RPNAME ! JNZ S193 MVI A,32H ! STA INST ! LHLD SAVVAL ! SHLD INST+1 MVI A,3 ! STA LEN ! JMP ENDSTMT ; S193 EQU $ LDA VAL CPI 4 ! JZ S196 CPI 0FFH ! JZ S198 CPI 0FEH ! JZ S200 ; MVI A,0EDH ! STA INST LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 43H ! STA INST+1 LHLD SAVVAL ! SHLD INST+2 MVI A,4 ! STA LEN ! JMP ENDSTMT ; S196 EQU $ MVI A,22H ! STA INST LHLD SAVVAL ! SHLD INST+1 ! MVI A,3 ! STA LEN ! JMP ENDSTMT ; S198 EQU $ MVI A,0DDH ! STA INST S199 EQU $ MVI A,22H ! STA INST+1 ! LHLD SAVVAL ! SHLD INST+2 MVI A,4 ! STA LEN ! JMP ENDSTMT ; S200 EQU $ MVI A,0FDH ! STA INST ! JMP S199 ; S202 EQU $ LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 2 ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; S204 EQU $ CALL GNC ! CALL GNC ! CALL GNC ! CALL GNC CALL EVAL LDA EVFLAGS ! ANI RNAME ! JNZ S209 MVI A,36H ! STA INST ! LDA VAL ! STA INST+1 ! MVI A,2 ! STA LEN JMP ENDSTMT ; S209 EQU $ LDA VAL ! ADI 70H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S210A MVI A,0DDH ! STA INST ! JMP S211 S210B MVI A,0FDH ! STA INST S211 EQU $ CALL GNC ! CALL GNC ! CALL GNC ! CALL EVAL LHLD VAL ! SHLD SAVVAL CALL GNC ;BYPASS COMMA CALL EVAL LDA EVFLAGS ! ANI RNAME ! JNZ S218 MVI A,36H ! STA INST+1 LDA SAVVAL ! STA INST+2 ! LDA VAL ! STA INST+3 MVI A,4 ! STA LEN ! JMP ENDSTMT ; S218 EQU $ LDA VAL ! ADI 70H ! STA INST+1 ! LDA SAVVAL ! STA INST+2 MVI A,3 ! STA LEN ! JMP ENDSTMT ; ; EJECT ;END OF LD PROCESSING ; ; CLASS 9 - PUSH POP ; ; S220 EQU $ CALL EVAL LDA VAL ! CPI 0FFH ! JZ S224 ! CPI 0FEH ! JZ S226 LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE ! ADD B STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; S224 EQU $ MVI A,0DDH ! STA INST S225 EQU $ LDA OPCODE ! ADI 20H ! STA INST+1 ! MVI A,2 ! STA LEN JMP ENDSTMT ; S226 MVI A,0FDH ! STA INST ! JMP S225 ; ; EJECT ; ; ; CLASS 10 - EXCHANGE (EX) ; ; S228 EQU $ CALL GNC ! CPI '(' ! JZ S235 ;BRANCH IF () FORM CPI 'A' ! JZ S233 ; BRANCH IF EX AF,AF' MVI A,0EBH ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S233 EQU $ MVI A,8 ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S235 EQU $ LHLD PTR1 ! LXI D,5 ! DAD D ! SHLD PTR1 CALL GNC CPI 'L' ! JZ S239 CPI 'Y' ! JZ S241 ; MVI A,0DDH ! STA INST S238 EQU $ MVI A,0E3H ! STA INST+1 ! MVI A,2 ! STA LEN ! JMP ENDSTMT ; S239 EQU $ MVI A,0E3H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S241 EQU $ MVI A,0FDH ! STA INST ! JMP S238 ; ; EJECT ; ; ; CLASS 11 - RETURNS ; ; S243 EQU $ CALL GNC CPI 0AH ! JZ S248 ;BRANCH IF NO OPERAND CPI 0DH ! JZ S248 ! CPI ';' ! JZ S248 ;BRANCH IF NO OPERAND LHLD SYMCND ! SHLD SYMPT ;FOR ELIMINATING REG NAME CONFLICTS CALL BACKUP ! CALL EVAL LXI H,SYM ! SHLD SYMPT ;PUT IT BACK LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 0C0H ! STA INST MVI A,1 ! STA LEN ! JMP ENDSTMT ; S248 EQU $ LDA OPCODE ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; CLASS 12 - BIT,SET,RES ; ; S250 EQU $ CALL EVAL ! LHLD VAL ! SHLD SAVVAL ;SAVE BIT NUMBER CALL GNC ! CPI '(' ! JZ S257 CALL BACKUP ! CALL EVAL MVI A,0CBH ! STA INST LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE ! ADD B MOV B,A ! LDA VAL ! ADD B ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; S257 EQU $ CALL GNC ! CALL GNC ! CPI 'L' ! JZ S266 CPI 'Y' ! JZ S264 ; MVI A,0DDH ! STA INST S260 CALL GNC CALL EVAL MVI A,0CBH ! STA INST+1 ! LDA VAL ! STA INST+2 LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ! ADI 6 ! MOV B,A LDA OPCODE ! ADD B ! STA INST+3 MVI A,4 ! STA LEN ! JMP ENDSTMT ; S264 EQU $ MVI A,0FDH ! STA INST ! JMP S260 ; S266 EQU $ MVI A,0CBH ! STA INST ! LDA SAVVAL ! RLC ! RLC ! RLC ! ANI 38H ADI 6 ! MOV B,A ! LDA OPCODE ! ADD B ! STA INST+1 MVI A,2 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; CLASS 13 - INC,DEC ; ; S268 EQU $ CALL GNC ! CPI '(' ! JZ S290 CALL BACKUP ! CALL EVAL LDA EVFLAGS ! ANI RNAME ! JNZ S280 LDA VAL ! CPI 0FFH ! JZ S275 ! CPI 0FEH ! JZ S278 LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE+1 ! ADD B STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S275 MVI A,0DDH ! STA INST S276 LDA OPCODE+1 ! ADI 20H ! STA INST+1 ! MVI A,2 ! STA LEN JMP ENDSTMT ; S278 EQU $ MVI A,0FDH ! STA INST ! JMP S276 ; S280 EQU $ LDA VAL ! RLC ! RLC ! RLC ! ANI 38H ! MOV B,A ! LDA OPCODE ! ADD B STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; S290 EQU $ CALL GNC ! CALL GNC CPI 'L' ! JZ S299 CPI 'Y' ! JZ S297 MVI A,0DDH ! STA INST S293 CALL GNC ! CALL EVAL LDA OPCODE ! ADI 30H ! STA INST+1 ! LDA VAL ! STA INST+2 MVI A,3 ! STA LEN ! JMP ENDSTMT ; S297 EQU $ MVI A,0FDH ! STA INST ! JMP S293 ; S299 EQU $ LDA OPCODE ! ADI 30H ! STA INST ! MVI A,1 ! STA LEN ! JMP ENDSTMT ; ; EJECT ; ; CLASS 14 - PSEUDO OPERATORS ; ; S301 EQU $ LDA OPCODE ! DCR A ! ADD A MOV E,A ! MVI D,0 ! LXI H,PSDTAB ! DAD D MOV E,M ! INX H ! MOV D,M XCHG PCHL ; PSDTAB EQU $ DW S302 ;EQU DW S305 ;DEFS DW S308 ;DEFB DW S317 ;DEFW DW S320 ;END DW S323 ;ORG DW S324 ;EJECT DW S325 ;IBM FOR FORMATTING 3270 (ICC) SCREENS ; ; S302 EQU $ ;EQU CALL EVAL ! LHLD VAL ! XCHG ! LHLD SYMADR MOV M,E ! INX H ! MOV M,D LHLD VAL ! SHLD EQUVAL ! MVI A,1 ! STA EQUFLG JMP ENDSTMT ; S305 EQU $ ;DEFS CALL EVAL ! LHLD VAL ! SHLD LEN2 ! JMP ENDSTMT ; S308 EQU $ ;DEFB CALL GNC ! CPI 27H ! JZ S313 ;BRANCH IF QUOTE CALL BACKUP ! CALL EVAL ! MVI A,1 ! STA LEN LDA VAL ! STA INST JMP ENDSTMT ; S313 EQU $ LXI D,INST LHLD PTR1 S313A LDA LEN ! INR A ! STA LEN MOV A,M ! INX H ! STAX D ! INX D ! MOV A,M CPI 0DH ! JZ ENDSTMT ! CPI 27H ! JNZ S313A JMP ENDSTMT ; S317 EQU $ CALL EVAL ;DEFW LHLD VAL ! SHLD INST MVI A,2 ! STA LEN JMP ENDSTMT ; S320 EQU $ ;END CALL EVAL ! LHLD VAL ! SHLD ENDADR ! SHLD EQUVAL S321 MVI A,1 STA EQUFLG ! STA EFLG JMP ENDSTMT ; S323 EQU $ ;ORG CALL EVAL ! LHLD VAL ! SHLD PC SHLD EQUVAL ! MVI A,1 ! STA EQUFLG JMP ENDSTMT ; ; S324 EQU $ ;EJECT MVI A,MAXLNE-1 ! STA CURLNE ;CAUSE HOF ON RECORD AFTER EJECT JMP ENDSTMT ;TREAT THIS LIKE A COMMENT ; ; S325 EQU $ ;IBM PSEUDO FOR 3270 (ICC 40+) SCREEN FORMATTING LXI H,INST ! SHLD TEMP ;SET UP FOR MULTI-BYTE OUTPUT S325X EQU $ CALL GNC ! CPI 27H ! JZ S326 ;BRANCH IF LEADING QUOTE ; ; DO HEX UNTIL COMMA FOUND ; S325A EQU $ CALL S325B ;CONVERT TO BINARY AND STORE AWAY LDA LEN ! INR A ! STA LEN ;INCREMENT LENGTH CALL GNC ;GET NEXT CHARACTER CPI ',' ! JZ S326 ;IF COMMA THEN SWITCH TO ASCII CPI 0DH ! JNZ S325A ;BRANCH IF NOT DONE JMP ENDSTMT ;BRANCH IF CARRIAGE RETURN FOUND ; ; DO ASCII UNTIL COMMA FOUND ; S326 EQU $ LHLD PTR1 ! MOV A,M ! INX H ! SHLD PTR1 ;(GNC SKIPS BLANKS) CPI 0DH ! JZ ENDSTMT ;BRANCH IF END CPI ',' ! JZ S325X ;BRANCH IF END OF ASCII- SWITCH BACK TO HEX LHLD TEMP ! MOV M,A ! INX H ! SHLD TEMP ;PUT CHARACTER AWAY LDA LEN ! INR A ! STA LEN ;INCREMENT LENGTH COUNTER JMP S326 ;AND CONTINUE ; ; CONVERT HEX TO BIN FOR 'IBM' PSEUDO (INTERNAL SUBROUTINE) ; S325B EQU $ LXI B,0 ;SET UP FOR POSSIBLE SINGLE CHAR HEX DIG, ZERO B AND C CALL CNVDIG ;CONVERT DIGIT WE ALREADY HAVE CALL GNC CPI ',' ! JZ S325D ! CPI 0DH ! JZ S325D ;BRANCH IF ONLY SINGLE DIGIT PUSH PSW ;SAVE CHARACTER MOV A,B ! RLC ! RLC ! RLC ! RLC ! ANI 0F0H ! MOV C,A ;SET UP POP PSW ! CALL CNVDIG ;CONVERT SECOND DIGIT S325C EQU $ ;NOW COMBINE THEM MOV A,B ! ORA C LHLD TEMP ! MOV M,A ! INX H ! SHLD TEMP ;PUT CHARACTER AWAY RET ; S325D CALL BACKUP JMP S325C ; CNVDIG EQU $ ;CONVERT DIGIT TO BINARY (0-9 , A-F) CPI 'A' ! JC CNVD2 ;BRANCH IF NUMBER ADI 9 ;ADJUST 41 (A) TO 4A TO MAKE IT BINARY EQUIVALENT CNVD2 ANI 0FH ! MOV B,A RET ; ; EJECT ; ; ; E N D O F S T A T E M E N T P R O C E S S I N G ; ; ; ENDSTMT------HERE IT IS!!!! ; ; ENDSTMT EQU $ LDA PASSNO ! ORA A ! JZ S417 ;DONT PRINT DURING PASS 1 LDA UFLAG ! ORA A ! JZ $+8 ! MVI A,'U' ! STA ERRFLG ! XRA A ! STA UFLAG LDA ERRFLG ! CPI ' ' ! JNZ S402 ;ALWAYS PRINT ERRORS LDA LFLAG ! CPI 'N' ! JZ S412 ;DON'T PRINT IF USER ASKED US NOT TO S402 EQU $ LDA ERRFLG ! STA HDRBUF MVI A,' ' ! STA HDRBUF+1 LXI H,HDRBUF+2 ! LXI D,HDRBUF+1 ! LXI B,14 ! CALL MOVE LDA EQUFLG ! ORA A ! JNZ S410 ;BRANCH IF TO USE EQUVAL LHLD PC ! XCHG ! LXI H,HDRBUF+1 MOV A,D ! CALL CNV2HX MOV A,E ! CALL CNV2HX INX H LXI D,INST MVI C,4 ! LDA LEN ! MOV B,A ORA A ! JZ S408 ;BRANCH IF LENGTH IF ZERO S406 EQU $ LDAX D ! CALL CNV2HX INX D DCR B ! JZ S408 DCR C ! JNZ S406 S408 EQU $ LXI H,HDRBUF ! CALL PLINE ;WRITE AND PAGE JMP S412 ; S410 EQU $ LHLD EQUVAL ! XCHG ! LXI H,HDRBUF+1 MOV A,D ! CALL CNV2HX MOV A,E ! CALL CNV2HX LXI H,HDRBUF ! CALL PLINE ; S412 EQU $ LDA LEN ! ORA A ! JZ S417 MOV B,A LXI D,INST LHLD PC ! SHLD TEMP S414 EQU $ PUSH B LDAX D ! LHLD TEMP ! CALL WOBJ POP B INX D LHLD TEMP ! INX H ! SHLD TEMP DCR B ! JNZ S414 ; S417 EQU $ LHLD PC ! LDA LEN ! MOV C,A ! MVI B,0 ! DAD B XCHG ! LHLD LEN2 ! DAD D ! SHLD PC LDA EFLG ! ORA A ! JZ NEXT ;GO PROCESS NEXT RECORD LDA PASSNO ! CMA ! STA PASSNO CPI 0 ! JZ ENDIT LXI H,FCB1+12 ! MVI M,0 LXI D,FCB1 ! CALL OPNFIL LXI H,FCB1+32 ! MVI M,0 LXI H,INBUF+1024 ! SHLD IBP XRA A ! STA EFLG ;RESET END OF RECORD FLAG LXI H,0 ! SHLD PC ;RESET PC MVI A,1 ! STA PAGENO ;SET UP PAGE NUMBER MVI A,MAXLNE+1 ! STA CURLNE LXI D,-1 ! SHLD OBJADR JMP NEXT ; ENDIT EQU $ LDA HFLAG ! CPI 'N' ! JZ ENDITX ;BRANCH IF NO HEX FILE LDA OBJCNT ! ORA A ! JZ ENDIT1 ;BRANCH IF NO OBJ TO WRITE CALL WREC ;ELSE WRITE FINAL RECORD ENDIT1 LXI H,EOFREC ! MVI B,13 ENDIT2 MOV A,M ! CALL WNB2 ! INX H ! DCR B ! JNZ ENDIT2 MVI B,255 ;FLUSH BUFFER ENDIT3 MVI A,1AH ! CALL WNB2 ! DCR B ! JNZ ENDIT3 LXI D,FCB2 ! CALL CLSFIL ENDITX EQU $ LHLD PC ! XCHG ! LXI H,PCMSGA MOV A,D ! CALL CNV2HX ! MOV A,E ! CALL CNV2HX LXI D,PCMSG ! CALL WMSG LHLD SYMPTR ! XCHG ! LXI H,SYMSGA MOV A,D ! CALL CNV2HX ! MOV A,E ! CALL CNV2HX LXI D,SYMSG ! CALL WMSG LXI D,ENDMSG ! CALL WMSG JMP 0000H PCMSG DB 13,10,'LAST ADDRESS USED IN THIS ASSEMBLY IS: ' PCMSGA DB 'XXXX','$' ; SYMSG DB 13,10,'NEXT SYMBOL ADDRESS IS: ' SYMSGA DB 'XXXX$' ; ENDMSG DB 13,10,10,'Z-80 ASSEMBLY COMPLETE',13,10,10,'$' ; EOFREC DB ':00000001FF',13,10 ; ; EJECT ; ; WOBJ - WRITE OBJECT BYTE ROUTINE ; ; INPUT BYTE IN A REGISTER ; WOBJ EQU $ MOV B,A ;SAVE INPUT LDA HFLAG ! CPI 'N' ! RZ ;RETURN IF NO HEX FILE MOV A,B ;GET INPUT CHARACTER BACK PUSH D ! PUSH PSW PUSH H ! LHLD OBJADR ! LXI D,-1 CALL CMPHD ! POP H ! JZ WOBJ0 ;BRANCH IF FIRST TIME THROUGH XCHG ! LHLD OLDADR ! INX H ! CALL CMPHD ! JZ WOBJ1 ;BRA IF NEXT SEQ BYT CALL WREC WOBJ0 EQU $ XCHG ! SHLD OBJADR ! XCHG XRA A ! STA OBJCNT WOBJ1 EQU $ XCHG ! SHLD OLDADR LDA OBJCNT ! CPI 10H ! JC WOBJ2 ;BRANCH IF NOT TIME TO WRITE CALL WREC LHLD OBJADR ! LXI D,16 ! DAD D ! SHLD OBJADR ;ADVANCE ADDR XRA A ! STA OBJCNT WOBJ2 EQU $ INR A ! STA OBJCNT ;UPDATE COUNT DCR A ! MOV E,A ! MVI D,0 ! LXI H,OBJ ! DAD D WOBJ3 POP PSW ! MOV M,A POP D RET ; ; WREC - FORMAT AND WRITE HEX RECORD ; ; WREC EQU $ PUSH H ! PUSH D LHLD OLDADR ! LXI D,-1 ! CALL CMPHD ! JZ WREC3 ;BRANCH IF FIRST TIME LDA OBJCNT ! MOV C,A ! MOV B,A ;SET CHKSUM AND COUNT LXI H,REC ! MVI M,':' ! INX H MOV A,B ! CALL CNV2HX LDA OBJADR+1 ! ADD C ! MOV C,A ! LDA OBJADR+1 ! CALL CNV2HX LDA OBJADR ! ADD C ! MOV C,A ! LDA OBJADR ! CALL CNV2HX XRA A ! CALL CNV2HX LXI D,OBJ WREC1 EQU $ LDAX D ! ADD C ! MOV C,A ! LDAX D ! CALL CNV2HX INX D ! DCR B ! JNZ WREC1 MOV A,C ! CMA ! INR A ! CALL CNV2HX MVI M,0DH ! INX H ! MVI M,0AH ;PUT CRLF ON END LXI H,REC ;WRITE OUT RECORD WREC2 EQU $ MOV A,M ! CALL WNB2 MOV A,M ! CPI 0AH ! INX H ! JNZ WREC2 ;GO UNTIL LF WREC3 EQU $ POP D ! POP H RET ; ; EJECT ; ; ; PLINE ROUTINE - WRITE AND PAGE ; ; PLINE EQU $ LDA CURLNE ! CPI MAXLNE ! JC PLINE1 ;BRANCH IF LESS LXI D,FCB1+1 ! LXI H,HOFNAM ! LXI B,8 ! CALL MOVE ;GET FILE NAME LXI H,HOFPG ! LDA PAGENO ! CALL CNV2HX LDA HOFPG ! CPI '0' ! JNZ $+8 ! MVI A,' ' ! STA HOFPG LDA PAGENO ! ADI 1 ! DAA ! STA PAGENO LXI H,HOFMSG ! CALL WLINE ! XRA A PLINE1 EQU $ INR A ! STA CURLNE LXI H,HDRBUF ! CALL WLINE RET ; HOFMSG EQU $ DB 0DH,8AH,0DH,8AH,0CH DB 'Z80ASM-2.0A (C) 1977 LCS' DB 0DH,8AH,0DH,8AH DB 'SOURCE FILE NAME: ' HOFNAM DB 'XXXXXXXX PAGE # ' HOFPG DB 'XX' DB 8AH,0DH,8AH,0DH,0AH ; ; ; EJECT ; ;