Rust
asm! macro
Write assembly with core::arch::asm!.
The asm! macro
core::arch::asm! lets you write processor instructions directly inside Rust code (stable since Rust 1.59). It can only be used inside unsafe, because the compiler can't check what the instructions do. The default syntax on x86 is Intel:
use std::arch::asm;
let mut x: u64 = 3;
unsafe {
asm!("add {0}, 4", inout(reg) x);
}
// x == 7
{0} is a placeholder; the compiler puts a register of its choosing there. The code is platform-specific, so it's usually guarded with #[cfg(target_arch = "x86_64")].
Portability
Assembly is tied to an architecture. To keep code buildable on every platform, a separate implementation per architecture or a generic fallback is written:
#[cfg(target_arch = "x86_64")]
fn dort_ekle(mut x: u64) -> u64 {
unsafe { std::arch::asm!("add {0}, 4", inout(reg) x) };
x
}
#[cfg(not(target_arch = "x86_64"))]
fn dort_ekle(x: u64) -> u64 {
x + 4
}
Supported architectures: x86/x86-64, ARM/AArch64, RISC-V, LoongArch and a few others.
Exercise First assembly
Write the dort_ekle function above with asm! for x86-64 and in plain Rust for other architectures. Print the result of dort_ekle(3).
Show example solution
#[cfg(target_arch = "x86_64")]
fn dort_ekle(mut x: u64) -> u64 {
// SAFETY: yalnızca x'in yazmacını değiştirir.
unsafe { std::arch::asm!("add {0}, 4", inout(reg) x) };
x
}
#[cfg(not(target_arch = "x86_64"))]
fn dort_ekle(x: u64) -> u64 {
x + 4
}
fn main() {
println!("{}", dort_ekle(3));
}
Test yourself
-
When is inline assembly a justified choice?
- For readability
- Never
- When a special instruction or hardware access that Rust can't express is needed
- Always, to speed code up
Show answer
When a special instruction or hardware access that Rust can't express is needed — The compiler usually produces code as good as hand-written assembly; std::arch intrinsics and measurement are tried first.
-
Assembly macro
unsafe {
std::arch::____!("add {0}, 4", inout(reg) x);
}
Show answer
unsafe {
std::arch::asm!("add {0}, 4", inout(reg) x);
}
-
Item and meaning
- asm!(..)
- Inline assembly
- {0}
- Placeholder
- inout(reg) x
- Input and output
- #[cfg(target_arch)]
- Architecture guard
Next lesson: Operands