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