You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/unsafe/asm.md
+33-1Lines changed: 33 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -18,6 +18,8 @@ Inline assembly is currently supported on the following architectures:
18
18
Let us start with the simplest possible example:
19
19
20
20
```rust
21
+
usestd::arch::asm;
22
+
21
23
unsafe {
22
24
asm!("nop");
23
25
}
@@ -34,6 +36,8 @@ Now inserting an instruction that does nothing is rather boring. Let us do somet
34
36
actually acts on data:
35
37
36
38
```rust
39
+
usestd::arch::asm;
40
+
37
41
letx:u64;
38
42
unsafe {
39
43
asm!("mov {}, 5", out(reg) x);
@@ -55,6 +59,8 @@ the template and will read the variable from there after the inline assembly fin
55
59
Let us see another example that also uses an input:
56
60
57
61
```rust
62
+
usestd::arch::asm;
63
+
58
64
leti:u64=3;
59
65
leto:u64;
60
66
unsafe {
@@ -89,6 +95,8 @@ readability, and allows reordering instructions without changing the argument or
89
95
We can further refine the above example to avoid the `mov` instruction:
90
96
91
97
```rust
98
+
usestd::arch::asm;
99
+
92
100
letmutx:u64=3;
93
101
unsafe {
94
102
asm!("add {0}, 5", inout(reg) x);
@@ -102,6 +110,8 @@ This is different from specifying an input and output separately in that it is g
102
110
It is also possible to specify different variables for the input and output parts of an `inout` operand:
103
111
104
112
```rust
113
+
usestd::arch::asm;
114
+
105
115
letx:u64=3;
106
116
lety:u64;
107
117
unsafe {
@@ -123,6 +133,8 @@ There is also a `inlateout` variant of this specifier.
123
133
Here is an example where `inlateout`*cannot* be used:
124
134
125
135
```rust
136
+
usestd::arch::asm;
137
+
126
138
letmuta:u64=4;
127
139
letb:u64=4;
128
140
letc:u64=4;
@@ -143,6 +155,8 @@ Here the compiler is free to allocate the same register for inputs `b` and `c` s
143
155
However the following example can use `inlateout` since the output is only modified after all input registers have been read:
144
156
145
157
```rust
158
+
usestd::arch::asm;
159
+
146
160
letmuta:u64=4;
147
161
letb:u64=4;
148
162
unsafe {
@@ -160,6 +174,8 @@ Therefore, Rust inline assembly provides some more specific constraint specifier
160
174
While `reg` is generally available on any architecture, explicit registers are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi` among others can be addressed by their name.
161
175
162
176
```rust,no_run
177
+
use std::arch::asm;
178
+
163
179
let cmd = 0xd1;
164
180
unsafe {
165
181
asm!("out 0x64, eax", in("eax") cmd);
@@ -173,6 +189,8 @@ In this example we call the `out` instruction to output the content of the `cmd`
173
189
Consider this example which uses the x86 `mul` instruction:
174
190
175
191
```rust
192
+
usestd::arch::asm;
193
+
176
194
fnmul(a:u64, b:u64) ->u128 {
177
195
letlo:u64;
178
196
lethi:u64;
@@ -206,6 +224,8 @@ This state is generally referred to as being "clobbered".
206
224
We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
207
225
208
226
```rust
227
+
usestd::arch::asm;
228
+
209
229
letmutebx:u32;
210
230
letmutedx:u32;
211
231
letmutecx:u32;
@@ -246,6 +266,8 @@ However we still need to tell the compiler that `eax` and `edx` have been modifi
246
266
This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:
247
267
248
268
```rust
269
+
usestd::arch::asm;
270
+
249
271
// Multiply x by 6 using shifts and adds
250
272
letmutx:u64=4;
251
273
unsafe {
@@ -266,6 +288,8 @@ assert_eq!(x, 4 * 6);
266
288
By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted.
267
289
268
290
```rust
291
+
usestd::arch::asm;
292
+
269
293
extern"C"fnfoo(arg:i32) ->i32 {
270
294
println!("arg = {}", arg);
271
295
arg*2
@@ -300,6 +324,8 @@ By default the compiler will always choose the name that refers to the full regi
300
324
This default can be overriden by using modifiers on the template string operands, just like you would with format strings:
301
325
302
326
```rust
327
+
usestd::arch::asm;
328
+
303
329
letmutx:u16=0xab;
304
330
305
331
unsafe {
@@ -323,6 +349,8 @@ You have to manually use the memory address syntax specified by the target archi
323
349
For example, on x86/x86_64 using Intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands:
@@ -343,6 +371,8 @@ As a consequence, you should only use GNU assembler **numeric** [local labels] i
343
371
Moreover, on x86 when using the default Intel syntax, due to [an LLVM bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_`asm!` block. (See [Options](#options), below, for more on `options`.)
344
372
345
373
```rust
374
+
usestd::arch::asm;
375
+
346
376
letmuta=0;
347
377
unsafe {
348
378
asm!(
@@ -381,6 +411,8 @@ By default, an inline assembly block is treated the same way as an external FFI
381
411
Let's take our previous example of an `add` instruction:
382
412
383
413
```rust
414
+
usestd::arch::asm;
415
+
384
416
letmuta:u64=4;
385
417
letb:u64=4;
386
418
unsafe {
@@ -400,4 +432,4 @@ Options can be provided as an optional final argument to the `asm!` macro. We sp
400
432
401
433
These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.
402
434
403
-
See the [reference](../../reference/asm.htmt) for the full list of available options and their effects.
435
+
See the [reference](../../reference/inline-assembly.html) for the full list of available options and their effects.
0 commit comments