前缀不同:
在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,[ecx] | movl (%ecx),%eax |
内存单元操作数不同:
在Intel的语法中,基寄存器用“[]”括起来,而在AT&T中,用“()”括起来。
Intel语法 | AT&T语法 |
mov eax,[ebx+5] | movl 5(%ebx),%eax |
寻址方式不同:
常见形式
D(Rb,Ri,s) Mem[Reg[Rb]+S*Reg[Ri]+ D]
D:常量( 地址偏移量 )
Rb: 基址寄存器: 8个通用寄存器之一
Ri: 索引寄存器: esp不作为索引寄存器一般 ebp也不用做这个用途
S: 比例因子 1,2, 4,or 8其他变形
(Rb, Ri)Mem[Reg[Rb]+ Reg[Ri]]
D(Rb, Ri)Mem[Reg[Rb]+Reg[Ri]+D]
(Rb,Ri,S)Mem[Reg[Rb]+S*Reg[Ri]]
Intel语法 | AT&T语法 |
指令 foo,segreg:[base+index*scale+disp] | 指令 %segreg:disp(base,index,scale),foo |
mov eax,[ebx+20h] | movl 0x20(%ebx),%eax |
add eax,[ebx+ecx*2h | addl (%ebx,%ecx,0x2),%eax |
lea eax,[ebx+ecx] | leal (%ebx,%ecx),%eax |
sub eax,[ebx+ecx*4h-20h] | subl -0x20(%ebx,%ecx,0x4),%eax |
后缀不同:
在AT&T的操作码后面有一个后缀,其含义就是指出操作码的大小。"l"表示长整数(32位),"w"表示字(16位),"b"表示字节(8位)。而在Intel的语法中,则要在内存单元操作数的前面加上byte ptr, word ptr 和 dword ptr。
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 |
语法格式
首先看AT&T汇编语言语法结构。可以看做由两部分组成:操作码和操作数。
操作数是参加某种功能操作的数据,有三种方式提供:立即数;通过寄存器;通过内存。
立即数
立即数是一个常量,可以写成十进制(D),十六进制(H),八进制(O),二进制(B)
例如:addl 0xFFH,%eax
立即数只能作为源操作数,不能放在目的操作数位置。
寄存器操作数
指操作数存放在寄存器中,用来存放参加运算的数据或存放运算结果。寄存器包括段寄存器、控制寄存器和通用寄存器。
(1)段寄存器(DS、SS、ES)
是存放段地址的,要将段地址送入,必须以通用寄存器为中间桥梁,即通过通用寄存器将数据传送到DS、SS、ES段寄存器中。
例如:
将段地址2000H送数据段寄存器中。
movl 0x20000,%eax
movl %eax,DS
通过通用寄存器传送,不能直接将立即数传送到段寄存器中。而代码段CS不准用户干预,是由系统分配的。
(2)控制寄存器
控制寄存器包括:指令指针寄存器IP,EIP和标志寄存器FLAGS,控制寄存器也不能直接送操作数
(3)通用寄存器
通用寄存器可以装操作数。
内存操作数
内存操作数是指操作数存放在内存中,其操作是往内存中写数或从内存中取操作数,CPU与内存打交道是通过内存地址完成的。
例如:
movl 0x20000,%eax
movl %eax,(0x20000)
注意:
对于单操作数指令:操作数只能是寄存器操作数和内存操作数。
对于双操作数指令:源操作数可以是寄存器操作数、内存操作数和立即数,目的操作数可以是寄存器操作数和内存操作数。源操作数、目的操作数不能同时为内存操作数。