]> git.lizzy.rs Git - rust.git/blob - src/doc/unstable-book/src/asm.md
Fix invalid associated type rendering in rustdoc
[rust.git] / src / doc / unstable-book / src / asm.md
1 # `asm`
2
3 The tracking issue for this feature is: [#29722]
4
5 [#29722]: https://github.com/rust-lang/rust/issues/29722
6
7 ------------------------
8
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.
12
13 ```rust,ignore
14 asm!(assembly template
15    : output operands
16    : input operands
17    : clobbers
18    : options
19    );
20 ```
21
22 Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
23 crate to allow) and of course requires an `unsafe` block.
24
25 > **Note**: the examples here are given in x86/x86-64 assembly, but
26 > all platforms are supported.
27
28 ## Assembly template
29
30 The `assembly template` is the only required parameter and must be a
31 literal string (i.e. `""`)
32
33 ```rust
34 #![feature(asm)]
35
36 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
37 fn foo() {
38     unsafe {
39         asm!("NOP");
40     }
41 }
42
43 // Other platforms:
44 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
45 fn foo() { /* ... */ }
46
47 fn main() {
48     // ...
49     foo();
50     // ...
51 }
52 ```
53
54 (The `feature(asm)` and `#[cfg]`s are omitted from now on.)
55
56 Output operands, input operands, clobbers and options are all optional
57 but you must add the right number of `:` if you skip them:
58
59 ```rust
60 # #![feature(asm)]
61 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
62 # fn main() { unsafe {
63 asm!("xor %eax, %eax"
64     :
65     :
66     : "eax"
67    );
68 # } }
69 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
70 # fn main() {}
71 ```
72
73 Whitespace also doesn't matter:
74
75 ```rust
76 # #![feature(asm)]
77 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
78 # fn main() { unsafe {
79 asm!("xor %eax, %eax" ::: "eax");
80 # } }
81 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
82 # fn main() {}
83 ```
84
85 ## Operands
86
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:
90
91 ```rust
92 # #![feature(asm)]
93 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
94 fn add(a: i32, b: i32) -> i32 {
95     let c: i32;
96     unsafe {
97         asm!("add $2, $0"
98              : "=r"(c)
99              : "0"(a), "r"(b)
100              );
101     }
102     c
103 }
104 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
105 # fn add(a: i32, b: i32) -> i32 { a + b }
106
107 fn main() {
108     assert_eq!(add(3, 14159), 14162)
109 }
110 ```
111
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:
117
118 ```rust
119 # #![feature(asm)]
120 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
121 # unsafe fn read_byte_in(port: u16) -> u8 {
122 let result: u8;
123 asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
124 result
125 # }
126 ```
127
128 ## Clobbers
129
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
133 stay valid.
134
135 ```rust
136 # #![feature(asm)]
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");
141 # } }
142 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
143 # fn main() {}
144 ```
145
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.
149
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.
153
154 ## Options
155
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:
159
160 Current valid options are:
161
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.
168
169 ```rust
170 # #![feature(asm)]
171 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
172 # fn main() {
173 let result: i32;
174 unsafe {
175    asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
176 }
177 println!("eax is currently {}", result);
178 # }
179 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
180 # fn main() {}
181 ```
182
183 ## More Information
184
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,
188 constraints, etc.
189
190 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
191