This commit is contained in:
neauoire 2021-01-29 17:49:10 -08:00
parent 588a0f8b92
commit 72d9c98f35
4 changed files with 67 additions and 50 deletions

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
#12 #34 add
LIT 25 26 LIT DUP ADD BRK

View File

@ -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;
}