最近在学习汇编语言,结果出现了很奇怪的是,在vc++6.0下反编译的代码,gcc编译器下的代码不一样,后来才发现linux继承unix家族的汇编指令,平时常见的都是intel汇编语言。接下来就和我一起探而二者的对比关系吧。
1.前缀
在Intel的语法中,寄存器和和立即数都没有前缀。但是在AT&T中,寄存器前冠以“%”,而立即数前冠以“$”。在Intel的语法中,十六进制和二进制立即数后缀分别冠以“h”和“b”,而在AT&T中,十六进制立即数前冠以“0x”,表2.2给出几个相应的例子。
表2.2 Intel与AT&T前缀的区别
Intel语法 | AT&T语法
|
Mov eax 8 | Movl $8,%eax |
Mov ebx ,0fffh | Movl $0xffff,%ebx |
Int 80h | Int $0x80 |
2. 操作数的方向
Intel与AT&T操作数的方向正好相反。在Intel语法中,第一个操作数是目的操作数,第二个操作数源操作数。而在AT&T中,第一个数是源操作数,第二个数是目的操作数。由此可以看出,AT&T 的语法符合人们通常的阅读习惯。
例如:在Intel中, mov eax,[ecx]
在AT&T中,movl (%ecx),%eax
3.内存单元操作数
从上面的例子可以看出,内存操作数也有所不同。在Intel的语法中,基寄存器用“[]”括起来,而在AT&T中,用“()”括起来。
例如: 在Intel中,mov eax,[ebx+5]
在AT&T,movl 5(%ebx),%eax
4.间接寻址方式
与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中时,不应当在其前冠以“$”前缀,表2.3给出其语法及几个相应的例子。
表2.3 内存操作数的语法及举例
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的语法比较晦涩难懂,因为[base+index*scale+disp]一眼就可以看出其含义,而disp(base,index,scale)则不可能做到这点。
这种寻址方式常常用在访问数据结构数组中某个特定元素内的一个字段,其中,base为数组的起始地址,scale为每个数组元素的大小,index为下标。如果数组元素还是一个结构,则disp为具体字段在结构中的位移。
5.操作码的后缀
在上面的例子中你可能已注意到,在AT&T的操作码后面有一个后缀,其含义就是指出操作码的大小。“l”表示长整数(32位),“w”表示字(16位),“b”表示字节(8位)。而在Intel的语法中,则要在内存单元操作数的前面加上byte ptr、 word ptr,和dword ptr,“dword”对应“long”。表2.4给出几个相应的例子。
表2.4 操作码的后缀举例
Intel语法
|
| ||
Mov al,bl | movb %bl,%al
| ||
Mov ax,bx
| movw %bx,%ax
| ||
Mov eax, dword ptr [ebx] | movl (%ebx),%eax
| ||
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。