;REF NO. C00008.C80 ;PROGRAM TITLE CROSS ASSEMBLER FOR INTEL 8080 MICROPROCESSOR ; ; 1 ! CROSS ASSEMBLER WRITTEN BY R. TAPP APRIL 1975 2 ! MODIFIED FOR 8080 BY G. D. YOUNG, MAY 1975 ! ! DIFFERENCES BETWEEN THE PROGRAM AND THE ASSEMBLER FOR THE 8080: 3 ! -LXI IS AN 8080 INSTRUCTION, NOT A PSEUDO-OP ! -THE 8080 INSTRUCTIONS WHOLE INCLUDING THE 8008 MNEMONICS AS A ! SUBSET, ENCODE INTO DIFFERENT BINARY VALUES. HENCE, PASS 2 OF 4 ! THE ORIGINAL ASSEMBLER HAS BEEN REWRITTEN (LINES 200-270). ! -INSTRUCTION ENCODING (FIRST BYTE) IS BY TABLE LOOKUP THEN ADDING 5 ! IN 3-BIT REGISTER ARGUMENTS. ! -THE REGISTER LOOKUP SUBR (8000) HAS BEEN EXPANDED TO ALLOW THE ! NAMES SP, PC, PSW FOR REGISTER ARGUMENTS. 6 ! -REGISTER-PAIR INSTRUCTIONS HAVE ADDITIONAL CHECK ON REGISTER ! VALUE (IT MUST BE EVEN). 9 ! INITIALIZATION ! 10 INPUT "SOURCE FILE", I$ : OPEN I$ DOR INPUT AS FILE 1% : INPUT "LISTING FILE"; O$ : OPEN O$ FOR OUTPUT AS FILE 3% 20 O$=SYS(CHR$(6%)+CHR$(-7%)) : ON ERROR GOTO 9000 : PRINT #2%, CHR$(0%); FOR I%=1% TO 50% 30 DIM S%(200),M$(85),Q$(85),S$(200) ! S$ IS THE SYMBOL TABLE, S% THE SYMBOL VALUE 40 B$="SYMBOL" : M$="CODES" : R$=BCDEHLMA" : S$=B$+":" : X$="XX" : Y$=SPACE$(43%) ! THE REGISTERS ARE IN DIFFERENT ORDER 45 DEF FNL$=S$+" "+M$+" "+LEFT(L$,INSTR(N%+2%,L$," ")-1%) : DEF FNC$=LEFT(C$,INSTR(2%,C$CHR$(10%))) : DEF FNP$=" PAGE"+NUM$(P%)+"LINE"+NUM$(Q%)+">"+FNL$+" "+FNC$ !FNL PRINTS LINE; FNC COMMENT PART PF LINE; FNP ERROR MSG PRINTOUT 50 READ M$(I%) FOR I%=0% TO 83% : FOR I%=0% TO 77% : READ A% : Q$(I%)=CHR$(A%) : NEXT I% 79 ! ! START OF PASS 1. PASS ONE COMPOSES THE SYMBOL TABLE ! 80 GOSUB 1000 : IF S%<>0% THEN S$(K%)=LEFT(S$,S%-1%) : S%(K%)=L% : K%=K%+1% !S% IS RETURNED BY 1000 AND FLAGS TAG ON CURRENT LINE !N%=NR OF BYTES IN THIS INSTRN; C%=1 FOR INSTRN, ! 2, 3,...,7 FOR POSN OF PSEUDO OP 100 L%=L%+N% : ON C% GO TO 80,120,130,140,150,160,170,80 120 L%=L%+1% !WORD PSEUDO OP, ADVANCE 2 BYTES 130 L%=L%+1% : GOTO 80 !BYTE 140 GOSUB 3000 : L%=L%+N% : GO TO 80 !ASCII PSEUDO 150 GOSUB 2000 : L%=A% : GO TO 80 !ORG PSEUDO OP 160 CLOSE 1% : OPEN I$ FOR INPUT AS FILE 1% : L%=0% : GOTO 190 161 !END OF FIRST PASS. RESET TO BEGINING OF FILE 170 GOSUB 1500 : S$(K%)=LEFT(L$,M%-1%) : S%(K%)=A% : K%=K%+1% : GOTO 80 189 ! ! START OF PASS 2 ! 190 GOSUB 1100 : GOSUB 1000 : IF C%>4% THEN PRINT #3%, SPACE$(8%); 200 ON C% GOTO 210,320,330,340,350,360,370,280 210 R%=ASCII(Q$(M%)): IF M%>24% THEN 220 ELSE A%=R%: GOTO 270 !STRAIGHT LOOKUP FOR FIRST ONES 220 IF M%=55% THEN 250 ELSE IF M%>44% THEN A%=R%: GOTO 270 !LOOKUP OF FIRST BYTE FOR ALL REST BUT LXI 230 IF M%=25% THEN GOSUB 8000:R%=R%+A*8% !GET REG FOR MID ARG AND ADD IT IN TO LOOKUP VALUE 232 GOSUB 8000 : IF M%<34% THEN A%=R%+A%: GOTO 270 !ADD IN RIGHT REG ARGUMENT 234 IF M%<44% AND M%>36% THEN IF A%<>A%/2%*2% THEN GOSUB 8010 !MAAE SURE REGS ARE EVEN FOR LAST SINGLE BYTE INSTRNS 235 A%=R%+A%*8%: GO TO 270 250 GOSUB 8000: A%=R%+A%*8%: !ADD IN MID REG FOR LXI 270 GOSUB 5000 : IF N%=1% THEN 280 ELSE GOSUB 2000 : IF N%=2% THEN GOSUB 5000 ELSE GOSUB 4000 280 PRINT #3%,, FNC$; : GOTO 190 PRINT #3%, FNC$, : GO TO 280 !WORD 320 GOSUB 2000 : GOSUB 4000 : GOTO 280 !ORG !BYTE 339 !ASCII 340 GOSUB 3000 : C%=0% : FOR M%=1% TO N% : A%=ASCII(RIGHT(A$,M%)) : GOSUB 5000 : C%=C%+1% : IF C%=4% THEN C%=0% : PRINT #3% : GOSUB 1100 : PRINT #3%, SPACE$(8%); 345 NEXT M% : GOTO 280 350 GOSUB 2000 : L%=A% : GOSUB 5050 UNLESS X%0% : GOTO 280 !ORG 360 GOSUB 5050 UNLESS X%=0% : PRINT #2%, ":0000000000" : GOTO 280 !END ! GENERATE AND PRINT THE SYMBOL TABLE ! 400 FOR I%=0% TO K%-2% : FOR J%=I% TO K%-1% : FOR L%=1% TO 6% : C%=ASCII(RIGHT(S$(J%),L%)) : S%ASCII(RIGHT(S$(I%),L%) : IF C%S% THEN 430 410 NEXT L% 420 S$=S$(J%)+"" : A%=S%(J%) : S$(J%)=S$(I%)+"" : S%(J%)=S%(I%) : S$(I%)=S$+"" : S%(I%)=A% 430 NEXT J% : NEXT I% : C%=0% : GOSUB 1100 : FOR M%=0% TO K%-1% IF C%=4% THEN C%=0% : PRINT #3% : GOSUB 1100 440 A%=S%(M%) : R%=A% : PRINT #3%,, : PRINT #3% USING " S$(M%)," = #"; : GOSUB 8100 : PRINT #3%, " = %"R%; : C%=C%+1% : NEXT M% : PRINT #3% : GOTO 9010 999 ! !SUBROUTINE TO SCAN AN INPUT LINE ! 1000 INPUT LINE #1%, L$ : C%=INSTR(1%,L$,";") IF C%=0% THEN C%=INSTR(1%,L$,CHR$(13%)) 1010 C$=RIGHT(L$,C%) : LSET L$=LEFT(L$,C%-1%) : 8%=INSTR(1%,L$,":") : LSET S$=LEFT(L$,8%) : LSET L$=RIGHT(L$,8%+1%) 1020 GOSUB 7000 : I%=INSTR(1%,L$,CHR$(9%))-1% : J%=INSTR(1%,L$," ")-1% : IF I%=0% THEN J%=I% 1025 RSET M$=LEFT(L$,J%) : LSET L$=RIGHT(L$,J%+2%) 1030 GOSUB 7000 : I%=INSTR(2%,L$,CHR$(9%)) : LSET L$=LEFT(L$,I%-1%) UNLESS I%=0% : A$=L$+"" : IF ASCII(M$)<33% THEN N%=0% : C%=8% : RETURN 1031 !GIVE ILLEGAL CHAR MESSAGE IF NO GOOD 1032 !GET MNEMONIC ALONE IN LEFT OF L$ FREE OF LEADING SPACES OR TABS 1039 INITIALIZE C%, M%: SEARCH MNEMONIC TABLE FOR THE INSTRUCTION 1040 C%=1% : M%=0% : M%=M%+1% UNTIL LEFT(M$,J%)=M$(M%) OR M%=84% : IF M%<44% THEN N%=1% ELSE IF M%<55% THEN N%=2% ELSE IF M%<78% THEN N%=3% ELSE N%=0% : C%=M%-76% : IF C%=8% THEN PRINT "*I*"FNP$; : PRINT #3%, "*I*"; 1050 RETURN 1099 ! !PAGE AND LINE FORMATTING FOR LISTING ! 1100 IF Q%=0% THEN P%=P%+1% : PRINT #3%, CHR$(12%);CHR$(10%) "PAGE"P%,I$ : PRINT #3% 1110 Q%=Q%+1% : PRINT #3% USING "## ",Q%; : IF Q%=50% THEN Q%=0% 1120 RETURN 1499 ! !PRELIMINARY ARG EVALUATION FOR SET PSEUDO OP 1500 M%=INSTR(1%,A$,"=") * LSET A$=RIGHT(A$,M%+1%) 1999 ! !2000 SUBROUTINE TO EVALUATE AN EXPRESSION ! 2000 A%=0% : C%=ASCII(A$) : IF C%=43% OR C%=45% THEN LSET A$=RIGHT(A$,2%) ELSE C%=43% 2010 IF C%=45% THEN S%=1% ELSE IF C%=43% THEN S%=0% ELSE RETURN 2020 C%=48% : C%=ASCII8RIGHT8A$,I%)) FOR I%=2% UNTIL C%<47% : I%=I%-2% : LSET B$=LEFT(A$,I%) : LSET A$=RIGHT(A$,I%+2%) 2030 J%=ASCII(B$) : IF J%=35% THEN 2050 ELSE IF J%=37% THEN 2080 ELSE IF J%=46% THEN 2090 ELSE J%=0% : J%=J%+1% UNTIL S$(J%)=LEFT(B$,I%) OR J%=K% : IF J%32% THEN 2120 2060 NEXT I% : FOR I%=3% TO 6% : IF A%(I%)>70% THEN 2120 ELSE IF A%(I%)>64% THEN A%(I%)=A%(I%)=A%(I%)-55% ELSE IF A%(I%)>57% THEN 2120 ELSE IF A%(I%)>47% THEN A%(I%)=A%(I%)-48% ELSE IF A%(I%)=32% THEN A%(I%)=0% ELSE 2120 2070 NEXT I% : A%(4%)=A%(3%)*16%+A%(4%) : A%(6%)=A%(5%*16%+A%(6%) : J%=CVT$%(CHR$(A%(4%))+CHR$(A%(6%))) : GOTO 2100 2080 J%V 2080 J%=VAL(VAL(MID(B$,2%,I%-1%)) : GOTO 2100 2090 IF N%<2% THEN J%=L% ELSE J%=L%-1% 2100 IF S% THEN A%=A%-J% ELSE A%=A%+J% 2110 GOTO 2010 2120 A%=0% : PRINT "*N*"FNP$; : PRINT #3%. "*N*"; : RETURN 2999 ! !SUBROUTINE TO RETURN ASCII STRING FOR ASCII PSEUDO OP ! 3000 N%=INSTR(2%,A$,CHR$(ASCII(A$)))-2% : LSET A$=RIGHT(A$,2%) : RETURN UNLESS N%=-2% : N%=6% : PRINT "*S*"FNP$; : PRINT #3%, "*S$"; : RETURN 3998 ! !4000-OUTPUT A WORD AS TWO BYTES, LOW BYTE FIRST 3999 !5000-OUTPUT A BYTE ! 4000 CHANGE CVT%$(A%) TO A% : A%=A%(2%) : GOSUB 5000 : A%=A%(1%) 5000 IF X%=0% THEN X0%=L% : Y%=0% : Z%=0% 5005 IF A%<-128% OR A%>255% THEN GOSUB 5500 ELSE IF A%<0% THEN A%=ASCII(RIGHT(CVT%$(A%),2%)) 5010 GOSUB 6000 : LSET Y$=LEFT(Y$,Y%)+X$ : PRINT #3%, X$; : Y%=Y%+2% : L%=L%+1% : CHANGE CVT%$(L%) TO B% : IF B%(2%)-B%(2%)/16%*16% THEN RETURN 5050 A%=X% : GOSUB 6000 : LSET B$=X$ : CHANGE CVT%$(X0%) TO B% FOR J%=1% TO 2% : A%=B%(J) : GOSUB 6000 : A%=J%+J% : LSET B$=LEFT(B$,A%)+X$ : NEXT J% 5060 A%=ASCII(RIGHT(CVT%$(Z%),2%)) : GOSUB 6000 : LSET Y$=":"+B$"00"+LEFT(Y$,Y%)+X$ : PRINT #2%, Y$ : X%=0% : RETURN 5499 ! ! *A* ERROR SUBROUTINE 5500 A%=0% : PRINT "*A*; : PRINT #3%, "*A*"; : RETURN 5998 ! !PRELIM UPDATE OF CHECKSUM AND BYTE COUNT FOR HEX OUTPUT 5999 !SUBR TO CONVERT BYTE INTEGER TO TWO BYTE HEX STRING ! 6000 Z%=Z%-A% : X%=X%+1% 6005 A%(7%)=A%/16% : A%(8%)=A%-16%*A%(7%) : FOR I%=7% TO 8% : IF A%(I%)>9% THEN A%(I%)=A%(I%)+55% ELSE A%(I%)=A%(I%)+48% 6010 BEXT I% : LSET X$=CHR$(A%(7%))+CHR$(A%(8%)) : RETURN 6999 ! !LEFT JUSTIFY L$ 7000 LSET L$=RIGHT(L$,"%) FOR I%=1% WHILE ASCII(L$)<33% AND I%<10% : RETURN 7999 ! !EVALUATE REGISTER NUMBER - NOW INCL PC, PSW, SP ! 8000 A%=INSTR(1%,R$,LEFT(A$,1%))-1% : IF A%=-1% THEN 8020 ELSE LSET A$=RIGHT(A$,3%) : RETURN 8010 PRINT "*R*"FNP$; : PRINT #3%, "*R*"; : RETURN 8020 IF LEFT(A$,2%) = "SP" OR LEFT(A$,2%)="PC" THEN A%=6%: LSET A$=RIGHT(A$,4%): RETURN 8021 IF LEFT(A$,3%)<>"PSW" THEN 8010 ELSE A%=6%: LSET A$=RIGHT(A$,5%): RETURN 8099 ! !CONVERT WORD ADDRESS TO HEX 8100 CHANGE CVT%$(A%) TO A% : FOR J%=1% TO 2% : A%=A%(J%) : GOSUB 6005 : PRINT #3%, X$; : NEXT J% : RETURN 9000 IF ERL=2080% THEN RESUME 2120 ELSE Q%=0% : IF ERR=11% THEN RESUME 400 9010 PRINT #2%, CHR$(0%); FOR I%=1% TO 50% : PRINT #I%, CHR$(26%); FOR I%=2% TO 3% : CLOSE 1%,2%,3% 9020 IF ERL=80% OR ERL=170% THEN PRINT "SYMBOL TABLE OVERFLOW" ELSE IF ERR=28% THEN RESUME 9999 ELSE ON ERROR GOTO 0 9499 ! ! 8080 INSTRUCTION MNEMONICS - READ INTO M$ ON INITIALIZN ! ARRANGED ONE BYTE FIRST (M% 0,1,...,43) THEN TWO-BYTE ! (M% = 44, 45, ... ,54), THEN THREE-BYTE (M%=55,...,77) ! AND FINALLY PSEUDO-OPS (M%=78,...,83--C%=55,...,7) 9500 DATA RLC,RRC,RAL,RAR,HLT,RET,RC,RNC,RZ,RNZ,RP,RM,RPE,RPO 9501 DATA XCHG,XTHL,SPHL,PCHL,CMA,STC,CMC,DAA,EI,DI,NOP 9502 DATA MOV,ADD,ADC,SUB,SBB,ANA,XRA,ORA,CMP 9503 DATA INR,DCR,RST,PUSH, POP ,DAD,STAX,LDAX,INX,DCX 9504 DATA MVI,ADI,ACI,SUI,SBI,ANI,XRI,ORI,CPI,IN,OUT 9505 DATA LXI,JMP,JC,JNC,JZ,JNZ,JP,JM,JPE,JPO 9506 DATA CALL,CC,CNC,CZ,CNZ,CP,CM,CPE,CPO,STA,LDA,SHLD,LHLD 9507 DATA WORD,BYTE ASCII,ORG,END SET 9509 ! !INTERGER VALUES FOR THE INSTRUCTIONS- ONE FOR ONE CORRESPONDENCE !WITH ABOVE TABLE--BUT OMITS PSEUDO-OPS ! 9510 DATA 7,15,23,31,118,201,216,208,200,192,240,248,232,224 9511 DATA 235,227,249,233,47,55,63,39,251,243,0 9512 DATA 64,128,136,144,152,160,168,176,184 9513 DATA 4,5,199,197,197,193,9,2,10,3,11 9514 DATA 6,198,206,214,222,230,238,246,254,219,211 9515 DATA 1,195,218,210,202,194,242,250,234,226 9516 DATA 205,220,212,204,196,244,252,236,228,50,58,34,42 32767 END