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