Intel Syntax: mov eax, 1 (指令的目标,源)
AT&T Syntax: movl $1, %eax (指令的源,目标)
Intel语法相当直观。在上面的例子中,移动的数据量是从寄存器的大小推断出来的(在eax的情况下为32位)。所使用的寻址模式是从操作数本身推断出来的。
在使用AT&T语法时会有一些怪癖。首先,请注意mov
指令末尾的l
后缀,它代表long
,表示32位的数据。其他指令后缀包括w
表示一个字(16位 - 不要与CPU的字长混淆!),q
表示四个字(64位),b
表示一个单字节。虽然不总是必需的,但通常您会看到使用AT&T语法的汇编代码明确说明指令所操作的数据量。
在涉及源和目标操作数使用的寻址模式时需要更多的明确性。符号$
表示立即寻址
,即使用指令本身中的值。在上面的例子中,如果没有这个$
,将会使用直接寻址
,即CPU会尝试获取内存地址1处的值(这很可能会导致分段错误)。符号%
表示寄存器寻址
,如果在上面的例子中没有包含它,则eax将被视为一个符号
,即一个带标签的内存地址,这很可能会在链接时导致未定义引用
。因此,您必须明确地说明源和目标操作数所使用的寻址模式,这是强制性的。
指定内存操作数的方法也不同:
Intel: [基础寄存器 + 索引 * 索引的大小 + 偏移量]
AT&T: offset(基础寄存器, 索引, 索引的大小)
Intel语法更清楚地说明了计算寻找内存地址的过程。使用AT&T语法时,结果相同,但您需要知道正在进行的计算。
理论上应该产生相同的二进制文件
这完全取决于您的工具链。
有什么理由支持其中之一吗?
当然,这是个人偏好。在我看来,关键在于你在处理内存时感觉哪种语法更舒适。你喜欢AT&T语法的强制明确性吗?还是你喜欢汇编器为你处理这些低级细节?
是命令行选项吗?宏?非助记符关键字?
这与汇编器(GAS,NASM)本身有关。同样,这也是个人偏好。
objdump
的Intel语法反汇编保留了兼容缺陷的操作数翻转,因此它实际上并没有生成正确的FP代码的Intel语法反汇编。除此之外,我通常更喜欢AT&T语法。Intel语法对于某些向量洗牌操作更友好。此外,在AVX中,目标是第一个操作数,而不是有时在长行末尾丢失的最后一个操作数。 - Peter Cordes