汇编原理深入了解 > 汇编语法
AT&T 与 Intel 的汇编语言语法区别

x86汇编一直存在两种不同的语法,在intel的官方文档中使用intel语法,Windows也使用intel语法,而UNIX平台的汇编器一直使用AT&T语法。

AT&T 和 Intel 汇编语言的语法区别主要体现在操作数前缀、赋值方向、间接寻址语法、操作码的后缀上,而就具体的指令而言,在同一平台上,两种汇编语言是一致的。下面仅列出这两种汇编语言在语法上的不同点。

操作数前缀

在 Intel 的汇编语言语法中,寄存器和和立即数都没有前缀。但是在 AT&T 中,寄存器前冠以“%”,而立即数前冠以“$”。在 Intel 的语法中,十六进制和二进制立即数后缀分别

冠以“h”和“b”,而在 AT&T 中,十六进制立即数前冠以“0x”:

Intel 语法

AT&T 语法

Mov eax,8

movl $8,%eax

Mov ebx,0ffffh

movl $0xffff,%ebx

int 80h

int $0x80


源/目的操作数顺序

Intel 汇编语言的指令与 AT&T的指令操作数的方向上正好相反:在 Intel 语法中,第一个操作数是目的操作数,第二个操作数源操作数。而在 AT&T 中,第一个数是源操作数,第二个数是目的操作数。

Intel 语法

AT&T 语法

MOV EAX,8

movl $8,%eax


寻址方式

与 Intel 的语法比较,AT&T 间接寻址方式可能更晦涩难懂一些。 Intel 的指令格式是segreg: [base+index*scale+disp],而 AT&T 的格式是%segreg:disp(base,index,scale)。其中index/scale/disp/segreg 全部是可选的, 完全可以简化掉。如果没有指定 scale 而指定了 index,则 scale 的缺省值为 1。 segreg 段寄存器依赖于指令以及应用程序是运行在实模式还是保护模式下,在实模式下,它依赖于指令,而在保护模式下, segreg 是多余的。在 AT&T 中,当立即数用在 scale/disp 中时, 不应当在其前冠以“$”前缀, 而且 scale,disp 不需要加前缀“&”。另外在 Intel 中基地址使用“[”、“]”,而在 AT&T 中则使用“(”、“)

Intel 语法

AT&T 语法

Instr foo,segreg: [base+index*scale+disp]

instr %segreg: disp(base,index,scale),foo

[eax]

(%eax)

[eax + _variable]

_variable(%eax)

[eax*4 + _array]

_array(,%eax,4)

[ebx + eax*8 + _array]

_array(%ebx,%eax,8)


标识长度的操作码前缀和后缀

在 AT&T 汇编中远程跳转指令和子过程调用指令的操作码使用前缀“l”,分别为 ljmp,lcall,与之相应的返回指令伪 lret。例如:

Intel 语法

AT&T 语法

LL SECTION:OFFSET

lcall secion:offset

FAR SECTION:OFFSET

ljmp secion:offset

FAR STACK_ADJUST

lret $stack_adjust

在 AT&T 的操作码后面有时还会有一个后缀,其含义就是指出操作码的大小。“l”表示

长整数(32 位),“w”表示字(16 位),“b”表示字节(8 位)。而在 Intel 的语法中,则要

在内存单元操作数的前面加上 byte ptr、 word ptr,和 dword ptr,“dword”对应“long”。

Intel 语法

AT&T 语法

Mov al,bl

movb %bl,%al

Mov ax,bx

movw %bx,%ax

Mov eax,ebx

movl %ebx,%eax

Mov eax, dword ptr [ebx]

movl (%ebx),%eax

 

如何在gdb 中切换反汇编的汇编语言

1.直接在gdb 调试窗口输入

切换到intel 语法

set disassembly-flavor intel

切换到 AT&T语法

set disassembly-flavor at

2. 修改 home目录的 .gdbinit 文件

sudo echo "set disassembly-flavor intel"> ~/.gdbinit

source   ~/.gdbinit