Assembler reference
Dialect declaration
To use the assembler mode start your file with the following line:
(mod asm)
Imports
To import functions from another module use the use
statement:
(use module-name)
Static variables
Static variables are variables that are directly stored inside the binary.
The assembler supports static variables of the following types:
int
(64-bit)uint
(64-bit)float
(64-bit)str
buffer
(zero-initialized)
str
Static strings (str
) consist of a uint
representing the size of the string
in bytes followed by the bytes of the string terminated by a zero-byte.
Strings are aligned to 4 bytes by appending zero-bytes to the end.
Referencing a string returns the address to the bytes of the string.
Syntax
Static variables are declared like this:
(static a 10) ; int
(static b 10u) ; uint
(static c 10.0) ; float
(static d "A string") ; str
(static e (buffer 1024u)) ; buffer of size 1024
Labels
Labels are like functions though they do not have a signature and may interact with the state of the runtime in any way possible.
Labels may be public (+label
) or private (-label
).
Public modules can be accessed by other modules while private modules can only be accessed from the module they were declared in.
Syntax
A label is declared like this:
(+label add (do
(add r0 r0 r1)
))
Control flow
The assembler does conditional code execution through control flow statements.
do
The do
statement executes multiple instructions after one another.
It looks like this:
(+label exit-failure (do
(mov r0 1u)
(int 4u)
(crash)
))
if
The if
statement executes code conditionally.
It takes one of the possible conditions (=
, !=
, <
, >
, <=
, >=
, =0
,
!0
), a register with the source, and code to execute.
It can be used like this:
(+label abs (do
(mov r1 0u)
(cmps r1 r0 r1)
(if >= r1 (ret))
(mov r1 0u)
(sub r0 r1 r0)
))
Here it is used with the early return pattern.
while
The while
statement executes code while a certain condition is met.
It has a syntax similar to the one of an if
statement:
(+label factorial (do
(mov r1 1u)
(while !0 r0 (do
(mul r1 r0 r1)
(sub r0 r0 1u)
))
(mov r0 r1)
))
do-while
Alternatively to the while
loop you can use a do-while
loop.
The difference is that for the do-while
loop the first iteration is executed
always.
Additionally the syntax is a bit different:
(+label test (do
; ...
(do-while (do
; ...
) !0 r0)
; ...
))
Instructions
add Xdst Xlhs u17
- Add
u17
toXlhs
and store the result inXdst
- Supports signed and unsigned integers
- Add
add Xdst Xlhs Xrhs
- Add
Xrhs
toXlhs
and store the result inXdst
- Supports signed and unsigned integers
- Add
sub Xdst Xlhs u17
- Subtract
u17
fromXlhs
and store the result inXdst
- Supports signed and unsigned integers
- Subtract
sub Xdst Xlhs Xrhs
- Subtract
Xrhs
fromXlhs
and store the result inXdst
- Supports signed and unsigned integers
- Subtract
mul Xdst Xlhs u17
- Multiply
Xlhs
byu17
and store the result inXdst
- Supports signed and unsigned integers
- Multiply
mul Xdst Xlhs Xrhs
- Multiply
Xlhs
byXrhs
and store the result inXdst
- Supports signed and unsigned integers
- Multiply
div Xdst Xlhs u17
- Divide
Xlhs
byu17
and store the result inXdst
- Supports unsigned integers only
- Divide
div Xdst Xlhs Xrhs
- Divide
Xlhs
byXrhs
and store the result inXdst
- Supports unsigned integers only
- Divide
rem Xdst Xlhs u17
- Store the remainder of
Xlhs
andu17
inXdst
- Supports unsigned integers only
- Store the remainder of
rem Xdst Xlhs Xrhs
- Store the remainder of
Xlhs
andXrhs
inXdst
- Supports unsigned integers only
- Store the remainder of
divs Xdst Xlhs i17
- Divide
Xlhs
byi17
and store the result inXdst
- Supports signed integers only
- Divide
divs Xdst Xlhs Xrhs
- Divide
Xlhs
byXrhs
and store the result inXdst
- Supports signed integers only
- Divide
rems Xdst Xlhs i17
- Store the remainder of
Xlhs
andi17
inXdst
- Supports signed integers only
- Store the remainder of
rems Xdst Xlhs Xrhs
- Store the remainder of
Xlhs
andXrhs
inXdst
- Supports signed integers only
- Store the remainder of
mov Xdst u22
- Move
u22
intoXdst
- Move
mov Xdst Xsrc
- Move
Xsrc
intoXdst
- Move
movs Xdst i22
- Move
i22
intoXdst
with sign extension
- Move
shl Xdst Xlhs u11
- Move
Xlhs
shifted left byu11
intoXdst
- Move
shl Xdst Xlhs Xrhs
- Move
Xlhs
shifted left byXrhs
intoXdst
- Move
shr Xdst Xlhs u11
- Move
Xlhs
shifted right byu11
intoXdst
- Move
shr Xdst Xlhs Xrhs
- Move
Xlhs
shifted right byXrhs
intoXdst
- Move
shrs Xdst Xlhs u11
- Move
Xlhs
arithmetically shifted right byu11
intoXdst
- Move
shrs Xdst Xlhs Xrhs
- Move
Xlhs
arithmetically shifted right byXrhs
intoXdst
- Move
ldrb Xdst Xsrc i11
- Load 8 bits from address
Xsrc
with offseti11
intoXdst
- Load 8 bits from address
ldrh Xdst Xsrc i11
- Load 16 bits from address
Xsrc
with offseti11
intoXdst
- Load 16 bits from address
ldrw Xdst Xsrc i11
- Load 32 bits from address
Xsrc
with offseti11
intoXdst
- Load 32 bits from address
ldr Xdst Xsrc i11
- Load 64 bits from address
Xsrc
with offseti11
intoXdst
- Load 64 bits from address
strb Xdst Xsrc i11
- Store 8 bits from
Xsrc
to addressXdst
with offseti11
- Store 8 bits from
strh Xdst Xsrc i11
- Store 16 bits from
Xsrc
to addressXdst
with offseti11
- Store 16 bits from
strw Xdst Xsrc i11
- Store 32 bits from
Xsrc
to addressXdst
with offseti11
- Store 32 bits from
str Xdst Xsrc i11
- Store 64 bits from
Xsrc
to addressXdst
with offseti11
- Store 64 bits from
int 16u
- Interrupt the runtime with code
u16
- Interrupt the runtime with code
ncall u21
- Call a native function with id
u21
- Call a native function with id
ncall Xid
- Call a native function with id
Xid
- Call a native function with id
vcall u21
- Call a virtual function with id
u21
- Call a virtual function with id
vcall Xid
- Call a virtual function with id
Xid
- Call a virtual function with id
addf Xdst Xlhs Xrhs
- Add the float
Xrhs
to the floatXlhs
and store the result inXdst
- Add the float
subf Xdst Xlhs Xrhs
- Subtract the float
Xrhs
from the floatXlhs
and store the result inXdst
- Subtract the float
mulf Xdst Xlhs Xrhs
- Multiply the float
Xrhs
by the floatXlhs
and store the result inXdst
- Multiply the float
divf Xdst Xlhs Xrhs
- Divide the float
Xrhs
by the floatXlhs
and store the result inXdst
- Divide the float
and Xdst Xlhs Xrhs
- Move
Xlhs
&Xrhs
intoXdst
(bitwise and)
- Move
or Xdst Xlhs Xrhs
- Move
Xlhs
|Xrhs
intoXdst
(bitwise or)
- Move
xor Xdst Xlhs Xrhs
- Move
Xlhs
^Xrhs
intoXdst
(bitwise xor)
- Move
cmp Xdst Xlhs Xrhs
- Compare
Xlhs
andXrhs
and store the result inXdst
- Supports unsigned integers only
- Compare
cmps Xdst Xlhs Xrhs
- Compare
Xlhs
andXrhs
and store the result inXdst
- Supports signed integers only
- Compare
cmpf Xdst Xlhs Xrhs
- Compare the float
Xlhs
and the floatXrhs
and store the result inXdst
- Compare the float
not Xdst Xsrc
- Move !
Xsrc
intoXdst
(bitwise not)
- Move !
fti Xdst Xsrc
- Move the float
Xsrc
converted to an integer intoXdst
- Move the float
itf Xdst Xsrc
- Move the integer
Xsrc
converted to a float intoXdst
- Move the integer
ldbo Xdst
- Load the address of the first byte after the binary header into
Xdst
- Load the address of the first byte after the binary header into
ldpc Xdst
- Load the program counter into
Xdst
- Load the program counter into
zero Xdst
- Move zero into
Xdst
- Move zero into
dbg Xreg
- Debug print the integer
Xreg
- Debug print the integer
inc Xreg
- Increment the integer
Xreg
- Increment the integer
nop
- Do nothing
halt
- Halt the runtime
ret
- Return from a call
crash
- Insert an invalid opcode and crash the runtime dumping the register contents
ref Xdst <static variable>
orlea Xdst <static variable>
- Load the effective address of a static variable into
Xdst
- Load the effective address of a static variable into