Inline Assembly in Sway
While many users will never have to touch assembly language while writing Sway code, it is a powerful tool that enables many advanced use-cases (e.g., optimizations, building libraries, etc).
ASM Block
In Sway, the way we use assembly inline is to declare an asm
block like this:
asm() {...}
Declaring an asm
block is similar to declaring a function.
We can specify register names to operate on as arguments, we can perform assembly instructions within the block, and we can return a value by specifying a return register.
Here's an example showing what this might look like:
pub fn add_1(num: u32) -> u32 {
asm(r1: num, r2) {
add r2 r1 one;
r2: u32
}
}
The return register is specified at the end of the asm
block, after all the assembly instructions. It consists of the register name and an optional return type. In the above example, the return register name is r2
and the return type is u32
.
If the return type is omitted, it is u64
by default.
The return register itself is optional. If it is not specified, similar to functions, the returned value from the asm
block will be unit, ()
.
An asm
block can only return a single register. If you really need to return more than one value, you can modify a tuple. Here's an example showing how you can implement this for (u64, u64)
:
script;
fn adder(a: u64, b: u64, c: u64) -> (u64, u64) {
let empty_tuple = (0u64, 0u64);
asm(output: empty_tuple, r1: a, r2: b, r3: c, r4, r5) {
add r4 r1 r2; // add a & b and put the result in r4
add r5 r2 r3; // add b & c and put the result in r5
sw output r4 i0; // store the word in r4 in output + 0 words
sw output r5 i1; // store the word in r5 in output + 1 word
output: (u64, u64) // return both values
}
}
fn main() -> bool {
let (first, second) = adder(1, 2, 3);
assert(first == 3);
assert(second == 5);
true
}
Note that this is contrived example meant to demonstrate the syntax; there's absolutely no need to use assembly to add integers!
Note that in the above example:
- we initialized the register
r1
with the value ofnum
. - we declared a second register
r2
(you may choose any register names you want). - we use the
add
opcode to addone
to the value ofr1
and store it inr2
. one
is an example of a "reserved register", of which there are 16 in total. Further reading on this is linked below under "Semantics".- we return
r2
and specify the return type as beingu32
.
An important note is that the ji
and jnei
opcodes are not available within an asm
block. For those looking to introduce control flow to asm
blocks, it is recommended to surround smaller chunks of asm
with control flow (if
, else
, and while
).
Helpful Links
For examples of assembly in action, check out the Sway standard library.
For a complete list of all instructions supported in the FuelVM: Instructions.
And to learn more about the FuelVM semantics: Semantics.