commit - 9767aa1c8b0eaa8b6fea2fb3487f6edbe2d440f2
commit + eb9ae0480b840f316f65a14c778441d4f7886942
blob - 3c163430545f1b9dd0e3c52f1d1c29f19de89495
blob + ee27252780c0e3fe07d444bbc7354984b05de6f2
Binary files BASASM,PRG and BASASM,PRG differ
blob - 1fd795b36202ef6c7052d17c7c739d133569e6e6
blob + b10442f369b9c48599e62915b17e6e6be782aa8b
--- BASASM.lst
+++ BASASM.lst
0 REM BASASM - A SIMPLE ASSEMBLER MADE
-1 REM V.27 IN BASIC. PESCO 2026
+1 REM V.28 IN BASIC. PESCO 2026
2 REM 10 VARIABLES 700 *SAVE ML PRG
3 REM 100 LOAD OPCODES 720 *PRINT SEQ F
4 REM 130 SUBROUTINES 740 *MEMSTAT
23 DIM LN%(MN%) :REM OPERAND LENGTHS
24 DIM MI%(26) :REM ALPH. MNEM. INDEX
25 SY% = 0 :REM SYMBOL COUNT
-26 SM% = 255 :REM SYMBOL MAX
+26 SM% = 150 :REM SYMBOL MAX
27 DIM SY$(SM%) :REM SYMBOL NAMES
28 DIM SY(SM%) :REM SYMBOL VALUES
30 PA% = 0 :REM PATCH COUNT
-31 PM% = 99 :REM PATCH MAX
+31 PM% = 63 :REM PATCH MAX
32 DIM PA(PM%) :REM PATCH POSITION
33 DIM PA%(PM%) :REM PATCH LENGTH
34 DIM PA$(PM%) :REM PATCH EXPRESSION
118 IF B = A THEN 120
119 A = A + 1: MI%(A) = I: GOTO 118
120 I = I + 1: GOTO 110
-125 PRINT: IF I = MN% + 1 THEN 200
+125 PRINT: IF I = MN% + 1 THEN 201
127 PRINT "INVALID OPCODE DATA": END
128 REM
129 REM SUB: PARSE NUMBER, DEC OR HEX
130 A = VAL(A$)
-132 IF LEFT$(A$,1) <> "$" THEN RETURN
-138 A$ = MID$(A$,2)
-139 IF A$ = "" THEN RETURN
-140 A = A * 16 + ASC(A$) - 48
-145 IF ASC(A$) > 64 THEN A = A - 7
-146 GOTO 138
+131 IF LEFT$(A$,1) <> "$" THEN RETURN
+132 A$ = MID$(A$,2)
+133 IF A$ = "" THEN RETURN
+134 A = A * 16 + ASC(A$) - 48
+135 IF ASC(A$) > 64 THEN A = A - 7
+136 GOTO 132
+138 REM
+139 REM SUB: PARSE ARGUMENT, SYM OR NUM
+140 EX = 0: B$ = A$
+141 HI = (RIGHT$(A$,1) = "↑")
+142 PL = (RIGHT$(A$,1) = "+")
+143 IF NOT (HI OR PL) THEN 156
+144 EX = 1
+145 A$ = LEFT$(A$, LEN(A$) - 1)
+146 GOTO 156
148 REM
-149 REM SUB: PARSE ARGUMENT, SYM OR NUM
-150 EX = 0: B$ = A$
-151 HI = (RIGHT$(A$,1) = "↑")
-152 PL = (RIGHT$(A$,1) = "+")
-153 IF NOT (HI OR PL) THEN 156
-154 EX = 1
-155 A$ = LEFT$(A$, LEN(A$) - 1)
+149 REM SUB: PARSE ARG, PRINT [EXPR]
+150 GOSUB 140
+151 IF EX THEN PRINT "["; A$; "] ";
+152 RETURN
+154 REM
+155 REM PARSE ARG (CONT)
156 IF ASC(A$) > 64 THEN 160 :REM "A"
-157 IF EX THEN PRINT "["; B$; "] ";
+157 IF ASC(A$) = 39 THEN 160 :REM "'"
158 GOSUB 130: A$ = B$: GOTO 165
159 REM
-160 PRINT "["; B$; "] ";
+160 EX = 1
161 GOSUB 170: A$ = B$
162 IF SY(A) = XX THEN A% = 1: RETURN
163 A = SY(A) :REM GET SYM. VALUE
167 A% = 0: RETURN :REM SUCCESS
168 REM
169 REM SUB: LOOK UP SYMBOL
-170 A = 0
-171 IF A = SY% THEN 174 :REM NOT FND
-172 IF SY$(A) = A$ THEN RETURN
-173 A = A + 1: GOTO 171
-174 IF SY% < SM% + 1 THEN 176
-175 PRINT "TOO MANY SYMBOLS": END
-176 SY% = SY% + 1: UN = UN + 1
-177 SY$(A) = A$: SY(A)=XX: RETURN
+170 T = SY%: FOR A = 0 TO SY% - 1
+171 IF SY$(A) = A$ THEN RETURN
+172 IF SY$(A) = "" THEN T = A
+173 NEXT: A = T: GOTO 340 :REM ALLOC
178 REM
179 REM SUB: DEFINE SYMBOL
180 GOSUB 170
219 A$ = M$: GOSUB 130 :REM NUM
220 C = A: L% = 0: GOTO 270
223 A$ = MID$(M$,2): V = P: GOSUB 180
-225 PRINT P; TAB(12); M$ :REM SYMDEF
-227 GOTO 210
+224 PRINT P; TAB(12); M$ :REM SYMDEF
+225 IF ASC(A$) = 39 THEN 229:REM LOCAL
+226 REM ON TOP-LEVEL LABEL ('ABC)...
+227 GOSUB 370 :REM PATCH FWD REFS
+228 GOSUB 330 :REM CLEAR LOCAL SYMS
+229 GOTO 210
230 READ A$: GOSUB 130 :REM NUM -> A
231 A$ = LEFT$(M$, LEN(M$) - 1)
232 V = A: GOSUB 180 :REM SYMDEF
-233 PRINT P; TAB(12); A$; " = "; V
-234 GOTO 210
+233 PRINT P; TAB(12); A$; " =";
+234 PRINT LEFT$(" ", -(V < 0)); V
+235 GOTO 210
239 REM SEARCH FOR MNEMONIC
240 A = ASC(M$) - 64
242 FOR I = MI%(A) TO MN%
298 REM
299 REM - AFTER END OF INPUT -
300 IF P > PQ THEN PQ = P
-305 PRINT "PATCH FWD REFS..."
-306 GOSUB 370 :REM PATCH FWD REFS
-310 IF UN = 0 THEN 340
-320 PRINT "UNDEFINED SYMBOLS:"
-325 FOR I = 0 TO SY%
-330 IF SY(I) = XX THEN PRINT SY$(I),;
-335 NEXT: PRINT
-340 PRINT "ASSEMBLY FINISHED."
-341 PRINT "P =";PP; TAB(12); "Q =";PQ;
-342 PRINT TAB(24); "Q-P ="; PQ-PP
-350 END
+305 GOSUB 370 :REM PATCH FWD REFS
+310 IF UN = 0 THEN 320
+311 PRINT "UNDEFINED SYMBOLS:"
+312 FOR I = 0 TO SY%
+313 IF SY(I) = XX THEN PRINT SY$(I),;
+314 NEXT: PRINT
+320 PRINT "ASSEMBLY FINISHED."
+321 PRINT "P =";PP; TAB(12); "Q =";PQ;
+322 PRINT TAB(24); "Q-P ="; PQ-PP
+323 END
+328 REM
+329 REM SUB: CLEAR LOCAL SYMBOLS
+330 FOR I = 0 TO SY% - 1
+331 IF LEFT$(SY$(I), 1) <> "'" THEN 336
+332 IF SY(I) <> XX THEN 335
+333 PRINT "UNRESOLVED LOCAL LABEL: ";
+334 PRINT SY$(I): END
+335 SY$(I) = ""
+336 NEXT: RETURN
+338 REM
+339 REM SUB: ALLOCATE SYMBOL (IDX A)
+340 UN = UN + 1
+341 IF A <= SM% THEN 343
+342 PRINT "TOO MANY SYMBOLS": END
+343 IF A > SY% THEN STOP :REM BUG
+344 IF A = SY% THEN SY% = SY% + 1
+345 SY$(A) = A$: SY(A) = XX: RETURN
358 REM
359 REM SUB: VALIDATE & PREPARE OPERAND
360 IF M$ <> "R" THEN 364
368 END
369 REM SUB: PATCH FWD SYMBOL REFS
370 IF PA% = 0 THEN RETURN
-371 FOR I = 0 TO PA% - 1
-372 P = PA(I): L% = PA%(I)
-373 A$ = PA$(I): M$ = PM$(I)
-375 PRINT P + 1; TAB(13);
-376 GOSUB 150: IF A% THEN PRINT: NEXT
-377 GOSUB 190: PRINT
-378 PA(I) = -1: NEXT
+371 Q=P: FOR I = 0 TO PA% - 1
+372 IF PA(I) = -1 THEN 379
+373 P = PA(I): L% = PA%(I)
+374 A$ = PA$(I): M$ = PM$(I)
+375 GOSUB 140: IF A% THEN 379
+376 PRINT P, "← ";
+377 IF EX THEN PRINT "["; A$; "] ";
+378 GOSUB 190: PRINT: PA(I) = -1
+379 NEXT: P=Q
380 FOR I = PA% - 1 TO 0 STEP -1
382 IF PA(I) <> -1 THEN RETURN
383 PA% = I :REM REMOVE
384 NEXT: RETURN
388 REM
389 REM SUB: RECORD SYM REF TO PATCH
-390 IF PA% <= PM% THEN 394
-391 PRINT: PRINT "TOO MANY FWD REFS"
-392 END
-394 PA(PA%) = P: PA%(PA%) = L%
-395 PA$(PA%) = A$: PM$(PA%) = M$
-396 PA% = PA% + 1: RETURN
+390 IF PA% <= PM% THEN 396
+391 FOR I = 0 TO PA% - 1
+392 IF PA(I) = -1 THEN 397
+393 NEXT: PRINT
+394 PRINT "TOO MANY FORWARD REFERENCES"
+395 END
+396 I = PA%: PA% = PA% + 1
+397 PA(I) = P: PA%(I) = L%
+398 PA$(I) = A$: PM$(I) = M$
+399 RETURN
400 REM
401 REM - ASSEMBLER DIRECTIVES -
408 REM
578 REM
579 REM .DZ - OUTPUT N ZERO BYTES
580 READ A$: GOSUB 150: N=A
-582 IF A <= 0 THEN PRINT N: GOTO 499
+582 IF A <= 0 THEN 587
584 POKE P,0: P=P+1
586 A=A-1: GOTO 582
+587 PRINT MID$(STR$(N), 2): GOTO 499
588 REM
589 REM .LIM - LIMIT OUTPUT POSITION
590 READ A$: GOSUB 150
blob - 8f98de9ad02c66ea51cf0765bd27c3618bef8130
blob + 96c0cb7b2209776b8434ad441157144b1643000e
--- README
+++ README
- Mnemonic instructions, aware of operand sizes.
- Decimal and hexadecimal notation.
- Symbolic labels, absolute and relative addressing.
+ - Locally-scoped labels.
- User-defined symbolic constants.
- Single-pass operation with forward references.
- Range checks for operands.
blob - 8bbb53978627510982e193f24d132249234dd567
blob + 39f8222c30892f2ae04238a302488e682f5676e6
Binary files TEST.B,PRG and TEST.B,PRG differ
blob - 2c85b0f88c4fec4ffc526385580b0b27550b00bd
blob + 9f1a65b1af0d350367ef7d3ecd0a10be461b998c
--- TEST.B.lst
+++ TEST.B.lst
1003 DATA .DB, HALLO↑
1004 DATA .DB, 1 2 3
1005 DATA PHA
-1010 DATA BMIR, L1, RTI
-1014 DATA 'L1
-1015 DATA BITZ, -123
-1016 DATA BEQR, L1
+1006 DATA STA, 2048: REM OK, FULL RNG
+1007 REM STAZ, 2048: REM ERR, >255
+1010 DATA BMIR, 'L1, RTI
+1014 DATA ''L1
+1015 DATA BITZ, 123
+1016 DATA BEQR, 'L1
1017 DATA JSR, L2
1018 DATA 'L2
+1019 REM BCCR, 'L1: REM UNDEF HERE
1020 DATA ORA(X, $23
1023 DATA HALLO=, -555
1024 DATA .DB, -1 $16, .DW, HALLO $4242
1030 DATA .LIM, 49210
1040 DATA AND#, 255
1041 DATA ORA, $C80A+
+1042 DATA ADC#, -1025
1050 DATA JMP, START+
+1099 DATA .LIM, $C100: REM 49408
2000 DATA .=,49200, BEQR, FAR+
2001 DATA .=,49328, 'FAR
9999 DATA .END