In the physical layer (as encoded in the QR code in alphanumeric mode), two characters are encoded in 11 bits: so 5.5 bits per character. This 31% less space than two characters stored in byte-mode.
Each machine instruction consists of an opcode character, followed by an optional argument. The argument is a 1-3 signed or unsigned number encoded in base 44.
Encoding | Opcode | Stack Effect | Description |
---|---|---|---|
Arithmetic | |||
0 | inc | (n -- n) | Increment top of stack |
1 | dec | (n -- n) | Decrement top of stack |
2 | neg | (n -- n) | Negate top of stack |
3 | add | (n n -- n) | Add two numbers |
4 | sub | (n n -- n) | Subtract top of stack from next of stack |
5 | mul | (n n -- n) | Multiply two number on top of stack |
6 | div | (n n -- n) | Divide second on stack by top of stack |
7 | mod | (n n -- n) | Push remainder from division of second on stack by top of stack |
Bitwise | |||
8 | not | (n -- n) | Complement top of stack |
9 | shl | (n n -- n) | Bitwise shift left |
A | shr | (n n -- n) | Bitwise shift right |
B | xor | (n n -- n) | Exclusive or |
C | or | (n n -- n) | Or |
D | and | (n n -- n) | Bitwise and |
Conditionals | |||
E | z ? <op> | (cnd -- ) | Execute next op if zero, else skip |
F | nz ? <op> | (cnd -- ) | Execute next op if not zero, else skip |
G | m ? <op> | (cnd -- ) | Execute next op if minus, else skip |
H | p ? <op> | (cnd -- ) | Execute next op if positive, else skip |
Control Flow | |||
I | ret | (--) R(pc -- ) |
Return from subroutine call. Pop and continue execution from address on return stack |
J <s1> K <u2> |
jmp <dst> | ( -- ) | Jump to dst. Dst is either a signed 1char relative offset, or unsigned absolute address |
L <s1> M <u2> |
call <dst> | R(-- nxt) | Call subroutine at dst, pushing the address of the subsequent instruction to be executed on subroutine return on the return stack. Dst is either a signed 1char relative offset, or unsigned absolute address. |
N <s1> | loop <dst> |
i > 0: R(i -- i-1) else: R(i -- ) |
Decrement top of return stack. If greater than 0, jump to dst. Else, drop top of return stack. Dst is a signed 1char relative offset |
Load & Store | |||
O <s1> P <s2> Q <s3> |
ldi | ( -- n ) | Load an immediate signed number argument onto the stack |
R | ld | (addr -- n) | Load a number from the address specified by top of stack |
S | st | (val addr -- n) | Store a value at address specified by top of stack |
T <u1> | ldz <i> | (--) | Load from immediate offset in zero-page |
U <u1> | stz <i> | (val --) | Store to immediate offset in zero-page |
V | ldp | (offset --) | Load* from offset in program memory |
W | st | ( val addr -- ) | Store value at given memory address |
Stackrobatics | |||
X | dup | (n -- n n) | Duplicate top of stack |
Y | drop | (n --) | Drop top of stack |
Z | over | (a b -- a b a) | Push second on stack |
_ | swap | (a b -- b a) | Swap the top two items on the stack |
$ | nip | ( a b -- b ) | Drop second on stack |
$ | rot | (a b c -- b c a) | Rotate top 3 elements on stack |
% | rtop | (-- n) | Push a copy of the top of the return stack |
* | tos | ( -- n) R( n -- ) |
Move the top of the return stack to the data stack |
+ | tor | ( n -- ) R( -- n ) |
Move top of the data stack to the return stack |
rdrop | r( n -- ) | X | Drop top of return stack |
Control Flow | |||
nop | ( -- ) | X | No operation |
hlt | ( -- ) | X | Halt the system |
sys | ( ... n -- ... ) | X | Execute a system call n |
Name | Code | Stack Effect | Description |
---|---|---|---|
INCHAR | 0 | ( -- c) | Input a char from stdin |
OUTCHAR | 1 | (c 1 --) | Output a character to stdout |
OUTNUM | 2 | (n --) | Output a number to stdout |
DRAWDOT | 3 | (x y 3 --) | Draw dot on canvas |
RANDINT | 4 | (max 4 -- n) | Generate a random number between 0..max |
The assembler converts a program text into its encoded form. In listing form, the space " " character may be substituted for an underscore "_" for clarity. This is not substituted in the binary output.
The assembler supports labels. A label l1
can be defined and referenced in arguments to instructions:
l1: jmp l1
Labels may be redefined. Forward references are also supported:
call hop ldi 3 hop: dup
Forward references may be encoded non-optimally (specifically, they will use the 2-character absolute encoding of a branch instruction).
A number of assembler directives are available:
Directive | Description |
---|---|
res n | Reserve n bytes, filling with nop |
equ <name>, <val> | Assign a number to a name, which can be substitued later |
equ <name>, <val> | Assign a number to a name, which can be substitued later |
const n1[, n2, n3, ...] | Store constant value(s) at the end of program memory. The address of the value(s) in program memory can be referenced by <name> |