3 The tracking issue for this feature is: [#29722]
5 [#29722]: https://github.com/rust-lang/rust/issues/29722
7 ------------------------
9 For extremely low-level manipulations and performance reasons, one
10 might wish to control the CPU directly. Rust supports using inline
11 assembly to do this via the `asm!` macro.
14 asm!(assembly template
22 Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
23 crate to allow) and of course requires an `unsafe` block.
25 > **Note**: the examples here are given in x86/x86-64 assembly, but
26 > all platforms are supported.
30 The `assembly template` is the only required parameter and must be a
31 literal string (i.e. `""`)
36 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
44 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
45 fn foo() { /* ... */ }
54 (The `feature(asm)` and `#[cfg]`s are omitted from now on.)
56 Output operands, input operands, clobbers and options are all optional
57 but you must add the right number of `:` if you skip them:
61 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
62 # fn main() { unsafe {
69 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
73 Whitespace also doesn't matter:
77 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
78 # fn main() { unsafe {
79 asm!("xor %eax, %eax" ::: "eax");
81 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
87 Input and output operands follow the same format: `:
88 "constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
89 expressions must be mutable lvalues, or not yet assigned:
93 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
94 fn add(a: i32, b: i32) -> i32 {
104 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
105 # fn add(a: i32, b: i32) -> i32 { a + b }
108 assert_eq!(add(3, 14159), 14162)
112 If you would like to use real operands in this position, however,
113 you are required to put curly braces `{}` around the register that
114 you want, and you are required to put the specific size of the
115 operand. This is useful for very low level programming, where
116 which register you use is important:
120 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
121 # unsafe fn read_byte_in(port: u16) -> u8 {
123 asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
130 Some instructions modify registers which might otherwise have held
131 different values so we use the clobbers list to indicate to the
132 compiler not to assume any values loaded into those registers will
137 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
138 # fn main() { unsafe {
139 // Put the value 0x200 in eax:
140 asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
142 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
146 Input and output registers need not be listed since that information
147 is already communicated by the given constraints. Otherwise, any other
148 registers used either implicitly or explicitly should be listed.
150 If the assembly changes the condition code register `cc` should be
151 specified as one of the clobbers. Similarly, if the assembly modifies
152 memory, `memory` should also be specified.
156 The last section, `options` is specific to Rust. The format is comma
157 separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
158 specify some extra info about the inline assembly:
160 Current valid options are:
162 1. *volatile* - specifying this is analogous to
163 `__asm__ __volatile__ (...)` in gcc/clang.
164 2. *alignstack* - certain instructions expect the stack to be
165 aligned a certain way (i.e. SSE) and specifying this indicates to
166 the compiler to insert its usual stack alignment code
167 3. *intel* - use intel syntax instead of the default AT&T.
171 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
175 asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
177 println!("eax is currently {}", result);
179 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
185 The current implementation of the `asm!` macro is a direct binding to [LLVM's
186 inline assembler expressions][llvm-docs], so be sure to check out [their
187 documentation as well][llvm-docs] for more information about clobbers,
190 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
192 If you need more power and don't mind losing some of the niceties of
193 `asm!`, check out [global_asm](global-asm.md).