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