]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/inline-assembly.md
TRPL: Add `rust` Marker to Some Code Block
[rust.git] / src / doc / trpl / inline-assembly.md
1 % Inline Assembly
2
3 For extremely low-level manipulations and performance reasons, one
4 might wish to control the CPU directly. Rust supports using inline
5 assembly to do this via the `asm!` macro. The syntax roughly matches
6 that of GCC & Clang:
7
8 ```ignore
9 asm!(assembly template
10    : output operands
11    : input operands
12    : clobbers
13    : options
14    );
15 ```
16
17 Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
18 crate to allow) and of course requires an `unsafe` block.
19
20 > **Note**: the examples here are given in x86/x86-64 assembly, but
21 > all platforms are supported.
22
23 ## Assembly template
24
25 The `assembly template` is the only required parameter and must be a
26 literal string (i.e. `""`)
27
28 ```rust
29 #![feature(asm)]
30
31 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
32 fn foo() {
33     unsafe {
34         asm!("NOP");
35     }
36 }
37
38 // other platforms
39 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
40 fn foo() { /* ... */ }
41
42 fn main() {
43     // ...
44     foo();
45     // ...
46 }
47 ```
48
49 (The `feature(asm)` and `#[cfg]`s are omitted from now on.)
50
51 Output operands, input operands, clobbers and options are all optional
52 but you must add the right number of `:` if you skip them:
53
54 ```rust
55 # #![feature(asm)]
56 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
57 # fn main() { unsafe {
58 asm!("xor %eax, %eax"
59     :
60     :
61     : "{eax}"
62    );
63 # } }
64 ```
65
66 Whitespace also doesn't matter:
67
68 ```rust
69 # #![feature(asm)]
70 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
71 # fn main() { unsafe {
72 asm!("xor %eax, %eax" ::: "{eax}");
73 # } }
74 ```
75
76 ## Operands
77
78 Input and output operands follow the same format: `:
79 "constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
80 expressions must be mutable lvalues, or not yet assigned:
81
82 ```rust
83 # #![feature(asm)]
84 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
85 fn add(a: i32, b: i32) -> i32 {
86     let c: i32;
87     unsafe {
88         asm!("add $2, $0"
89              : "=r"(c)
90              : "0"(a), "r"(b)
91              );
92     }
93     c
94 }
95 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
96 # fn add(a: i32, b: i32) -> i32 { a + b }
97
98 fn main() {
99     assert_eq!(add(3, 14159), 14162)
100 }
101 ```
102
103 If you would like to use real operands in this position, however,
104 you are required to put curly braces `{}` around the register that
105 you want, and you are required to put the specific size of the
106 operand. This is useful for very low level programming, where 
107 which register you use is important:
108
109 ```rust
110 # #![feature(asm)]
111 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
112 # unsafe fn read_byte_in(port: u16) -> u8 {
113 let result: u8;
114 asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
115 result
116 # }
117 ```
118
119 ## Clobbers
120
121 Some instructions modify registers which might otherwise have held
122 different values so we use the clobbers list to indicate to the
123 compiler not to assume any values loaded into those registers will
124 stay valid.
125
126 ```rust
127 # #![feature(asm)]
128 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
129 # fn main() { unsafe {
130 // Put the value 0x200 in eax
131 asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}");
132 # } }
133 ```
134
135 Input and output registers need not be listed since that information
136 is already communicated by the given constraints. Otherwise, any other
137 registers used either implicitly or explicitly should be listed.
138
139 If the assembly changes the condition code register `cc` should be
140 specified as one of the clobbers. Similarly, if the assembly modifies
141 memory, `memory` should also be specified.
142
143 ## Options
144
145 The last section, `options` is specific to Rust. The format is comma
146 separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
147 specify some extra info about the inline assembly:
148
149 Current valid options are:
150
151 1. *volatile* - specifying this is analogous to
152    `__asm__ __volatile__ (...)` in gcc/clang.
153 2. *alignstack* - certain instructions expect the stack to be
154    aligned a certain way (i.e. SSE) and specifying this indicates to
155    the compiler to insert its usual stack alignment code
156 3. *intel* - use intel syntax instead of the default AT&T.
157
158 ```rust
159 # #![feature(asm)]
160 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
161 # fn main() {
162 let result: i32;
163 unsafe {
164    asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
165 }
166 println!("eax is currently {}", result);
167 # }
168 ```