Skip to content

Commit fd9ed30

Browse files
committed
asm: Update chapter in unstable book for multiple template string arguments
Update all examples to use the new formatting, and update explanations to document it.
1 parent 1078b6f commit fd9ed30

File tree

1 file changed

+36
-21
lines changed
  • src/doc/unstable-book/src/library-features

1 file changed

+36
-21
lines changed

src/doc/unstable-book/src/library-features/asm.md

+36-21
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,13 @@ Let us see another example that also uses an input:
6868
let i: u64 = 3;
6969
let o: u64;
7070
unsafe {
71-
asm!("
72-
mov {0}, {1}
73-
add {0}, {number}
74-
", out(reg) o, in(reg) i, number = const 5);
71+
asm!(
72+
"mov {0}, {1}",
73+
"add {0}, {number}",
74+
out(reg) o,
75+
in(reg) i,
76+
number = const 5,
77+
);
7578
}
7679
assert_eq!(o, 8);
7780
```
@@ -82,13 +85,18 @@ and then adding `5` to it.
8285

8386
The example shows a few things:
8487

85-
First we can see that inputs are declared by writing `in` instead of `out`.
88+
First, we can see that `asm!` allows multiple template string arguments; each
89+
one is treated as a separate line of assembly code, as if they were all joined
90+
together with newlines between them. This makes it easy to format assembly
91+
code.
92+
93+
Second, we can see that inputs are declared by writing `in` instead of `out`.
8694

87-
Second one of our operands has a type we haven't seen yet, `const`.
95+
Third, one of our operands has a type we haven't seen yet, `const`.
8896
This tells the compiler to expand this argument to value directly inside the assembly template.
8997
This is only possible for constants and literals.
9098

91-
Third we can see that we can specify an argument number, or name as in any format string.
99+
Fourth, we can see that we can specify an argument number, or name as in any format string.
92100
For inline assembly templates this is particularly useful as arguments are often used more than once.
93101
For more complex inline assembly using this facility is generally recommended, as it improves
94102
readability, and allows reordering instructions without changing the argument order.
@@ -137,10 +145,13 @@ let mut a: u64 = 4;
137145
let b: u64 = 4;
138146
let c: u64 = 4;
139147
unsafe {
140-
asm!("
141-
add {0}, {1}
142-
add {0}, {2}
143-
", inout(reg) a, in(reg) b, in(reg) c);
148+
asm!(
149+
"add {0}, {1}",
150+
"add {0}, {2}",
151+
inout(reg) a,
152+
in(reg) b,
153+
in(reg) c,
154+
);
144155
}
145156
assert_eq!(a, 12);
146157
```
@@ -233,7 +244,7 @@ unsafe {
233244
// ECX 0 selects the L0 cache information.
234245
inout("ecx") 0 => ecx,
235246
lateout("ebx") ebx,
236-
lateout("edx") _
247+
lateout("edx") _,
237248
);
238249
}
239250
@@ -255,12 +266,14 @@ This can also be used with a general register class (e.g. `reg`) to obtain a scr
255266
// Multiply x by 6 using shifts and adds
256267
let mut x: u64 = 4;
257268
unsafe {
258-
asm!("
259-
mov {tmp}, {x}
260-
shl {tmp}, 1
261-
shl {x}, 2
262-
add {x}, {tmp}
263-
", x = inout(reg) x, tmp = out(reg) _);
269+
asm!(
270+
"mov {tmp}, {x}",
271+
"shl {tmp}, 1",
272+
"shl {x}, 2",
273+
"add {x}, {tmp}",
274+
x = inout(reg) x,
275+
tmp = out(reg) _,
276+
);
264277
}
265278
assert_eq!(x, 4 * 6);
266279
```
@@ -338,7 +351,7 @@ unsafe {
338351
asm!(
339352
"add {0}, {1}",
340353
inlateout(reg) a, in(reg) b,
341-
options(pure, nomem, nostack)
354+
options(pure, nomem, nostack),
342355
);
343356
}
344357
assert_eq!(a, 8);
@@ -371,17 +384,19 @@ reg_operand := dir_spec "(" reg_spec ")" operand_expr
371384
operand := reg_operand / "const" const_expr / "sym" path
372385
option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "att_syntax"
373386
options := "options(" option *["," option] [","] ")"
374-
asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")"
387+
asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
375388
```
376389

377390
The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
378391

379392
[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax
380393

381-
## Template string
394+
## Template string arguments
382395

383396
The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
384397

398+
An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments.
399+
385400
As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
386401

387402
Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.

0 commit comments

Comments
 (0)