25.13 Inline Assembly
Rust supports inline assembly for cases where you need direct control over the CPU or hardware—important in some low-level systems programming tasks. You use the asm!
macro (from std::arch
), and it must live inside an unsafe block because the compiler cannot validate the assembly's correctness or safety.
25.13.1 When and Why to Use Inline Assembly
Inline assembly is useful for:
- Performance-Critical Operations: Certain optimizations might require instructions the compiler does not normally emit.
- Hardware Interaction: For instance, manipulating CPU registers or interfacing with specialized hardware.
- Low-Level Algorithms: Some algorithms need unusual instructions or extra tuning.
25.13.2 Using Inline Assembly
The asm!
macro specifies the assembly instructions, input/output operands, and additional options. Below is a simple example (on x86_64) that moves an immediate value into a variable:
use std::arch::asm; fn main() { let mut x: i32 = 0; unsafe { // Moves the immediate value 5 into the register bound to 'x'. asm!("mov {0}, 5", out(reg) x); } println!("x is: {}", x); }
mov {0}, 5
loads the literal 5 into the register bound tox
.out(reg) x
places the result inx
after the assembly finishes.- The entire block is
unsafe
because the compiler cannot check assembly code.
25.13.3 Best Practices and Considerations
- Encapsulation: Keep inline assembly in small functions or modules, exposing a safe API if possible.
- Platform Specifics: Inline assembly is architecture-specific; code written for x86_64 may not work on other platforms.
- Stability: Inline assembly might require nightly Rust on certain targets or for specific features.
- Documentation: Explain the rationale and assumptions behind any assembly so that future maintainers understand its safety requirements.
Used sparingly and carefully, inline assembly in unsafe blocks gives you fine-grained control while preserving most of Rust's safety guarantees elsewhere.