1
0
mirror of https://github.com/agn453/RSTS-E.git synced 2026-01-11 23:22:42 +00:00

Include microcomputer cross-assemblers

This commit is contained in:
Tony Nicholson 2021-11-12 11:44:23 +11:00
parent a143648efd
commit 634765cfb3
18 changed files with 3087 additions and 0 deletions

4
.gitattributes vendored
View File

@ -8,10 +8,14 @@ README.md text eol=crlf
*.pat text eof=crlf linguist-language=DIGITAL Command Language
*.txt text eof=crlf
*.tsk binary
*.TSK binary
*.jpeg binary
*.txt text eof=crlf
*.mac text eol=crlf linguist-language=Assembly
*.com text eol=crlf
*.COM text eol=crlf
*.HLP text eol=crlf
*.B2S text eol=crlf linguist-language=BASIC
*.obj binary
*.zip binary
*.pdf binary

View File

@ -251,6 +251,45 @@ also has information about Forth's handling of program SCREENs and
files.
## Microcomputer cross-assemblers etc.
In the
[micros](https://github.com/agn453/RSTS-E/blob/master/micros)
subdirectory, I've added a few of the microcomputer cross-assemblers
that I developed whilst an undergraduate. These were originally
written in BASIC-PLUS - and the source files have been converted
to a format now acceptable to both BASIC-PLUS and the PDP-11
BASIC-PLUS-2 V2.7-00 compiler. (The original source files used
continuation lines of a <LF> <CR> <NUL>, with <CR> <LF> at the
end of each statement).
Cross-assemblers for
* National Semiconductor SC/MP
[SCMPCA.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/SCMPCA.B2S)
* Intel 8080/8085 with some Zilog Z80 op-codes (using Intel/TDL-style
mnemonics)
[X80.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/X80.B2S)
* MOS Technology 6502
[X65.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/X65.B2S)
A dis-assembler for
* National Semiconductor SC/MP
[DISASM.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/DISASM.B2S)
and,
* A program to convert hexadecimal output from the cross-assembler
to an Intel HEX format absolute loader format file
[INTEL.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/INTEL.B2S)
There are DCL command files to compile them, and I've included a binary
task-image for each.
## Background
I've been a User/Systems Programmer/System Manager/Computer Networking

13
micros/DISASB.COM Normal file
View File

@ -0,0 +1,13 @@
$! Command file to build DISASM.B2S (with Basic-Plus-2)
$!
$ set noOn
$ run $bp2ic2
SCALE 0
OLD DISASM.B2S
COMPILE DISASM/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN
BUILD DISASM
SCRATCH
EXIT
$ tkb @DISASM
$ del disasm.odl, disasm.obj, disasm.cmd
$ exit

248
micros/DISASM.B2S Normal file
View File

@ -0,0 +1,248 @@
1010 REM &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
REM !! !! &
REM !! SC/MP DIS ASSEMBLER !! &
REM !! !!
1020 REM !! A.G. NICHOLSON, NEWCASTLE UNI. !! &
REM !! !! &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
1030 REM ! LAST EDITED 13-MAY-77 ! &
1040 DIM O$(46%), O%(46%), X(3%), L(100%), C$(32%)
1050 ! INITIALISE
1060 D%,F%,N0%,T%=0% &
\ P%=1%
1070 L(0%)=-1%
1080 U$=" #### \ \ \\ \\ \ \ \ \ \ \ "
1090 H$="0123456789ABCDEF" &
\ READ X(I%) FOR I%=0% TO 3%
1100 DATA 1,16,256,4096
1110 READ O$(I%), O%(I%) FOR I%=1% TO 46%
1120 ! MEMORY REFERENCE INSTRUCTIONS 1-8
1130 DATA LD,192,ST,200,AND,208,OR,216,XOR,224,DAD,232,ADD,240,CAD,248
1140 ! TRANSFER INSTRUCTIONS 9-12
1150 DATA JMP,144,JP,148,JZ,152,JNZ,156
1160 ! MEMORY INCREMENT, DECREMENT INSTRUCTIONS 13-14
1170 DATA ILD,168,DLD,184
1180 ! IMMEDIATE INSTRUCTIONS 15-21
1190 DATA LDI,196,ANI,212,ORI,220,XRI,228,DAI,236,ADI,244,CAI,252
1200 ! DELAY INSTRUCTION 22
1210 DATA DLY,143
1220 ! POINTER MOVE INSTRUCTIONS 23-25
1230 DATA XPAL,48,XPAH,52,XPPC,60
1240 ! EXTENSION REGISTER INSTRUCTIONS 26-33
1250 DATA LDE,64,XAE,1,ANE,80,ORE,88,XRE,96,DAE,104,ADE,112,CAE,120
1260 ! SERIAL I/O, SHIFT & ROTATE INSTRUCTIONS 34-38
1270 DATA SIO,25,SR,28,SRL,29,RR,30,RRL,31
1280 ! MISCELLANEOUS INSTRUCTIONS 39-46
1290 DATA HALT,0,CCL,2,SCL,3,IEN,5,DINT,4,CSA,6,CAS,7,NOP,8
1300 MAT READ C$
1310 ! ASCII CHARACTERS 0 TO 32
1320 DATA NUL,SOH,STX,EXT,EOT,ENQ,ACK,BEL,BS,HT,LF,VT,FF,CR,SO,SI
1330 DATA DEL,DC1,DC2,DC3,DC4,NAK,SYN,ETB,CAN,EM,SUB,ESC,FS,GS,RS,US
1340 OPEN "KB:" AS FILE 1%
1350 Z%=1% ! OUTPUT CHANNEL NUMBER
1360 PRINT #1% &
\ PRINT #1%,"SC/MP DIS-ASSEMBLER" &
\ PRINT #1%
1370 PRINT #1%,"#"; &
\ INPUT LINE #1%,F$ &
\ F$=CVT$$(F$,4%)
1380 I%=INSTR(1%,F$,"<") OR INSTR(1%,F$,"=")
1390 IF I% THEN X$=LEFT(F$,I%-1%) &
\ OPEN X$ FOR OUTPUT AS FILE 3% &
\ PRINT #1%," OUTPUT TO ";X$ &
\ Z%=3% &
\ F$=RIGHT(F$,I%+1%) &
\ PRINT #1%
1400 OPEN F$ FOR INPUT AS FILE 2% &
\ PRINT #1%
1410 PRINT #1%," STARTING ADDRESS (HEX) ?"; &
\ INPUT #1%,A$ &
\ N1=FND(A$) &
\ PRINT #1%
1420 ! PASS 1
1430 PRINT #1%," PASS 1"
1440 GOSUB 2240%
1450 ! GET SINGLE BYTE PORTIONS AND DECODE
1460 FOR J%=2% TO L% STEP 2%
1470 B$=MID(L$,J%-1%,2%) &
\ GOTO 1530% IF D% &
\ GOTO 1630% IF B$="XX"
1480 B%=FND(B$) &
\ N0%=N0%+1%
1490 GOTO 1610% IF B%<128%
1500 ! TWO BYTE INSTRUCTIONS
1510 IF J%=L% THEN D%=-1% &
\ GOTO 1610%
1520 J%=J%+2% &
\ B$=MID(L$,J%-1%,2%)
1530 IF B$="XX" THEN PRINT #1%, &
"MISSING ARGUMENT AT LINE ";FNH$(N1+N0%);" (HEX)" &
\ GOTO 1630%
1540 D%=0% ! RESET CONTINUATION BYTE
1550 N0%=N0%+1%
1560 ! TEST FOR A TRANSFER INSTRUCTION
1570 IF B%<144% OR B%>159% THEN B%=FND(B$) &
\ GOTO 1610%
1580 B%=FND(B$)
1590 ! ENTER LINE NUMBER REFERENCED IN TABLE T()
1600 B%=B%-256% IF B%>127% &
\ GOTO 1610% IF L(I%)=N1+N0%+B%+1% FOR I%=0% TO T% &
\ T%=T%+1% &
\ L(T%)=N1+N0%+B%+1%
1610 NEXT J% ! PROCESS NEXT CHARACTER
1620 GOTO 1440%
1630 ! END PASS 1
1640 CLOSE 2%
1650 D%,F%=0%
1660 ! PASS 2
1670 OPEN F$ FOR INPUT AS FILE 2% &
\ PRINT #1%," PASS 2" &
\ PRINT #1%
1680 PRINT #Z%," ADDR B1 B2 LABEL OPCODE ARGUMENT "; &
"[DECIMAL] <ASCII>" &
\ PRINT #Z%
1690 PRINT #Z%
1700 P%=2% &
\ N0%=0%
1710 GOSUB 2240%
1720 FOR J%=2% TO L% STEP 2%
1730 B$=MID(L$,J%-1%,2%) &
\ GOTO 1950% IF D% &
\ B1$=B$ &
\ GOTO 2210% IF B$="XX"
1740 B%=FND(B$) &
\ N0%=N0%+1%
1750 S$,O$,A$=""
1760 ! CHECK TO SEE WHETHER STATEMENT IS LABELED
1770 S$="L"+CVT$$(NUM$(I%),2%)+":" IF L(I%)=N1+N0% FOR I%=0% TO T%
1780 O%=B% &
\ GOTO 2060% IF B%<128%
1790 ! TWO BYTE INSTRUCTIONS
1800 N1%=2% ! NUMBER OF BYTES
1810 ! POINTER REFERENCE CHECK FOR TRANSFER, MEMORY INC/DEC
1820 FOR I%=1% TO 3% &
\ FOR K%=9% TO 14%
1830 IF O%(K%)+I%=O% THEN A$=A$+"("+CVT$$(NUM$(I%),2%)+")" &
\ O%=O%-I% &
\ GOTO 1910%
1840 NEXT K% &
\ NEXT I%
1850 ! AUTO INDEX AND POINTER CHECK FOR MEMORY REFERENCE
1860 FOR K%=1% TO 8% &
\ FOR I%=1% TO 3%
1870 IF O%(K%)+4%+I%=O% THEN A$="@("+CVT$$(NUM$(I%),2%)+")" &
\ O%=O%-4%-I% &
\ GOTO 1910%
1880 IF O%(K%)+I%=O% THEN A$="("+CVT$$(NUM$(I%),2%)+")" &
\ O%=O%-I% &
\ GOTO 1910%
1890 NEXT I% &
\ NEXT K%
1900 ! FIND OPCODE FOR DOUBLE BYTE INSTRUCTION
1910 O$=O$(I%) IF O%(I%)=O% FOR I%=1% TO 22%
1920 ! GET SECOND BYTE
1930 IF J%=L% THEN D%=-1% &
\ GOTO 2180% ! SECOND BYTE ON NEXT PHYSICAL LINE IN FILE F$
1940 J%=J%+2% &
\ B$=MID(L$,J%-1%,2%)
1950 GOTO 2210% IF B$="XX"
1960 D%=0%
1970 B2$=B$
1980 N0%=N0%+1%
1990 ! CHECK FOR TRANSFER INSTRUCTION
2000 GOTO 2030% IF B%<144% OR B%>159%
2010 ! ADD LABEL REFERENCED TO ARGUMENT
2020 B%=FND(B$) &
\ B%=B%-256% IF B%>127% &
\ A$=A$+"L"+CVT$$(NUM$(I%),2%) IF L(I%)=N1+N0%+B%+1% FOR I%=0% TO T% &
\ GOTO 2050%
2030 A$=A$+"X'"+B2$
2040 ! OUTPUT TO CHANNEL 1
2050 GOSUB 2300% &
\ GOTO 2180%
2060 ! SINGLE BYTE INSTRUCTIONS
2070 N1%=1% ! NUMBER OF BYTES
2080 ! CHECK POINTER MOVE
2090 FOR K%=23% TO 25% &
\ FOR I%=0% TO 3%
2100 IF O%(K%)+I%=O% THEN A$=CVT$$(NUM$(I%),2%) &
\ O%=O%-I% &
\ GOTO 2130%
2110 NEXT I% &
\ NEXT K%
2120 ! SET OPCODE FOR SINGLE BYTE INSTRUCTION
2130 O$=O$(I%) IF O%(I%)=O% FOR I%=23% TO 46%
2140 IF O$="" THEN O$=".BYTE" \ A$="X'"+B1$
2150 B2$=""
2160 ! OUTPUT TO CHANNEL 1
2170 GOSUB 2300%
2180 NEXT J%
2190 ! GET NEXT LINE FROM FILE F$
2200 GOTO 1710%
2210 ! EXIT
2220 CLOSE 2% &
\ PRINT #Z% FOR I%=1% TO 3% &
\ CLOSE 1%,3%
2230 GOTO 32767%
2240 ! SUBROUTINE TO GET A LINE FROM FILE F$
2250 INPUT LINE #2%,L$ &
\ L$=CVT$$(L$,6%) &
\ L%=LEN(L$) &
\ GOTO 2250% IF L%=0%
2260 ! F% IS THE NUMBER OF THE LINE READ FROM FILE F$
2270 F%=F%+1%
2280 IF (L%/2%)*2%<>L% THEN PRINT #1%, &
"INCOMPLETE BYTE READ FROM ";F$;", LINE";F% &
\ L$=L$+" "
2290 RETURN
2300 ! OUTPUT ROUTINE TO CHANNEL Z%
2310 PRINT #Z% USING U$,N0%-N1%,FNH$(N1+N0%-N1%),B1$,B2$,S$,O$,A$;
2320 ! LINE NUMBER, ADDR B1 B2 LABEL: OPCODE ARGUMENT
2330 IF B2$="" THEN B$=B1$ ELSE B$=B2$ &
\ B%=FND(B$)
2340 IF B%<32% THEN C$=C$(B%+1%) ELSE IF B%<96% THEN C$=CHR$(B%)
2350 B%=B%-256% IF B%>127%
2360 PRINT #Z% USING "[ #### ]",B%;
2370 IF C$<>"" THEN PRINT #Z% USING " < \ \ >",C$ ELSE PRINT #Z%
2380 C$=""
2390 RETURN
2400 DEF* FNH$(X) ! HEXADECIMAL CONVERSION
2410 X0=X &
\ X0=X0+65536 IF X0<0% &
\ X0=INT(X0+0.1) &
\ GOTO 2440% IF X0>65536 &
\ X$=""
2420 FOR X%=3% TO 1% STEP -1% &
\ X1=X(X%) &
\ X2=INT(X0/X1) &
\ X0=X0-X1*X2 &
\ X2=X2+1% &
\ X$=X$+MID(H$,X2,1%)
2430 NEXT X% &
\ FNH$=X$+MID(H$,X0+1%,1%) &
\ GOTO 2450%
2440 PRINT #1%,"OVERFLOW IN HEX CONVERSION" &
\ E%=E%+1% &
\ FNH$=" "
2450 FNEND
2460 DEF* FND(X$) ! HEX TO DECIMAL CONVERSION
2470 X=LEN(X$) &
\ X0=0% &
\ GOTO 2500% IF X>4%
2480 FOR X%=0% TO X-1% &
\ X1$=MID(X$,X-X%,1%) &
\ GOTO 2490% IF X1$=MID(H$,X1,1%) FOR X1=1% TO 16% &
\ PRINT #1%,"ILLEGAL CHARACTER IN HEX NUMBER :";X$ &
\ GOTO 2510%
2490 X0=X0+(X1-1%)*X(X%) &
\ NEXT X% &
\ FND=X0 &
\ GOTO 2520%
2500 PRINT #1%,"OVERFLOW IN DECIMAL CONVERSION :"
2510 E%=E%+1% &
\ FND=0%
2520 FNEND
32767 END

BIN
micros/DISASM.TSK Normal file

Binary file not shown.

53
micros/INTEL.B2S Normal file
View File

@ -0,0 +1,53 @@
10 ON ERROR GOTO 220
15 PRINT "Hex dump to INTEL absolute load format"
16 PRINT
20 PRINT "Filename ";
30 INPUT LINE F$
40 OPEN F$ FOR INPUT AS FILE 1%
50 PRINT "Output to ";
60 INPUT LINE O$
70 OPEN O$ FOR OUTPUT AS FILE 2%
80 INPUT "Start address (hex) ";S$
90 WHILE -1%
100 INPUT #1%,L$
111 N$=RIGHT(FNH$(LEN(L$)/2%),3%)
112 N%=FND%(N$)
113 C%=N%+FND%(LEFT(S$,2%))+FND%(RIGHT(S$,3%))
120 PRINT #2%,":"+N$+S$+"00";
150 FOR I%=1% TO 31% STEP 2%
151 D$=MID(L$,I%,2%)
152 D%=FND%(D$)
153 C%=C%+D%
160 PRINT #2%,D$;
170 NEXT I%
180 PRINT #2%,RIGHT(FNH$(-C%),3%)
200 S$=FNH$(FND%(S$)+16%)
210 NEXT
220 PRINT #2%
230 CLOSE 1%,2%
240 PRINT
250 PRINT "Done"
260 GOTO 32767
1000 DEF* FND%(X$)
1010 X0%=0%
1020 FOR X1%=1% TO LEN(X$)
1030 X2%=ASCII(MID(X$,X1%,1%))
1040 IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN &
PRINT "Illegal hex character in "+X$ \ STOP
1050 X2%=X2%-48%
1060 X2%=X2%-7% IF X2%>9%
1070 X0%=X2%+X0%*16%
1080 NEXT X1%
1090 FND%=X0%
1100 FNEND
2000 DEF* FNH$(X%)
2010 X$=""
2020 FOR X1%=0% TO 3%
2030 X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%)
2040 X0%=X0%+16% IF X0%<0%
2050 X$=CHR$(48%+X0%)+X$ IF X0%<10%
2060 X$=CHR$(55%+X0%)+X$ IF X0%>9%
2070 NEXT X1%
2080 FNH$=X$
2090 FNEND
32767 END

BIN
micros/INTEL.TSK Normal file

Binary file not shown.

13
micros/INTELB.COM Normal file
View File

@ -0,0 +1,13 @@
$! Command file to build INTEL.B2S (with Basic-Plus-2)
$!
$ set noOn
$ run $bp2ic2
SCALE 0
OLD INTEL.B2S
COMPILE INTEL/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN
BUILD INTEL
SCRATCH
EXIT
$ tkb @INTEL
$ del intel.odl, intel.obj, intel.cmd
$ exit

13
micros/SCMBLD.COM Normal file
View File

@ -0,0 +1,13 @@
$! Command file to build SCMPCA.B2S (with Basic-Plus-2)
$!
$ set noOn
$ run $bp2ic2
SCALE 0
OLD SCMPCA.B2S
COMPILE SCMPCA/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN
BUILD SCMPCA
SCRATCH
EXIT
$ tkb @SCMPCA
$ del scmpca.odl, scmpca.obj, scmpca.cmd
$ exit

549
micros/SCMPCA.B2S Normal file
View File

@ -0,0 +1,549 @@
1010 REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
REM !! !! &
REM !! SC/MP CROSS ASSEMBLER !! &
REM !! !!
1020 REM !! A.G. NICHOLSON, NEWCASTLE UNI. !! &
REM !! !! &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1021 REM &
REM ! Last edited: 30-Jan-79 &
1025 C9%=0%
1030 DIM O$(51), O%(51), T$(255), T%(255), D%(3)
1040 ! -- Set up error trap routine --
1050 ON ERROR GOTO 31020 &
\ X$=SYS(CHR$(6%)+CHR$(-7%))
1060 ! -- Initialise --
1070 N%=51% &
\ T%(0%)=255% &
\ T0%=TIME(1%) &
\ F1$="KB:" &
\ READ O$(I%), O%(I%) FOR I%=0% TO N%
1080 ! -- Print header --
1090 OPEN F1$ AS FILE 1% &
\ GOTO 1130 IF C9% &
\ PRINT #1%,"SC/MP Cross assembler" &
\ PRINT #1%,"#";
1100 ! -- Get listing, source filenames --
1110 INPUT LINE #1%, F2$ &
\ F2$=CVT$$(F2$,-1%)
1120 ! -- Check for errors only switch --
1130 F0%=-1% &
\ L%=INSTR(1%,F2$,"/E") &
\ IF L% THEN F2$=LEFT(F2$,L%-1%)+RIGHT(F2$,L%+2%) &
\ F0%=0%
1140 ! -- Check for object module output switch --
1150 F4%=0% &
\ L%=INSTR(1%,F2$,"/O") &
\ IF L% THEN F2$=LEFT(F2$,L%-1%)+RIGHT(F2$,L%+2%) &
\ F4%=-1%
1160 ! -- Check for listing file and add default extensions --
1170 F5%=INSTR(1%,F2$,"=") &
\ IF F5% THEN F1$=LEFT(F2$,F5%-1%) &
\ F1$=F1$+".LST" UNLESS INSTR(1%,F1$,".") &
\ F2$=RIGHT(F2$,F5%+1%)
1180 F2$=F2$+".SRC" UNLESS INSTR(1%,F2$,".")
1190 PRINT #1%,"Listing sent to ";F1$ IF F5%
1200 IF F4% THEN F4$=LEFT(F2$,INSTR(1%,F2$,"."))+"BIN" &
\ PRINT #1%,"Object module to ";F4$
1210 ! -- Get a unique workfile name --
1220 W$="SCMP"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+CHR$(9%)))/2%),3%,2%)+".TMP"
1230 ! -- Commence assembly --
1240 GOSUB 1310 &
\ GOSUB 1860 &
\ X%=1% &
\ GOSUB 2460
1250 ! -- Print symbol table --
1260 GOSUB 2480 IF T% AND F0% &
\ PRINT #1%
1270 ! -- Finish up and exit --
1280 CLOSE 1 &
\ IF F5% THEN X%=0% &
\ GOSUB 2460
1290 PRINT "Runtime was";(TIME(1%)-T0%)/10;"sec" &
\ GOTO 32767
1300 ! -- Pass 1 Driver routine --
1310 E%,T%,N0%,N1%,F1%,O%=0% \ P0%=1% &
\ OPEN F2$ FOR INPUT AS FILE 2% &
\ PRINT #1% &
\ OPEN W$ FOR OUTPUT AS FILE 3% &
\ PRINT #1%,"Pass 1"
1320 FOR L%=1% STEP 1% UNTIL O%=N% &
\ INPUT LINE #2%, L$ &
\ L$=CVT$$(L$,165%) &
\ L1%=LEN(L$)
1330 IF L1%=0% THEN O%=0% &
\ GOTO 1450
1340 ! -- Scan source line --
1350 GOSUB 1470 &
\ GOSUB 1520
1360 ! -- Comment line ? --
1370 IF D3%=1% THEN O%=0% &
\ GOTO 1450
1380 ! -- Get argument field --
1390 IF D3% THEN A$=CVT$$(MID(L$,D2%+1%,D3%-D2%-1%),136%) &
ELSE A$=CVT$$(RIGHT(L$,D2%+1%),8%)
1400 ! -- Label ? --
1410 IF D1% THEN S$=CVT$$(LEFT(L$,D1%-1%),128%) &
\ S1%=N1% &
\ GOSUB 1600
1420 ! -- Assignment ? --
1430 IF D4% THEN GOSUB 1650 &
ELSE GOSUB 1690
1440 ! -- Write to workfile --
1450 GOSUB 1710 &
\ NEXT L% &
\ CLOSE 2,3 &
\ RETURN
1460 ! -- Scan for strings in L$, D%() is the delimiter table --
1470 D%=-1% &
\ S2%=0%
1480 S1%=INSTR(S2%+1%,L$,"'") &
\ RETURN UNLESS S1% &
\ IF MID(L$,S1%-1%,1%)="X" THEN S2%=S1% &
\ GOTO 1480
1490 S2%=INSTR(S1%+1%,L$,"'") &
\ IF S2% THEN D%=D%+1% &
\ IF D%<4% THEN D%(D%)=SWAP%(S1% AND 255%) OR (S2% AND 255%) &
\ GOTO 1480
1500 RETURN
1510 &
! -- Search for token delimiters -- &
! D1% Label &
! D2% Opcode &
! D3% Comment &
! D4% Assignment
1520 D1%=INSTR(1%,L$,":") &
\ D1%=0% IF FNS%(D1%) &
\ D3%=0%
1530 D3%=INSTR(D3%+1%,L$,";") &
\ GOTO 1530 IF FNS%(D3%) &
\ D1%=0% IF (D1%>D3% AND D3%<>0%) &
\ D2%=D1%
1540 D2%=D2%+1% &
\ IF D2%>=L1% THEN 1560 &
ELSE X%=ASCII(RIGHT(L$,D2%)) &
\ IF X%=9% OR X%=32% THEN 1540
1550 D2%=D2%+1% &
\ IF D2%<L1% THEN X%=ASCII(RIGHT(L$,D2%)) &
\ IF X%<>9% AND X%<>32% THEN 1550 &
ELSE D2%=D2%-1%
1560 D4%=INSTR(1%,L$,"=") &
\ D4%=0% IF FNS%(D4%) OR (D4%>D3% AND D3%<>0%) &
\ D2%=D4% IF D4%
1570 D2%=D3%-1% IF (D2%>=D3% AND D3%<>0%) &
\ RETURN
1590 &
! Enter symbol S$ and its value S1% into T$() and T%() &
1600 X%=ASCII(S$) &
\ IF X%<65% OR X%>90% OR LEN(S$)>6% THEN &
X%=FNE%("Inv sym "+S$) &
\ RETURN
1610 FOR I%=1% TO T% &
\ IF S$=T$(I%) THEN S1%=FNE%("Redef sym "+S$) &
\ RETURN
1620 NEXT I% &
\ IF T%=T%(0%) THEN PRINT #1%,"Sym ovf" &
\ RETURN
1630 T%=T%+1% &
\ T$(T%)=S$ &
\ T%(T%)=S1% &
\ RETURN
1640 ! -- Enter assignment --
1650 S$=CVT$$(MID(L$,D1%+1%,D4%-D1%-1%),136%) &
\ S1%=FNA%(A$)
1660 IF S$="." THEN N1%=S1% &
ELSE IF S$<>"" THEN GOSUB 1600 &
ELSE S1%=FNE%("Missing symbol")
1670 O%=0% &
\ RETURN
1680 ! -- Get opcode subscript --
1690 X1$=CVT$$(MID(L$,D1%+1%,D2%-D1%),8%) &
\ RETURN IF X1$=O$(O%) FOR O%=0% TO N% &
\ O%=FNE%("Inv opc "+X1$) &
\ RETURN
1700 ! -- Get byte count and output to workfile --
1710 IF O%>46% THEN GOSUB 1770 &
ELSE IF O%>22% THEN N2%=1% &
ELSE IF O%>0% THEN N2%=2% &
ELSE N2%=0%
1720 PRINT #3%,N1%;",";N2%;",";O%;",";F1% &
\ PRINT #3%,A$ &
\ N0%=N0%+N2% &
\ N1%=N1%+N2% &
\ F1%=0% &
\ RETURN
1760 ! -- Get byte count for pseudo-op --
1770 ON O%-46% GOTO 1790, 1790, 1810, 1840, 1840
1780 ! -- .BYTE, .DBYTE --
1790 S1%=0% \ S2%=-1% &
\ FOR N2%=0% WHILE S2% &
\ S1%, S2%=INSTR(S1%+1%,A$,",") &
\ NEXT N2% &
\ N2%=N2%*2% IF O%=48% &
\ RETURN
1800 ! -- .ASCII --
1810 S1%=INSTR(2%,A$,LEFT(A$,1%)) &
\ IF S1% THEN N2%=S1%-2% &
\ RETURN
1820 O%=FNE%("Missing delim") &
\ RETURN
1830 ! -- .LIST, END --
1840 N2%=0% &
\ RETURN
1850 ! -- Pass 2 Driver routine --
1860 L%,C%,F2%=0% &
\ P0%=2% &
\ F3%=-1% &
\ PRINT #1%,"Pass 2" &
\ CLOSE 1 &
\ OPEN F1$ FOR OUTPUT AS FILE 1% &
\ OPEN F2$ FOR INPUT AS FILE 2% &
\ OPEN W$ FOR INPUT AS FILE 3%
1870 ! -- If object out then output leader and <stx> and byte count --
1880 IF F4% THEN OPEN F4$ FOR OUTPUT AS FILE 4% &
\ GOSUB 2350 &
\ B%=2% &
\ GOSUB 2440 &
\ B%=SWAP%(N0%) AND 255% &
\ GOSUB 2440 &
\ B%=N0% AND 255% &
\ GOSUB 2440
1890 IF F0% THEN PRINT #1% &
\ PRINT #1%," Line Addr B1 B2" &
\ PRINT #1%
1900 INPUT #3%,N1%,N2%,O%,F1% &
\ INPUT LINE #3%, A$ &
\ A$=CVT$$(A$,4%) &
\ INPUT LINE #2%, L$ &
\ L$=CVT$$(L$,4%) &
\ L%=L%+1%
1910 ! -- Form object code and output to listing file --
1920 IF O%=N% THEN GOSUB 1980 &
\ RETURN
1930 IF O%=0% THEN GOSUB 2370 &
\ GOTO 1900
1940 O1$=FNH$(N1%,0%) &
\ V%=O%(O%)
1950 IF O%>46% THEN GOSUB 2140 &
ELSE IF O%>25% THEN GOSUB 2120 &
ELSE IF O%>22% THEN GOSUB 2100 &
ELSE IF O%>14% THEN GOSUB 2080 &
ELSE IF O%>8% THEN GOSUB 2030 &
ELSE GOSUB 2010
1960 GOTO 1900
1970 ! -- End of assembly, tidy up --
1980 GOSUB 2370 &
\ IF F4% THEN B%=2% &
\ GOSUB 2440 &
\ B%=C% AND 255% &
\ GOSUB 2440 &
\ GOSUB 2350
1990 CLOSE 2,3,4 &
\ KILL W$ &
\ RETURN
2000 ! -- Memory reference --
2010 S1%=INSTR(1%,A$,"@") &
\ IF S1% THEN V%=V%+4% &
\ A$=LEFT(A$,S1%-1%)+RIGHT(A$,S1%+1%)
2020 ! -- Memory reference, inc, dec and transfer --
2030 GOSUB 2290 &
\ V%=V%+P% &
\ GOSUB 2250
2040 V%=FNA%(A$) &
\ IF P%=0% THEN V%=V%-N1%-1% &
\ IF O%>8% AND O%<13% THEN V%=V%-1%
2041 ! Quirk for wrap around within 4K page - fixed 09-Oct-2018
2042 IF V%>(4096%-127%) THEN V%=V%-4096%
2050 IF V%<-128% OR V%>127% THEN V%=FNE%("Inv disp ="+NUM$(V%))
2060 GOSUB 2270 &
\ GOSUB 2370 &
\ RETURN
2070 ! -- Immediate and Delay --
2080 GOSUB 2250 &
\ V%=FNA%(A$) &
\ GOSUB 2270 &
\ GOSUB 2370 &
\ RETURN
2090 ! -- Pointer exchange --
2100 GOSUB 2290 &
\ P%=FNA%(A$) UNLESS P% &
\ V%=V%+P%
2110 ! -- Single byte --
2120 GOSUB 2250 &
\ GOSUB 2370 &
\ RETURN
2130 ! -- Pseudo-ops. --
2140 ON O%-46% GOTO 2160, 2160, 2210, 2230
2150 ! -- .BYTE, .DBYTE --
2160 A$=A$+"," &
\ FOR I%=1% TO N2% STEP O%-46% &
\ O1$=FNH$(N1%+I%-1%,0%) &
\ S1%=INSTR(1%,A$,",")
2170 S2%=FNA%(LEFT(A$,S1%-1%)) &
\ IF O%=48% THEN V%=SWAP%(S2%) &
\ GOSUB 2250 &
\ V%=S2% &
\ GOSUB 2270
2180 IF O%=47% THEN V%=S2% &
\ GOSUB 2250
2190 GOSUB 2370 &
\ A$=RIGHT(A$,S1%+1%) &
\ NEXT I% &
\ RETURN
2200 ! -- .ASCII --
2210 A$=MID(A$,2%,N2%) &
\ FOR I%=1% TO N2% &
\ O1$=FNH$(N1%+I%-1%,0%) &
\ V%=ASCII(RIGHT(A$,I%)) &
\ GOSUB 2250 &
\ GOSUB 2370 &
\ NEXT I% &
\ RETURN
2220 ! -- .LIST --
2230 F3%=FNA%(A$) &
\ RETURN
2240 ! -- Form B1 and update checksum --
2250 O2$=FNH$(V%,3%) &
\ B%=V% AND 255% &
\ GOSUB 2440 IF F4% &
\ C%=C%+B% &
\ RETURN
2260 ! -- Form B2 and update checksum --
2270 O3$=FNH$(V%,3%) &
\ B%=V% AND 255% &
\ GOSUB 2440 IF F4% &
\ C%=C%+B% &
\ RETURN
2280 ! -- Extract pointer from argument --
2290 P%, S1%=0%
2300 S1%=INSTR(S1%+1%,A$,"(") &
\ RETURN UNLESS S1% &
\ X$=LEFT(A$,S1%-1%) &
\ GOTO 2300 IF X$="H" OR X$="L"
2310 S2%=INSTR(S1%+1%,A$,")") &
\ P%=FNA%(MID(A$,S1%+1%,S2%-S1%-1%)) &
\ A$=LEFT(A$,S1%-1%)+RIGHT(A$,S2%+1%)
2320 IF P%<0% OR P%>3% THEN P%=FNE%("Inv ptr ="+NUM$(P%))
2330 RETURN
2340 ! -- Output a leader to object file --
2350 PRINT #4%,STRING$(80%,0%); &
\ RETURN
2360 ! -- Output assembled code to listing file --
2370 GOTO 2420 UNLESS F0% OR F1%
2380 IF F1% THEN PRINT #1%,"?"; ELSE PRINT #1%," ";
2390 IF F2%<L% THEN PRINT #1% USING "#### ",L%; ELSE PRINT #1%," ";
2400 PRINT #1% USING"\ \ \\ \\",O1$,O2$,O3$; &
\ IF F3% AND L$<>"" THEN PRINT #1%,CHR$(9%);L$ &
ELSE PRINT #1%
2410 ! -- Set a flag, clear output strings --
2420 F2%=L% &
\ O1$,O2$,O3$,L$="" &
\ RETURN
2430 ! -- Output binary byte to object file --
2440 PRINT #4%,CHR$(B%); &
\ RETURN
2450 ! -- Print error count, checksum --
2460 PRINT #X% &
\ PRINT #X%,"Errors detected";E% &
\ PRINT #X%,"Source checksum ";FNH$(C%,0%) &
\ PRINT #X%,"Total bytes ";N0% &
\ PRINT #X% &
\ RETURN
2470 ! -- Print sorted symbol table --
2480 PRINT #1%," Symbol Table" &
\ PRINT #1%
2490 ! -- Bubble sort symbol table --
2500 S2%=-1% &
\ FOR S1%=T%-1% STEP -1% WHILE S2% &
\ S2%=0% &
\ FOR I%=1% TO S1%
2510 IF T$(I%+1%)<T$(I%) THEN S$=T$(I%) &
\ X%=T%(I%) &
\ T$(I%)=T$(I%+1%) &
\ T%(I%)=T%(I%+1%) &
\ T$(I%+1%)=S$ &
\ T%(I%+1%)=X% &
\ S2%=S2%+1%
2520 NEXT I% &
\ NEXT S1%
2530 ! -- Output to listing file --
2540 FOR I%=1% TO T% &
\ PRINT #1% USING " \ \ \ \ ",T$(I%),FNH$(T%(I%),0%); &
\ PRINT #1% IF CCPOS(1%)>63% &
\ NEXT I%
2550 PRINT #1% IF CCPOS(1%) &
\ RETURN
2560 &
! -- Check position of char X% in L$ using -- &
! -- tables D%(). FNS%=-1% means in string --
2570 DEF* FNS%(X%)
2580 GOTO 2600 IF D%=-1% OR X%=0% &
\ FOR X0%=0% TO D% &
\ GOTO 2600 IF X%<(SWAP%(D%(X0%)) AND 255%) &
\ IF X%<(D%(X0%) AND 255%) THEN FNS%=-1% &
\ GOTO 2610
2590 NEXT X0%
2600 FNS%=0%
2610 FNEND
2620 ! -- Evaluate the argument expression --
2630 DEF* FNA%(X$)
2640 ! -- Main driver routine --
2650 X3$=CVT$$(X$,136%) &
\ GOSUB 2680 &
\ GOSUB 2710 &
\ X3%=X0%
2660 GOTO 2890 UNLESS X5% &
\ X7%=X5% &
\ GOSUB 2680 &
\ GOSUB 2710 &
\ GOSUB 2840 &
\ GOTO 2660
2670 REM ! -- Scan for the next operator { ! & % + * - / } --
2680 IF X3$="" THEN X5%,X4%=0% &
\ RETURN
2690 X9%=-1% &
\ FOR X4%=1% TO LEN(X3$) &
\ X5%=ASCII(RIGHT(X3$,X4%)) &
\ X9%= NOT X9% IF X5%=39% &
\ RETURN IF X9% AND ( X5%=33% OR X5%=37% OR X5%=38% &
OR X5%=42% OR X5%=43% OR X5%=45% OR X5%=47%) &
\ NEXT X4% &
\ X5%=0% &
\ X4%=X4%+1% &
\ RETURN
2700 ! -- Get value of term --
2710 X2$=CVT$$(LEFT(X3$,X4%-1%),136%) &
\ X3$=RIGHT(X3$,X4%+1%)
2720 IF X2$="" THEN X0%=0% &
\ RETURN
2730 ! -- H() or L() ? --
2740 X1$=LEFT(X2$,2%) &
\ IF X1$="H(" THEN X9%=1% &
ELSE IF X1$="L(" THEN X9%=2% &
ELSE X9%=0%
2750 IF X9% THEN IF RIGHT(X2$,LEN(X2$))=")" THEN X2$=MID(X2$,3%,LEN(X2$)-3%) &
ELSE 2820
2760 ! -- Hex or Dec number ? -- &
! -- Ascii character ? -- &
! -- Current LC (".") ? -- &
! -- or Symbol ? -- &
2770 IF X1$="X'" THEN X0%=FND%(RIGHT(X2$,3%)) &
\ GOTO 2800
2780 X1$=LEFT(X2$,1%)
2790 IF X1$="0" THEN X0%=FND%(RIGHT(X2$,2%)) &
ELSE IF X1$>="1" AND X1$<="9" THEN X0%=VAL(X2$) &
ELSE IF X1$>="A" AND X1$<="Z" THEN X0%=FNV%(X2$) &
ELSE IF X1$="'" THEN X0%=ASCII(RIGHT(X2$,2%)) &
ELSE IF X2$="." THEN X0%=N1% &
ELSE 2820
2800 IF X9%=1% THEN X0%=SWAP%(X0%) AND 255% &
ELSE IF X9%=2% THEN X0%=X0% AND 255%
2810 RETURN
2820 X0%=FNE%("Inv term = "+X2$) &
\ RETURN
2830 ! -- Carry out the arithmetic or logical operation --
2840 IF X7%>38% THEN 2860 &
ELSE IF X7%=33% THEN X3%=X3% OR X0% &
ELSE IF X7%=37% THEN X3%=X3%+(NOT X0%) &
ELSE IF X7%=38% THEN X3%=X3% AND X0%
2850 RETURN
2860 IF X7%=42% THEN X3%=X3%*X0% &
ELSE IF X7%=43% THEN X3%=X3%+X0% &
ELSE IF X7%=45% THEN X3%=X3%-X0% &
ELSE IF X7%=47% THEN X3%=X3%/X0%
2870 RETURN
2880 ! -- Exit with value of expression --
2890 FNA%=X3%
2900 FNEND
2905 ! -- Print the given error message to the listing file
2906 DEF* FNE%(X$) &
\ PRINT #1%,X$; &
\ IF P0%=1% THEN PRINT #1%," at line";L% ELSE PRINT #1%
2907 E%=E%+1% &
\ F1%=-1% &
\ FNE%=0% &
\ FNEND
2910 ! -- Look up value of symbol --
2920 DEF* FNV%(X$)
2930 GOTO 2940 IF X$=T$(X%) FOR X%=1% TO T% &
\ FNV%=FNE%("Undef sym = "+X$) &
\ GOTO 2950
2940 FNV%=T%(X%)
2950 FNEND
2960 ! -- Dec to Hex conversion --
2970 DEF* FNH$(X%,D%)
2980 X$="" &
\ FOR X1%=0% TO 3% &
\ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) &
\ X0%=X0%+16% IF X0%<0% &
\ X$=CHR$(48%+X0%)+X$ IF X0%<10% &
\ X$=CHR$(55%+X0%)+X$ IF X0%>9% &
\ NEXT X1% &
\ IF D% THEN X$=MID(X$,D%,2%)
2990 FNH$=X$
3000 FNEND
3010 ! -- Hex to Dec conversion --
3020 DEF* FND%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%)) &
\ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN &
FND%=FNE%("Inv Hex const = "+X$) &
\ GOTO 3040
3030 X2%=X2%-48% &
\ X2%=X2%-7% IF X2%>9% &
\ X0%=X2%+X0%*16% &
\ NEXT X1% &
\ FND%=X0%
3040 FNEND
30000 ! CCL Entry point
30010 F2$=CVT$$(SYS(CHR$(7%)),188%) &
\ I%=INSTR(1%,F2$,"SCMPCA") &
\ IF I% THEN F2$=RIGHT(F2$,7%) &
ELSE PRINT "?SCMPCA - Illegal entry" &
\ GOTO 32767
30020 C9%=-1% &
\ GOTO 1050
31000 ! -- Error routine --
31010 ! -- No "END" --
31020 IF ERR=11% AND ERL=1320% THEN O%=N%+FNE%("Missing END") &
\ RESUME 1450
31030 IF ERR=11% AND ERL=1900% THEN L$="" &
\ RESUME 1920
31040 ! -- ^Z at filename request --
31050 RESUME 32767 IF ERL=1110%
31060 ! -- Illegal number in FNA%() --
31070 IF ERR=51% AND ERL=2790% THEN X0%=VAL(X2$)-65536 &
\ RESUME 2800
31080 RESUME 2820 IF ERR=52% AND ERL=2790%
31090 CLOSE 1,2,3 &
\ KILL W$ IF LINE>=1310% &
\ RESUME 32767 IF ERR=28%
31100 ! -- Print any unanticipated error --
31110 ON ERROR GOTO 0
32000 ! -- Opcode data --
32010 DATA "",0
32020 ! Memory reference 1-8
32030 DATA LD,192,ST,200,AND,208,OR,216,XOR,224,DAD,232,ADD,240,CAD,248
32040 ! Transfer 9-12
32050 DATA JMP,144,JP,148,JZ,152,JNZ,156
32060 ! Memory inc,dec 13-14
32070 DATA ILD,168,DLD,184
32080 ! Immediate 15-21
32090 DATA LDI,196,ANI,212,ORI,220,XRI,228,DAI,236,ADI,244,CAI,252
32100 ! Delay 22
32110 DATA DLY,143
32120 ! Pointer 23-25
32130 DATA XPAL,48,XPAH,52,XPPC,60
32140 ! Extension 26-33
32150 DATA LDE,64,XAE,1,ANE,80,ORE,88,XRE,96,DAE,104,ADE,112,CAE,120
32160 ! SIO, Shift, Rotate 34-38
32170 DATA SIO,25,SR,28,SRL,29,RR,30,RRL,31
32180 ! Miscellaneous 39-46
32190 DATA HALT,0,CCL,2,SCL,3,IEN,5,DINT,4,CSA,6,CAS,7,NOP,8
32200 ! Assembler pseudo-ops 47-51
32210 DATA .BYTE,0,.DBYTE,0,.ASCII,0,.LIST,0,END,0
32767 END

BIN
micros/SCMPCA.TSK Normal file

Binary file not shown.

987
micros/X65.B2S Normal file
View File

@ -0,0 +1,987 @@
1000 REM &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
REM !! !! &
REM !! 6502 Cross Assembler !! &
REM !! !!
1010 REM !! A.G. Nicholson, Newcastle Uni . !! &
REM !! !! &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
1020 REM &
REM ! Version of 26-Nov-79 &
1030 EXTEND
1040 DIM SYMBOLS$(767%), &
VALUES%(767%), &
FLAGS%(767%), &
SYMBOL.CHARS%(6%), &
DELIMITER.TABLE%(3%)
1050 ! -- Set up error trap routine --
1060 ON ERROR GOTO 31020 &
\ X$=SYS(CHR$(6%)+CHR$(-7%))
1070 ! -- Initialise --
1080 NUMBER.OF.SYMBOLS%=0% &
\ SYMBOL.TABLE.SIZE%=768% &
\ START.CPU.TIME%=TIME(1%) &
\ LISTING.FILE$="KB:"
1090 FOR I%=1% TO 65% &
\ READ SYMBOL$,VALUE%,FLAG.WORD% &
\ GOSUB 2490 &
\ NEXT I% &
! Read in opcodes
1100 ! -- Print header --
1110 OPEN LISTING.FILE$ AS FILE 1% &
\ PRINT #1%,"6502 Cross assembler" &
\ PRINT #1%,"#";
1120 ! &
1130 ! -- Get listing, source filenames --
1140 INPUT LINE #1%, SOURCE.FILE$ &
\ SOURCE.FILE$=CVT$$(SOURCE.FILE$,-1%)
1150 ! -- Check for errors only switch --
1160 ERRORS.ONLY.SWITCH%=-1% &
\ I%=INSTR(1%,SOURCE.FILE$,"/E") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ ERRORS.ONLY.SWITCH%=0%
1170 ! -- Check for symbol table listing switch --
1180 SYMBOL.TABLE.LIST.FLAG%=INSTR(1%,SOURCE.FILE$,"/S") &
\ IF SYMBOL.TABLE.LIST.FLAG% THEN SOURCE.FILE$= &
LEFT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%-1%)+ &
RIGHT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%+2%)
1190 ! -- Check for object module output switch --
1200 OBJECT.OUT.FLAG%=0% &
\ I%=INSTR(1%,SOURCE.FILE$,"/O") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ OBJECT.OUT.FLAG%=-1%
1210 ! -- Check for listing file and add default extensions --
1220 LISTING.TO.FILE.FLAG%=INSTR(1%,SOURCE.FILE$,"=") &
\ IF LISTING.TO.FILE.FLAG% THEN LISTING.FILE$= &
LEFT(SOURCE.FILE$,LISTING.TO.FILE.FLAG%-1%) &
\ LISTING.FILE$=LISTING.FILE$+".LST" UNLESS &
INSTR(1%,LISTING.FILE$,".") &
\ SOURCE.FILE$=RIGHT(SOURCE.FILE$, &
LISTING.TO.FILE.FLAG%+1%)
1230 SOURCE.FILE$=SOURCE.FILE$+".SRC" UNLESS &
INSTR(1%,SOURCE.FILE$,".")
1240 PRINT #1%,"Listing output to "+ &
LISTING.FILE$ IF LISTING.TO.FILE.FLAG%
1250 IF OBJECT.OUT.FLAG% THEN OBJECT.FILE$= &
LEFT(SOURCE.FILE$,INSTR(1%,SOURCE.FILE$,"."))+"HEX" &
\ PRINT #1%,"Object module to ";OBJECT.FILE$
1260 ! -- Get a unique workfile name --
1270 WORK.FILE$="X65X"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+ &
CHR$(9%)))/2%),3%,2%)+".TMP"
1280 ! -- Commence assembly --
1290 GOSUB 2010 &
\ GOSUB 3010 &
\ X%=1% &
\ GOSUB 3630
1300 ! -- Print symbol table --
1310 GOSUB 3660 IF SYMBOL.TABLE.LIST.FLAG% &
\ PRINT #1%
1320 ! -- Finish up and exit --
1330 CLOSE 1% &
\ IF LISTING.TO.FILE.FLAG% THEN X%=0% &
\ GOSUB 3630
1340 PRINT "Runtime was";(TIME(1%)-START.CPU.TIME%)/10;"sec" &
\ GOTO 32767
1350 ! &
2000 &
! -- Pass 1 Driver routine -- &
2010 ERROR.COUNT%, &
TOTAL.BYTES%, &
LOCATION.COUNTER%, &
ERROR.LINE.FLAG%, &
OPCODE.TABLE.SUBSCRIPT%=0% &
\ PASS.NUMBER%=1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR OUTPUT AS FILE 3% &
\ PRINT #1%,"Pass 1"
2020 INPUT LINE #2%,SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,421%) &
\ LINE.LENGTH%=LEN(SOURCE.LINE$) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
2030 IF LINE.LENGTH%=0% OR LEFT(SOURCE.LINE$,1%)="$" THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2040 ! -- Scan source line --
2050 GOSUB 2360 &
\ GOSUB 2410
2060 ! -- Comment line ? --
2070 IF COMMENT.DELIMITER%=1% THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2080 ! -- Get argument field --
2090 IF COMMENT.DELIMITER% THEN ARGUMENT$= &
CVT$$(MID(SOURCE.LINE$,OPCODE.DELIMITER%+1%, &
COMMENT.DELIMITER%-OPCODE.DELIMITER%-1%),258%) &
ELSE ARGUMENT$=CVT$$(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%+1%),258%)
2100 ! -- Label ? --
2110 IF LABEL.DELIMITER% THEN SYMBOL$= &
CVT$$(LEFT(SOURCE.LINE$,LABEL.DELIMITER%-1%),128%) &
\ VALUE%=LOCATION.COUNTER% &
\ FLAG.WORD%=-2% &
\ GOSUB 2490
2120 ! -- Assignment ? --
2130 IF EQU.DELIMITER% THEN GOSUB 2560 &
ELSE GOSUB 2610
2140 ! -- Write to workfile --
2150 GOSUB 2770 &
\ GOTO 2020 IF OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2020 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<>1%
2160 CLOSE 2%,3% &
\ RETURN &
! -- End of Pass 1
2170 ! &
2180 &
! -- Determine the addressing mode &
! -- and the number of bytes for this opcode &
2190 OP.TYPE%=SWAP%(VALUES%(OPCODE.TABLE.SUBSCRIPT%)) AND 255%
2200 IF OP.TYPE%=0% THEN BYTE.COUNT%=1% &
\ TEMP1%=FNERROR.PRINT%("No argument required") &
IF ARGUMENT$<>"" &
\ RETURN
2210 IF OP.TYPE%=1% THEN BYTE.COUNT%=2% &
\ RETURN &
! relative branch
2220 IF OP.TYPE%=2% THEN BYTE.COUNT%=3% &
\ RETURN &
! transfer
2230 ARG.LENGTH%=LEN(ARGUMENT$) &
\ IF ARG.LENGTH%=0% THEN BYTE.COUNT%=FNERROR.PRINT%( &
"Missing argument") &
\ OPCODE.TABLE.SUBSCRIPT%=-1% &
\ RETURN
2240 TEMP2$=MID(ARGUMENT$,ARG.LENGTH%-2%,3%) &
\ TEMP3$=LEFT(ARGUMENT$,1%) &
\ IF TEMP2$=",X)" AND TEMP3$="(" THEN ADDR.MODE%=0% &
\ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-4%) &
\ BYTE.COUNT%=2% &
\ RETURN &
! (ind ,X)
2250 IF TEMP2$="),Y" AND TEMP3$="(" THEN ADDR.MODE%=16% &
\ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-4%) &
\ BYTE.COUNT%=2% &
\ RETURN &
! (ind),Y
2260 IF TEMP3$="#" THEN ADDR.MODE%=8% &
\ ARGUMENT$=RIGHT(ARGUMENT$,2%) &
\ BYTE.COUNT%=2% &
\ RETURN &
! #
2270 IF ARGUMENT$="A" THEN ADDR.MODE%=8% &
\ BYTE.COUNT%=1% &
\ RETURN &
! A
2280 TEMP2$=RIGHT(TEMP2$,2%) &
\ IF OP.TYPE%>7% AND TEMP2$=",Y" THEN TEMP2$=",X" &
\ GOTO 2300 &
! Convert ',Y' to ',X' for idx store and load
2290 IF TEMP2$=",Y" THEN ADDR.MODE%=24% &
\ ARGUMENT$=LEFT(ARGUMENT$,ARG.LENGTH%-2%) &
\ BYTE.COUNT%=3% &
\ RETURN &
! abs,Y
2300 IF TEMP2$<>",X" THEN 2320 &
ELSE ARGUMENT$=LEFT(ARGUMENT$,ARG.LENGTH%-2%) &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF UNDEFINED.SYMBOL% OR ( VALUE% AND -256% ) THEN &
ADDR.MODE%=28% &
\ BYTE.COUNT%=3% &
\ RETURN &
! abs,X
2310 ADDR.MODE%=20% &
\ BYTE.COUNT%=2% &
\ RETURN &
! z page,X
2320 VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF UNDEFINED.SYMBOL% OR ( VALUE% AND -256% ) THEN &
ADDR.MODE%=12% &
\ BYTE.COUNT%=3% &
\ RETURN &
! abs
2330 ADDR.MODE%=4% &
\ BYTE.COUNT%=2% &
\ RETURN &
! zero page
2340 ! &
2350 &
! -- Scan for strings in SOURCE.LINE$ -- &
2360 DELIMITER%=-1% &
\ TEMP2%=0%
2370 TEMP1%=INSTR(TEMP2%+1%,SOURCE.LINE$,"'") &
\ RETURN UNLESS TEMP1%
2380 TEMP2%=INSTR(TEMP1%+1%,SOURCE.LINE$,"'") &
\ IF TEMP2% THEN DELIMITER%=DELIMITER%+1% &
\ IF DELIMITER%<4% THEN DELIMITER.TABLE%(DELIMITER%)= &
SWAP%(TEMP1% AND 255%) OR (TEMP2% AND 255%) &
\ GOTO 2370
2390 RETURN
2400 &
! -- Search for token delimiters -- &
! LABEL.DELIMITER% Label &
! OPCODE.DELIMITER% Opcode &
! COMMENT.DELIMITER% Comment &
! EQU.DELIMITER% Assignment &
2410 LABEL.DELIMITER%=INSTR(1%,SOURCE.LINE$,":") &
\ LABEL.DELIMITER%=0% IF FNCHECK.SYNTAX%(LABEL.DELIMITER%) &
\ COMMENT.DELIMITER%=0%
2420 COMMENT.DELIMITER%=INSTR(COMMENT.DELIMITER%+1%,SOURCE.LINE$,";") &
\ GOTO 2420 IF FNCHECK.SYNTAX%(COMMENT.DELIMITER%) &
\ LABEL.DELIMITER%=0% IF (LABEL.DELIMITER%> &
COMMENT.DELIMITER% AND COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=LABEL.DELIMITER%
2430 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%>=LINE.LENGTH% THEN 2450 &
ELSE X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%=9% OR X%=32% THEN 2430
2440 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%<LINE.LENGTH% THEN &
X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%<>9% AND X%<>32% THEN 2440 &
ELSE OPCODE.DELIMITER%=OPCODE.DELIMITER%-1%
2450 EQU.DELIMITER%=INSTR(1%,SOURCE.LINE$,"=") &
\ EQU.DELIMITER%=0% IF FNCHECK.SYNTAX%(EQU.DELIMITER%) OR &
(EQU.DELIMITER%>COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=EQU.DELIMITER% IF EQU.DELIMITER%
2460 OPCODE.DELIMITER%=COMMENT.DELIMITER%-1% IF &
(OPCODE.DELIMITER%>=COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ RETURN
2470 ! &
2480 &
! Enter symbol SYMBOL$ into symbol table &
! and its value VALUE% &
2490 IF NUMBER.OF.SYMBOLS%=SYMBOL.TABLE.SIZE% THEN &
VALUE%=FNERROR.PRINT%("?X65 - FATAL: Symbol table overflow") &
\ STOP &
! Symbol table full
2500 X%=ASCII(SYMBOL$) &
\ IF X%<>46% AND ( X%<65% OR X%>90% ) THEN &
VALUE%=FNERROR.PRINT%("Invalid symbol = "+SYMBOL$) &
\ RETURN &
! Invalid symbol
2510 TEMP2%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) &
! Hash symbol
2520 IF SYMBOLS$(TEMP2%)="" THEN SYMBOLS$(TEMP2%)=SYMBOL$ &
\ VALUES%(TEMP2%)=VALUE% &
\ FLAGS%(TEMP2%)=FLAG.WORD% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%+1% &
\ RETURN &
! If slot empty, enter symbol, value and flagword
2530 IF SYMBOLS$(TEMP2%)=SYMBOL$ AND FLAGS%(TEMP2%)<0% THEN &
VALUE%=FNERROR.PRINT%("Redefined symbol = "+SYMBOL$) &
\ RETURN &
! Multiple definition not allowed
2540 TEMP2%=FNREHASH.SYMBOL%(TEMP2%,SYMBOL.TABLE.SIZE%) &
\ GOTO 2520
2550 &
! -- Enter assignment -- &
2560 SYMBOL$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
EQU.DELIMITER%-LABEL.DELIMITER%-1%),136%) &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF UNDEFINED.SYMBOL% THEN VALUE%= &
FNERROR.PRINT%("Undefined value")
2570 IF SYMBOL$="." THEN LOCATION.COUNTER%=VALUE% &
ELSE IF SYMBOL$="" THEN VALUE%= &
FNERROR.PRINT%("Missing symbol") &
ELSE FLAG.WORD%=-1% &
\ GOSUB 2490
2580 OPCODE.TABLE.SUBSCRIPT%=-1% &
\ RETURN
2590 ! &
2600 &
! -- Get opcode subscript -- &
2610 OPCODE$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
OPCODE.DELIMITER%-LABEL.DELIMITER%),8%) &
\ IF OPCODE$<>"" THEN OPCODE.TABLE.SUBSCRIPT%= &
FNHASH.SYMBOL%(OPCODE$,SYMBOL.TABLE.SIZE%) &
ELSE OPCODE.TABLE.SUBSCRIPT%=-1% \ RETURN
2620 IF SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)=OPCODE$ THEN RETURN &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<0% OR &
SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)="" THEN &
OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Invalid opcode = "+OPCODE$)-1% &
ELSE OPCODE.TABLE.SUBSCRIPT%= &
FNREHASH.SYMBOL%(OPCODE.TABLE.SUBSCRIPT%, &
SYMBOL.TABLE.SIZE%) &
\ GOTO 2620 &
! Check for opcode match in the symbol table &
! If flagword < 0 then report an error else rehash
2630 RETURN
2640 &
! -- Get address mode and check for validity &
2650 GOSUB 2190 &
\ RETURN IF OP.TYPE%<3% &
! O.K. if single byte, branch or transfer
2660 ON OP.TYPE%-2% GOTO &
2670, 2680, 2690, 2700, &
2710, 2720, 2730 &
! shift accum bit idx cmp &
! inc/dec load idx store idx
2670 RETURN IF ( ADDR.MODE%=8% AND ARGUMENT$="A" ) &
OR ADDR.MODE%=4% OR ADDR.MODE%=20% &
OR ADDR.MODE%=12% OR ADDR.MODE%=28% &
\ GOTO 2740
2680 RETURN
2690 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=12% &
\ GOTO 2740
2700 RETURN IF ADDR.MODE%>0% AND ADDR.MODE%<16% &
\ GOTO 2740
2710 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=20% &
OR ADDR.MODE%=12% OR ADDR.MODE%=28% &
\ GOTO 2740
2720 RETURN UNLESS ADDR.MODE%=0% OR ADDR.MODE%=16% &
OR ADDR.MODE%=24% &
\ GOTO 2740
2730 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=12% &
OR ADDR.MODE%=20%
2740 OPCODE.TABLE.SUBSCRIPT%=FNERROR.PRINT%( &
"Illegal addressing mode")-1% &
\ RETURN
2750 ! &
2760 &
! -- Get byte count and output to workfile -- &
2770 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN BYTE.COUNT%=0% &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>0% THEN &
GOSUB 2800 &
ELSE GOSUB 2650 &
! Get byte count into BYTE.COUNT%
2780 PRINT #3%,LOCATION.COUNTER%;","; &
BYTE.COUNT%;","; &
OPCODE.TABLE.SUBSCRIPT%;","; &
ADDR.MODE%;","; &
ERROR.LINE.FLAG% &
\ PRINT #3%,ARGUMENT$ &
\ TOTAL.BYTES%=TOTAL.BYTES%+BYTE.COUNT% &
\ LOCATION.COUNTER%=LOCATION.COUNTER%+BYTE.COUNT% &
\ ERROR.LINE.FLAG%=0% &
\ RETURN
2790 &
! -- Get byte count for pseudo-op -- &
2800 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%) &
GOTO 2890, 2820, 2820, 2820, &
2840, 2840, 2840, 2870, &
2890 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .BLKB &
! .LIST
2810 ! -- .BYTE, .DBYTE, .WORD --
2820 TEMP1%=0% &
\ TEMP2%=-1% &
\ FOR BYTE.COUNT%=0% WHILE TEMP2% &
\ TEMP1%,TEMP2%=INSTR(TEMP1%+1%,ARGUMENT$,",") &
\ NEXT BYTE.COUNT% &
\ BYTE.COUNT%=BYTE.COUNT%*2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% &
\ RETURN
2830 ! -- .ASCII, .ASCIP, .ASCIZ --
2840 TEMP1%=INSTR(2%,ARGUMENT$,LEFT(ARGUMENT$,1%)) &
\ IF TEMP1%=0% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing delimiter")-1% &
ELSE BYTE.COUNT%=TEMP1%-2%
2850 BYTE.COUNT%=BYTE.COUNT%+1% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=7% &
\ RETURN
2860 ! -- .BLKB
2870 BYTE.COUNT%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ RETURN
2880 ! -- .LIST, .END --
2890 BYTE.COUNT%=0% &
\ RETURN
2900 ! &
3000 &
! -- Pass 2 Driver routine -- &
3010 LINE.NUMBER%, &
CHECKSUM%, &
NEW.LINE.FLAG%=0% &
\ PASS.NUMBER%=2% &
\ LIST.FLAG%=-1% &
\ PRINT #1%,"Pass 2" &
\ CLOSE 1% &
\ OPEN LISTING.FILE$ FOR OUTPUT AS FILE 1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR INPUT AS FILE 3% &
\ KILL WORK.FILE$
3020 IF OBJECT.OUT.FLAG% THEN &
OPEN OBJECT.FILE$ FOR OUTPUT AS FILE 4% &
\ NEW.OBJ.LINE%=0%
3030 IF ERRORS.ONLY.SWITCH% THEN PRINT #1%," Line Addr B1 B2 B3" &
\ PRINT #1%
3040 INPUT #3%,LOCATION.COUNTER%, &
BYTE.COUNT%, &
OPCODE.TABLE.SUBSCRIPT%, &
ADDR.MODE%, &
ERROR.LINE.FLAG% &
\ INPUT LINE #3%, ARGUMENT$ &
\ ARGUMENT$=CVT$$(ARGUMENT$,4%) &
\ INPUT LINE #2%, SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,4%) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
3050 ! -- Form object code and output to listing file --
3060 IF LEFT(SOURCE.LINE$,1%)="$" THEN &
SOURCE.LINE$=RIGHT(SOURCE.LINE$,2%)
3070 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN GOSUB 3540 &
\ GOTO 3040
3080 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=1% THEN &
GOSUB 3130 &
\ RETURN
3090 ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%,0%) &
\ VALUE%=VALUES%(OPCODE.TABLE.SUBSCRIPT%) &
\ FLAG.WORD%=SWAP%(VALUE%) AND 255% &
\ VALUE%=VALUE% AND 255%
3100 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>0% THEN GOSUB 3260 &
ELSE IF FLAG.WORD% THEN GOSUB 3170 &
ELSE GOSUB 3450 &
\ GOSUB 3540
3110 GOTO 3040
3120 &
! -- End of assembly, tidy up -- &
3130 GOSUB 3540 &
\ PRINT #4% IF OBJECT.OUT.FLAG%
3140 CLOSE 2%,3%,4% &
\ RETURN
3150 ! &
3160 &
! -- Process operands -- &
3170 IF FLAG.WORD%=1% THEN GOSUB 3450 &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$)-LOCATION.COUNTER%-2% &
\ VALUE%=FNERROR.PRINT%("Invalid displacement ="+NUM$(VALUE%)) &
IF VALUE%<-128% OR VALUE%>127% &
\ GOSUB 3470 &
\ GOTO 3540 &
! relative branch
3180 IF FLAG.WORD%<>2% THEN 3200 &
ELSE ARG.LENGTH%=LEN(ARGUMENT$) &
\ IF LEFT(ARGUMENT$,1%)="(" AND &
RIGHT(ARGUMENT$,ARG.LENGTH%)=")" AND &
VALUE%=76% THEN VALUE%=VALUE%+32% &
\ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-2%) &
! JMP ( )
3190 GOSUB 3450 &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ GOSUB 3470 &
\ GOTO 3230 &
! transfer
3200 IF FLAG.WORD%=6% THEN &
ADDR.MODE%=0% IF ADDR.MODE%=8% &
! kludge for compare idx
3210 IF FLAG.WORD%=8% THEN &
ADDR.MODE%=ADDR.MODE%+4% &
\ ADDR.MODE%=4% IF ADDR.MODE%=12% &
! kludge for load idx
3220 VALUE%=VALUE%+ADDR.MODE% &
\ GOSUB 3450 &
\ GOTO 3540 IF BYTE.COUNT%=1% &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ GOSUB 3470 &
\ GOTO 3540 IF BYTE.COUNT%=2%
3230 VALUE%=SWAP%(VALUE%) &
\ GOSUB 3490 &
\ GOTO 3540 &
! multi mode
3240 ! &
3250 &
! -- Pseudo-ops. -- &
3260 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%) &
GOTO 3430, 3280, 3280, 3280, &
3340, 3340, 3340, 3410, &
3390 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .BLKB &
! .LIST
3270 ! -- .BYTE, .DBYTE, .WORD --
3280 ARGUMENT$=ARGUMENT$+"," &
\ TEMP3%=1% &
\ TEMP3%=2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% &
\ FOR I%=1% TO BYTE.COUNT% STEP TEMP3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ TEMP1%=INSTR(1%,ARGUMENT$,",")
3290 TEMP2%=FNEVALUATE.EXPR%(LEFT(ARGUMENT$,TEMP1%-1%)) &
\ IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% THEN &
VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3450 &
\ VALUE%=TEMP2% &
\ GOSUB 3470
3300 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% THEN &
VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3470 &
\ VALUE%=TEMP2% &
\ GOSUB 3450
3310 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=2% THEN &
VALUE%=TEMP2% &
\ GOSUB 3450
3320 GOSUB 3540 &
\ ARGUMENT$=RIGHT(ARGUMENT$,TEMP1%+1%) &
\ NEXT I% &
\ RETURN
3330 ! -- .ASCII, .ASCIP, .ASCIZ --
3340 ARGUMENT$=MID(ARGUMENT$,2%,BYTE.COUNT%) &
\ ARGUMENT$=LEFT(ARGUMENT$,BYTE.COUNT%-1%)+CHR$(0%) &
IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=7% &
\ FOR I%=1% TO BYTE.COUNT% STEP 3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ VALUE%=FNCHAR%(I%) &
\ GOSUB 3450 &
\ VALUE%=FNCHAR%(I%+1%) &
\ GOSUB 3470 IF I%+1%<=BYTE.COUNT% &
\ VALUE%=FNCHAR%(I%+2%) &
\ GOSUB 3490 IF I%+2%<=BYTE.COUNT% &
\ GOSUB 3540 &
\ NEXT I% &
\ RETURN
3350 ! &
3360 ! -- Get character J% from ARGUMENT$
3370 DEF* FNCHAR%(J%) &
\ CHAR%=ASCII(MID(ARGUMENT$,J%,1%)) &
\ CHAR%=CHAR% OR 128% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=6% &
AND J%=BYTE.COUNT% &
\ FNCHAR%=CHAR% &
\ FNEND &
3380 ! -- .LIST --
3390 LIST.FLAG%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ ADDRESS$="" &
\ RETURN
3400 ! -- .BLKB
3410 TEMP1%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF OBJECT.OUT.FLAG% THEN VALUE%=0% &
\ FOR X%=1% TO TEMP1% &
\ GOSUB 3520 &
\ NEXT X%
3420 GOSUB 3540
3430 RETURN
3440 &
! -- Form B1 -- &
3450 BYTE1$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3520 &
\ RETURN
3460 &
! -- Form B2 -- &
3470 BYTE2$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3520 &
\ RETURN
3480 &
! -- Form B3 -- &
3490 BYTE3$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3520 &
\ RETURN
3500 ! &
3510 &
! -- Output object and update checksum -- &
3520 OBJECT.BYTE%=VALUE% AND 255% &
\ OBJECT.BYTE%=FNOBJECT.OUTPUT%(VALUE%) IF OBJECT.OUT.FLAG% &
\ CHECKSUM%=CHECKSUM%+OBJECT.BYTE% &
\ RETURN
3530 &
! -- Output assembled code to listing file -- &
3540 GOTO 3590 UNLESS ERRORS.ONLY.SWITCH% OR ERROR.LINE.FLAG%
3550 IF ERROR.LINE.FLAG% THEN PRINT #1%,"?"; ELSE PRINT #1%," ";
3560 IF NEW.LINE.FLAG%<LINE.NUMBER% THEN &
PRINT #1% USING "#### ",LINE.NUMBER%; &
ELSE PRINT #1%," ";
3570 PRINT #1% USING"\ \ \\ \\ \\",ADDRESS$,BYTE1$,BYTE2$,BYTE3$; &
\ IF LIST.FLAG% AND SOURCE.LINE$<>"" THEN &
PRINT #1%,CHR$(9%);SOURCE.LINE$ &
ELSE PRINT #1%
3580 ! -- Set a flag, clear output strings --
3590 NEW.LINE.FLAG%=LINE.NUMBER% &
\ ADDRESS$,BYTE1$,BYTE2$,BYTE3$,SOURCE.LINE$="" &
\ RETURN
3600 &
! -- Output binary byte to object file -- &
3610 DEF* FNOBJECT.OUTPUT%(X%) &
\ OBJECT.BYTE%=X% AND 255% &
\ PRINT #4%,FNDEC.TO.HEX$(OBJECT.BYTE%,3%); &
\ NEW.OBJ.LINE%=NEW.OBJ.LINE%+1% &
\ PRINT #4% IF (NEW.OBJ.LINE% AND 15%)=0% &
\ FNOBJECT.OUTPUT%=OBJECT.BYTE% &
\ FNEND
3620 &
! -- Print error count, checksum -- &
3630 PRINT #X% &
\ PRINT #X%,"Errors detected ";FNDEC.TO.HEX$(ERROR.COUNT%,0%) &
\ PRINT #X%,"Source checksum ";FNDEC.TO.HEX$(CHECKSUM%,0%) &
\ PRINT #X%,"Total hex bytes ";FNDEC.TO.HEX$(TOTAL.BYTES%,0%) &
\ PRINT #X% &
\ RETURN
3640 ! &
3650 &
! -- Print sorted symbol table -- &
3660 TEMP1%,TEMP2%=0% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%-66% &
\ RETURN IF NUMBER.OF.SYMBOLS%<0%
3670 PRINT #1%," Symbol Table" &
\ PRINT #1%
3680 TEMP1%=TEMP1%+1% WHILE FLAGS%(TEMP1%)>=0% &
\ SYMBOLS$(TEMP2%)=SYMBOLS$(TEMP1%) &
\ VALUES%(TEMP2%)=VALUES%(TEMP1%) &
\ FLAGS%(TEMP2%)=FLAGS%(TEMP1%) &
\ TEMP2%=TEMP2%+1% &
\ TEMP1%=TEMP1%+1% &
\ GOTO 3680 UNLESS TEMP2%=NUMBER.OF.SYMBOLS%
3690 ! -- Quick sort the symbol table
3700 TEMP1%=FNQUICKSORT%(0%,NUMBER.OF.SYMBOLS%,0%,NUMBER.OF.SYMBOLS%)
3710 ! -- Output to listing file --
3720 FOR I%=0% TO NUMBER.OF.SYMBOLS% &
\ IF FLAGS%(I%)=-1% THEN S$="#" ELSE S$=" "
3730 PRINT #1% USING " \ \ \ \ ", &
SYMBOLS$(I%),FNDEC.TO.HEX$(VALUES%(I%),0%)+S$; &
\ PRINT #1% IF CCPOS(1%)>63% &
\ NEXT I%
3740 PRINT #1% IF CCPOS(1%) &
\ RETURN
3750 &
! -- Check position of char X% in SOURCE.LINE$ using tables &
! -- DELIMITER%(). FNCHECK.SYNTAX%=-1% means in string &
3760 DEF* FNCHECK.SYNTAX%(X%)
3770 GOTO 3790 IF DELIMITER%=-1% OR X%=0% &
\ FOR X0%=0% TO DELIMITER% &
\ GOTO 3790 IF X%<(SWAP%(DELIMITER.TABLE%(X0%)) AND 255%) &
\ IF X%<(DELIMITER.TABLE%(X0%) AND 255%) THEN &
FNCHECK.SYNTAX%=-1% &
\ GOTO 3800
3780 NEXT X0%
3790 FNCHECK.SYNTAX%=0%
3800 FNEND
3810 ! &
4000 &
! -- Evaluate the argument expression -- &
4010 DEF* FNEVALUATE.EXPR%(X$) &
\ UNDEFINED.SYMBOL%=0%
4020 &
! -- Main driver routine -- &
4030 EXPR$=X$ &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ EXP.VAL%=TERM%
4040 GOTO 4290 UNLESS OP% &
\ LAST.OP%=OP% &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ GOSUB 4190 &
\ GOTO 4040
4050 &
REM ! -- Scan for the next operator { ! & % + * - / } -- &
4060 EXP.FLAG%=-1% &
\ FOR TOK.PTR%=1% TO LEN(EXPR$) &
\ TOK.CHR$=MID(EXPR$,TOK.PTR%,1%) &
\ EXP.FLAG%= NOT EXP.FLAG% IF TOK.CHR$="'" &
\ OP%=INSTR(1%,"!%&*+-/",TOK.CHR$) &
\ RETURN IF OP% AND EXP.FLAG% &
\ NEXT TOK.PTR% &
\ OP%=0% &
\ TOK.PTR%=TOK.PTR%+1% &
\ RETURN
4070 &
! -- Get value of term -- &
4080 TERM$=LEFT(EXPR$,TOK.PTR%-1%) &
\ EXPR$=RIGHT(EXPR$,TOK.PTR%+1%)
4090 IF TERM$="" THEN TERM%=0% &
\ RETURN
4100 ! -- H() or L() ? --
4110 TEMP1$=LEFT(TERM$,2%) &
\ IF TEMP1$="H(" THEN EXP.FLAG%=1% &
ELSE IF TEMP1$="L(" THEN EXP.FLAG%=2% &
ELSE EXP.FLAG%=0%
4120 IF EXP.FLAG% THEN IF RIGHT(TERM$,LEN(TERM$))=")" THEN &
TERM$=MID(TERM$,3%,LEN(TERM$)-3%) &
ELSE 4170
4130 TEMP1$=LEFT(TERM$,1%)
4140 IF TEMP1$>="A" AND TEMP1$<="Z" THEN TERM%=FNSYMBOL.LOOKUP%(TERM$) &
ELSE IF TEMP1$="0" OR TEMP1$="$" THEN &
TERM%=FNHEX.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$>="1" AND TEMP1$<="9" THEN TERM%=VAL(TERM$) &
ELSE IF TEMP1$="'" THEN TERM%=ASCII(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$="^" THEN TERM%=FNOCT.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TERM$="." THEN TERM%=LOCATION.COUNTER% &
ELSE 4170
4150 IF EXP.FLAG%=1% THEN TERM%=SWAP%(TERM%) AND 255% &
ELSE IF EXP.FLAG%=2% THEN TERM%=TERM% AND 255%
4160 RETURN
4170 TERM%=FNERROR.PRINT%("Invalid term = "+TERM$) &
\ RETURN
4180 &
! -- Carry out the arithmetic or logical operation -- &
4190 ON LAST.OP%+1% &
GOTO 4270, 4200, 4210, 4220, &
4230, 4240, 4250, 4260 &
! or not and &
! mult add sub div
4200 EXP.VAL%=EXP.VAL% OR TERM% &
\ RETURN &
! or
4210 EXP.VAL%=EXP.VAL%+(NOT TERM%) &
\ RETURN &
! not
4220 EXP.VAL%=EXP.VAL% AND TERM% &
\ RETURN &
! and
4230 EXP.VAL%=EXP.VAL%*TERM% &
\ RETURN &
! multiply
4240 EXP.VAL%=EXP.VAL%+TERM% &
\ RETURN &
! add
4250 EXP.VAL%=EXP.VAL%-TERM% &
\ RETURN &
! subtract
4260 IF TERM%=0% THEN EXP.VAL%=FNERROR.PRINT%("Division by zero") &
ELSE EXP.VAL%=EXP.VAL%/TERM%
4270 RETURN
4280 &
! -- Exit with value of expression --
4290 FNEVALUATE.EXPR%=EXP.VAL%
4300 FNEND
4310 ! &
4320 &
! -- Print the given error message to the listing file &
4330 DEF* FNERROR.PRINT%(X$) &
\ PRINT #1%,"********";X$; &
\ IF PASS.NUMBER%=1% THEN PRINT #1%," at line";LINE.NUMBER% &
ELSE PRINT #1%
4340 ERROR.COUNT%=ERROR.COUNT%+1% &
\ ERROR.LINE.FLAG%=-1% &
\ FNERROR.PRINT%=0% &
\ FNEND
4350 &
! -- Look up value of symbol -- &
4360 DEF* FNSYMBOL.LOOKUP%(SYMBOL$) &
\ X%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%)
4370 IF SYMBOLS$(X%)=SYMBOL$ AND FLAGS%(X%)<=0% THEN &
FNSYMBOL.LOOKUP%=VALUES%(X%) &
ELSE IF SYMBOLS$(X%)="" THEN GOSUB 4390 &
ELSE X%=FNREHASH.SYMBOL%(X%,SYMBOL.TABLE.SIZE%) &
\ GOTO 4370
4380 FNEND
4390 UNDEFINED.SYMBOL%=-1% &
\ IF PASS.NUMBER%=2% THEN &
FNSYMBOL.LOOKUP%=FNERROR.PRINT%( &
"Undefined symbol "+SYMBOL$)
4400 RETURN
4410 &
! -- Dec to Hex conversion -- &
4420 DEF* FNDEC.TO.HEX$(X%,D%)
4430 X$="" &
\ FOR X1%=0% TO 3% &
\ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) &
\ X0%=X0%+16% IF X0%<0% &
\ X$=CHR$(48%+X0%)+X$ IF X0%<10% &
\ X$=CHR$(55%+X0%)+X$ IF X0%>9% &
\ NEXT X1% &
\ IF D% THEN X$=MID(X$,D%,2%)
4440 FNDEC.TO.HEX$=X$
4450 FNEND
4460 &
! -- Hex to Dec conversion -- &
4470 DEF* FNHEX.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%)) &
\ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN &
FNHEX.TO.DEC%=FNERROR.PRINT%("Invalid HEX constant = "+X$) &
\ GOTO 4490
4480 X2%=X2%-48% &
\ X2%=X2%-7% IF X2%>9% &
\ X0%=X2%+X0%*16% &
\ NEXT X1% &
\ FNHEX.TO.DEC%=X0%
4490 FNEND
4500 &
! -- Octal to Dec conversion -- &
4510 DEF* FNOCT.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%))-48% &
\ IF X2%<0% OR X2%>7% THEN &
FNOCT.TO.DEC%=FNERROR.PRINT%("Invalid OCTAL constant = "+X$) &
\ GOTO 4530
4520 X0%=X0%*8% + X2% &
\ NEXT X1% &
\ FNOCT.TO.DEC%=X0%
4530 FNEND
4540 &
! -- Calculate X1% modulo X2% -- &
4550 DEF* FNMOD%(X1%,X2%) &
\ X1%=X1%-(X1%/X2%)*X2% &
\ X1%=X1%+X2% IF X1%<0% &
\ FNMOD%=X1% &
\ FNEND
4560 &
! -- Hash symbol X$, modulo SYMBOL.TABLE.SIZE% -- &
4570 DEF* FNHASH.SYMBOL%(SYMBOL$,M%) &
\ SYMBOL$=LEFT(SYMBOL$+" ",6%) &
\ CHANGE SYMBOL$ TO SYMBOL.CHARS% &
\ SYMBOL.CHARS%(X%)=SYMBOL.CHARS%(X%)-48% FOR X%=1% TO 6% &
\ FNHASH.SYMBOL%=FNMOD%(SYMBOL.CHARS%(1%)*23%+ &
SYMBOL.CHARS%(2%)*19%+SYMBOL.CHARS%(3%)*17%+ &
SYMBOL.CHARS%(4%)*13%+SYMBOL.CHARS%(5%)*11%+ &
SYMBOL.CHARS%(6%)*7%,M%) &
\ FNEND
4580 &
! -- Rehash function, modulo X2% &
4590 DEF* FNREHASH.SYMBOL%(X1%,X2%)=FNMOD%(X1%+23%,X2%)
4600 &
! -- Quick sort symbol table &
4610 ! &
4620 DEF* FNQUICKSORT%(LOW%,HIGH%,I%,J%) &
\ I%=LOW% &
\ J%=HIGH% &
\ X$=SYMBOLS$((HIGH%+LOW%)/2%)
4630 I%=I%+1% WHILE SYMBOLS$(I%)<X$
4640 J%=J%-1% WHILE X$<SYMBOLS$(J%)
4650 IF I%>J% THEN 4670 &
ELSE IF I%<>J% THEN VALUE%=VALUES%(I%) &
\ FLAG.WORD%=FLAGS%(I%) &
\ SYMBOL$=SYMBOLS$(I%) &
\ VALUES%(I%)=VALUES%(J%) &
\ FLAGS%(I%)=FLAGS%(J%) &
\ SYMBOLS$(I%)=SYMBOLS$(J%) &
\ VALUES%(J%)=VALUE% &
\ FLAGS%(J%)=FLAG.WORD% &
\ SYMBOLS$(J%)=SYMBOL$
4660 I%=I%+1% &
\ J%=J%-1% &
\ IF I%<=J% THEN 4630
4670 IF LOW%<J% THEN TEMP1%=FNQUICKSORT%(LOW%,J%,LOW%,J%)
4680 IF I%<HIGH% THEN TEMP1%=FNQUICKSORT%(I%,HIGH%,I%,HIGH%)
4690 FNQUICKSORT%=-1% &
\ FNEND
4700 ! &
31000 &
! -- Error routine -- &
31010 ! -- No ".END" --
31020 IF ERR=11% AND ERL=2020% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing .END")+ &
FNHASH.SYMBOL%(".END",SYMBOL.TABLE.SIZE%) &
\ SOURCE.LINE$="" &
\ RESUME 2150
31030 IF ERR=11% AND ERL=3040% THEN SOURCE.LINE$="" &
\ OPCODE.TABLE.SUBSCRIPT%=FNHASH.SYMBOL%(".END", &
SYMBOL.TABLE.SIZE%) &
\ RESUME 3080
31040 ! -- ^Z at filename request --
31050 RESUME 32767 IF ERL=1140%
31060 ! -- Illegal number in FNEVALUATE.EXPR%() --
31070 IF ERR=51% AND ERL=4140% THEN X0%=VAL(TERM$)-65536 &
\ RESUME 4150
31080 RESUME 4170 IF ERR=52% AND ERL=4140%
31090 CLOSE 1%,2%,3%,4% &
\ RESUME 32767% IF ERR=28%
31100 ! -- Print any unanticipated error --
31110 ON ERROR GOTO 0
31120 ! &
32000 &
! -- Opcode data &
32010 ! Table is of the form: &
! SYMBOL,value,flag &
! where: the low byte of value is the opcode base &
! and the high byte a flag indicating the &
! instruction type. flag is used by the &
! symbol table routines &
!
32020 ! Assembler pseudo-ops
32030 DATA .END, 0, 1, .BYTE, 0, 2, &
.DBYTE, 0, 3, .WORD, 0, 4, &
.ASCII, 0, 5, .ASCIP, 0, 6, &
.ASCIZ, 0, 7, .BLKB, 0, 8, &
.LIST, 0, 9
32040 ! Single byte instructions
32050 DATA BRK, 0, 0, CLC, 24, 0, &
CLD, 216, 0, CLI, 88, 0, &
CLV, 184, 0, DEX, 202, 0, &
DEY, 136, 0, INX, 232, 0, &
INY, 200, 0, NOP, 234, 0, &
PHA, 72, 0, PHP, 8, 0, &
PLA, 104, 0, PLP, 40, 0, &
RTI, 64, 0, RTS, 96, 0, &
SEC, 56, 0, SED, 248, 0, &
SEI, 120, 0, TAX, 170, 0, &
TAY, 168, 0, TSX, 186, 0, &
TXA, 138, 0, TYA, 152, 0, &
TXS, 154, 0
32060 ! Two byte relative branches
32070 DATA BCC, 400, 0, BCS, 432, 0, &
BEQ, 496, 0, BMI, 304, 0, &
BNE, 464, 0, BPL, 272, 0, &
BVC, 336, 0, BVS, 368, 0
32080 ! Three byte transfer
32090 DATA JMP, 588, 0, JSR, 544, 0
32100 ! Shifts and rotates
32110 DATA ASL, 770, 0, LSR, 834, 0, &
ROL, 802, 0, ROR, 866, 0
32120 ! Accumulator
32130 DATA ADC, 1121, 0, AND, 1057, 0, &
CMP, 1217, 0, EOR, 1089, 0, &
LDA, 1185, 0, ORA, 1025, 0, &
SBC, 1249, 0, STA, 1153, 0
32140 ! Bit test
32150 DATA BIT, 1312, 0
32160 ! Compare index
32170 DATA CPX, 1760, 0, CPY, 1728, 0
32180 ! Increment, Decrement
32190 DATA DEC, 1986, 0, INC, 2018, 0
32200 ! Index load
32210 DATA LDX, 2206, 0, LDY, 2204, 0
32220 ! Index store
32230 DATA STX, 2434, 0, STY, 2432, 0
32767 END

BIN
micros/X65.TSK Normal file

Binary file not shown.

13
micros/X65BLD.COM Normal file
View File

@ -0,0 +1,13 @@
$! Command file to build X65.B2S (with Basic-Plus-2)
$!
$ set noOn
$ run $bp2ic2
SCALE 0
OLD X65.B2S
COMPILE X65/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN
BUILD X65
SCRATCH
EXIT
$ tkb @X65
$ del x65.odl, x65.obj, x65.cmd
$ exit

921
micros/X80.B2S Normal file
View File

@ -0,0 +1,921 @@
1000 REM &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
REM !! !! &
REM !! 8080/8085 Cross Assembler !! &
REM !! !!
1010 REM !! A.G. Nicholson, Newcastle Uni . !! &
REM !! !! &
REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! &
1020 REM &
REM ! Version of 12-May-80 &
1030 EXTEND
1040 CCL.ENTRY%=0%
1050 DIM SYMBOLS$(767%), &
VALUES%(767%), &
FLAGS%(767%), &
SYMBOL.CHARS%(6%), &
DELIMITER.TABLE%(3%)
1060 ! -- Set up error trap routine --
1070 ON ERROR GOTO 31020 &
\ X$=SYS(CHR$(6%)+CHR$(-7%))
1080 ! -- Initialise --
1090 NUMBER.OF.SYMBOLS%=0% &
\ SYMBOL.TABLE.SIZE%=768% &
\ START.CPU.TIME%=TIME(1%) &
\ LISTING.FILE$="KB:"
1100 FOR I%=1% TO 97% &
\ READ SYMBOL$,VALUE%,FLAG.WORD% &
\ GOSUB 2310 &
\ NEXT I% &
! Read in opcodes
1110 FLAG.WORD%=0% &
\ FOR I%=1% TO 13% &
\ READ SYMBOL$,VALUE% &
\ GOSUB 2310 &
\ NEXT I% &
! Read in register definitions
1120 ! -- Print header --
1130 OPEN LISTING.FILE$ AS FILE 1% &
\ GOTO 1180 IF CCL.ENTRY% &
\ PRINT #1%,"8080/8085 Cross assembler" &
\ PRINT #1%,"#";
1140 ! &
1150 ! -- Get listing, source filenames --
1160 INPUT LINE #1%, SOURCE.FILE$ &
\ SOURCE.FILE$=CVT$$(SOURCE.FILE$,-1%)
1170 ! -- Check for errors only switch --
1180 ERRORS.ONLY.SWITCH%=-1% &
\ I%=INSTR(1%,SOURCE.FILE$,"/E") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ ERRORS.ONLY.SWITCH%=0%
1190 ! -- Check for symbol table listing switch --
1200 SYMBOL.TABLE.LIST.FLAG%=INSTR(1%,SOURCE.FILE$,"/S") &
\ IF SYMBOL.TABLE.LIST.FLAG% THEN SOURCE.FILE$= &
LEFT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%-1%)+ &
RIGHT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%+2%)
1210 ! -- Check for object module output switch --
1220 OBJECT.OUT.FLAG%=0% &
\ I%=INSTR(1%,SOURCE.FILE$,"/O") &
\ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ &
RIGHT(SOURCE.FILE$,I%+2%) &
\ OBJECT.OUT.FLAG%=-1%
1230 ! -- Check for listing file and add default extensions --
1240 LISTING.TO.FILE.FLAG%=INSTR(1%,SOURCE.FILE$,"=") &
\ IF LISTING.TO.FILE.FLAG% THEN LISTING.FILE$= &
LEFT(SOURCE.FILE$,LISTING.TO.FILE.FLAG%-1%) &
\ LISTING.FILE$=LISTING.FILE$+".LST" UNLESS &
INSTR(1%,LISTING.FILE$,".") &
\ SOURCE.FILE$=RIGHT(SOURCE.FILE$, &
LISTING.TO.FILE.FLAG%+1%)
1250 SOURCE.FILE$=SOURCE.FILE$+".SRC" UNLESS &
INSTR(1%,SOURCE.FILE$,".")
1260 PRINT #1%,"Listing sent to "+ &
LISTING.FILE$ IF LISTING.TO.FILE.FLAG%
1270 IF OBJECT.OUT.FLAG% THEN OBJECT.FILE$= &
LEFT(SOURCE.FILE$,INSTR(1%,SOURCE.FILE$,"."))+"HEX" &
\ PRINT #1%,"Object module to ";OBJECT.FILE$
1280 ! -- Get a unique workfile name --
1290 WORK.FILE$="X80X"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+ &
CHR$(9%)))/2%),3%,2%)+".TMP"
1300 ! -- Commence assembly --
1310 GOSUB 2010 &
\ GOSUB 3010 &
\ X%=1% &
\ GOSUB 3720
1320 ! -- Print symbol table --
1330 GOSUB 3750 IF SYMBOL.TABLE.LIST.FLAG% &
\ PRINT #1%
1340 ! -- Finish up and exit --
1350 CLOSE 1% &
\ IF LISTING.TO.FILE.FLAG% THEN X%=0% &
\ GOSUB 3720
1360 PRINT "Runtime was";(TIME(1%)-START.CPU.TIME%)/10;"sec" &
\ GOTO 32767
1370 !
2000 &
! -- Pass 1 Driver routine -- &
2010 ERROR.COUNT%, &
TOTAL.BYTES%, &
LOCATION.COUNTER%, &
ERROR.LINE.FLAG%, &
OPCODE.TABLE.SUBSCRIPT%=0% &
\ PASS.NUMBER%=1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR OUTPUT AS FILE 3% &
\ PRINT #1%,"Pass 1"
2020 INPUT LINE #2%,SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,421%) &
\ LINE.LENGTH%=LEN(SOURCE.LINE$) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
2030 IF LINE.LENGTH%=0% OR LEFT(SOURCE.LINE$,1%)="$" THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2040 ! -- Scan source line --
2050 GOSUB 2190 &
\ GOSUB 2240
2060 ! -- Comment line ? --
2070 IF COMMENT.DELIMITER%=1% THEN &
OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2150
2080 ! -- Get argument field --
2090 IF COMMENT.DELIMITER% THEN ARGUMENT$= &
CVT$$(MID(SOURCE.LINE$,OPCODE.DELIMITER%+1%, &
COMMENT.DELIMITER%-OPCODE.DELIMITER%-1%),258%) &
ELSE ARGUMENT$=CVT$$(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%+1%),258%)
2100 ! -- Label ? --
2110 IF LABEL.DELIMITER% THEN SYMBOL$= &
CVT$$(LEFT(SOURCE.LINE$,LABEL.DELIMITER%-1%),128%) &
\ VALUE%=LOCATION.COUNTER% &
\ FLAG.WORD%=-2% &
\ GOSUB 2310
2120 ! -- Assignment ? --
2130 IF EQU.DELIMITER% THEN GOSUB 2380 &
ELSE GOSUB 2420
2140 ! -- Write to workfile --
2150 GOSUB 2460 &
\ GOTO 2020 IF OPCODE.TABLE.SUBSCRIPT%=-1% &
\ GOTO 2020 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<>10%
2160 CLOSE 2%,3% &
\ RETURN &
! -- End of Pass 1
2170 ! &
2180 &
! -- Scan for strings in SOURCE.LINE$ -- &
2190 DELIMITER%=-1% &
\ TEMP2%=0%
2200 TEMP1%=INSTR(TEMP2%+1%,SOURCE.LINE$,"'") &
\ RETURN UNLESS TEMP1%
2210 TEMP2%=INSTR(TEMP1%+1%,SOURCE.LINE$,"'") &
\ IF TEMP2% THEN DELIMITER%=DELIMITER%+1% &
\ IF DELIMITER%<4% THEN DELIMITER.TABLE%(DELIMITER%)= &
SWAP%(TEMP1% AND 255%) OR (TEMP2% AND 255%) &
\ GOTO 2200
2220 RETURN
2230 &
! -- Search for token delimiters -- &
! LABEL.DELIMITER% Label &
! OPCODE.DELIMITER% Opcode &
! COMMENT.DELIMITER% Comment &
! EQU.DELIMITER% Assignment &
2240 LABEL.DELIMITER%=INSTR(1%,SOURCE.LINE$,":") &
\ LABEL.DELIMITER%=0% IF FNCHECK.SYNTAX%(LABEL.DELIMITER%) &
\ COMMENT.DELIMITER%=0%
2250 COMMENT.DELIMITER%=INSTR(COMMENT.DELIMITER%+1%,SOURCE.LINE$,";") &
\ GOTO 2250 IF FNCHECK.SYNTAX%(COMMENT.DELIMITER%) &
\ LABEL.DELIMITER%=0% IF (LABEL.DELIMITER%> &
COMMENT.DELIMITER% AND COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=LABEL.DELIMITER%
2260 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%>=LINE.LENGTH% THEN 2280 &
ELSE X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%=9% OR X%=32% THEN 2260
2270 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% &
\ IF OPCODE.DELIMITER%<LINE.LENGTH% THEN &
X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) &
\ IF X%<>9% AND X%<>32% THEN 2270 &
ELSE OPCODE.DELIMITER%=OPCODE.DELIMITER%-1%
2280 EQU.DELIMITER%=INSTR(1%,SOURCE.LINE$,"=") &
\ EQU.DELIMITER%=0% IF FNCHECK.SYNTAX%(EQU.DELIMITER%) OR &
(EQU.DELIMITER%>COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ OPCODE.DELIMITER%=EQU.DELIMITER% IF EQU.DELIMITER%
2290 OPCODE.DELIMITER%=COMMENT.DELIMITER%-1% IF &
(OPCODE.DELIMITER%>=COMMENT.DELIMITER% AND &
COMMENT.DELIMITER%<>0%) &
\ RETURN
2300 &
! Enter symbol SYMBOL$ into symbol table &
! and its value VALUE% &
2310 IF NUMBER.OF.SYMBOLS%=SYMBOL.TABLE.SIZE% THEN &
VALUE%=FNERROR.PRINT%("?X80 - FATAL: Symbol table overflow") &
\ STOP &
! Symbol table full
2320 X%=ASCII(SYMBOL$) &
\ IF X%<>46% AND ( X%<65% OR X%>90% ) THEN &
VALUE%=FNERROR.PRINT%("Invalid symbol = "+SYMBOL$) &
\ RETURN &
! Invalid symbol
2330 TEMP2%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) &
! Hash symbol
2340 IF SYMBOLS$(TEMP2%)="" THEN SYMBOLS$(TEMP2%)=SYMBOL$ &
\ VALUES%(TEMP2%)=VALUE% &
\ FLAGS%(TEMP2%)=FLAG.WORD% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%+1% &
\ RETURN &
! If slot empty, enter symbol, value and flagword
2350 IF SYMBOLS$(TEMP2%)=SYMBOL$ AND FLAGS%(TEMP2%)<0% THEN &
VALUE%=FNERROR.PRINT%("Redefined symbol = "+SYMBOL$) &
\ RETURN &
! Multiple definition not allowed
2360 TEMP2%=FNREHASH.SYMBOL%(TEMP2%,SYMBOL.TABLE.SIZE%) &
\ GOTO 2340
2370 &
! -- Enter assignment -- &
2380 SYMBOL$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
EQU.DELIMITER%-LABEL.DELIMITER%-1%),136%) &
\ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$)
2390 IF SYMBOL$="." THEN LOCATION.COUNTER%=VALUE% &
ELSE IF SYMBOL$="" THEN VALUE%= &
FNERROR.PRINT%("Missing symbol") &
ELSE FLAG.WORD%=-1% &
\ GOSUB 2310
2400 OPCODE.TABLE.SUBSCRIPT%=-1% &
\ RETURN
2410 &
! -- Get opcode subscript -- &
2420 OPCODE$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, &
OPCODE.DELIMITER%-LABEL.DELIMITER%),8%) &
\ IF OPCODE$<>"" THEN OPCODE.TABLE.SUBSCRIPT%= &
FNHASH.SYMBOL%(OPCODE$,SYMBOL.TABLE.SIZE%) &
ELSE OPCODE.TABLE.SUBSCRIPT%=-1% \ RETURN
2430 IF SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)=OPCODE$ THEN RETURN &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<0% OR &
SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)="" THEN &
OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Invalid opcode = "+OPCODE$)-1% &
ELSE OPCODE.TABLE.SUBSCRIPT%= &
FNREHASH.SYMBOL%(OPCODE.TABLE.SUBSCRIPT%, &
SYMBOL.TABLE.SIZE%) &
\ GOTO 2430 &
! Check for opcode match in the symbol table &
! If flagword < 0 then report an error else rehash
2440 RETURN
2450 &
! -- Get byte count and output to workfile -- &
2460 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN BYTE.COUNT%=0% &
ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN &
GOSUB 2500 &
ELSE BYTE.COUNT%=FLAGS%(OPCODE.TABLE.SUBSCRIPT%) &
! Get byte count into BYTE.COUNT%
2470 PRINT #3%,LOCATION.COUNTER%;","; &
BYTE.COUNT%;","; &
OPCODE.TABLE.SUBSCRIPT%;","; &
ERROR.LINE.FLAG% &
\ PRINT #3%,ARGUMENT$ &
\ TOTAL.BYTES%=TOTAL.BYTES%+BYTE.COUNT% &
\ LOCATION.COUNTER%=LOCATION.COUNTER%+BYTE.COUNT% &
\ ERROR.LINE.FLAG%=0% &
\ RETURN
2480 ! &
2490 &
! -- Get byte count for pseudo-op -- &
2500 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% &
GOTO 2590, 2520, 2520, 2520, &
2540, 2540, 2540, 2590, &
2570 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .LIST &
! .BLKB
2510 ! -- .BYTE, .DBYTE, .WORD --
2520 TEMP1%=0% &
\ TEMP2%=-1% &
\ FOR BYTE.COUNT%=0% WHILE TEMP2% &
\ TEMP1%,TEMP2%=INSTR(TEMP1%+1%,ARGUMENT$,",") &
\ NEXT BYTE.COUNT% &
\ BYTE.COUNT%=BYTE.COUNT%*2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% &
\ RETURN
2530 ! -- .ASCII, .ASCIP, .ASCIZ --
2540 TEMP1%=INSTR(2%,ARGUMENT$,LEFT(ARGUMENT$,1%)) &
\ IF TEMP1%=0% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing delimiter")-1% &
ELSE BYTE.COUNT%=TEMP1%-2%
2550 BYTE.COUNT%=BYTE.COUNT%+1% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% &
\ RETURN
2560 ! -- .BLKB
2570 BYTE.COUNT%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ RETURN
2580 ! -- .LIST, END --
2590 BYTE.COUNT%=0% &
\ RETURN
2600 ! &
3000 &
! -- Pass 2 Driver routine -- &
3010 LINE.NUMBER%, &
CHECKSUM%, &
NEW.LINE.FLAG%=0% &
\ PASS.NUMBER%=2% &
\ LIST.FLAG%=-1% &
\ PRINT #1%,"Pass 2" &
\ CLOSE 1% &
\ OPEN LISTING.FILE$ FOR OUTPUT AS FILE 1% &
\ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% &
\ OPEN WORK.FILE$ FOR INPUT AS FILE 3% &
\ KILL WORK.FILE$
3020 IF OBJECT.OUT.FLAG% THEN &
OPEN OBJECT.FILE$ FOR OUTPUT AS FILE 4% &
\ NEW.OBJ.LINE%=0%
3030 IF ERRORS.ONLY.SWITCH% THEN PRINT #1%," Line Addr B1 B2 B3" &
\ PRINT #1%
3040 INPUT #3%,LOCATION.COUNTER%, &
BYTE.COUNT%, &
OPCODE.TABLE.SUBSCRIPT%, &
ERROR.LINE.FLAG% &
\ INPUT LINE #3%, ARGUMENT$ &
\ ARGUMENT$=CVT$$(ARGUMENT$,4%) &
\ INPUT LINE #2%, SOURCE.LINE$ &
\ SOURCE.LINE$=CVT$$(SOURCE.LINE$,4%) &
\ LINE.NUMBER%=LINE.NUMBER%+1%
3050 ! -- Form object code and output to listing file --
3060 IF LEFT(SOURCE.LINE$,1%)="$" THEN &
SOURCE.LINE$=RIGHT(SOURCE.LINE$,2%)
3070 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN GOSUB 3630 &
\ GOTO 3040
3080 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=10% THEN &
GOSUB 3130 &
\ RETURN
3090 ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%,0%) &
\ VALUE%=VALUES%(OPCODE.TABLE.SUBSCRIPT%) &
\ FLAG.WORD%=SWAP%(VALUE%) AND 255% &
\ VALUE%=VALUE% AND 255%
3100 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN GOSUB 3370 &
ELSE IF FLAG.WORD% THEN GOSUB 3170 &
ELSE GOSUB 3540 &
\ GOSUB 3630
3110 GOTO 3040
3120 &
! -- End of assembly, tidy up -- &
3130 GOSUB 3630 &
\ PRINT #4% IF OBJECT.OUT.FLAG%
3140 CLOSE 2%,3%,4% &
\ RETURN
3150 ! &
3160 &
! -- Process operands -- &
3170 FIRST.ARG.TYPE%=FLAG.WORD% AND 7% &
\ SECOND.ARG.TYPE%=(FLAG.WORD% AND 56%)/8% &
\ SHIFT.ARG.FLAG%=(FLAG.WORD% AND 192%)/64% &
\ SHIFT.ARG.FLAG%=4% IF SHIFT.ARG.FLAG%=2%
3180 ! -- If two operands evaluate the second into ARG2.VALUE%
3190 IF SECOND.ARG.TYPE%=0% THEN ARG2.VALUE%=0% &
ELSE TEMP2%=INSTR(1%,ARGUMENT$,",") &
\ IF TEMP2%=0% THEN ARG2.VALUE%= &
FNERROR.PRINT%("Missing operand") &
ELSE ARG2.VALUE%=FNEVALUATE.ARGUMENT%( &
RIGHT(ARGUMENT$,TEMP2%+1%),SECOND.ARG.TYPE%) &
\ ARGUMENT$=LEFT(ARGUMENT$,TEMP2%-1%)
3200 ! -- Evaluate the first (only) operand
3210 ARG1.VALUE%=FNEVALUATE.ARGUMENT%(ARGUMENT$,FIRST.ARG.TYPE%)
3220 ! -- If register , do appropriate shift and OR into opcode base
3230 IF FIRST.ARG.TYPE%<4% OR FIRST.ARG.TYPE%=7% THEN &
ARG1.VALUE%=ARG1.VALUE%*(2%^SHIFT.ARG.FLAG%) &
\ VALUE%=VALUE% OR ARG1.VALUE%
3240 IF SECOND.ARG.TYPE%<4% THEN VALUE%=VALUE% OR ARG2.VALUE% &
! -- Assemble the bytes for this instruction
3250 GOSUB 3540
3260 IF SHIFT.ARG.FLAG%=1% THEN GOSUB 3330 &
\ GOSUB 3560 &
\ GOSUB 3630 &
\ RETURN
3270 IF SECOND.ARG.TYPE%=4% THEN FIRST.ARG.TYPE%=4% &
\ ARG1.VALUE%=ARG2.VALUE%
3280 IF FIRST.ARG.TYPE%=4% THEN VALUE%=ARG1.VALUE% &
\ GOSUB 3560 &
\ GOSUB 3630 &
\ RETURN
3290 IF SECOND.ARG.TYPE%=5% THEN FIRST.ARG.TYPE%=6% &
\ ARG1.VALUE%=ARG2.VALUE%
3300 IF FIRST.ARG.TYPE%=6% THEN VALUE%=ARG1.VALUE% &
\ GOSUB 3560 &
\ VALUE%=SWAP%(ARG1.VALUE%) &
\ GOSUB 3580
3310 GOSUB 3630 &
\ RETURN
3320 ! -- Z80 relative branches
3330 VALUE%=ARG1.VALUE%-LOCATION.COUNTER%-2% &
\ IF VALUE%<-128% OR VALUE%>127% THEN &
VALUE%=FNERROR.PRINT%("Invalid displacement ="+NUM$(VALUE%))
3340 RETURN
3350 ! &
3360 &
! -- Pseudo-ops. -- &
3370 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% &
GOTO 3490, 3390, 3390, 3390, &
3450, 3450, 3450, 3490, &
3510 &
! .END .BYTE .DBYTE .WORD &
! .ASCII .ASCIP .ASCIZ .LIST &
! .BLKB
3380 ! -- .BYTE, .DBYTE, .WORD --
3390 ARGUMENT$=ARGUMENT$+"," &
\ TEMP3%=1% &
\ TEMP3%=2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% &
OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% &
\ FOR I%=1% TO BYTE.COUNT% STEP TEMP3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ TEMP1%=INSTR(1%,ARGUMENT$,",")
3400 TEMP2%=FNEVALUATE.EXPR%(LEFT(ARGUMENT$,TEMP1%-1%)) &
\ IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% THEN &
VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3540 &
\ VALUE%=TEMP2% &
\ GOSUB 3560
3410 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% THEN &
VALUE%=TEMP2% &
\ GOSUB 3540 &
\ VALUE%=SWAP%(TEMP2%) &
\ GOSUB 3560
3420 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=11% THEN &
VALUE%=TEMP2% &
\ GOSUB 3540
3430 GOSUB 3630 &
\ ARGUMENT$=RIGHT(ARGUMENT$,TEMP1%+1%) &
\ NEXT I% &
\ RETURN
3440 ! -- .ASCII, .ASCIP, .ASCIZ --
3450 ARGUMENT$=MID(ARGUMENT$,2%,BYTE.COUNT%) &
\ ARGUMENT$=LEFT(ARGUMENT$,BYTE.COUNT%-1%)+CHR$(0%) &
IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% &
\ FOR I%=1% TO BYTE.COUNT% STEP 3% &
\ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) &
\ VALUE%=FNCHAR%(I%) &
\ GOSUB 3540 &
\ VALUE%=FNCHAR%(I%+1%) &
\ GOSUB 3560 IF I%+1%<=BYTE.COUNT% &
\ VALUE%=FNCHAR%(I%+2%) &
\ GOSUB 3580 IF I%+2%<=BYTE.COUNT% &
\ GOSUB 3630 &
\ NEXT I% &
\ RETURN
3460 ! -- Get character J% from ARGUMENT$
3470 DEF* FNCHAR%(J%) &
\ CHAR%=ASCII(MID(ARGUMENT$,J%,1%)) &
\ CHAR%=CHAR% OR 128% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=15% &
AND J%=BYTE.COUNT% &
\ FNCHAR%=CHAR% &
\ FNEND &
3480 ! -- .LIST --
3490 LIST.FLAG%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ ADDRESS$="" &
\ RETURN
3500 ! -- .BLKB
3510 TEMP1%=FNEVALUATE.EXPR%(ARGUMENT$) &
\ IF OBJECT.OUT.FLAG% THEN VALUE%=0% &
\ FOR X%=1% TO TEMP1% &
\ GOSUB 3610 &
\ NEXT X%
3520 GOSUB 3630 &
\ RETURN
3530 &
! -- Form B1 -- &
3540 BYTE1$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3550 &
! -- Form B2 -- &
3560 BYTE2$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3570 &
! -- Form B3 -- &
3580 BYTE3$=FNDEC.TO.HEX$(VALUE%,3%) &
\ GOSUB 3610 &
\ RETURN
3590 ! &
3600 &
! -- Output object and update checksum -- &
3610 OBJECT.BYTE%=VALUE% AND 255% &
\ OBJECT.BYTE%=FNOBJECT.OUTPUT%(VALUE%) IF OBJECT.OUT.FLAG% &
\ CHECKSUM%=CHECKSUM%+OBJECT.BYTE% &
\ RETURN
3620 &
! -- Output assembled code to listing file -- &
3630 GOTO 3680 UNLESS ERRORS.ONLY.SWITCH% OR ERROR.LINE.FLAG%
3640 IF ERROR.LINE.FLAG% THEN PRINT #1%,"?"; ELSE PRINT #1%," ";
3650 IF NEW.LINE.FLAG%<LINE.NUMBER% THEN &
PRINT #1% USING "#### ",LINE.NUMBER%; &
ELSE PRINT #1%," ";
3660 PRINT #1% USING"\ \ \\ \\ \\",ADDRESS$,BYTE1$,BYTE2$,BYTE3$; &
\ IF LIST.FLAG% AND SOURCE.LINE$<>"" THEN &
PRINT #1%,CHR$(9%);SOURCE.LINE$ &
ELSE PRINT #1%
3670 ! -- Set a flag, clear output strings --
3680 NEW.LINE.FLAG%=LINE.NUMBER% &
\ ADDRESS$,BYTE1$,BYTE2$,BYTE3$,SOURCE.LINE$="" &
\ RETURN
3690 &
! -- Output binary byte to object file -- &
3700 DEF* FNOBJECT.OUTPUT%(X%) &
\ OBJECT.BYTE%=X% AND 255% &
\ PRINT #4%,FNDEC.TO.HEX$(OBJECT.BYTE%,3%); &
\ NEW.OBJ.LINE%=NEW.OBJ.LINE%+1% &
\ PRINT #4% IF (NEW.OBJ.LINE% AND 15%)=0% &
\ FNOBJECT.OUTPUT%=OBJECT.BYTE% &
\ FNEND
3710 &
! -- Print error count, checksum -- &
3720 PRINT #X% &
\ PRINT #X%,"Errors detected ";FNDEC.TO.HEX$(ERROR.COUNT%,0%) &
\ PRINT #X%,"Source checksum ";FNDEC.TO.HEX$(CHECKSUM%,0%) &
\ PRINT #X%,"Total hex bytes ";FNDEC.TO.HEX$(TOTAL.BYTES%,0%) &
\ PRINT #X% &
\ RETURN
3730 ! &
3740 &
! -- Print sorted symbol table -- &
3750 TEMP1%,TEMP2%=0% &
\ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%-111% &
\ RETURN IF NUMBER.OF.SYMBOLS%<0%
3760 PRINT #1%," Symbol Table" &
\ PRINT #1%
3770 TEMP1%=TEMP1%+1% WHILE FLAGS%(TEMP1%)>=0% &
\ SYMBOLS$(TEMP2%)=SYMBOLS$(TEMP1%) &
\ VALUES%(TEMP2%)=VALUES%(TEMP1%) &
\ FLAGS%(TEMP2%)=FLAGS%(TEMP1%) &
\ TEMP2%=TEMP2%+1% &
\ TEMP1%=TEMP1%+1% &
\ GOTO 3770 UNLESS TEMP2%=NUMBER.OF.SYMBOLS%+1%
3780 ! -- Quick sort the symbol table
3790 TEMP1%=FNQUICKSORT%(0%,NUMBER.OF.SYMBOLS%,0%,NUMBER.OF.SYMBOLS%)
3800 ! -- Output to listing file --
3810 FOR I%=0% TO NUMBER.OF.SYMBOLS% &
\ IF FLAGS%(I%)=-1% THEN S$="#" ELSE S$=" "
3820 PRINT #1% USING " \ \ \ \ ", &
SYMBOLS$(I%),FNDEC.TO.HEX$(VALUES%(I%),0%)+S$; &
\ PRINT #1% IF CCPOS(1%)>63% &
\ NEXT I%
3830 PRINT #1% IF CCPOS(1%) &
\ RETURN
3840 &
! -- Check position of char X% in SOURCE.LINE$ using tables &
! -- DELIMITER%(). FNCHECK.SYNTAX%=-1% means in string &
3850 DEF* FNCHECK.SYNTAX%(X%)
3860 GOTO 3880 IF DELIMITER%=-1% OR X%=0% &
\ FOR X0%=0% TO DELIMITER% &
\ GOTO 3880 IF X%<(SWAP%(DELIMITER.TABLE%(X0%)) AND 255%) &
\ IF X%<(DELIMITER.TABLE%(X0%) AND 255%) THEN &
FNCHECK.SYNTAX%=-1% &
\ GOTO 3890
3870 NEXT X0%
3880 FNCHECK.SYNTAX%=0%
3890 FNEND
3900 ! &
4000 &
! -- Evaluate the argument expression -- &
4010 DEF* FNEVALUATE.EXPR%(X$)
4020 &
! -- Main driver routine -- &
4030 EXPR$=X$ &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ EXP.VAL%=TERM%
4040 GOTO 4290 UNLESS OP% &
\ LAST.OP%=OP% &
\ GOSUB 4060 &
\ GOSUB 4080 &
\ GOSUB 4190 &
\ GOTO 4040
4050 &
REM ! -- Scan for the next operator { ! & % + * - / } -- &
4060 EXP.FLAG%=-1% &
\ FOR TOK.PTR%=1% TO LEN(EXPR$) &
\ TOK.CHR$=MID(EXPR$,TOK.PTR%,1%) &
\ EXP.FLAG%= NOT EXP.FLAG% IF TOK.CHR$="'" &
\ OP%=INSTR(1%,"!%&*+-/",TOK.CHR$) &
\ RETURN IF OP% AND EXP.FLAG% &
\ NEXT TOK.PTR% &
\ OP%=0% &
\ TOK.PTR%=TOK.PTR%+1% &
\ RETURN
4070 &
! -- Get value of term -- &
4080 TERM$=LEFT(EXPR$,TOK.PTR%-1%) &
\ EXPR$=RIGHT(EXPR$,TOK.PTR%+1%)
4090 IF TERM$="" THEN TERM%=0% &
\ RETURN
4100 ! -- H() or L() ? --
4110 TEMP1$=LEFT(TERM$,2%) &
\ IF TEMP1$="H(" THEN EXP.FLAG%=1% &
ELSE IF TEMP1$="L(" THEN EXP.FLAG%=2% &
ELSE EXP.FLAG%=0%
4120 IF EXP.FLAG% THEN IF RIGHT(TERM$,LEN(TERM$))=")" THEN &
TERM$=MID(TERM$,3%,LEN(TERM$)-3%) &
ELSE 4170
4130 TEMP1$=LEFT(TERM$,1%)
4140 IF TEMP1$>="A" AND TEMP1$<="Z" THEN TERM%=FNSYMBOL.LOOKUP%(TERM$) &
ELSE IF TEMP1$="0" THEN TERM%=FNHEX.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$>="1" AND TEMP1$<="9" THEN TERM%=VAL(TERM$) &
ELSE IF TEMP1$="'" THEN TERM%=ASCII(RIGHT(TERM$,2%)) &
ELSE IF TEMP1$="^" THEN TERM%=FNOCT.TO.DEC%(RIGHT(TERM$,2%)) &
ELSE IF TERM$="." THEN TERM%=LOCATION.COUNTER% &
ELSE 4170
4150 IF EXP.FLAG%=1% THEN TERM%=SWAP%(TERM%) AND 255% &
ELSE IF EXP.FLAG%=2% THEN TERM%=TERM% AND 255%
4160 RETURN
4170 TERM%=FNERROR.PRINT%("Invalid term = "+TERM$) &
\ RETURN
4180 &
! -- Carry out the arithmetic or logical operation -- &
4190 ON LAST.OP%+1% &
GOTO 4270, 4200, 4210, 4220, &
4230, 4240, 4250, 4260 &
! or not and &
! mult add sub div
4200 EXP.VAL%=EXP.VAL% OR TERM% &
\ RETURN &
! or
4210 EXP.VAL%=EXP.VAL%+(NOT TERM%) &
\ RETURN &
! not
4220 EXP.VAL%=EXP.VAL% AND TERM% &
\ RETURN &
! and
4230 EXP.VAL%=EXP.VAL%*TERM% &
\ RETURN &
! multiply
4240 EXP.VAL%=EXP.VAL%+TERM% &
\ RETURN &
! add
4250 EXP.VAL%=EXP.VAL%-TERM% &
\ RETURN &
! subtract
4260 IF TERM%=0% THEN EXP.VAL%=FNERROR.PRINT%("Division by zero") &
ELSE EXP.VAL%=EXP.VAL%/TERM%
4270 RETURN
4280 &
! -- Exit with value of expression -- &
4290 FNEVALUATE.EXPR%=EXP.VAL%
4300 FNEND
4310 &
! -- Find value of argument of the type TYPE% &
4320 DEF* FNEVALUATE.ARGUMENT%(X$,TYPE%) &
\ EXP.VAL%=FNEVALUATE.EXPR%(X$)
4330 IF TYPE%=1% AND (EXP.VAL%<0% OR EXP.VAL%>7%) THEN &
EXP.VAL%=FNERROR.PRINT%("Invalid register id") &
ELSE IF (TYPE%=2% AND EXP.VAL% AND 4%) OR &
(TYPE%=3% AND EXP.VAL%>1%) THEN &
EXP.VAL%=FNERROR.PRINT%("Invalid register pair") &
ELSE IF TYPE%=7% AND (EXP.VAL%<0% OR EXP.VAL%>7%) &
THEN EXP.VAL%=FNERROR.PRINT%("Invalid RST vector")
4340 FNEVALUATE.ARGUMENT%=EXP.VAL% &
\ FNEND
4350 ! &
4360 &
! -- Print the given error message to the listing file &
4370 DEF* FNERROR.PRINT%(X$) &
\ PRINT #1%,"********";X$; &
\ IF PASS.NUMBER%=1% THEN PRINT #1%," at line";LINE.NUMBER% &
ELSE PRINT #1%
4380 ERROR.COUNT%=ERROR.COUNT%+1% &
\ ERROR.LINE.FLAG%=-1% &
\ FNERROR.PRINT%=0% &
\ FNEND
4390 &
! -- Look up value of symbol -- &
4400 DEF* FNSYMBOL.LOOKUP%(SYMBOL$) &
\ X%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%)
4410 IF SYMBOLS$(X%)=SYMBOL$ AND FLAGS%(X%)<=0% THEN &
FNSYMBOL.LOOKUP%=VALUES%(X%) &
ELSE IF SYMBOLS$(X%)="" THEN FNSYMBOL.LOOKUP%= &
FNERROR.PRINT%("Undefined symbol = "+SYMBOL$) &
ELSE X%=FNREHASH.SYMBOL%(X%,SYMBOL.TABLE.SIZE%) &
\ GOTO 4410
4420 FNEND
4430 &
! -- Dec to Hex conversion -- &
4440 DEF* FNDEC.TO.HEX$(X%,D%)
4450 X$="" &
\ FOR X1%=0% TO 3% &
\ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) &
\ X0%=X0%+16% IF X0%<0% &
\ X$=CHR$(48%+X0%)+X$ IF X0%<10% &
\ X$=CHR$(55%+X0%)+X$ IF X0%>9% &
\ NEXT X1% &
\ IF D% THEN X$=MID(X$,D%,2%)
4460 FNDEC.TO.HEX$=X$
4470 FNEND
4480 &
! -- Hex to Dec conversion -- &
4490 DEF* FNHEX.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%)) &
\ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN &
FNHEX.TO.DEC%=FNERROR.PRINT%("Invalid HEX constant = "+X$) &
\ GOTO 4510
4500 X2%=X2%-48% &
\ X2%=X2%-7% IF X2%>9% &
\ X0%=X2%+X0%*16% &
\ NEXT X1% &
\ FNHEX.TO.DEC%=X0%
4510 FNEND
4520 &
! -- Octal to Dec conversion -- &
4530 DEF* FNOCT.TO.DEC%(X$) &
\ X0%=0% &
\ FOR X1%=1% TO LEN(X$) &
\ X2%=ASCII(MID(X$,X1%,1%))-48% &
\ IF X2%<0% OR X2%>7% THEN &
FNOCT.TO.DEC%=FNERROR.PRINT%("Invalid OCTAL constant = "+X$) &
\ GOTO 4550
4540 X0%=X0%*8% + X2% &
\ NEXT X1% &
\ FNOCT.TO.DEC%=X0%
4550 FNEND
4560 &
! -- Calculate X1% modulo X2% -- &
4570 DEF* FNMOD%(X1%,X2%) &
\ X1%=X1%-(X1%/X2%)*X2% &
\ X1%=X1%+X2% IF X1%<0% &
\ FNMOD%=X1% &
\ FNEND
4580 &
! -- Hash symbol X$, modulo SYMBOL.TABLE.SIZE% -- &
4590 DEF* FNHASH.SYMBOL%(SYMBOL$,M%) &
\ SYMBOL$=LEFT(SYMBOL$+" ",6%) &
\ CHANGE SYMBOL$ TO SYMBOL.CHARS% &
\ SYMBOL.CHARS%(X%)=SYMBOL.CHARS%(X%)-48% FOR X%=1% TO 6% &
\ FNHASH.SYMBOL%=FNMOD%(SYMBOL.CHARS%(1%)*23%+ &
SYMBOL.CHARS%(2%)*19%+SYMBOL.CHARS%(3%)*17%+ &
SYMBOL.CHARS%(4%)*13%+SYMBOL.CHARS%(5%)*11%+ &
SYMBOL.CHARS%(6%)*7%,M%) &
\ FNEND
4600 &
! -- Rehash function, modulo X2% &
4610 DEF* FNREHASH.SYMBOL%(X1%,X2%)=FNMOD%(X1%+23%,X2%)
4620 &
! -- Quick sort symbol table &
4630 DEF* FNQUICKSORT%(LOW%,HIGH%,I%,J%) &
\ I%=LOW% &
\ J%=HIGH% &
\ X$=SYMBOLS$((HIGH%+LOW%)/2%)
4640 I%=I%+1% WHILE SYMBOLS$(I%)<X$
4650 J%=J%-1% WHILE X$<SYMBOLS$(J%)
4660 IF I%>J% THEN 4680 &
ELSE IF I%<>J% THEN VALUE%=VALUES%(I%) &
\ FLAG.WORD%=FLAGS%(I%) &
\ SYMBOL$=SYMBOLS$(I%) &
\ VALUES%(I%)=VALUES%(J%) &
\ FLAGS%(I%)=FLAGS%(J%) &
\ SYMBOLS$(I%)=SYMBOLS$(J%) &
\ VALUES%(J%)=VALUE% &
\ FLAGS%(J%)=FLAG.WORD% &
\ SYMBOLS$(J%)=SYMBOL$
4670 I%=I%+1% &
\ J%=J%-1% &
\ IF I%<=J% THEN 4640
4680 IF LOW%<J% THEN TEMP1%=FNQUICKSORT%(LOW%,J%,LOW%,J%)
4690 IF I%<HIGH% THEN TEMP1%=FNQUICKSORT%(I%,HIGH%,I%,HIGH%)
4700 FNQUICKSORT%=-1% &
\ FNEND
4710 ! &
30000 &
! CCL Entry point &
30010 SOURCE.FILE$=CVT$$(SYS(CHR$(7%)),188%) &
\ I%=INSTR(1%,SOURCE.FILE$,"X80") &
\ IF I% THEN SOURCE.FILE$=RIGHT(SOURCE.FILE$,4%) &
ELSE PRINT "?X80 - Illegal entry" &
\ GOTO 32767
30020 IF SOURCE.FILE$<>"" THEN CCL.ENTRY%=-1% ELSE CCL.ENTRY%=0%
30030 GOTO 1070
30999 ! &
31000 &
! -- Error routine -- &
31010 ! -- No ".END" --
31020 IF ERR=11% AND ERL=2020% THEN OPCODE.TABLE.SUBSCRIPT%= &
FNERROR.PRINT%("Missing .END")+ &
FNHASH.SYMBOL%(".END",SYMBOL.TABLE.SIZE%) &
\ SOURCE.LINE$="" &
\ RESUME 2150
31030 IF ERR=11% AND ERL=3040% THEN SOURCE.LINE$="" &
\ OPCODE.TABLE.SUBSCRIPT%=FNHASH.SYMBOL%(".END", &
SYMBOL.TABLE.SIZE%) &
\ RESUME 3080
31040 ! -- ^Z at filename request --
31050 RESUME 32767 IF ERL=1160%
31060 ! -- Illegal number in FNEVALUATE.EXPR%() --
31070 IF ERR=51% AND ERL=4140% THEN X0%=VAL(TERM$)-65536 &
\ RESUME 4150
31080 RESUME 4170 IF ERR=52% AND ERL=4140%
31090 CLOSE 1%,2%,3%,4% &
\ RESUME 32767% IF ERR=28%
31100 ! -- Print any unanticipated error --
31110 ON ERROR GOTO 0
31999 ! &
32000 &
! -- Opcode data &
32010 ! Table is of the form: &
! SYMBOL,value,byte count &
! where: the low byte of value is the opcode base &
! and the high byte a flag consisting of &
! bits 15,14 a shift flag 0=none,2=four,3=three &
! bits 13-11,10-8 are arg2, arg1 types &
! 0-none, 1-register, 2-register pair, &
! 3-limited register pair, 4-data byte, &
! 5-data word, 6-address and 7-for RST
32020 DATA .END, 0, 10, .BYTE, 0, 11, &
.DBYTE, 0, 12, .WORD, 0, 13, &
.ASCII, 0, 14, .ASCIP, 0, 15, &
.ASCIZ, 0, 16, .LIST, 0, 17, &
.BLKB, 0, 18
32030 DATA CALL, 1741, 3, CC, 1756, 3, &
CM, 1788, 3, CNC, 1748, 3, &
CNZ, 1732, 3, CP, 1780, 3, &
CPE, 1772, 3, CPO, 1764, 3, &
CZ, 1740, 3
32040 DATA JC, 1754, 3, JM, 1786, 3, &
JMP, 1731, 3, JNC, 1746, 3, &
JNZ, 1730, 3, JP, 1778, 3, &
JPE, 1770, 3, JPO, 1762, 3, &
JZ, 1738, 3
32050 DATA LDA, 1594, 3, LHLD, 1578, 3, &
SHLD, 1570, 3, STA, 1586, 3, &
LXI, -22015, 3
32060 DATA ACI, 1230, 2, ADI, 1222, 2, &
ANI, 1254, 2, CPI, 1278, 2, &
ORI, 1270, 2, SBI, 1246, 2, &
SUI, 1238, 2, XRI, 1262, 2, &
IN, 1243, 2, OUT, 1235, 2, &
MVI, -7930, 2
32070 DATA DJNZ, 17936, 2, JR, 17944, 2, &
JRNZ, 17952, 2, JRZ, 17960, 2, &
JRNC, 17968, 2, JRC, 17976, 2
32080 DATA ADC, 392, 1, ADD, 384, 1, &
ANA, 416, 1, CMP, 440, 1, &
ORA, 432, 1, SBB, 408, 1, &
SUB, 400, 1, XRA, 424, 1, &
DAD, -32247, 1, DCX, -32245, 1, &
INX, -32253, 1, POP, -32063, 1, &
PUSH, -32059, 1
32090 DATA DCR, -16123, 1, INR, -16124, 1, &
LDAX, -31990, 1, STAX, -31998, 1, &
MOV, -14016, 1, RST, -14393, 1
32100 DATA CMA, 47, 1, CMC, 63, 1, &
DAA, 39, 1, EI, 251, 1, &
HLT, 118, 1, NOP, 0, 1, &
DI, 243, 1, PCHL, 233, 1, &
RAL, 23, 1, RAR, 31, 1, &
RC, 216, 1, RET, 201, 1, &
RLC, 7, 1, RM, 248, 1, &
RNC, 208, 1, RNZ, 192, 1, &
RP, 240, 1, RPE, 232, 1, &
RPO, 224, 1, RRC, 15, 1, &
RZ, 200, 1, SPHL, 249, 1, &
STC, 55, 1, XCHG, 235, 1, &
XTHL, 227, 1
32110 DATA RIM, 32, 1, SIM, 48, 1, &
EXX, 217, 1, EXAF, 8, 1
32120 !--Register symbol definitions
32130 DATA B, 0, C, 1, D, 2, &
E, 3, H, 4, L, 5, &
M, 6, A, 7, BC, 0, &
DE, 1, HL, 2, SP, 3, &
PSW, 3
32767 END

221
micros/X80.HLP Normal file
View File

@ -0,0 +1,221 @@
Cross Assembler for 8080/8085 A.G. Nicholson
----------------------------------------------
To enable users of 8080 based systems to quickly develop
their application programs - by eliminating the tedious task of
hand assembling, I have written a cross assembler for the use of
interested persons.
The cross assembler is written in DEC's Basic-plus(I) and is
available for use on a PDP-11 series processor using the RSTS/E
( V06B onwards ) operating system.
The following describes some of its features and gives the
operating procedure using RSTS/E.
* General features :-
Input to the assembler consists of lines of mnemonics which
have the general form :-
label: opcode argument(s) ; comments
Each of these lines is formed according to the following
syntax rules :-
1) The label (if any) consists of up to six alphanumeric
characters, the first of which must be alphabetic,
followed by a colon ":". (eg: "LOOP:")
2) The opcode (instruction or assembler mnemonic) must
be followed by at least one space or tab character if
an argument is to be present. Standard mnemonics are
used.
3) The argument (if required) consists of a valid
expression, the form of which is determined by the
opcode. For 8080/8085 instructions, these are :-
a/ Input/Output instructions
(IN,OUT)
dev
(eg: "IN 0FB" )
b/ Primary memory reference
(LDAX,STAX)
rp
(LDA,STA,LHLD,SHLD)
addr
(eg: "LHLD COUNT")
c/ Immediate
(LXI rp,data16
MVI reg,data )
(eg: "LXI HL,0" )
d/ Jumps
(JMP,JC,JNC,JZ,JNZ,JP,JM,JPE,JPO)
addr
( eg: "JMP LOOP" )
(PCHL)
e/ Calls and returns
(CALL,CC,CNC,CZ,CNZ,CP,CM,CPE,CPO)
addr
(eg: "CNC SUBR" )
(RET,RC,RNC,RZ,RNZ,RP,RM,RPE,RPO)
f/ Immediate operate
(ADI,ACI,SUI,SBI,ANI,XRI,ORI,CPI)
data
( eg: "CPI 1" )
g/ Move
( MOV reg,reg )
( eg: "MOV B,A" )
h/ Accumulator
(ADD,ADC,SUB,SBB,ANA,XRA,ORA,CMP)
reg
( eg: "ADD M" )
(DAD rp)
( eg: "DAD HL" )
i/ Register operate
(INR,DCR)
reg
( eg: "DCR B" )
(INX,DCX)
rp
( eg: "DCX DE" )
(CMA,DAA,RLC,RRC,RAL,RAR)
j/ Stack
(PUSH,POP)
rp
( eg: "PUSH BC" )
k/ Interrupt
( RST n )
( eg: "RST 7" )
(EI,DI)
and l/ Miscellaneous
Also included are the Z80 relative branches and exchange
instructions.
(JR,JRNZ,JRZ,JRNC,JRC)
( eg: "JRNZ LOOP6" )
(EXX,EXAF)
Where :-
data,addr,data16 are arithmetic or logical expressions
consisting of numeric constants and / or
the operators :-
! logical OR
% logical NOT
& logical AND
* multiplication
+ addition
- subtraction
/ integer division
H( ) high order byte
L( ) low order byte
Expressions are evaluated from left to
right, and may not contain parentheses.
reg is one of the 8 bit registers (A,B,C,D,E,H,L,M)
rp is one of the register pairs (BC,DE,HL,SP,PSW)
n is a restart vector ( 0 to 7 )
Some argument examples are :-
03E the hexadecimal constant "3E"
^377 the octal constant "377"
'D' the ascii value of "D"
-120 the decimal integer constant
"-120". (the range allowed is
-32768 to +32767)
L(ADDR)-1 the low order byte of the symbol
"ADDR", minus 1.
The currently available assembler directives are :-
i) .BYTE or assigns the byte or double byte
.DBYTE or expressions given in the argu-
.WORD ment to current sequential addr-
esses. '.WORD' allocates two bytes
in 8080 address format, low byte
followed by the high byte.
(eg: ".BYTE 0F,LABEL,'A'")
ii) = assigns to the symbol on its
left the value of the expression
on its right.
(eg: "VALUE=OFFSET-START+1")
A period "." is a special symbol
used to specify the location
counter.
(eg: " .=01C0 ; start addr")
iii) .ASCII translates the character string
.ASCIP argument to ascii ( with parity
set on the last character in the
case of .ASCIP ) and assigns
these values to the current
sequential address(es).
(eg: ".ASCII 'TEXT STRING'" )
iv) .LIST to enable/disable the listing of
the source program in assembler
output. If the value of the expr
given is zero, the listing is
disabled, else it is enabled.
(eg: ".LIST 0 ; no list")
v) .BLKB reserves the number of bytes
given in the argument expression
(eg: ".BLKB 0100 ; buffer area")
vi) .END to tell the assembler it has
reached the end of your source
program. This statement must
be included as the last line of
source.
4) The (optional) comments are proceeded by a semi-colon
";" and may contain any other character. The label,
opcode and argument fields may be omitted for a
comment line. A line with a dollar "$" sign as the
first character is treated as a comment line and
is printed to the listing file minus the "$" sign.
* Use of assembler on RSTS/E :-
After logging on to the system, perform the following steps :-
(1) Enter the source program into a file on the system
using the $PIP or $EDIT programs or the "CREATE" command
(2) Run the cross assembler by typing "RUN !X80",
responding to the "#" sign with a command string of the
form: eg: LIST=PROG/switch(es)
which directs the listing to the file "LIST.LST" from the
source file "PROG. SRC". The switch(es) are optional but
/E specifies an errors only listing
/O specifies an object module output, in the format
of a hexadecimal dump in ASCII, 16 bytes/line.
(this is useful for later punching of paper tape)
/S specifies that the sorted symbol table be printed.
Only specifying the source file ( eg: PROG ) causes all
output to the user's terminal.
(3) If any errors are detected, it is neccessary to edit
the source file using the $EDIT program or the "EDIT"
command, and repeat step 2 above until no errors are
detected.
Any queries ? - don't hesitate to contact Tony Nicholson c/o
Electrical Engineering Department, for advice or help with your
problems regarding the cross assembler. You might also want to
attend on the second and fourth Mondays of the month in Physics
building room G12 at 7pm, when the Newcastle Microcomputer Club
meets.

BIN
micros/X80.TSK Normal file

Binary file not shown.

13
micros/X80BLD.COM Normal file
View File

@ -0,0 +1,13 @@
$! Command file to build X80.B2S (with Basic-Plus-2)
$!
$ set noOn
$ run $bp2ic2
SCALE 0
OLD X80.B2S
COMPILE X80/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN
BUILD X80
SCRATCH
EXIT
$ tkb @X80
$ del x80.odl, x80.obj, x80.cmd
$ exit