汇编语言
GCC与Intel汇编语法的几个差异点

GCC最初是一个GNU C语言编译器(GNU C Compiler),只能处理C语言。 后来扩展并支持了更多的编程语言,现在GCC代表的是GNU编译器集合(GNU Compiler Collection)。

GCC编译器使用了 AT&T/UNIX 汇编语法,AT&T与Intel的汇编语法存在比较大的差异,下面是一些主要的差异点。

源操作数与目标操作数的顺序

AT&T语法中操作数的方向与Intel相反。
在Intel语法中,第一个是目标操作数,第二个是源操作数;
而在AT&T语法中,第一个是源操作数,第二个是目标操作数。

例如Intel语法:

Op-code dst src
(操作码 目标操作数 源操作数)

对应于AT&T语法:

Op-code src dst
(操作码 源操作数 目标操作数)

寄存器命名

如果要使用eax寄存器,使用Intel语法直接写为eax。

而AT&T语法需要在寄存器前面添加前缀%,即写为%eax。

立即操作数

AT&T的立即数操作数前面带有美元符号。

对于静态'C'变量,同样要在其前面加上美元符号。

在Intel语法中,对于十六进制常量,需要添加后缀h。例如

80h

而对于AT&T语法,不是添加后缀,而是在常量前面添加前缀0x。因此,对于一个十六进制数,开头是美元符号,然后是0x,最后是常量值。例如

$0x80

操作数大小

在AT&T语法中,内存操作数的大小由操作码名称的最后一个字符确定。 使用操作码后缀'b'、'w'和'l',分别用于指定字节(8位)、字(16位)和双字(32位)的内存引用。

Intel语法通过在内存操作数(而不是操作码)前添加'byte ptr'、'word ptr'和'dword ptr'来分别指定字节(8位)、字(16位)和双字(32位)的内存引用。

因此,Intel语法的

mov al, byte ptr foo

对应于AT&T语法的

movb foo, %al

内存操作数

在Intel语法中,基址寄存器被包含在中括号'['和']'内,而在AT&T中则使用小括号'('和')'替代中括号。

此外,在Intel语法中,间接的内存引用类似于

[base + index*scale + disp]

而在AT&T中则表示为

disp(base, index, scale)

需要注意一点,当常量值被用于disp或scale时,不需要在常量前面加上美元符号。

(进一步了解可参考 x86汇编指南之寄存器与内存寻址模式 (opens in a new tab) 一文的 内存寻址 一小节)

以上就是Intel语法和AT&T语法的一部分区别。如果想更完整的了解,可以查阅GNU汇编程序文档。

为了更好地理解,下面给出一些指令的对照表。

参考

https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html (opens in a new tab)

http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html