Assembly language for a tape-based computer system, but every instruction is an emoji.
- General-purpose registers X and Y (both 8 bits wide)
- Accumulator Register A (8 bits wide)
- 3x Tape Drives, T0 T1 and T2 (descibed below), each with the following:
- 1 input buffer register (TnI)
- 1 ouput buffer register (TnO)
- 1 write flag (TnW)
- Obviously each tape drive has a position on the tape as well, which changes as the tape gets moved. (TnP)
"n" here refers to the tape id, so for instance the input buffer register of tape 2 (T2) is known as T2I.
Each tape drive supports the following operations:
- Forward - move the tape forward one space (and other things, described below)
- Backward - move the tape backward one space
- Rewind - reset the tape's position to 0, and clear both buffers and the write flag.
- Set-write - write a byte to the output buffer and set the write flag.
The forward operation is special because it also does the following:
- Reads the data in the space it has just passed over into the input buffer register
- If the write flag is set:
- Write the data in the output buffer register to the byte just passed over
- Clear the write flag
None of those things happen when going backwards, and this is the only way to read and write to or from any tape.
Each tape drive is 256 bytes long. Trying to move forwards or backwards past the end of the tape has no effect.
Emoji | arg | Description | Code |
---|---|---|---|
➡️ | n | Moves tape n forward 1 space | [see above] |
⬅️ | n | Moves tape n backward 1 space | TnP ← TnP-1 |
⏪ | n | Rewinds tape n | TnP, TnI, TnO, TnW ← 0 |
👁️ | n | Reads from tape n | A ← TnI |
✏️ | n | Set-writes to tape n | TnO ← A, TnW ← 1 |
Args for all the above must immediately follow their instruction, and are as follows:
Tape ID | Emoji Arg |
---|---|
T0 | 📼 |
T1 | 🎞️ |
T2 | 🎥 |
Emoji | arg | Description | Code |
---|---|---|---|
➕ | r | Add two numbers | A ← A + r |
🍴 | r | Bitwise AND two numbers | A ← A & r |
🎷 | r | Bitwise OR two numbers | A ← A | r |
💡 | r | Increment a register | r ← r + 1 |
🦔 | r | Decrement a register | r ← r - 1 |
➗ | r | Perform integer division | A ← A // r |
Emoji | arg | Description | Code |
---|---|---|---|
📤 | Outputs a character | out ← chr(A) |
|
📥 | Input a character | A ← ord(in) |
Note: on some systems, the 📥 instruction may be disabled. On such systems, this instruction sets A to 0 instead.
Emoji | arg | Description | Code |
---|---|---|---|
📦 | r | Transfers A to r | r ← A |
🎁 | r | Transfers r to A | A ← r |
🔨 | Transfers X to Y | Y ← X |
|
⛏️ | Transfers Y to X | X ← Y |
|
⚒️ | Swaps X and Y | X ↔ Y |
Args for the above must immediately follow their instruction, and are as follows:
Register | Emoji arg |
---|---|
X | 🔨 |
Y | ⛏️ |
A | 🗃️ |
A is the low 8 bits of a 16 bit register called RJMP. Writing to A zeroes the high 8 bits of RJMP, and reading from A reads the low 8 bits of RJMP.
The following comparison flags are available:
- Equal (
EQ
): the two values compared are equal.
More may follow in future.
Emoji | arg | Description | Code |
---|---|---|---|
❓ | r | Compare r and A | flags ← cmp(r, A) |
❔ | r | Compare r and 0 | flags ← cmp(r, 0) |
Program memory offsets are the number of characters (unicode codepoints) from the start of the file. This takes into account emojis that are actually multiple codepoints, so beware.
Emoji | arg | Description | Code |
---|---|---|---|
🐰 | Jump to memory address in RJMP | PC ← RJMP |
|
⚖️ | Jump if EQ | {if flags.EQ set} PC ← RJMP |
|
🏷️ | Jump if not EQ | {if flags.EQ not set} PC ← RJMP |
Emoji | args | Description | Code |
---|---|---|---|
✉️ | msb lsb | Load literal value into A | A ← value |
🐇 | himsb lomsb hilsb lolsb | Load literal value into RJMP | RJMP ← value |
🗿 | Halt the program | [HALT] |
Both or all 4 args should follow the ✉️ or 🐇 instruction respectively in the order shown.
Emojis for value:
emoji | value |
---|---|
😀 | 0 |
😁 | 1 |
😂 | 2 |
😃 | 3 |
😄 | 4 |
😅 | 5 |
😆 | 6 |
😇 | 7 |
😈 | 8 |
😉 | 9 |
😊 | A |
😋 | B |
😌 | C |
😍 | D |
😎 | E |
😏 | F |
Why? Why would you do such thing?