ANASM documentation

Table of contents

Instructions

All instructions in ANASM are 3 characters long. Their names are the same as specified in the AVM documentation, except they are lower case.

Some instructions take a parameter. That parameter is written right after the instruction, separated from the instruction by a space, like so

INST PARAMETER

Literals

Instruction parameters are all just numbers, but they are a bit abstracted in anasm. One type of parameters are literals. Literals can be decimal integers, hexadecimal integers, octal integers, binary data, floating point numbers or ascii characters.

Decimal

Decimal integers have no prefix, they are written like normal decimal integers

1024
5
256

Hexadecimal

Hexadecimal integers are prefixed with 0x or 0X, and the letters in them can be both lower or upper case

0xff
0xEDA
0X5AB4ED

Octal

octal integers are prefixed with 0o or 0O

0o7
0O452

Binary

Binary data is prefixed with 0b or 0B

0b110
0B11010

Floating point numbers

Floating point numbers, similar to decimal integers, are written normally, with no prefix, and the floating point is marked with a .

3.14
12.7

ASCII characters

ASCII character literals are surrounded by ' and can only be a single character. There are exceptions - the escape sequences, which are talked about later in the strings escape sequences section

'A'
'$'

Strings

String literals are special, because they cannot be passed as parameters to instructions. They can only be assigned to variables. Strings are surrounded by " quotes

"Hello, world!"
"How are you?"

Escape sequences

Strings also have escape sequences, which are used for putting special ascii characters that are not printable into the string, such as a newline or the carriage return. These escape sequences start with a \ and are two characters long (including the slash). This is a table of the escape sequences and the bytes they turn into

Escape sequence Value
\0 0x00
\a 0x07
\b 0x08
\e 0x1b
\f 0x0c
\n 0x0a
\r 0x0d
\t 0x09
\v 0x0b
\\ 0x5c (\)
\" 0x22 (")
\' 0x27 (')

Example of escape sequences in a string

"Hello, world!\n"

Labels

Another type of instruction parameters are labels. Labels mark a position in the program (an instruction address), so we can jump to that position easily, without having to manually calculate its address. When we create a label, we prefix it with a . and then type the name after it

.my_label
	psh 5

This label holds the address of the psh instruction right below it. Example of using the label:

jmp my_label

Label names can only contain lower case or upper case ASCII letters, digits, _ and $

Entry point label

A special kind of label is the entry point label, which is defined with

.entry

This label marks the start of the program - where the program will begin executing.

Constant expressions

Constant expressions allow you to do calculations which will be evaluated at compile time. Instead of using a calculator to divide 8 by 2, you can use a constant expression to calculate it. The syntax is similar to lisp:

(OPERATOR PARAMS)

where OPERATOR is one of the available operators to use, and PARAM are its parameters. See the table of operations

Operation Description
+ Any amount of parameters, adds them together
- Any amount of parameters, subtracts them
* Any amount of parameters, multiplies them
/ Any amount of parameters, divides them
% Any amount of parameters, performs modulus on them
^ Any amount of parameters, performs power on them
& Any amount of parameters, performs bit and on them
| Any amount of parameters, performs bit or on them
>> Any amount of parameters, performs bit shifting to right on them
<< Any amount of parameters, performs bit shifting to left on them
sizeof One parameter, which can be either a type or a variable, and returns its size

The true power of constant expressions comes with using them to calculate an offset of a variable, for example:

let NUMS byte = 5, 12

.entry
	psh (+ NUMS 1)
	r08
	prt

This example would print 12.

Nested constant expressions are also allowed:

prt (+ (+ 5 5) 2)

However, constant expressions do not work with floating point numbers as you would expect. All simple literals are turned into words at compile time, and these constant expression operators operate on them as if they were integers, because they have no way of knowing what they were originally.

Variables

Being able to write data to memory is nice, but manually keeping track of all the addresses and stuff is painful. For automating this, ANASM has the let keyword, which is used to define variables that automatically calculate their address in memory.

The syntax of the keyword is

let NAME TYPE = DATA

where NAME is the name of the variable that we will use to reference it (variable names can only contain the same characters as label names), TYPE is the type (size) of a single element and DATA is a list of the data it holds. The available types are below

Keyword Size (in bytes)
char 1
byte 1
i16 2
i32 4
i64 8
f64 8

The data list elements are separated with a , and can be anything of the literals (including strings). Example of a valid variable

 let ABC char = 'a', 'b', 'c'

This variable will be 3 bytes in total, because it contains 3 data elements each of the size 1 byte (sz8)

Using the variables data addresses is the same as with labels.

psh @ABC
r08
prt

Macros

Macros are made to eliminate magic numbers. They are identifiers tied to a value, and when they are used somewhere, they are replaced by that value during compilation. The syntax of a macro definition is

mac NAME = DATA

where NAME is the name of the macro and DATA is the value it will be replaced with. Example:

mac FIVE_PLUS_TWO = (+ 5 2)

.entry
	psh FIVE_PLUS_TWO
	prt

Includes

To avoid long source files, anasm provides file including. Including simply copy-pastes the code of the included file into the source file. The syntax is

include PATH

where PATH is the path of the file to include. Example:

include "test.anasm"

Embeds

To eliminate the cost and annoyance of reading files at runtime, you can embed the file into the programs memory at compilation. The syntax is

emb NAME PATH

where NAME is the name of the variable with the file contents, and PATH is the path of the file to embed. Example:

emb MY_FILE "file.txt"

Identifiers created by the emb keyword are just like variables with element type char. The data is not ended by a 0 or by an EOF.

Comments

Comments are an important part of assembly, because without them you will probably forget how any of the code works. Comments start with a # and last until the end of the line

# Hello, i am a comment!

Examples

Probably the best way to learn is by seeing examples. Example ANASM programs are in the examples folder in the ANASM github repo.