Inline assembly
When you need an instruction the compiler will not emit on its own — a special register, a fence, a custom-ABI trampoline — drop to assembly with #asm. The template is a string; the compiler hands it to the backend and wires up the operands you describe.
unsafe {
#asm("nop");
}
#asm is unsafe: the body is opaque to sema and the borrow checker, so it must sit inside an unsafe block.
Operands and clobbers
Operands are named, Rust-style. Each binds a template placeholder {name} to a C+ value with a direction and a register constraint:
fn add(a: i64, b: i64) -> i64 {
let mut sum: i64 = 0;
unsafe {
#asm("add {s}, {a}, {b}",
s = out(reg) sum,
a = in(reg) a,
b = in(reg) b,
clobber("cc"));
}
return sum;
}
- Direction.
inreads a value into the instruction,outwrites a result back, andinoutdoes both through one register. - Constraint.
reglets the compiler pick a register — when you usereg, the matching{name}must appear in the template. Pin a specific register with a string instead, e.g."x0". - Targets. An
outorinoutoperand must name amutvariable. Operands are register-sized scalars. clobber("...")tells the compiler which registers or flags ("cc", a named register) the block trashes, so it does not assume they survive.
#[naked] functions
A #[naked] function gets no compiler-generated prologue or epilogue. Its body is inline assembly that handles the ABI itself and returns on its own. This is the tool for entry stubs, trampolines, and custom-ABI shims where even the standard frame setup is in the way.
#[naked]
fn trampoline() {
unsafe {
#asm("ret");
}
}
The body must be asm-only — any non-asm statement in a #[naked] function is E0909.
Module-level global assembly (a top-level
#asmoutside any function) is deferred to a later release. Today inline assembly lives inside function bodies.