commit cd7ba6c
zzo38
·
2022-11-06 20:49:24 +0000 UTC
parent e8a5ebb
More improvements of assembler.
M
asm.doc
+34,
-2
1@@ -46,7 +46,9 @@ The following standard tokens are available:
2 $ and a number will advance the address by that number. (The padding will
3 be all zeros if not filled in.)
4
5- @ and a name will make a label with that name.
6+ @ and a name will make a label with that name. If the label name starts
7+ with a uppercase letter, then warnings about that label being unused are
8+ suppressed. (Otherwise, a warning is emitted if the label is never used.)
9
10 & and a name will make a label whose name is the same as the most recent
11 @ command and then / and then the name specified by the & command.
12@@ -89,6 +91,8 @@ The following nonstandard tokens are available:
13 which exists only at compile-time).
14
15 \: and a name will push the address of the name to the special stack.
16+ The label must come before this command; forward references cannot be
17+ used with this command.
18
19 \@ and a name will pop an address from the special stack and define a
20 label whose address is the address which has been popped in this way.
21@@ -97,6 +101,20 @@ The following nonstandard tokens are available:
22 about special calculations. These are executed immediately at compile
23 time, before the compiled program is written to the output file.
24
25+ [@ makes a anonymous label; the matching ] command will reference the
26+ same anonymous label as this one. (Nesting is allowed.)
27+
28+ ]@ will make a anonymous label which the matching [ before it will
29+ reference it.
30+
31+ [, [. [; [: will act like a , . ; : referencing the anonymous label
32+ defined by the matching ]@ command.
33+
34+ ], ]. ]; ]: will act like a , . ; : referencing the anonymous label
35+ defined by the matching ]@ command.
36+
37+ ]\ acts like \: for the matching [@ command.
38+
39 For the . , : ; commands, the name can optionally start with & to mean
40 that it is interpreted the same as for a & command.
41
42@@ -107,7 +125,7 @@ Each instruction is a single character.
43
44 Numbers 0 to 9 push that number to the special stack.
45
46-_ ( -- ) Set loop point (currently not used for anything).
47+_ ( -- ) Set loop point.
48
49 ! ( x -- ) Set current address.
50
51@@ -140,10 +158,16 @@ $ ( -- x ) Get current length.
52
53 . ( x -- ) Discard.
54
55+E ( code -- ) Emit an error and stop compiling.
56+
57 g ( address -- value ) Read 8-bits from memory.
58
59 G ( address -- value ) Read 16-bits from memory.
60
61+o ( count -- count? ) If count is nonzero, decrement and go back to the
62+beginning; if it is already zero then just discards it and continues the
63+execution from here instead.
64+
65 p ( value address -- ) Write 8-bits to memory. You can write anywhere
66 including the zero page and can also overwrite memory that has already
67 been written. Anything written to the zero page can be read back by other
68@@ -158,6 +182,14 @@ cannot write in the zero page or overwrite what is already written.
69 W ( value -- ) Write 16-bits at the current address and advance. You
70 cannot write in the zero page or overwrite what is already written.
71
72+() ( condition -- ) Put other commands in the () block; it will be
73+executed only if the condition is zero, and skipped if nonzero. Conditional
74+blocks of the same kind cannot be nested.
75+
76+[] ( condition -- ) Put other commands in the [] block; it will be
77+executed only if the condition is nonzero, and skipped if zero. Conditional
78+blocks of the same kind cannot be nested.
79+
80
81 === Name output format ===
82
M
uxnasm.c
+28,
-3
1@@ -57,6 +57,8 @@ static Program p;
2 static char line_comment;
3 static int ssptr;
4 static Uint16 sstack[256];
5+static int bsptr,bcnt;
6+static Uint16 bstack[256];
7
8 /* clang-format off */
9
10@@ -279,7 +281,7 @@ static int special_calc(const char*w) {
11 const char*loop=w;
12 Uint16 a,b;
13 while(*w) switch(*w++) {
14- case '_': loop=w; break;
15+ case '_': loop=w+1; break;
16 case '0' ... '9': if(ssptr>255) return 0; sstack[ssptr++]=w[-1]-'0'; break;
17 case '!': if(ssptr<1) return 0; p.ptr=sstack[--ssptr]; break;
18 case '@': if(ssptr>255) return 0; sstack[ssptr++]=p.ptr; break;
19@@ -296,13 +298,20 @@ static int special_calc(const char*w) {
20 case ':': if(ssptr<1 || ssptr>255) return 0; a=sstack[ssptr-1]; sstack[ssptr++]=a; break;
21 case ',': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=b; sstack[ssptr++]=a; break;
22 case '.': if(ssptr<1) return 0; --ssptr; break;
23+ case 'D': fprintf(stderr,"Depth #%x\n",ssptr); if(ssptr) fprintf(stderr,"Debug #%x\n",sstack[ssptr-1]); break;
24+ case 'E': if(ssptr) fprintf(stderr,"User error #%x\n",sstack[ssptr-1]); return 0;
25 case 'g': if(ssptr<1) return 0; a=sstack[--ssptr]; sstack[ssptr++]=p.data[a]; break;
26 case 'G': if(ssptr<1) return 0; a=sstack[--ssptr]; if(a==0xFFFF) return 0; sstack[ssptr++]=(p.data[a]<<8)|p.data[a+1]; break;
27+ case 'o': if(ssptr<1) return 0; if(sstack[ssptr-1]--) w=loop; else --ssptr; break;
28 case 'p': if(ssptr<2) return 0; a=sstack[--ssptr]; b=sstack[--ssptr]; p.data[a]=b; break;
29 case 'P': if(ssptr<2) return 0; a=sstack[--ssptr]; b=sstack[--ssptr]; if(a==0xFFFF) return 0; p.data[a]=b>>8; p.data[a+1]=b&255; break;
30 case 'w': if(ssptr<1) return 0; a=sstack[--ssptr]; writebyte(a); break;
31 case 'W': if(ssptr<1) return 0; a=sstack[--ssptr]; writeshort(a,0); break;
32- default: return 0;
33+ case '(': if(ssptr<2) return 0; if(!sstack[--ssptr]) break; while(*w && *w!=')') w++; break;
34+ case ')': /* do nothing */ break;
35+ case '[': if(ssptr<2) return 0; if(sstack[--ssptr]) break; while(*w && *w!=']') w++; break;
36+ case ']': /* do nothing */ break;
37+ default: fprintf(stderr,"Unrecognized special calculation command: %c\n",w[-1]); return 0;
38 }
39 return 1;
40 }
41@@ -390,7 +399,7 @@ parse(char *w, FILE *f)
42 switch(w[1]) {
43 case '\\': line_comment=1; break;
44 case '~': if(!doinclude_binary(w+2)) return error("Invalid include",w); break;
45- case ':':
46+ case ':': spec_ref:
47 if(!(l=findlabel(w+2))) return error("Invalid reference",w);
48 if(ssptr==256) return error("Stack overflow",w);
49 sstack[ssptr++]=l->addr;
50@@ -413,6 +422,22 @@ parse(char *w, FILE *f)
51 case '[':
52 case ']':
53 if(slen(w) == 1) break; /* else fallthrough */
54+ if((w[1]=='.' || w[1]==',' || w[1]==':' || w[1]==';' || w[1]=='@' || w[1]=='\\') && !w[2]) {
55+ if(*w=='[') {
56+ if(bsptr==256) return error("Stack overflow",w);
57+ bstack[bsptr++]=i=bcnt++;
58+ } else if(*w==']') {
59+ if(!bsptr) return error("Stack underflow",w);
60+ i=bstack[--bsptr];
61+ }
62+ snprintf(w+2,10,"\\%x\\",i);
63+ switch(w[1]) {
64+ case '@': if(!makelabel(w+2)) return error("Invalid label",w); break;
65+ case '\\': goto spec_ref;
66+ default: return parse(w+1,f);
67+ }
68+ break;
69+ }
70 default: defa:
71 /* opcode */
72 if(findopcode(w) || scmp(w, "BRK", 4)) {