Skip to content

Commit d17ba8a

Browse files
authored
Merge pull request #1490 from Amanieu/fix-asm
Fix asm tests
2 parents 32c5904 + ee9f439 commit d17ba8a

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

.github/workflows/rbe.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
run: |
1616
rustup set profile minimal
1717
rustup toolchain install stable -c rust-docs
18-
rustup default stable
18+
rustup default nightly
1919
2020
- name: Install mdbook
2121
run: |

src/unsafe/asm.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Inline assembly is currently supported on the following architectures:
1818
Let us start with the simplest possible example:
1919

2020
```rust
21+
use std::arch::asm;
22+
2123
unsafe {
2224
asm!("nop");
2325
}
@@ -34,6 +36,8 @@ Now inserting an instruction that does nothing is rather boring. Let us do somet
3436
actually acts on data:
3537

3638
```rust
39+
use std::arch::asm;
40+
3741
let x: u64;
3842
unsafe {
3943
asm!("mov {}, 5", out(reg) x);
@@ -55,6 +59,8 @@ the template and will read the variable from there after the inline assembly fin
5559
Let us see another example that also uses an input:
5660

5761
```rust
62+
use std::arch::asm;
63+
5864
let i: u64 = 3;
5965
let o: u64;
6066
unsafe {
@@ -89,6 +95,8 @@ readability, and allows reordering instructions without changing the argument or
8995
We can further refine the above example to avoid the `mov` instruction:
9096

9197
```rust
98+
use std::arch::asm;
99+
92100
let mut x: u64 = 3;
93101
unsafe {
94102
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
102110
It is also possible to specify different variables for the input and output parts of an `inout` operand:
103111

104112
```rust
113+
use std::arch::asm;
114+
105115
let x: u64 = 3;
106116
let y: u64;
107117
unsafe {
@@ -123,6 +133,8 @@ There is also a `inlateout` variant of this specifier.
123133
Here is an example where `inlateout` *cannot* be used:
124134

125135
```rust
136+
use std::arch::asm;
137+
126138
let mut a: u64 = 4;
127139
let b: u64 = 4;
128140
let c: u64 = 4;
@@ -143,6 +155,8 @@ Here the compiler is free to allocate the same register for inputs `b` and `c` s
143155
However the following example can use `inlateout` since the output is only modified after all input registers have been read:
144156

145157
```rust
158+
use std::arch::asm;
159+
146160
let mut a: u64 = 4;
147161
let b: u64 = 4;
148162
unsafe {
@@ -160,6 +174,8 @@ Therefore, Rust inline assembly provides some more specific constraint specifier
160174
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.
161175

162176
```rust,no_run
177+
use std::arch::asm;
178+
163179
let cmd = 0xd1;
164180
unsafe {
165181
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`
173189
Consider this example which uses the x86 `mul` instruction:
174190

175191
```rust
192+
use std::arch::asm;
193+
176194
fn mul(a: u64, b: u64) -> u128 {
177195
let lo: u64;
178196
let hi: u64;
@@ -206,6 +224,8 @@ This state is generally referred to as being "clobbered".
206224
We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
207225

208226
```rust
227+
use std::arch::asm;
228+
209229
let mut ebx: u32;
210230
let mut edx: u32;
211231
let mut ecx: u32;
@@ -246,6 +266,8 @@ However we still need to tell the compiler that `eax` and `edx` have been modifi
246266
This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:
247267

248268
```rust
269+
use std::arch::asm;
270+
249271
// Multiply x by 6 using shifts and adds
250272
let mut x: u64 = 4;
251273
unsafe {
@@ -266,6 +288,8 @@ assert_eq!(x, 4 * 6);
266288
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.
267289

268290
```rust
291+
use std::arch::asm;
292+
269293
extern "C" fn foo(arg: i32) -> i32 {
270294
println!("arg = {}", arg);
271295
arg * 2
@@ -300,6 +324,8 @@ By default the compiler will always choose the name that refers to the full regi
300324
This default can be overriden by using modifiers on the template string operands, just like you would with format strings:
301325

302326
```rust
327+
use std::arch::asm;
328+
303329
let mut x: u16 = 0xab;
304330

305331
unsafe {
@@ -323,6 +349,8 @@ You have to manually use the memory address syntax specified by the target archi
323349
For example, on x86/x86_64 using Intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands:
324350

325351
```rust
352+
use std::arch::asm;
353+
326354
fn load_fpu_control_word(control: u16) {
327355
unsafe {
328356
asm!("fldcw [{}]", in(reg) &control, options(nostack));
@@ -343,6 +371,8 @@ As a consequence, you should only use GNU assembler **numeric** [local labels] i
343371
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`.)
344372

345373
```rust
374+
use std::arch::asm;
375+
346376
let mut a = 0;
347377
unsafe {
348378
asm!(
@@ -381,6 +411,8 @@ By default, an inline assembly block is treated the same way as an external FFI
381411
Let's take our previous example of an `add` instruction:
382412

383413
```rust
414+
use std::arch::asm;
415+
384416
let mut a: u64 = 4;
385417
let b: u64 = 4;
386418
unsafe {
@@ -400,4 +432,4 @@ Options can be provided as an optional final argument to the `asm!` macro. We sp
400432

401433
These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.
402434

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

Comments
 (0)