Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3247941
  • 博文数量: 530
  • 博客积分: 13360
  • 博客等级: 上将
  • 技术积分: 5473
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-13 13:32
文章分类

全部博文(530)

文章存档

2017年(1)

2015年(2)

2013年(24)

2012年(20)

2011年(97)

2010年(240)

2009年(117)

2008年(12)

2007年(8)

2006年(9)

分类: C/C++

2011-12-14 20:28:22

1.概述
       大多数情况下 Linux 程序员不需要使用汇编语言,因为即便是硬件驱动这样的底层程序在 Linux 操作系统中也可以用完全用 C 语言来实现,再加上 GCC 这一优秀的编译器目前已经能够对最终生成的代码进行很好的优化,的确有足够的理由让我们可以暂时将汇编语言抛在一边了。但实现情况是 Linux 程序员有时还是需要使用汇编,或者不得不使用汇编,理由很简单:精简、高效和 libc 无关性。
fafdasfas

       GCC只支持AT&T汇编语言语法。

2. 寄存器
      引用寄存器要在寄存器号前加百分号%,如“movl %eax, %ebx”。

80386有如下寄存器:
8个32-bit寄存器
       %eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp;

8个16-bit寄存器--它们事实上是上面8个32-bit寄存器的低16位
       %ax,%bx,%cx,%dx,%di,%si,%bp,%sp;

8个8-bit寄存器--它们事实上是寄存器%ax,%bx,%cx,%dx的高8位和低8位
       %ah,%al,%bh,%bl,%ch,%cl,%dh,%dl

6个段寄存器
       %cs(code),%ds(data),%ss(stack), %es,%fs,%gs;

3个控制寄存器
       %cr0,%cr2,%cr3;

6个debug寄存器
       %db0,%db1,%db2,%db3,%db6,%db7;

2个测试寄存器
       %tr6,%tr7;

8个浮点寄存器栈
       %st(0),%st(1),%st(2),%st(3),%st(4),%st(5),%st(6),%st(7)。

2.立即数
       使用立即数,要在数前面加符号$, 如“movl $0x04, %ebx”
       或者:
              para = 0x04
              movl $para, %ebx
       指令执行的结果是将立即数04装入寄存器ebx。

3.操作数顺序
       操作数排列是从源(左)到目的(右),如“movl %eax(源), %ebx(目的)”

操作数的长度
       操作数的长度用加在指令后的符号表示b(byte, 8-bit), w(word, 16-bits), l(long, 32-bits),
       比如:“movb %al, %bl”
                 “movw %ax, %bx”
                 “movl %eax, %ebx ”
       如果没有指定操作数长度的话,编译器将按照目标操作数的长度来设置。
       比如指令“mov %ax, %bx”,
       由于目标操作数bx的长度为word,那么编译器将把此指令等同于“movw %ax, %bx”。同样道理,指令“mov $4, %ebx”等同于指令“movl $4, %ebx”,“push %al”等同于“pushb %al”。对于没有指定操作数长度,但编译器又无法猜测的指令,编译器将会报错,比如指令“push $4”。

4.调用和跳转指令
       段内调用和跳转指令
                  "call","ret"和"jmp"
       段间调用和跳转指令为
                  "lcall","lret"和"ljmp"。
       段间调用和跳转指令的格式为
                “lcall/ljmp $SECTION, $OFFSET”
       段间返回指令则为
                “lret $STACK-ADJUST”。

5.符号扩展和零扩展指令
       绝大多数面向80386的AT&T汇编指令与Intel格式的汇编指令都是相同的,符号扩展指令和零扩展指令则是仅有的不同格式指令。
       符号扩展指令和零扩展指令需要指定源操作数长度和目的操作数长度,即使在某些指令中这些操作数是隐含的。
       在AT& T语法中,符号扩展和零扩展指令的格式为,基本部分"movs"和"movz"(对应Intel语法的movsx和movzx),后面跟上源操作数长度和目的操作数长度。
       movsbl意味着movs (from)byte (to)long;
       movbw意味着movs (from)byte (to)word;
       movswl意味着movs (from)word (to)long。
      对于movz指令也一样。比如指令“movsbl %al, %edx”意味着将al寄存器的内容进行符号扩展后放置到edx寄存器中。
其它的Intel格式的符号扩展指令还有:
       cbw -- sign-extend byte in %al to word in %ax;
       cwde -- sign-extend word in %ax to long in %eax;
       cwd -- sign-extend word in %ax to long in %dx:%ax;
       cdq -- sign-extend dword in %eax to quad in %edx:%eax;
       对应的AT&T语法的指令为cbtw,cwtl,cwtd,cltd。

参考文献
1.80386汇编+GCC的内嵌汇编. http://blog.csdn.net/joliny/article/details/4217160
阅读(990) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~