QFTASM (Quest for Tetris Assembly) is the “human readable” representation of the instructions that will be performed by our processor.  El’endia has written an interpreter for QFTASM at his website, complete with documentation and example code.


Since we are using 4 bits for the opcode, there is a limit of 16 possible operations, of which we have currently assigned 11.  Below is a more detailed explanation of each command, taken from El’endia’s documentation.

  • MNZ [test] [value] [dest] – Move if not zero; sets [dest] to [value] if [test] is not zero.
  • MLZ [test] [value] [dest] – Move if less than zero; sets [dest] to [value] if [test] is less than zero.
  • ADD [val1] [val2] [dest] – Add; adds [val1] to [val2] and stores the result in [dest].
  • SUB [val1] [val2] [dest] – Subtract; subtracts [val2] from [val1] and stores the result in [dest].
  • AND [val1] [val2] [dest] – Bitwise AND; bitwise ANDs together [val1] and [val2] and stores the result in [dest].
  • OR [val1] [val2] [dest] – Bitwise OR; bitwise ORs together [val1] and [val2] and stores the result in [dest].
  • XOR [val1] [val2] [dest] – Bitwise XOR; bitwise XORs together [val1] and [val2] and stores the result in [dest].
  • ANT [val1] [val2] [dest] – Bitwise AND-NOT; bitwise ANDs together [val1] and (NOT [val2]) and stores the result in [dest].
  • SL [val1] [val2] [dest] – Shift left; shifts [val1] left by [val2] bits and stores the result in [dest].
  • SRL [val1] [val2] [dest] – Shift right (logical); shifts [val1] right by [val2] bits and stores the result in [dest]. Doesn’t preserve sign.
  • SRA [val1] [val2] [dest] – Shift right (arithmetic); shifts [val1] right by [val2] bits and stores the result in [dest], while preserving sign.


As of right now, we do not have specialized JUMP commands or an unconditional MOV command, because all of those can be represented as conditional moves. We might eventually add an unconditional move command if we determine that it will provide a good performance improvement.

For example, an unconditional jump is typically represented as MLZ -1 28 0 to jump to instruction 28.

Addressing Modes

Addressing modes are represented as letter prefixes to the values.  For example, the value 753 represents a hardcoded value (mode 0), while the value A753 represents the contents of address 753 (mode 1).  Mode 2 is represented as B753, and mode 3 is represented as C753.

Input / Output

Input and output are represented using hard-coded RAM addresses, which serve as “ports” to other devices, like the “screen” or a “button.”  This means that there are no special opcodes for I/O.  With the interpreter, input is provided by manually editing a specified RAM address, and output is read from a specified address.

Line Numbering

The interpreter requires that every line of QFTASM be prefixed by a line number, with one instruction per line.  This is more for the convenience of the programmer, so that I can tell where jumps go.


Comments can be added to a line by adding a semicolon, after which everything is ignored. Comments can be hand-written or auto-generated by the compiler.

Future Expansions

Among the opcodes that may be added to QFTASM in the future are:

  • NOT, which can be currently represented as ANT 65535 [value].
  • NAND, NOR, XNOR, which currently require two steps, but which we haven’t needed yet.
  • Something that’s related to multiplication, although we will probably just implement the shift-and-add algorithm in QFTASM.
  • Something that’s related to division or modulus, although we will probably just implement relevant algorithms in QFTASM.

Example Code

The following is a very inefficient program that calculates prime numbers through trial subtraction.  It was compiled by my compiler, which will be the subject of a later post.  This program is runnable on the interpreter.

0. MLZ -1 3 3;
1. MLZ -1 7 6; preloadCallStack
2. MLZ -1 2 1; beginDoWhile0_infinite_loop
3. MLZ -1 1 4; beginDoWhile1_trials
4. ADD A4 2 4;
5. MLZ -1 A3 5; beginDoWhile2_repeated_subtraction
6. SUB A5 A4 5;
7. SUB 0 A5 2;
8. MLZ A2 6 0;
9. MLZ 0 0 0; endDoWhile2_repeated_subtraction
10. MLZ A5 4 0;
11. MLZ 0 0 0; endDoWhile1_trials
12. SUB A4 A3 2;
13. MNZ A2 16 0; beginIf3_prime_found
14. MLZ 0 0 0;
15. MLZ -1 A3 1; endIf3_prime_found
16. ADD A3 2 3;
17. MLZ -1 4 0;
18. MLZ -1 1 4; endDoWhile0_infinite_loop

One thought on “QFTASM

  1. I just thought: Number limit is 65.536, I might just let it calculate all the prime numbers up to 65.536 and see what it does when it overflows. Well, turns out, with the fastest speed you can set it takes 51 years to get there. Nice.

Leave a Reply

Your email address will not be published. Required fields are marked *