我遇到了一个看起来像这样的代码:
asm volatile (
# [...]
"movl $1200, %%ecx;"
# [...]
);
我知道movl $1200, %ecx
在 x86 中做了什么。但我对为什么有两个百分号感到困惑。
GCC 内联汇编使用 %0、%1、%2 等来引用输入和输出操作数。这意味着您需要将两个 %% 用于实际寄存器。
查看此操作指南以获取重要信息。
这取决于
如果字符串后面有一个冒号:
,那么它是一个扩展的 asm,并转义了Carl 提到的%%
可能具有特殊含义的百分比。例子:
uint32_t in = 1;
uint32_t out = 0;
asm volatile (
"movl %1, %%eax;"
"inc %%eax;"
"movl %%eax, %0"
: "=m" (out) /* Outputs. '=' means written to. */
: "m" (in) /* Inputs. No '='. */
: "%eax"
);
assert(out == in + 1);
否则,这将是一个编译时错误,因为没有冒号它是一个基本的 asm,它不支持变量约束并且不需要或支持转义%1
。例如:
asm volatile ("movl $1200, %ecx;");
工作得很好。
扩展 asm 更常用,因为它更强大。
这有助于 GCC 区分操作数和寄存器。操作数有一个 % 作为前缀。'%%' 总是与寄存器一起使用。