25.13 Inline Assembly
Rust supports inline assembly for cases where you need direct control over the CPU or hardware—often a requirement in certain low-level tasks. You use the asm!
macro (from std::arch
), and it must reside in an unsafe block because the compiler cannot validate the correctness or safety of raw assembly code.
25.13.1 When and Why to Use Inline Assembly
Inline assembly is useful for:
- Performance-Critical Operations: Specific optimizations may require instructions the compiler does not typically generate.
- Hardware Interaction: Managing CPU registers or working with specialized hardware instructions.
- Low-Level Algorithms: Some algorithms demand unusual instructions or extra fine-tuning.
25.13.2 Using Inline Assembly
The asm!
macro specifies assembly instructions, input and output operands, and optional settings. Below is a simple x86_64 example that moves a constant 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 has finished.- The entire block is
unsafe
because the compiler cannot check the assembly code.
25.13.3 Best Practices and Considerations
- Encapsulation: Keep inline assembly in small functions or modules, exposing a safe API wherever possible.
- Platform Specifics: Inline assembly is architecture-dependent; code for x86_64 may not run elsewhere.
- Stability: Certain aspects of inline assembly may require nightly Rust on some targets.
- Documentation: Explain your assembly’s purpose and assumptions so maintainers understand its safety considerations.
Used judiciously, inline assembly in unsafe blocks grants fine control while retaining Rust’s safety for the rest of your code.