Website Summary Files Commits Branches @commit @diff @stats
path: root / assembler / README.md
blob: 0b148e589fd977d9bba19d2d00ca4425072952c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# tonkobali assembler

This is a very limited assembler.
Since we support only a single instruction (SUBLEQ), the assembler can also take in "higher-level" instructions which are then simplified (an operation which I call in the codebase as "collapse") to SUBLEQ.

The main goal is to use these higher-order instructions, not subleq itself.
Look at the `examples` directory for examples.

## Text format

There are two types of lines in your source file: instruction calls and variable definitions.
Blank lines are allowed.

### Instruction calls

```asm
label: instruction arg1, arg2, ... ; Comment until the end of the line
```

Labels and comments are optional.
A label is a name, refer to [names](#names) for allowed characters.

You may separate a label and it's instruction by a newline and blank lines.
You may issue multiple labels one after another, but **only** when separated by at least one newline (meaning you may not define two labels on the same line).

Instruction must be separated from their first argument with a blank (space or tab).
Capitalisation is **not** ignored.

Arguments are [values](#values), with minor type limitations in certain higher-order instructions.
They are seprated by commas with arbitrary amount of blank (space or tab) characters around the commas.
All arguments must be on the same line as their instruction.

### Variable definitions

```asm
name = value ; Comment until the end of the line
```

Comments are optional.

### Names

A name is a sequence of ASCII letters (capital and lowercase), numbers, underscore, dot, $ and ?.
Capitalization is **not** ignored.

There is no scoping of names, or in other words, every name is global.
Labels are also names.

Repeat names overwrite previous ones **globally**, meaning no matter where two definitions are, the second will override the first everywhere in your program.

### Values

All values are reduced to addresses in the memory (after all, all SUBLEQ arguments are addresses).
We distinguish between three "types" of values:

- Absolute addresses, these are addresses in the memory and are passed down as-is

  They are defined as unsigned numbers, prepended with the `%` symbol.
  For example: `%384`.

- Number constants, they're placed somewhere in memory and their address is passed

  They are signed 64-bit numbers (as is the Word type for our VM).
  For example: `56`, `-912`.

- Strings, they're converted into a sequence of numbers, each being the decimal ASCII representation of the character, ending with a zero. The address of the first "ltter" is passed

  They are a sequence of characters, surrounded by double quotes.
  Double quotes and backwards slash can be escaped by prepending a backwards slash.
  For example: `"Hello World"`, `"He said \"Wow\""`, `"C:\\System"`.

## Higher-order instructions

| Instruction | Description                                                               | Argument 1          | Argument 2          |
| ----------- | ------------------------------------------------------------------------- | ------------------- | ------------------- |
| jmp         | Jump to address                                                           | Location to jump to |                     |
| inc         | Increment value                                                           | Location of value   |                     |
| dec         | Decrement value                                                           | Location of value   |                     |
| add         | Add the first value to the second and store the result in the second      | First value         | Second value        |
| sub         | Subtract the first value to the second and store the result in the second | First value         | Second value        |
| mov         | Move (copy) the value from the first address to the second address        | First location      | Second location     |
| beq         | Branch if first value is equal to zero                                    | Value to check      | Location to jump to |
| jsr         | Jump to subroutine                                                        | Location to jump to |                     |
| rts         | Return from subroutine                                                    |                     |                     |

The idea of subroutines is that jumping to one is the same as normal jump, however the address after the jump is stored.
So, returning from a subroutine allows you to jump back after the location you entered the subroutine from.
Addresses are stored in the memory via a "stack", in the first 1024 addresses.