Registers

r0 - r12

The above registers are general purpose registers; Meaning that you can set them to integers, read from them and use them in commands.

acc

The Accumulator has two roles.

  1. Acts as a general purpose register

  2. Stores the result of the logic operators (teq, tne, …​)

Special Operators

#

Syntax: #[number]

The above operator is used to define tell the compiler that the number following it is a constant.

+

Syntax: + [cmd]

The above operator is a prefix. Commands prefixed with this execute only if the value stored in the accumulator is not equal to 0.

Example: + mov r0 #100

In the above example, the value of r0 will be set to 100, only if the value stored in the accumulator is not equal to 0.

labels

Syntax: [name]:

Labels are used to define subroutines. You need to write the name of the subroutine and add a colon to define a label. All the instructions following it have to be indented.

Example:

start:
    mov r0 #100
end:
    mov r7 #1
    swi

General Commands

mov

Syntax: mov [register] [constant]

This sets the value of the specified register to the specified constant

Example: mov r10 #23

In the above example, the value of r10 is set to 23

print

Syntax: print [register | constant]

This prints the value stored in the specified register, or the constant to the console

Example: print r4 | print #10

In the first example, the value of r4 is printed. In the second example, 10 is printed.

swi

Syntax: swi

This checks the value in r7 and performs actions. As of right now, it defaults to exit the program no matter which value is stored in r7.

Arithmetic

add

Syntax: add [register to store the result] [register | constant] [register | constant]

This adds the values of the first two arguments and stores it in the register specified by the first argument.

Example: add r0 r1 r2

sub

Syntax: sub [register to store the result] [register | constant] [register | constant]

This subtracts the value of the second argument by the value of the third argument and stores it in the register specified by the first argument.

Example: sub r0 r0 #100

mul

Syntax: sub [register to store the result] [register | constant] [register | constant]

This multiplies the value of the first argument by the value of the second argument and stores it in the register specified by the first argument.

Example: mul r0 #1233333 #100000

div

Syntax: div [register to store the result] [register | constant] [register | constant]

This divides the value of the first argument by the value of the second argument and stores it in the register specified by the first argument.

Example: div r0 r4 #78

Logic

teq

Syntax: teq [register | constant] [register | constant]

This tests whether the value of the first argument is equal to the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: teq r0 #100

tne

Syntax: tne [register | constant] [register | constant]

This tests whether the value of the first argument is not equal to the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: tne #10 #20

tgt

Syntax: tgt [register | constant] [register | constant]

This tests whether the value of the first argument is greater than the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: tgt r8 r12

tgte

Syntax: tgte [register | constant] [register | constant]

This tests whether the value of the first argument is greater than or equal to the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: tgte #100 r1

tlt

Syntax: tlt [register | constant] [register | constant]

This tests whether the value of the first argument is lesser than the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: tlt r0 r2

tlte

Syntax: tlte [register | constant] [register | constant]

This tests whether the value of the first argument is lesser than or equal to the value of the second argument and stores the result as a 1 (True) or 0 (False) in the 'acc' register.

Example: tlte r0 #100

Subroutines

jmp

Syntax: jmp [label]

This pushes the current page to the stack and executes the instructions of the specified subroutine.

Example: jmp add_loop

In the above example, the program will jump to the 'add_loop' subroutine and execute its instructions.

return

Syntax: return

This ends the current subroutine and returns to the subroutine that called it.

Structure

Similar to public static void main(String[] args) in Java and func main() in Go, the subroutine _start is where the main code goes to.

_start:
    ....

While you could most definitely write all your code in the _start subroutine, you could create other subroutines to help out as well, as you will see below.

Example Project

Let’s build an example project. This project will add the number 23 to r0, fifteen times. Here’s how it would look.

_start:
    mov r0 #0
    mov r1 #0
    jmp add_loop
    jmp end

add_loop:
    add r0 r0 #23
    add r1 r1 #1
    tne r1 #15
    + jmp add_loop
    return

end:
    print r1
    print r0
    mov r7 #1
    swi

In _start, we set the value of r0 (The main result) to 0 and the value of r1 (The counter) to 0. We then jump to the add_loop subroutine. Once it returns, we jump to the end subroutine.

In add_loop, we add 23 to the value stored in r0, and increment r1 by 1. We then check if the value stored in r1 is not equal to 15, which will lead to calling the same subroutine again. This is done until the value of r1 is equal to 15, where we return to the calling subroutine by using the return keyword (Though it does have to fall through quite a few pages).

In end, we print the value of r1 (The counter) and r0 (The value) and end the program. You could run it for yourself and see if the output is correct.