我不相信Intel语法使用百分号。也许我遗漏了什么?
你被搞混了
%operand
单一的
%
)
,而不是汇编程序看到的最后一个asm。
%%
使用文字
"mov %%eax, 1"
在Intel syntax inline asm中,但仍然使用
"mov %0, 1"
或
%[named_operand]
.
见
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
. 在Basic asm(没有操作数)中,没有替换,而且%在模板中不特殊,因此您可以编写
mov $1, %eax
mov $1, %%eax
在Extended中,如果出于某种原因,您没有使用
mov $1, %[tmp]
或
mov $1, %0
.
uint32_t rnds_00_15;
使用
%[rnds_00_15]
和编译
-masm=intel
.att_syntax
最后;这将破坏编译器生成后面的asm。)
DWORD PTR
,因为操作数扩展已经包含了它,例如。
DWORD PTR [rsp - 4]
,并在
DWORD PTR DWORD PTR [rsp - 4]
. (气体接受它很好,但第二个接受进动,所以它毫无意义,可能会误导我们。)
"=m"
如果希望编译器在堆栈上保留一些暂存空间,则输出操作数。不能修改只输入的操作数,即使它在C中未使用。也许编译器决定它可以重叠其他操作数,因为它没有被写入和初始化(即UB)。(我不确定你的
"memory"
clobber使其安全,但没有理由不在这里使用早期的clobber输出操作数。)
并且您希望通过使用
%=
得到一个唯一的号码。
工作示例(GCC和ICC,但不幸的是不是clang)
,
on the Godbolt compiler explorer
. 您可以使用“二进制模式”(11010按钮)来证明它在编译到asm后实际上是在没有警告的情况下进行汇编的。
int libtest_intel()
{
uint32_t rnds_00_15;
// Intel syntax operand-size can only be overriden with operand modifiers
// because the expansion includes an explicit DWORD PTR
__asm__ __volatile__
( // ".intel_syntax noprefix \n\t"
"mov %[rnds_00_15], 1 \n\t"
"cmp %[rnds_00_15], 1 \n\t"
"je .Ldone%= \n\t"
".Ldone%=: \n\t"
: [rnds_00_15] "=&m" (rnds_00_15)
:
: // no clobbers
);
return 0;
}
编译(使用
gcc -O3
)为了这个小高潮。也与
gcc -m32
当然:
libtest_intel:
mov DWORD PTR [rsp-4], 1
cmp DWORD PTR [rsp-4], 1
je .Ldone8
.Ldone8:
xor eax, eax
ret
.intel_syntax noprefix
当我明确地把它放在
.
你必须使用
%b[tmp]
BYTE PTR [rsp-4]
只访问dword输入操作数的低位字节。如果您想做很多这方面的工作,我建议您使用AT&T语法。
使用
%[rnds_00_15]
Error: junk '(%ebp)' after expression.
那是因为你没有告诉编译器就切换到了英特尔语法。如果你想让它使用英特尔寻址模式,
编译时使用
-masm=英特尔
所以编译器可以用正确的语法替换到模板中。
这就是为什么我要不惜一切代价避免那个糟糕的GCC内联程序集。伙计,我看不起这个破工具。
你只是用错了。它有点麻烦,但是如果你理解它是如何设计的,它是有意义的,而且大部分工作得很好。
在我后面重复:
编译器不分析asm字符串
完全
,除了做文本替换
. 这就是为什么它没有注意到
.intel_syntax noprefex
并不断替换AT&T语法。
4 + %[mem]
在AT&T语法中工作)。
方言选择:
-masm=英特尔
或者不,
use Dialect alternatives
还演示操作数大小重写
#include <stdint.h>
int libtest_override_operand_size()
{
uint32_t rnds_00_15;
// Intel syntax operand-size can only be overriden with operand modifiers
// because the expansion includes an explicit DWORD PTR
__asm__ __volatile__
(
"{movl $1, %[rnds_00_15] | mov %[rnds_00_15], 1} \n\t"
"{cmpl $1, %[rnds_00_15] | cmp %k[rnds_00_15], 1} \n\t"
"{cmpw $1, %[rnds_00_15] | cmp %w[rnds_00_15], 1} \n\t"
"{cmpb $1, %[rnds_00_15] | cmp %b[rnds_00_15], 1} \n\t"
"je .Ldone%= \n\t"
".Ldone%=: \n\t"
: [rnds_00_15] "=&m" (rnds_00_15)
);
return 0;
}
使用英特尔语法,gcc将其编译为:
mov DWORD PTR [rsp-4], 1
cmp DWORD PTR [rsp-4], 1
cmp WORD PTR [rsp-4], 1
cmp BYTE PTR [rsp-4], 1
je .Ldone38
.Ldone38:
xor eax, eax
ret
使用AT&T语法,编译为:
movl $1, -4(%rsp)
cmpl $1, -4(%rsp)
cmpw $1, -4(%rsp)
cmpb $1, -4(%rsp)
je .Ldone38
.Ldone38:
xorl %eax, %eax
ret