diff --git a/README.md b/README.md index fcbb43b..54083c7 100644 --- a/README.md +++ b/README.md @@ -8,34 +8,29 @@ A stack-based VM, written in ANSI C. cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn ``` -## OP Codes +## Assembly Syntax ``` -VALUE OPCODE EXPLANATION -0x00000000 NOP do nothing -0x00000001 ADD pop a, pop b, push a + b -0x00000002 SUB pop a, pop b, push a - b -0x00000003 AND pop a, pop b, push a & b -0x00000004 OR pop a, pop b, push a | b -0x00000005 XOR pop a, pop b, push a ^ b -0x00000006 NOT pop a, push !a -0x00000007 IN read one byte from stdin, push as word on stack -0x00000008 OUT pop one word and write to stream as one byte -0x00000009 LOAD pop a, push word read from address a -0x0000000A STOR pop a, pop b, write b to address a -0x0000000B JMP pop a, goto a -0x0000000C JZ pop a, pop b, if a == 0 goto b -0x0000000D PUSH push next word -0x0000000E DUP duplicate word on stack -0x0000000F SWAP swap top two words on stack -0x00000010 ROL3 rotate top three words on stack once left, (a b c) -> (b c a) -0x00000011 OUTNUM pop one word and write to stream as number -0x00000012 JNZ pop a, pop b, if a != 0 goto b -0x00000013 DROP remove top of stack -0x00000014 PUSHIP push a in IP stack -0x00000015 POPIP pop IP stack to current IP, effectively performing a jump -0x00000016 DROPIP pop IP, but do not jump -0x00000017 COMPL pop a, push the complement of a +: starting a definition +& obtaining pointers +( stack comments +` inlining bytecodes +' strings +# numbers +$ characters +~ vector +[ 12 34 ] real values +< 12 34 > relative values +( 12 34 ) deadzone +``` + +``` +;add-two JSR + +BRK + +:add-two + [ 2 ] ADD RTS ``` ## Design @@ -50,12 +45,11 @@ VALUE OPCODE EXPLANATION ### Assembly -- `%25`, decimal -- `#25`, hex +#### Addressing -``` -2 2 + $ef -``` +- `label`, a named offset[TODO] +- `literal`, a numeric value +- `pointer`, pointer to an address[TODO] ### Assembler diff --git a/build.sh b/build.sh index 378eef4..ddb3cad 100755 --- a/build.sh +++ b/build.sh @@ -10,14 +10,14 @@ rm -f ./uxn # debug(slow) cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxnasm.c -o uxnasm -cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn +# cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn # build(fast) # cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn # Size -echo "Size: $(du -sk ./uxn)" +# echo "Size: $(du -sk ./uxn)" # run ./uxnasm program.usm program.rom -./uxn program.rom +# ./uxn program.rom diff --git a/program.usm b/program.usm index 4af9ba3..cd4b5dd 100644 --- a/program.usm +++ b/program.usm @@ -1 +1 @@ -#12 #34 add \ No newline at end of file +LIT 25 26 LIT DUP ADD BRK \ No newline at end of file diff --git a/uxnasm.c b/uxnasm.c index c3a6b5d..37d3232 100644 --- a/uxnasm.c +++ b/uxnasm.c @@ -14,13 +14,14 @@ WITH REGARD TO THIS SOFTWARE. #define PRGLEN 256 typedef unsigned char Uint8; -typedef unsigned short Uint16; typedef struct { int ptr; - Uint16 data[PRGLEN]; + Uint8 data[PRGLEN]; } Program; +char opcodes[][4] = {"BRK", "LIT", "DUP", "DRP", "SWP", "SLP", "PSH", "POP", "JMP", "JSR", "RST", "BEQ", "EQU", "NEQ", "LTH", "GTH"}; + Program p; #pragma mark - Helpers @@ -35,6 +36,16 @@ scmp(char *a, char *b) /* string compare */ return 0; } +char * +suca(char *s) /* string to uppercase */ +{ + int i = 0; + char c; + while((c = s[i])) + s[i++] = c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c; + return s; +} + int shex(char *s) /* string to num */ { @@ -53,10 +64,27 @@ shex(char *s) /* string to num */ Uint8 getopcode(char *s) { - if(scmp(s, "add")) { - return 0x01; + int i; + for(i = 0; i < 16; ++i) + if(scmp(opcodes[i], suca(s))) + return i; + return 0xff; +} + +void +echo(Uint8 *s, Uint8 len, Uint8 ptr, char *name) +{ + int i; + printf("%s\n", name); + for(i = 0; i < len; ++i) { + if(i % 16 == 0) + printf("\n"); + if(ptr == i) + printf("[%02x]", s[i]); + else + printf(" %02x ", s[i]); } - return 0; + printf("\n"); } void @@ -64,16 +92,10 @@ pass1(FILE *f) { char word[64]; while(fscanf(f, "%s", word) == 1) { - int lit = 0, val = 0; - if(word[0] == '#') { - lit = 0; - val = shex(word + 1); - } else { - lit = 1; - val = getopcode(word); - } - printf("#%d -> %s[%02x %02x]\n", p.ptr, word, lit, val); - p.data[p.ptr++] = (val << 8) + (lit & 0xff); + int op = getopcode(word); + if(op == 0xff) + op = shex(word); + p.data[p.ptr++] = op; } } @@ -95,5 +117,6 @@ main(int argc, char *argv[]) pass1(f); fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb")); fclose(f); + echo(p.data, 0x40, 0, "program"); return 0; }