在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。通过对汇编语言的学习有助于加深对计算机硬件的理解,重要参考资料。
1. 语法格式
首先看AT&T汇编语言语法结构。可以看做由两部分组成:操作码和操作数。
与Intel的汇编语法相比,在AT&T中,寄存器前需要加上“%”,而立即数前需要加上“$”,而Intel的汇编语法中,寄存器和和立即数都没有前缀。在Intel的语法中,十六进制和二进制立即数后缀分别是“h”和“b”,而在AT&T中,十六进制立即数前需要加上“0x”。其他更多差异参见这篇文章。
操作数是参加某种功能操作的数据,有三种方式提供:立即数;通过寄存器;通过内存。
- 立即数
立即数是一个常量,可以写成十进制(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)
注意:
对于单操作数指令:操作数只能是寄存器操作数和内存操作数。
对于双操作数指令:源操作数可以是寄存器操作数、内存操作数和立即数,目的操作数可以是寄存器操作数和内存操作数。源操作数、目的操作数不能同时为内存操作数。
2. 内联汇编
内联汇编通常是指在 C/C++ 代码中嵌入汇编代码,在操作系统开发中会经常用到,可以提高代码的执行效率并且实现高级语言无法实现的操作。
内联汇编的格式为:
带有C/C++表达式的内联汇编格式为:
_asm_ _volatile_ (
"Instruction List"
:Output operands(optional)
:Input operands(optional)
:list of clobbered registers(optional)
);
注:_asm_相当于asm,这样写是为了防止与C/C++表达式关键字冲突;_volatile_或volatile是可选的,可以用它也可以不用它。如果用了它,则是向GCC声明“不要动我所写的Instruction List,我需要原封不动的保留每一条指令”,否则当使用了优化选项(-O)进行编译时,GCC将会根据自己的判断决定是否将这个内联汇编表达式中的指令优化掉。所以希望确保编译器不会在“asm"内部优化指令,可以在“asm”后使用关键字"volatile"。如果程序必须与ANSIC兼容,则应该使用_asm_和_volatile_&#x