Chinaunix首页 | 论坛 | 博客
  • 博客访问: 478054
  • 博文数量: 174
  • 博客积分: 2502
  • 博客等级: 少校
  • 技术积分: 1923
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-28 09:47
文章分类

全部博文(174)

文章存档

2011年(8)

2010年(16)

2009年(68)

2008年(82)

我的朋友

分类: LINUX

2009-03-12 11:00:50


1. 前缀:
    在Intel的语法中,寄存器和立即数都没有前缀,但是在AT&T中,寄存器前冠以"%",而立即数前冠以"$"。在Intel的语法中,十六进制和二进制立即数后缀分别冠以"h"和"b",而在AT&T中,十六进制立即数前冠以"0x",
    Intel与AT&T前缀的区别
    Intel语法                        AT&T语法
    mov eax, 8;                        movl $8, %eax
    mov ebx, 0ffffH;                movl $0xffff, %ebx
    int 80H;                        int $0x80

2. 操作数的方向:
    Intel与AT&T操作数的方向正好相反。在Intel语法中,第一个操作数是目的操作数,第二个操作数是源操作数。而在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中时,不应当在其前冠以"$"前缀,下表给出了几个例子.
    内存操作数的语法及举例
    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"。下表给出几个相应的例子:
    操作码的后缀举例:
    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

写好一个汇编程序后,就需要对其进行汇编(assembly)和连接。在Linux下有两种方式,一种是使用汇编程序gas和连接程序ld,一种是使用gcc。
1.a    gas把汇编源文件(.s)转换为目标文件(.o)
    as test.s -o test.o
1.b    对目标文件进行连接
    ld test.o -o test
2.    gcc一步完成汇编和连接
    gcc -o test test.S
    注: 大写的后缀.S可以使gcc自动识别汇编程序中的C预处理命令,像#include、#define、#ifdef、#endif等。也就是说,使用gcc进行编译,可以在汇编程序中使用C的预处理命令。

相关阅读: 《Linux 中 x86 的内联汇编》
http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/index.html

阅读(815) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~