asm! macro
- Rust course
- Expert
- Lesson 25/46
- 4 min
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.
Practice 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).
Starter code
fn main() {
// buraya yaz
}Sample 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));
}Expected output
7
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 When is inline assembly a justified choice?
- For readability
- Never
- When a special instruction or hardware access that Rust can't express is needed Correct answer
- Always, to speed code up
Explanation: The compiler usually produces code as good as hand-written assembly; std::arch intrinsics and measurement are tried first.
2 Assembly macro
unsafe {
std::arch::____!("add {0}, 4", inout(reg) x);
}
unsafe {
std::arch::asm!("add {0}, 4", inout(reg) x);
}
Explanation: asm! is for writing inline assembly.
3 Item and meaning
| Term | Meaning |
|---|---|
asm!(..) |
Inline assembly |
{0} |
Placeholder |
inout(reg) x |
Input and output |
#[cfg(target_arch)] |
Architecture guard |