Intrinsics are built-in functions that generate static assembly output. The key difference between a keyword and an intrinsic is that the behavior of a keyword is dependent on other words in the program, whereas an intrinsic will always generate the same assembly output regardless of the context in which it is used.
- AND
- ARGC
- ARGV
- DIV
- DROP
- DUP
- ENVP
- EXEC
- EQ
- GE
- GT
- LE
- LOAD_BYTE
- LOAD_WORD
- LOAD_DWORD
- LOAD_QWORD
- LT
- MINUS
- MOD
- MUL
- NE
- OR
- OVER
- PLUS
- ROT
- SHL
- SHR
- STORE_BYTE
- STORE_WORD
- STORE_DWORD
- STORE_QWORD
- SWAP
- SYSCALL0
- SYSCALL1
- SYSCALL2
- SYSCALL3
- SYSCALL4
- SYSCALL5
- SYSCALL6
Perform a calculation operation for two integers and push the result.
- Pop two integers from the stack
- Perform a calculation operation to the popped values
- Push result
Different calculation intrinsics:
- PLUS (+)
- MINUS (-)
- MUL (*)
- DIV (/)
- MOD (%)
Perform a certain comparison operation to two integers.
Different comparison intrinsics:
- EQ: Equal (==)
- GE: Greater than or equal (>=)
- GT: Greater than (>)
- LE: Less than or equal (<=)
- LT: Less than (<)
- NE: Not equal (!=)
A bit shift moves each digit in a number's binary representation left or right.
Different bit shift intrinsics:
- SHL: Bit shift left (<<)
- SHR: Bit shift right (>>)
Perform bitwise AND for two integer values.
- Pop two integers from the stack
- Perform bitwise AND operation to the popped values
- Push the result of the bitwise operation as INT
Push the command line argument count to the stack.
Push the pointer to the command line argument array to the stack.
Remove the top element from the stack.
a b -> b
Duplicate the top element of the stack.
a b -> a a b
Push the environment pointer to the stack.
Pop and execute a function pointer from the stack.
Load a value from a memory location pointer by a PTR. LOAD-intrinsics push a value pointed by a pointer-like type to the stack.
- Pop a PTR type value from the stack
- Push the value pointed by the popped pointer to the stack
There are four different LOAD intrinsic variants:
- LOAD_BYTE (8-bit)
- LOAD_WORD (16-bit)
- LOAD_DWORD (32-bit)
- LOAD_QWORD (64-bit)
For example, to load a value of type INT (64-bit) from a memory location to the stack, you should use the LOAD_QWORD intrinsic. Also, it is preferred to use the type.load functions from the std-library which also explicitly cast the loaded value to the corresponding type. There is a typed load function for every built-in type, for example int.load
.
Perform bitwise OR for two integer values.
- Pop two integers from the stack
- Perform bitwise OR operation to the popped values
- Push the result of the bitwise operation as INT
Push a copy of the second element of the stack.
a b -> b a b
Rotate the top three items on the stack so that the third element moves to the top and the other two moves one spot deeper in the stack.
a b c -> c a b
A PTR stores a value to a memory location pointer. STORE-intrinsics pops two values from the stack. The second item of the stack is stored in the memory address pointed by the first.
- The top element should be of type PTR
- The second element is stored at the address pointed by the pointer
There are four different STORE intrinsic variants:
- STORE_BYTE (8-bit)
- STORE_WORD (16-bit)
- STORE_DWORD (32-bit)
- STORE_QWORD (64-bit)
For example, to store INT (64-bit) to a memory location, you should use the STORE_QWORD intrinsic. Also, it is preferred to use the type.store functions from the std-library, which also checks if the value in the stack that is to be stored is of the correct type. There is a typed store function for every built-in type, for example int.store
.
Swap the top two elements in the stack.
a b -> b a
SYSCALL-intrinsic variants call a Linux syscall. Syscalls require different amounts of arguments from 0 to 6. Different variants are named SYSCALL0 - SYSCALL6 by the amount of arguments. The first argument should be an integer.
- Pop the top element and the required number of arguments from the stack
- Call the syscall which matches the first popped element
The different syscall constants can be found from lib/sys.torth. Naming convention (case sensitive): SYS_. For example, SYS_write.