内联汇编语句(IBM 扩展)

在扩展语言级别下,编译器支持 C 和 C++ 源代码语句中的嵌入式汇编代码段。 此扩展已实现用于一般系统编程代码以及最初用 GNU C 开发的操作系统内核和设备驱动程序。

关键字 asm 代表汇编代码。 在编译中使用严格的语言级别时,C 编译器将 asm 视为常规标识并将 __asm__asm__ 保留为关键字。 C++ 编译器始终识别 asm__asm__asm__ 关键字。

语法如下:

asm 语句语法 - 局部范围中的语句

读取语法图跳过可视语法图asm__asm__asm__volatile( code_format_string:输出:输入:clobber )
input
读取语法图跳过可视语法图,修饰符约束(C_expression)
output
读取语法图跳过可视语法图,修饰符约束(C_expression)
易变变量
限定符 volatile 指示编译器仅对汇编块执行最少的优化。 编译器不能跨汇编块周围的隐式围栏移动任何指令。 请参阅示例 1 以获取详细用法信息。
code_format_string
code_format_stringasm 指令的源文本,并且是类似于 printf 格式说明符的字符串文字。

操作数以 %integer 格式引用,其中 integer 是指输入或输出操作数的序号。 请参阅 示例 1 以获取详细的用法信息。

为了提高可读性,可以为每个操作数指定一个括在方括号中的符号名称。 在汇编代码部分中,您可以 %[symbolic_name] 格式引用每个操作数,其中 symbolic_name 是在操作数列表中引用的。 您可以使用任何名称(包括现有 C 或 C++ 符号),因为符号名称与任何 C 或 C++ 标识无关。 但是,同一汇编语句中的两个操作数不能使用相同的符号名称。 请参阅 示例 2 ,以获取详细的用法信息。

输出
output 包含零个、一个或多个输出操作数,并将逗号用作分隔符。 每个操作包含一个 constraint(C_expression) 对。 输出操作数必须受 =+ 修饰符 (如下所述)约束,并且 (可选) 受附加 % & 修饰符约束。
输入
input 包含零个、一个或多个输入操作数,并将逗号用作分隔符。 每个操作包含一个 constraint(C_expression) 对。
clobber
clobber 是括在双引号中的寄存器名称的逗号分隔列表。 如果 asm 指令更新未在 asm 语句的 输入输出 中列出的寄存器,那么这些寄存器必须列示为已关闭的寄存器。 以下寄存器名称有效:
r0 到 r31
通用寄存器
f0 到 f31
浮点寄存器
lr
链接寄存器
ctr
循环计数、减量和分支寄存器
fpscr
浮点状态和控制寄存器
xer
定点异常寄存器
cr0 到 cr7
条件寄存器。 示例 3 显示 clobber 中条件寄存器的典型用法。
v0 到 v31
向量寄存器(仅在所选处理器上)
除寄存器名称外,还会在 clobber 寄存器中列表中使用 ccmemoryccmemory 的用法信息如下所示:
抄送
如果汇编程序指令可以改变 条件代码寄存器,请将 cc 添加到已关闭的寄存器列表中。
内存

如果汇编程序指令可以不可预测的方式更改内存位置,请将 memory 添加到 clobber 列表。 memory clobber 确保编译器不会在其他内存引用之间移动汇编程序指令,并确保在汇编语句完成后使用的任何数据有效。

但是,memory clobber 会导致许多不必要的重新装入,从而减少硬件预取的优势。 因此,memory clobber 可能会降低性能,应谨慎使用。 请参阅 示例 4示例 1 以获取详细的用法信息。

修饰符
修饰符可以是下列其中一个操作数:
=
指示该操作数对于此指令是只写的。 先前的值将被废弃并替换为输出数据。 请参阅 示例 5 以获取详细的用法信息。
+
指示操作数由指令读取和写入。 请参阅 示例 6 以获取详细的用法信息。
&
指示使用输入操作数完成指令之前可以修改操作数;用作输入的寄存器不应在此处重用。
%
声明此指令对于此操作数和下一个操作数是可交换的。 这意味着在生成指令时,此操作数和下一个操作数的顺序可能被交换。 此修饰符可以用于输入或输出操作数,但不能在最后一个操作数上指定。 请参阅示例 7 以获取详细用法信息。
约束
constraint 是一个字符串文字,描述允许的操作数的种类,每个约束一个字符。 支持下列配置:
b
使用除零之外的通用寄存器。 一些指令对寄存器 0 的指定进行了特殊处理,如果编译器选择 r0,则不会按预期运行。 对于这些指令,指定 r0 并不意味着使用 r0。 相反,它意味着指定字面值 0。 请参阅 示例 8 ,以获取详细的用法信息。
c
使用 CTR 寄存器。
d
使用浮点寄存器。
f
使用浮点寄存器。 请参阅示例 7 以获取详细用法信息。
g
使用通用寄存器、内存或立即操作数。 在 POWER ® 体系结构中,没有可互换使用寄存器,内存说明符或直接操作数的指令。 但是,在允许这样做的位置容许使用此约束。
h
使用 CTR 或 LINK 寄存器。
i
使用直接整数或字符串文字操作数。
l
使用 CTR 寄存器。
m
使用机器支持的内存操作数。 您可以将此约束用于 D(R) 格式的操作数,其中 D 是位移,R 是寄存器。 请参阅 示例 9 ,以获取详细的用法信息。
n
使用直接整数。
o
使用可偏移的内存操作数。 这意味着可以通过将整数添加到基地址来寻址内存操作数。 在 POWER 体系结构中,内存操作数始终是可偏移的,因此可以互换使用约束 om
r
使用通用寄存器。 请参阅 示例 5 以获取详细的用法信息。
s
使用字符串文字操作数。
v
使用向量寄存器。
0, 1, …8, 9
匹配约束。 在输出中分配与相应输入中相同的寄存器。
I, J, K, L, M, N, O, P
常量值 折叠操作数中的表达式,并将该值替换为 % 说明符。 这些约束指定操作数的最大值,如下所示:
  • I — 带符号 16 位
  • J — 无符号 16 位左移 16 位
  • K — 无符号 16 位常量
  • L — 带符号 16 位左移 16 位
  • M — 大于 31 的无符号常量
  • N — 作为 2 的精确幂的无符号常量
  • O — 零
  • P — 带符号常量,其相反数是带符号的 16 位常量
C_expression

C_expression 是 C 或 C++ 表达式,其值用作 asm 指令的操作数。 输出操作数必须是可修改的值。 C_expression 必须与针对它指定的约束一致。 例如,如果指定了 i ,那么操作数必须是整数常量。

注: 如果在 输入输出中使用了指针表达式,那么组合件指示信息将遵循 ANSI 别名判别规则 (请参阅 基于类型的别名判别 以获取更多信息)。 这意味着在指针表达式操作数中使用值的间接寻址应该与指针类型一致; 否则,必须在编译期间禁用 -qalias=ansi 选项。