22. Inline Assembly¶
Note
The contents of this section are informational.
Legality Rules
22:1 Inline assembly is hand-written assembly code that is integrated into a Rust program.
22:2
Inline assembly is written as an assembly code block that is
wrapped inside a macro invocation of macro core::arch::asm
or
macro core::arch::global_asm
.
22:3 Inline assembly is available on the following architectures:
22:4 AArch64
22:5 ARM
22:6 RISC-V
22:7 x86 and x86-64
22.1. Registers¶
Syntax
RegisterName
::= "ExplicitRegisterName
" |RegisterClassName
ExplicitRegisterName
::= a[0-31] | ah | al | ax | b[0-31] | bh | bl | bp | bpl | bx | ch | cl | cx | d[0-31] | dh | di | dil | dl | dx | eax | ebp | ebx | ecx | edi | edx | eip | esi | esp | f[0-31] | fa[0-7] | ffr | fp | fs[0-11] | ft[0-11] | gp | h[0-31] | ip | k[0-7] | lr | m[0-7] | p[0-15] | pc | q[0-31] | r[0-15] | r[8-15]d | r[8-15]w | ra | rax | rb[8-15] | rbp | rbx | rcx | rdi | rdx | rfp | rip | rsi | rsp | s[0-31] | si | sil | sl | sp | spl | st([0-7]) | t[0-6] | tmm[0-7] | tp | v[0-31] | w[0-31] | wsp | wzr | x[0-31] | xmm[0-31] | xzr | ymm[0-31] | zero | zmm[0-31]
Legality Rules
22.1:1 A register is a hardware component capable of holding data that can be read and written.
22.1:2
An input register is a register whose register name is used in
a register argument subject to direction modifier in
, inout
,
or inlateout
.
22.1:3
An output register is a register whose register name is
used in a register argument subject to direction modifier out
,
lateout
, inout
, or inlateout
.
22.1:4 A register that is not specified as an output register shall have the same value upon exit from an assembly code block as it did upon entry into the assembly code block.
22.1:5 A register name is either the explicit register name of a register, or the register class name of the register class a register belongs to.
22.1:6 An explicit register name is a target-specific string that identifies a register.
22.1:7 An explicit register name may be aliased as follows:
22.1:8 |
Architecture |
Explicit register name |
Aliases |
22.1:9 |
AArch64 |
|
|
22.1:10 |
AArch64 |
|
|
22.1:11 |
AArch64 |
|
|
22.1:12 |
AArch64 |
|
|
22.1:13 |
AArch64 |
|
|
22.1:14 |
AArch64 |
|
|
22.1:15 |
ARM |
|
|
22.1:16 |
ARM |
|
|
22.1:17 |
ARM |
|
|
22.1:18 |
ARM |
|
|
22.1:19 |
ARM |
|
|
22.1:20 |
ARM |
|
|
22.1:21 |
ARM |
|
|
22.1:22 |
ARM |
|
|
22.1:23 |
ARM |
|
|
22.1:24 |
RISC-V |
|
|
22.1:25 |
RISC-V |
|
|
22.1:26 |
RISC-V |
|
|
22.1:27 |
RISC-V |
|
|
22.1:28 |
RISC-V |
|
|
22.1:29 |
RISC-V |
|
|
22.1:30 |
RISC-V |
|
|
22.1:31 |
RISC-V |
|
|
22.1:32 |
RISC-V |
|
|
22.1:33 |
RISC-V |
|
|
22.1:34 |
RISC-V |
|
|
22.1:35 |
RISC-V |
|
|
22.1:36 |
RISC-V |
|
|
22.1:37 |
RISC-V |
|
|
22.1:38 |
RISC-V |
|
|
22.1:39 |
RISC-V |
|
|
22.1:40 |
x86 |
|
|
22.1:41 |
x86 |
|
|
22.1:42 |
x86 |
|
|
22.1:43 |
x86 |
|
|
22.1:44 |
x86 |
|
|
22.1:45 |
x86 |
|
|
22.1:46 |
x86 |
|
|
22.1:47 |
x86 |
|
|
22.1:48 |
x86 |
|
|
22.1:49 |
x86 |
|
|
22.1:50 |
x86 |
|
|
22.1:51 |
x86 |
|
|
22.1:52 Certain explicit register names are not supported on selected architectures, as follows:
22.1:53 |
Architecture |
Explicit register name |
Reason |
22.1:54 |
all |
|
The stack pointer must be restored to its original value on exit from an assembly code block. |
22.1:55 |
AArch64 |
|
OS-reserved register on some AArch64 targets. |
22.1:56 |
AArch64 |
|
Internally used by LLVM as a base pointer for functions with complex stack frames. |
22.1:57 |
AArch64 |
|
The frame pointer cannot be used as an input or output. |
22.1:58 |
AArch64 |
|
The constant zero register cannot be modified. |
22.1:59 |
ARM |
|
The program counter cannot be modified. |
22.1:60 |
ARM |
|
Internally used by LLVM as a base pointer for functions with complex stack frames. |
22.1:61 |
ARM |
|
The frame pointer cannot be used as an input or output. |
22.1:62 |
ARM |
|
OS-reserved register on some ARM targets. |
22.1:63 |
RISC-V |
|
Reserved registers. |
22.1:64 |
RISC-V |
|
The constant zero register cannot be modified. |
22.1:65 |
RISC-V |
|
The frame pointer cannot be used as an input or output. |
22.1:66 |
RISC-V |
|
Internally used by LLVM as a base pointer for functions with complex stack frames. |
22.1:67 |
x86 |
|
The frame pointer cannot be used as an input or output. |
22.1:68 |
x86 |
|
The program counter cannot be modified. |
22.1:69 |
x86-32 |
|
Internally used by LLVM as a base pointer for functions with complex stack frames. |
22.1:70 |
x86-64 |
|
Internally used by LLVM as a base pointer for functions with complex stack frames. |
22.1:71 It is a static error to use an unsupported explicit register name.
Undefined Behavior
22.1:72 It is undefined behavior if a register that is not specified as an output register has a different value upon exit from an assembly code block from the value it had upon entry into the assembly code block.
22.2. Register Classes¶
Syntax
RegisterClassName
::=
dreg
| dreg_low16
| dreg_low8
| freg
| kreg
| kreg0
| mmx_reg
| preg
| qreg
| qreg_low4
| qreg_low8
| reg
| reg_abcd
| reg_byte
| sreg
| sreg_low16
| tmm_reg
| vreg
| vreg_low16
| x86_reg
| xmm_reg
| ymm_reg
| zmm_reg
Legality Rules
22.2:1 A register class represents a set of registers.
22.2:2 A register class name is a target-specific string that identifies a register class.
22.2:3 Registers are organized into register classes as follows:
22.2:4 |
Architecture |
Register class name |
Explicit register names |
22.2:5 |
AArch64 |
|
|
22.2:6 |
AArch64 |
|
|
22.2:7 |
AArch64 |
|
|
22.2:8 |
AArch64 |
|
|
22.2:9 |
ARM / Thumb2 |
|
|
22.2:10 |
ARM / Thumb1 |
|
|
22.2:11 |
ARM |
|
|
22.2:12 |
ARM |
|
|
22.2:13 |
ARM |
|
|
22.2:14 |
ARM |
|
|
22.2:15 |
ARM |
|
|
22.2:16 |
ARM |
|
|
22.2:17 |
ARM |
|
|
22.2:18 |
ARM |
|
|
22.2:19 |
RISC-V |
|
|
22.2:20 |
RISC-V |
|
|
22.2:21 |
RISC-V |
|
|
22.2:22 |
x86 |
|
|
22.2:23 |
x86 |
|
|
22.2:24 |
x86 |
|
|
22.2:25 |
x86 |
|
|
22.2:26 |
x86 |
|
|
22.2:27 |
x86 |
|
|
22.2:28 |
x86 |
|
|
22.2:29 |
x86 |
|
|
22.2:30 |
x86 |
|
|
22.2:31 |
x86-32 |
|
|
22.2:32 |
x86-64 |
|
|
22.2:33 |
x86-64 |
|
|
22.2:34 If a value has a smaller size than the register it is allocated in, then
22.2:35 On RISC-V architectures, if the register belongs to register class
freg
, thenf32
values are NaN-boxed. in af64
value.22.2:36 Otherwise, for an input register, the upper bits of the register have an undefined value.
22.2:37 Otherwise, for an output register, the upper bits are ignored.
22.2:38
If a register argument has direction modifier inout
and an
input-output register expression, then the input register expression
and the output register expression shall have the same type.
22.3. Register Arguments¶
Syntax
RegisterArgument
::= (Identifier
=)?DirectionModifier
(RegisterName
)RegisterExpression
DirectionModifier
::= in | inlateout | inout | lateout | outRegisterExpression
::=InputOutputRegisterExpression
|SimpleRegisterExpression
|ConstRegisterExpression
InputOutputRegisterExpression
::=InputRegisterExpression
=>OutputRegisterExpression
|InputRegisterExpression
=>UnderscoreExpression
InputRegisterExpression
::=Expression
OutputRegisterExpression
::=Expression
SimpleRegisterExpression
::=Expression
|UnderscoreExpression
ConstRegisterExpression
::= constExpression
Legality Rules
22.3:1 A register argument is a construct that configures the input and output of a register, and optionally binds the configuration to an identifier.
22.3:2 A register argument shall be used within an assembly instruction.
22.3:3 A named register argument is a register argument whose configuration is bound to an identifier.
22.3:4 A positional register argument is a register argument whose configuration is not bound to an identifier.
22.3:5 A named register argument shall appear after a positional register argument.
22.3:6 An explicit register argument is a register argument that uses an explicit register name.
22.3:7 An explicit register argument shall appear after a named register argument.
22.3:8 A register class argument is a register argument that uses a register class name.
22.3:9 A register class argument causes an assembler to select a suitable register from the related register class.
22.3:10 A direction modifier is a construct that indicates whether a register argument initializes a register, assigns the value of a register to an expression, or both.
22.3:11 An input register expression is an expression that provides the initial value of a register.
22.3:12 An output register expression is an expression that is assigned the value of a register.
22.3:13 A const register expression is an expression that is evaluated at compile-time.
22.3:14 An input-output register expression is a construct that specifies both an input register expression and an output register expression.
22.3:15 A simple register expression is either an expression or an underscore expression.
22.3:16 A register expression is either an input-output register expression, a simple register expression or a const register expression.
22.3:17 The type of a const register expression shall be an integer type.
22.3:18 The type of an input register expression, output register expression, or simple register expression shall depend on the architecture and the target feature in effect, as follows:
22.3:19 |
Architecture |
Register class name |
Target feature |
Allowed types |
22.3:20 |
AArch64 |
|
n/a |
Only clobbers |
22.3:21 |
AArch64 |
|
none |
|
22.3:22 |
AArch64 |
|
|
|
22.3:23 |
ARM |
|
|
|
22.3:24 |
ARM |
|
none |
|
22.3:25 |
ARM |
|
|
|
22.3:26 |
RISC-V |
|
|
|
22.3:27 |
RISC-V |
|
|
|
22.3:28 |
RISC-V |
|
n/a |
Only clobbers |
22.3:29 |
RISC-V32 |
|
none |
|
22.3:30 |
RISC-V64 |
|
none |
|
22.3:31 |
x86 |
|
|
|
22.3:32 |
x86 |
|
|
|
22.3:33 |
x86 |
|
n/a |
Only clobbers |
22.3:34 |
x86 |
|
none |
|
22.3:35 |
x86 |
|
n/a |
Only clobbers |
22.3:36 |
x86 |
|
n/a |
Only clobbers |
22.3:37 |
x86 |
|
|
|
22.3:38 |
x86 |
|
|
|
22.3:39 |
x86 |
|
|
|
22.3:40 |
x86-32 |
|
none |
|
22.3:41 |
x86-64 |
|
none |
22.3:42
If a register argument has direction modifier in
and a
simple register expression, then
22.3:43 Upon entry of an assembly code block, the register contains the value of the simple register expression.
22.3:44 On exit from an assembly code block, the register shall contain the same value, unless the register is subject to direction modifier
lateout
.
22.3:45
If a register argument has direction modifier out
and a
simple register expression, then
22.3:46 Upon entry of an assembly code block, the register contains an undefined value.
22.3:47 On exit from an assembly code block, the value of the register is assigned to the simple register expression. The simple register expression shall be a place expression.
22.3:48 If the simple register expression is an underscore expression, then the value of the register is discarded.
22.3:49
If a register argument has direction modifier lateout
and a
simple register expression, then the register argument behaves as a
register argument with direction modifier out
, except that the
register can be reused with direction modifier in
.
22.3:50
If a register argument has direction modifier inout
and a
simple register expression, then
22.3:51 Upon entry of an assembly code block, the register contains the value of the simple register expression.
22.3:52 On exit from an assembly code block, the value of the register is assigned to the place indicated by the simple register expression. The simple register expression shall be a mutable place expression.
22.3:53
If a register argument has direction modifier inout
and an
input-output register expression, then
22.3:54 Upon entry of an assembly code block, the register contains the value of the input register expression.
22.3:55 On exit from an assembly code block, the value of the register is assigned to the place indicated by the output register expression. The output register expression shall be a place expression.
22.3:56 If the output register expression is an underscore expression, then the value of the register is discarded.
22.3:57
If a register argument has direction modifier inlateout
and a
simple register expression, then the register argument behaves as a
register argument with direction modifier inout
, except that the
register can be reused with direction modifier in
.
22.3:58
If a register argument has direction modifier inlateout
and an
input-output register expression, then the register argument behaves
as a register argument with direction modifier inout
, except that
the register can be reused with direction modifier in
.
22.3:59 It is a static error to specify a register argument with direction modifier and register expression other than the combinations listed above.
Dynamic Semantics
22.3:60 The evaluation of a register argument proceeds as follows:
22.3:61 If a register argument has an input-output register expression, then
22.3:62 The input register expression is evaluated.
22.3:63 The output register expression is evaluated.
22.3:64 If a register argument has a simple register expression, then the simple register expression is evaluated.
Examples
let mut left_value: i32 = 1;
let right_value: i32 = 2;
unsafe {
asm!(
"add {left} {right}",
left = inout(reg) left_value,
right = in(reg) right_value,
);
}
22.4. Assembly Instructions¶
Syntax
AssemblyCodeBlock
::=AssemblyInstruction
(,AssemblyInstruction
)*AssemblyInstruction
::=StringLiteral
Legality Rules
22.4:1 An assembly instruction is a string literal that represents a low-level assembly operation or an assembly directive.
22.4:2
An assembly instruction shall use the syntax of format strings as
defined in module std::fmt
, and contain zero or more
register parameters.
22.4:3 An assembly code block is a sequence of assembly instructions.
22.4:4 When an assembly code block contains multiple assembly instructions, the assembly instructions are treated as concatenated into a single string literal, with character 0x0A (new line) between them.
22.4:5 The set of memory locations that an assembly code block is allowed to read and write are the same as those for an external function, excluding the memory locations that are private to the assembly code block.
22.4:6 A tool is not required to guarantee that an assembly code block appears exactly once in the final assembly output.
22.4:7 A tool is not required to guarantee that two assembly code blocks appear in the same declarative order in the final assembly output, or appear contiguously in successive addresses.
22.4:8 A register parameter is a substring delimited by characters 0x7B (left curly bracket) and 0x7D (right curly bracket) that is substituted with a register argument in an assembly instruction.
22.4:9
On x86 architectures, direction flag DF
in register EFLAGS
shall
be cleared on exit from an assembly code block.
Undefined Behavior
22.4:10
On x86 architectures, it is undefined behavior if direction flag DF
in
register EFLAGS
remains set on exit from an assembly code block.
Examples
"shl {value} 2"
22.4.1. Register Parameter Modifiers¶
Legality Rules
22.4.1:1 A register parameter modifier is a substring that starts with character 0x3A (colon), follows a register parameter, and changes the formatting of the related register parameter.
22.4.1:2 The effects of a register parameter modifier depends on the architecture and register class, as follows:
22.4.1:3 |
Architecture |
Register class |
Modifier |
Example output |
22.4.1:4 |
AArch64 |
|
none |
|
22.4.1:5 |
AArch64 |
|
:w |
|
22.4.1:6 |
AArch64 |
|
:x |
|
22.4.1:7 |
AArch64 |
|
none |
|
22.4.1:8 |
AArch64 |
|
:b |
|
22.4.1:9 |
AArch64 |
|
:d |
|
22.4.1:10 |
AArch64 |
|
:h |
|
22.4.1:11 |
AArch64 |
|
:q |
|
22.4.1:12 |
AArch64 |
|
:s |
|
22.4.1:13 |
AArch64 |
|
:v |
|
22.4.1:14 |
ARM |
|
none |
|
22.4.1:15 |
ARM |
|
none |
|
22.4.1:16 |
ARM |
|
:e, :f |
|
22.4.1:17 |
ARM |
|
none |
|
22.4.1:18 |
ARM |
|
none |
|
22.4.1:19 |
RISC-V |
|
none |
|
22.4.1:20 |
RISC-V |
|
none |
|
22.4.1:21 |
x86 |
|
none |
|
22.4.1:22 |
x86 |
|
:e |
|
22.4.1:23 |
x86 |
|
:x |
|
22.4.1:24 |
x86 |
|
:h |
|
22.4.1:25 |
x86 |
|
none |
|
22.4.1:26 |
x86 |
|
none |
|
22.4.1:27 |
x86 |
|
none |
|
22.4.1:28 |
x86 |
|
none |
|
22.4.1:29 |
x86 |
|
:x |
|
22.4.1:30 |
x86 |
|
:y |
|
22.4.1:31 |
x86 |
|
:z |
|
22.4.1:32 |
x86-32 |
|
none |
|
22.4.1:33 |
x86-32 |
|
:l |
|
22.4.1:34 |
x86-64 |
|
none |
|
22.4.1:35 |
x86-64 |
|
:l |
|
22.4.1:36 |
x86-64 |
|
:r |
|
Examples
let mut left_value: i32 = 1;
let right_value: i32 = 2;
unsafe {
asm!(
"add {left}:e {right}:x",
left = inout(reg) left_value,
right = in(reg) right_value,
);
}
22.4.2. Directive Support¶
Legality Rules
22.4.2:1 An assembly directive is a request to the assembler to perform a particular action or change a setting.
22.4.2:2 If an assembly code block contains stateful assembly directives that modify how subsequent assembly code is processed, then the assembly code block shall undo the effects of the stateful assembly directives before the assembly code block is completed.
22.4.2:3 The common assembly directives are as follows:
22.4.2:4
.2byte
,.4byte
,.8byte
22.4.2:5
.align
,.ascii
,.asciz
,.alt_entry
22.4.2:6
.balign
,.balignl
,.balignw
,.balign
,.balignl
,.balignw
,.bss
,.byte
22.4.2:7
.comm
22.4.2:8
.data
,.def
,.double
22.4.2:9
.endef
,.equ
,.equiv
,.eqv
22.4.2:10
.fill
,.float
22.4.2:11
.globl
,.global
22.4.2:12
.inst
22.4.2:13
.lcomm
,.long
22.4.2:14
.octa
,.option
22.4.2:15
.private_extern
,.p2align
,.pushsection
,.popsection
22.4.2:16
.quad
22.4.2:17
.scl
,.section
,.set
,.short
,.size
,.skip
,.sleb128
,.space
,.string
22.4.2:18
.text
,.type
22.4.2:19
.uleb128
22.4.2:20
.word
22.4.2:21 The following assembly directives are relevant on ELF targets that support DWARF unwind info.
22.4.2:22
.cfi_adjust_cfa_offset
22.4.2:23
.cfi_def_cfa
,.cfi_def_cfa_offset
,.cfi_def_cfa_register
22.4.2:24
.cfi_endproc
,.cfi_escape
22.4.2:25
.cfi_lsda
22.4.2:26
.cfi_offset
22.4.2:27
.cfi_personality
22.4.2:28
.cfi_register
,.cfi_rel_offset
,.cfi_remember_state
,.cfi_restore
,.cfi_restore_state
,.cfi_return_column
22.4.2:29
.cfi_same_value
,.cfi_sections
,.cfi_signal_frame
,.cfi_startproc
22.4.2:30
.cfi_undefined
22.4.2:31
.cfi_window_save
22.4.2:32 The following assembly directives are relevant on targets with structured exception handling.
22.4.2:33
.seh_endproc
,.seh_endprologue
22.4.2:34
.seh_proc
,.seh_pushreg
22.4.2:35
.seh_savereg
,.seh_setframe
,.seh_stackalloc
22.4.2:36 The following assembly directives are relevant on ARM targets.
22.4.2:37
.code
22.4.2:38
.even
22.4.2:39
.fnstart
,.fnend
22.4.2:40
.movsp
22.4.2:41
.save
22.4.2:42
.thumb
,.thumb_func
22.4.2:43 The following assembly directives are relevant on x86 targets.
22.4.2:44
.code16
,.code32
,.code64
22.4.2:45
.nops
22.5. ABI Clobbers¶
Syntax
AbiClobber
::= clobber_abi (AbiKindList
)AbiKindList
::=AbiKind
(,AbiKind
)* ,?
Legality Rules
22.5:1
An ABI clobber is an argument to macro core::arch::asm
which
indicates that the values of selected registers might be
overwritten during the execution of an assembly code block.
22.5:2 Multiple ABI clobbers may be specified for an assembly code block. Clobber constraints are applied for all unique registers in the union of all specified ABIs.
22.5:3 The effects of an ABI clobber depend on the ABI in effect, as follows:
22.5:4 |
Architecture |
Clobbered registers |
|
22.5:5 |
AArch64 |
|
|
22.5:6 |
ARM |
|
|
22.5:7 |
RISC-V |
|
|
22.5:8 |
x86-32 |
|
|
22.5:9 |
x86-64 |
|
|
22.5:10 |
x86-64 |
|
|
22.5:11
On x86 architectures, the x87 floating-point register stack shall remain
unchanged unless all st(
[0
-7
])
registers have been
clobbered.
22.5:12 On x86 architectures, if all x87 registers are clobbered, then the x87 register stack is presumed empty upon entry of an assembly code block. The x87 register stack shall be empty on exit from an assembly code block.
Examples
clobber_abi("C", "system")
22.6. Assembly Options¶
Syntax
AssemblyOption
::= options (OptionList
)OptionList
::=Option
(,Option
)* ,?Option
::= att_syntax | nomem | noreturn | nostack | preserves_flags | pure | raw | readonly
Legality Rules
22.6:1 An assembly option is used to specify a characteristic of or a restriction on the related assembly code block.
22.6:2
Assembly option att_syntax
is applicable only to x86 architectures
and causes the assembler to use the .att_syntax
prefix mode which prefixes
registers with %
.
22.6:3
Assembly option nomem
indicates that the assembly code block does
not read or write memory.
22.6:4
Assembly option noreturn
indicates that the assembly code block
does not return, preventing the dropping of variables.
22.6:5
Assembly option nostack
indicates that the assembly code block
does not push on the stack, or write to the stack red-zone (if supported).
22.6:6
If assembly option nostack
is not in effect, then an
assembly code block is allowed to use stack space below the stack pointer.
Upon entry of an assembly code block, the stack pointer is suitably
aligned according to the target ABI for call expressions. The stack
pointer shall be restored to its original value on exit from the
assembly code block.
22.6:7
Assembly option preserves_flags
indicates that the
assembly code block does not modify the flags register.
22.6:8
If assembly option preserves_flags
is in effect, then the values
of the following flags registers shall be restored on exit from an
assembly code block:
22.6:9 |
Architecture |
Flag registers |
22.6:10 |
AArch64 |
Floating-point status Condition flags |
22.6:11 |
ARM |
Condition flags Condition flags Floating-point exception flags Greater than or equal flag Saturation flag Saturation flag |
22.6:12 |
RISC-V |
Floating-point exception flags Vector extension state |
22.6:13 |
x86 |
Status flags Floating-point exception flags Floating-point status word |
22.6:14
Assembly option pure
indicates that the assembly code block has no
side effects, and its outputs depend only on direct inputs.
22.6:15
Assembly option raw
causes assembly instructions to be parsed
raw, without any special handling of register parameters.
22.6:16
Assembly option readonly
indicates that the assembly code block
does not write memory.
22.6:17
Assembly options att_syntax
and raw
shall appear only in
GlobalAsmArguments
.
22.6:18
Assembly options nomem
and readonly
shall not be used together.
22.6:19
Assembly option noreturn
shall not be specified on an
assembly code block that has output registers.
22.6:20
Assembly option pure
shall appear with either assembly option
nomem
or assembly option readonly
.
22.6:21
Assembly option pure
shall not be specified on an
assembly code block that either lacks output registers or all
register expressions of output registers are
underscore expressions.
Undefined Behavior
22.6:22
It is undefined behavior if an assembly code block subject to
assembly option pure
has side effects other than its direct outputs.
22.6:23
It is undefined behavior if control reaches the end of an
assembly code block subject to assembly option noreturn
.
Examples
options(nomem, pure)
22.7. Macros asm and global_asm¶
Syntax
AsmArguments
::= (AssemblyCodeBlock
(,RegisterArgument
)* (,AbiClobber
)* (,AssemblyOption
)* ,? )GlobalAsmArguments
::= (AssemblyCodeBlock
(,RegisterArgument
)* (,AssemblyOption
)* ,? )
Legality Rules
22.7:1
Assembly code blocks are embedded within Rust source code using
macros core::arch::asm
and core::arch::global_asm
.
22.7:2
When invoking macro core::arch::asm
, the DelimitedTokenTree
of
the related macro invocation shall follow the syntax of AsmArguments
.
22.7:3
Invoking macro core::arch::asm
causes the related
assembly code block to be integrated into the generated assembly of the
function where the macro invocation took place. A tool is free to
encapsulate the assembly code block in a separate function and
generate a call expression to it.
22.7:4
When invoking macro core::arch::global_asm
, the
DelimitedTokenTree
of the related macro invocation shall follow the
syntax of GlobalAsmArguments
.
22.7:5
Invoking macro core::arch::global_asm
causes the related
assembly code block to be emitted outside the function where the
macro invocation took place.
Dynamic Semantics
22.7:6
The evaluation of a macro invocation to macro
core::arch::asm
or macro core::arch::global_asm
evaluates
register arguments in declarative order.
22.7:7 The execution of an assembly code block produced by inline assembly proceeds as follows:
22.7:8 All input registers are initialized to the values provided by the respective register arguments, in an undefined order.
22.7:9 The assembly instructions of the assembly code block are executed in declarative order.
22.7:10 The values of all output registers are assigned to the register expressions provided by the respective register arguments, in an undefined order.
Examples
fn asm_example() -> u32 {
let basepri;
unsafe {
asm!("
mrs {}, BASEPRI
",
out(reg) basepri,
options(nomem, nostack, preserves_flags))
}
basepri
}
global_asm!("
do_nothing:
push {r7, lr}
mov r7, sp
pop {r7, pc}
",
options(raw)
);
fn global_asm_example() {
extern "C" {
fn do_nothing();
}
unsafe { do_nothing() }
}