AT&T汇编

本文简单介绍AT&T汇编语言,基于学过X86汇编

1.语法格式

1.寄存器

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

832-bit寄存器 %eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp

816-bit寄存器 它们事实上是上面832-bit寄存器的低16位:
%ax,%bx,%cx,%dx,%di,%si,%bp,%sp

88-bit寄存器  %ah,%al,%bh,%bl,%ch,%cl,%dh,%dl
它们事实上是寄存器%ax,%bx,%cx,%dx的高8位和低86个段寄存器   %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)

寄存器功能

以E开头的寄存器为32位
EAX(累加器,是算术运算的主要寄存器)
EBX(基址寄存器,在内存中寻址时存放基址)
ECX(计数器)
EDX(数据寄存器)
ESI(源变址)
EDI(目标变址)
ESP(堆栈指针)
EBP(基址指针)
EIP(程序计数器,存储的是将要执行的下一条指令放在内存中的地址)
EFLAGS(保存的是根据运算得到的结果设置的条件码ZF,CF,SF,OF)

段寄存器:
CS:代码段寄存器
SS:堆栈段寄存器
DS:数据段寄存器
ES、FS、GS:附加数据段寄存器


2.指令的长度后缀
在指令后面加上后缀表示长度,根据操作的是1字节、2字节、4字节、8字节,分别对应后缀b, w, l, q

movq $1, %rax

3.操作数顺序
操作数排列是从源(左)到目的(右)

movl %eax(源), %ebx(目的)  (ebx) = (eax)

4.立即数
使用立即数,要在数前面加符号$

1:
movl $0x04, %ebx” 

2:
para = 0x04 
movl $para, %ebx

5.注释
在AT&T中,注释既可以使用" ;",也可以使用" ! "

6.符号常数
符号常数直接引用

 value: .long 0x12a3f2de 
    movl value , %ebx 

指令执行的结果是将常数0x12a3f2de装入寄存器ebx,
引用符号地址在符号前加符号$, 如“movl $value, % ebx”则是将符号value的地址装入寄存器ebx

7.调用和跳转指令
段内调用和跳转指令为"call",“ret"和"jmp”,段间调用和跳转指令为"lcall",“lret"和"ljmp”

段间调用和跳转指令的格式

lcall/ljmp $SECTION, $OFFSET

段间返回指令为

lret $STACK-ADJUST

jmp, jcc, call指令跳转
AT&T汇编_第1张图片
寄存器:如果想要跳到寄存器%rax内容对应的地址,不是写成jmpq %rax,而是写成*jmpq %rax

立即数:如上表所示,不用加*号

内存:如果想要跳转到%rip + 0x10对应的地址,不是写成jmpq 0x10(%rip),而是写成jmpq *0x10(%rip)

8.数据声明

格式:命令 数据类型

.ascii 文本字符串

.asciz 以空字符串结尾的文本字符串

.byte  字节值

.double       双精度浮点数

.float 单精度浮点数

.int    32位整数

.long 32位整数(同32.octa  16字节整数

.quad 8字节整数

.short 16位整数

.single        单精度浮点数(和.float同)

两个命令声明缓冲:
命令 描述
.comm        声明未初始化的数据的通用内存区域

.lcomm       声明未初始化的数据的本地通用内存区域

9.寻址方式

1.直接寻址
把某个地址上的值放到寄存器中
movl 0x8000, %eax  # 把地址0x8000上的值放到eax中

2. 间址寻址
把寄存器上的值所代表的地址所指向的值放到寄存器中
movl $0x8000, %ebx  
movl %ebx, %eax  # 间址寻址, 把地址0x8000(在寄存器ebx中)上的值放到eax中

3. 基址寻址
以寄存器里的数值作为基址,加上一个常数得到最终地址,把地址上的值放到寄存器中
movl $0x8000, %eax  
movl 4(%eax), %ebx  #基址寻址, 把地址0x80040x8000+4)上的值放到eax中

4. 变址寻址
以两个寄存器里的数值之和加上一个常数得到最终地址,把地址上的值放到寄存器中
movl $0x8000, %eax   
movl $0x4, %ebx   
movl (%eax,%ebx), %ecx   #变址寻址, 把地址0x80040x8000+4)上的值放到ecx中

movl  4%eax,%ebx), %ecx   #变址寻址, 把地址0x80080x8000+4+4)上的值放到ecx中


5. 比例变址寻址
以一个寄存器里的数值加上另一个寄存器里的数字 乘以一个比例因子(1,2,4,8)再加上一个常数得到最终地址,把地址上的值放到寄存器中
movl $0x2000, %eax   
movl $0x2, %ebx   
movl (,%eax,4, %ecx   #比例变址寻址, 把地址0x80000x2000 *4)上的值放到ecx中

movl  6(,%eax,4, %ecx   #比例变址寻址, 把地址0x80060x2000 *4+6)上的值放到ecx中

movl  (%ebx,%eax,4, %ecx   #变址寻址, 把地址0x80020x2000*4+2)上的值放到ecx中

movl  6%ebx,%eax,4, %ecx   #变址寻址, 把地址0x80080x2000*4+2+6)上的值放到ecx中

10.文件组成

.text:存放代码对应的指令 正文段

.bss:存放未初始化的全局和静态变量,在运行时该区域初始是全0

.rodata:存放只读数据和变量,例如字符串字面量

.data:存放余下的数据和变量,可读可写 数据段

.ascii:定义一个字符串并且用双引号包含

.byte: 定义一个字符用单引号

.org:定义当前的汇编的位置

伪操作符语句是汇编器使用的指示符,它通常并不会产生任何代码,它由伪操作码和0个或多个操作数组成。每个操作码都是由一个一个点字符’.'开始,表示编译过程中的位置计数器。其值是点符号出现机器指令第一个字节的地址。

11.编译

1)使用as命令对汇编文件进行汇编生成目标文件:as xxx.s -o xxx.o

2)使用ld命令对目标文件进行链接生成可执行文件:ld xxx.o -o xxx

注意,ld命令进行链接要求目标文件的.text段必须有一个入口点,ld默认认为_start标签对应的代码是入口点

12.操作码前缀
用于修饰随后的代码
AT&T汇编_第2张图片

Intel和AT&T汇编语法差异

1.前缀
Intel汇编寄存器和立即数无需前缀。后者寄存器前缀为%,立即数前缀为$

2.内存变量
Intel语法使用中括号[],后者使用小括号()

3.后缀
AT&T汇编指令有后缀(b,w,l,q),以表明数据类型(8位、16位等);Intel则根据寄存器自动识别

你可能感兴趣的:(#,汇编语言,开发语言)