Commit Diff


commit - 9767aa1c8b0eaa8b6fea2fb3487f6edbe2d440f2
commit + eb9ae0480b840f316f65a14c778441d4f7886942
blob - 3c163430545f1b9dd0e3c52f1d1c29f19de89495
blob + ee27252780c0e3fe07d444bbc7354984b05de6f2
Binary files BASASM,PRG and BASASM,PRG differ
blob - 1fd795b36202ef6c7052d17c7c739d133569e6e6
blob + b10442f369b9c48599e62915b17e6e6be782aa8b
--- BASASM.lst
+++ BASASM.lst
@@ -1,5 +1,5 @@
 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
@@ -20,11 +20,11 @@
 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
@@ -40,30 +40,38 @@
 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
@@ -73,14 +81,10 @@
 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
@@ -109,13 +113,18 @@
 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%
@@ -142,17 +151,33 @@
 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
@@ -166,25 +191,31 @@
 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
@@ -246,9 +277,10 @@
 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
@@ -28,6 +28,7 @@
         -  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
@@ -4,12 +4,15 @@
 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
@@ -19,7 +22,9 @@
 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