S-C Macro Assembler 3.0
1000 *SAVE X.ASM.GENERAL
1010 *--------------------------------
1020 * ASSEMBLER MAIN DRIVER
1030 *--------------------------------
1040 ASM
1050 * LDX #0 X=0 FROM COMMAND DISPATCHER
1060 STX PASS SET TO PASS 1
1070 STX ERROR.COUNT
1080 STX ERROR.COUNT+1
1090 * STX MACRO.LEVEL ALREADY DONE IN GNL
1100 * STX PARAM.PNTR ALREADY DONE IN GNL
1110 * STX PAGE.LENGTH ALREADY DONE IN GNL
1120 STX PAGE.NUMBER
1130 STX PAGE.NUMBER+1
1140 JSR STINIT INITIALIZE SYMBOL TABLE
1150 JSR RESTORE IF IN INCLUDE, RESTORE
1160 *--------------------------------
1170 * PERFORM NEXT PASS OF ASSEMBLY
1180 *--------------------------------
1190 ASM1 LDA ERROR.COUNT
1200 ORA ERROR.COUNT+1
1210 BEQ .1
1220 JMP ASM.END PRINT # ERRORS AND ABORT ASSEMBLY
1230 .1 LDX #1 INIT 2-BYTE VARIABLES
1240 .2 LDA PP,X POINT TO BEGINNING OF SOURCE PROGRAM
1250 STA SRCP,X
1260 STA MACSTK,X
1270 LDA #0
1280 STA CALL.CNTR,X TOTAL # MACRO CALLS
1290 STA CALL.NUM,X CURRENT MACRO CALL #
1300 STA ORGN+2,X HIGH 16 OF ORIGIN
1310 DEX
1320 BPL .2
1330 *---Following = $FF--------------
1340 STX DO.STACK SET OUTER LEVEL TRUE (=$FF)
1350 STX LF.CONDITIONAL do not list false sets (=$FF)
1360 *---Following = $00--------------
1370 STA DUMMY.FLAG NOT IN DUMMY SECTION
1380 STA PHASE.FLAG NOT IN PHASE
1390 STA DO.INDEX SET DO.STACK TO EMPTY
1400 STA LF.ALL turn on main listing
1410 STA LF.MACRO list macro expansions too
1420 STA LF.XTRA.BYTES list all bytes, use extra lines
1430 STA TF.FLAG not in ".TF"
1440 STA DO.SKIP.CNT not in ".DO"
1450 STA FLAG.MA not in ".MA"
1460 STA NYBBLE.FLAG .AC odd/even
1470 STA ORGN ORIGIN = $0800
1480 STA TRGT TARGET = $0800
1490 *---Following = $08--------------
1500 LDA #$08
1510 STA ORGN+1
1520 STA TRGT+1
1530 JSR ASM.INIT Initialize for particular assembler
1540 *--------------------------------
1550 * MOVE NEXT LINE INTO WORKING BUFFER
1560 *--------------------------------
1570 ASM2 LDA $C000 CHECK FOR ABORT WITHOUT
1580 CMP #CHR.RETURN CLEARING STROBE
1590 BNE .1
1600 JMP JMP.SOFT YES, STOP RIGHT NOW
1610 .1 LDX #$FF INITIALIZE STACK POINTER
1620 TXS
1630 INX MAKE X=0
1640 STX EMIT.COLUMN
1650 STX EXP.UNDEF CLEAR UNDEFINED FLAG
1660 JSR SETUP.NEXT.LINE
1670 BCC .2 GOT A LINE
1680 JMP ENDM NO MORE LINES, ACT LIKE .EN FOUND
1690 *---CHECK CURRENT CONDITION------
1700 .2 LDA DO.STACK CURRENT LEVEL IN SIGN BIT
1710 BMI ASSEMBLE.ONE.LINE TRUE, SO ASSEMBLE
1720 *--------------------------------
1730 * SKIP TO .FIN OR .ELSE
1740 *--------------------------------
1750 SKIP.TO.FIN
1760 JSR SCAN.TO.OPCODE
1770 BCS .3
1780 LDX #DIR.QT.DO
1790 JSR DIR.SCAN.OR.FAIL
1800 BCC .1 NOT .DO
1810 INC DO.SKIP.CNT .DO
1820 BNE .3 ...ALWAYS
1830 .1 LDY DO.SKIP.CNT
1840 BNE .2 INSIDE A NESTED .DO, IGNORE .ELSE'S
1850 JSR DIR.SCAN.OR.FAIL
1860 BCS ASSEMBLE.ONE.LINE FOUND .ELSE
1870 .2 LDX #DIR.QT.FI
1880 JSR DIR.SCAN.OR.FAIL
1890 BCC .3 NOT .FIN
1900 LDY DO.SKIP.CNT .FIN, SEE IF NESTED ONE
1910 BEQ ASSEMBLE.ONE.LINE NO, ASSEMBLE THIS .FIN
1920 DEC DO.SKIP.CNT YES, POP OFF THIS NEST
1930 .3 BIT LF.CONDITIONAL LIST CONDITIONAL LINES?
1940 BMI ASM2 NO, SKIP IT
1950 JSR CRLF.IF.LISTING YES, NEW LINE
1960 JMP CMNT AND LIST IT
1970 *--------------------------------
1980 * ANALYZE SOURCE LINE
1990 *--------------------------------
2000 ASSEMBLE.ONE.LINE
2010 JSR CRLF.IF.LISTING
2020 JSR PACK.MACRO.LINE
2030 BCS CMNT ...only list if MACRO definition line
2040 JSR GNC.UC.START not MACRO line, get first char
2050 BCS CMNT ...empty line
2060 BEQ .3 ...blank, so no label
2070 JSR CHECK.COMMENT.CHAR
2080 BEQ CMNT ...comment (* or ;)
2090 JSR LABL PROCESS LABEL DEFINITION
2100 .3 JSR GNNB Scan to opcode field
2110 BCS CMNT ...none, only label on this line
2120 JSR CHECK.COMMENT.CHAR might be a comment with no opcode
2130 BEQ CMNT ...yes, there is a comment
2140 CMP #'> CHECK IF MACRO OPCODE
2150 BEQ .4 ...YES
2160 CMP #'_ CHECK IF MACRO OPCODE
2170 BEQ .4 ...YES
2180 CMP #'='
2190 BEQ .5 '=' is synonym for .EQ
2200 STA SEARCH.KEY FIRST OPCODE CHAR
2210 JSR GNC.UC
2220 STA SEARCH.KEY+1 2ND OPCODE CHAR
2230 JSR GNC.UC
2240 STA SEARCH.KEY+2 3RD OPCODE CHAR
2250 LDA SEARCH.KEY
2260 CMP #'. IS IT A DIRECTIVE?
2270 BNE .6 NO, TRY NORMAL OPCODES
2280 LDA #OPTBL.DIR
2290 LDY /OPTBL.DIR
2300 CLC INITIAL SEARCH
2310 JSR SEARCH.COMPRESSED.TABLE
2320 BCC OPER ...NOT FOUND IN TABLE
2330 JSR PERFORM.DIRECTIVE
2340 JMP CMNT
2350 .4 JMP MACRO.CALL
2360 .5 JSR PSEQ "=" is synonym for .EQ
2370 JMP CMNT
2380 .6 JSR ASM.PARTICULAR
2390 *--------------------------------
2400 CMNT LDA EXP.UNDEF
2410 BPL .1 NO UNDEFINED EXPRESSIONS ON THIS LINE
2420 LDA PASS
2430 BEQ .1 IF WE GOT THIS FAR, OKAY IN PASS 1
2440 JMP UNDF
2450 .1 JSR LIST.SOURCE.IF.LISTING
2460 JMP ASM2 NEXT LINE
2470 *--------------------------------
2480 *--------------------------------
2490 PERFORM.DIRECTIVE
2500 INY POINT AT HIGH BYTE OF ADDRESS
2510 LDA (OPTBL.PNTR),Y
2520 PHA
2530 DEY
2540 LDA (OPTBL.PNTR),Y
2550 PHA
2560 RTS
2570 *--------------------------------
2580 OPER LDY #QER2 ERROR--BAD OPCODE
2590 JMP SOFT.ERROR
2600 *--------------------------------
2610 * EMIT ONE BYTE OF OBJECT CODE
2620 *
2630 * IF IN PASS TWO THEN
2640 * ! IF LISTING THEN
2650 * ! IF IN ".TF" THEN
2660 * ! !
2670 * ! ELSE IF NOT IN DUMMY SECTION THEN
2680 * ! ! ! IF IN PROTECTED AREA THEN
2690 * ! ! ! !
2700 * ! ! ! ELSE
2710 * INCREMENT ORIGIN AND ORIGIN.SAVE
2720 * IF NOT IN DUMMY SECTION THEN INCREMENT TARGET
2730 *--------------------------------
2740 EMIT.ZERO
2750 LDA #0
2760 EMIT LDY PASS CHECK WHICH PASS
2770 BEQ .5 PASS 1, JUST INCREMENT LOCATION
2780 STA OBJ.BYTE SAVE OBJECT BYTE
2790 *---LIST THE BYTE----------------
2800 JSR P.EMITTED.BYTE
2810 *---STORE THE BYTE---------------
2820 BIT DUMMY.FLAG No output inside dummy section
2830 BMI .6 ...only increment the origin
2840 LDA OBJ.BYTE GET OUTPUT BYTE
2850 BIT TF.FLAG SEE IF IN ".TF"
2860 BMI .4 YES
2870 JSR USER.OBJECT.BYTE
2880 JMP .5 ...ALWAYS
2890 .4 JSR DOUT WRITE ON TARGET FILE
2900 *---INCREMENT LOCATION-----------
2910 .5 LDA DUMMY.FLAG IF IN DUMMY SECTION,
2920 BMI .6 THEN ONLY INCREMENT ORGN
2930 >INCD TRGT BUMP TARGET ADDRESS
2940 >INCD ORIGIN.SAVE AND ORIGIN OUTSIDE .PH
2950 .6 >INCD ORGN BUMP CURRENT ORIGIN
2960 RTS
2970 *--------------------------------
2980 STORE.OBJECT.BYTE
2990 LDA TRGT+1 TARGET PAGE
3000 BNE .1 NOT PAGE ZERO
3010 LDA TRGT ALLOW $00-$1E
3020 CMP #$1F
3030 BCC .4 SAFE
3040 BCS .3 NOT SAFE
3050 *---ALLOW $300-$3CF--------------
3060 .1 CMP #$03 IN PAGE 3?
3070 BNE .2 NO
3080 LDA TRGT BELOW $3D0?
3090 CMP #$D0
3100 BCC .4 YES, SAFE
3110 BCS .3 NO, NOT SAFE
3120 .DO AUXMEM
3130 *---ALLOW $800-MACSTK------------
3140 .2 CMP #$08 BELOW PAGE 8?
3150 BCC .3 YES, NOT SAFE
3160 LDA TRGT
3170 CMP MACSTK
3180 LDA TRGT+1
3190 SBC MACSTK+1
3200 BCC .4 BELOW MACSTK, SAFE
3210 .ELSE
3220 *---ALLOW $800-MACLBL------------
3230 .2 CMP #$08 BELOW PAGE 8?
3240 BCC .3 YES, NOT SAFE
3250 LDA TRGT NO, COMPARE TO MACLBL
3260 CMP MACLBL
3270 LDA TRGT+1
3280 SBC MACLBL+1
3290 BCC .4 BELOW MACLBL, SO SAFE
3300 *---ALLOW EOT-MACSTK-------------
3310 LDA EOT
3320 CMP TRGT
3330 LDA EOT+1
3340 SBC TRGT+1
3350 BCS .3 BELOW EOT, NOT SAFE
3360 LDA TRGT
3370 CMP MACSTK
3380 LDA TRGT+1
3390 SBC MACSTK+1
3400 BCC .4 BELOW MACSTK, SAFE
3410 .FIN
3420 *---NOT SAFE, CHECK USER RANGE---
3430 .3 LDA TRGT
3440 CMP USER.MEM.LO
3450 LDA TRGT+1
3460 SBC USER.MEM.LO+1
3470 BCC .5 DEFINITELY OUT OF BOUNDS
3480 LDA USER.MEM.HI
3490 CMP TRGT
3500 LDA USER.MEM.HI+1
3510 SBC TRGT+1
3520 BCC .5 DEFINITELY OUT OF BOUNDS
3530 .4 LDY #0
3540 LDA OBJ.BYTE
3550 STA (TRGT),Y
3560 RTS
3570 .5 LDY #QMEMPRO
3580 JMP FIRM.ERROR
3590 *--------------------------------
3600 * LIST SOURCE LINE
3610 *--------------------------------
3620 LIST.SOURCE.IF.LISTING
3630 JSR CHECK.IF.LISTING
3640 LIST.SOURCE.REGARDLESS
3650 JSR P.MARGIN PRINT BLANKS TILL MARGIN
3660 LIST.SOURCE.AT.MARGIN
3670 JSR CONVERT.LINE.NUMBER.PRINT
3680 LDY MACRO.LEVEL
3690 BEQ .2
3700 LDA #'>'
3710 .1 JSR CHO
3720 DEY
3730 BNE .1 ...UNTIL Y=0
3740 .2 LDA #' ' ...NOW Y=0
3750 .3 JSR CHO
3760 INY
3770 LDA WBUF-1,Y
3780 BNE .3
3790 RTS
3800 *--------------------------------
3810 * PRINT CRLF IF IN PASS 2 AND IF LISTING IS ON
3820 *--------------------------------
3830 CRLF.CAUSED.FORM.FEED
3840 JSR FORM.FEED
3850 CRLF.IF.LISTING
3860 JSR CHECK.IF.LISTING
3870 CRLF.WITH.PAGING
3880 JSR CRLF
3890 INC LINE.COUNT
3900 LDA PAGE.LENGTH
3910 BEQ .1 ...NOT TITLING
3920 CMP LINE.COUNT
3930 BCC CRLF.CAUSED.FORM.FEED ...END OF PAGE
3940 .1 RTS
3950 *--------------------------------
3960 * PROCESS LABEL DEFINITION
3970 *--------------------------------
3980 LABL JSR PACK PACK AND CHECK SYMBOL
3990 BCC ERR.BS BAD SYMBOL
4000 JSR STSRCH SEE IF DEFINED
4010 BCC ERR.DD YES, DOUBLE DEFINITION
4020 JMP STADD ADD TO SYMBOL TABLE
4030 *--------------------------------
4040 ERR.DD LDY PASS ERROR IN PASS 1
4050 BEQ ERR.DBLDF OK IN PASS 2
4060 LDY #6 SET FLAG FOR TESTING FWD REFS
4070 >SYM LDA,STPNTR
4080 ORA #$40
4090 >SYM STA,STPNTR
4100 LDY WBUF LOOK AT COLUMN 1
4110 CPY #': IF PRIVATE LABEL...
4120 BEQ .2 ...THEN DON'T UPDATE C.M.LABEL
4130 LDA STPNTR SAVE POINTER TO THIS MAJOR LABEL
4140 STA CURRENT.MAJOR.LABEL
4150 LDA STPNTR+1
4160 STA CURRENT.MAJOR.LABEL+1
4170 .2 RTS
4180 ERR.DBLDF
4190 LDY #QER4 DOUBLE DEFN
4200 .HS 2C SKIP 2 BYTES
4210 ERR.BS LDY #QER7 BAD SYMBOL
4220 JMP SOFT.ERROR
4230 *--------------------------------
4240 * Search Compressed Opcode Table
4250 * If carry clear, (Y,A) = address of table
4260 * If carry set, continue searching same table
4270 *
4280 * Return with carry set if found, else carry clear.
4290 * (OPTBL.PNTR),Y points at 16-bit value
4300 * of entry which matched.
4310 *--------------------------------
4320 SEARCH.COMPRESSED.TABLE
4330 BCS .6 ...Continue searching same table
4340 STA OPTBL.PNTR
4350 STY OPTBL.PNTR+1
4360 *---Try matching 2nd letter------
4370 LDY #0
4380 .1 LDA (OPTBL.PNTR),Y Possible match
4390 ORA #$40 Make it ASCII
4400 CMP SEARCH.KEY+1 same as 2nd letter?
4410 BEQ .6 ...yes, matched.
4420 BNE .3 ...no
4430 *---Scan to next 8-bit entry-----
4440 .2 INY
4450 INY
4460 .3 INY
4470 LDA (OPTBL.PNTR),Y
4480 BMI .2 ...another 24-bit entry
4490 ASL check if beyond our sub-group
4500 BPL .1 ...no, valid 2nd letter option
4510 .4 CLC ...no match in table, carry clear
4520 RTS
4530 *---Try matching 3rd letter------
4540 .5 INY
4550 .6 INY
4560 LDA (OPTBL.PNTR),Y
4570 BPL .4 ...no more options, not in table
4580 INY point at data
4590 EOR #$C0 make like ASCII
4600 CMP SEARCH.KEY+2 compare to 3rd letter
4610 BNE .5 ...did not match, try another
4620 RTS ...found it, return carry set
4630 *--------------------------------
4640 .PG