# 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.