AT&T汇编总结
一. 传送数据
1. 定义数据元素:GNU汇编器提供了在汇编语言程序中定义和处理数据元素的很多方式,选择程序需要的处理数据的最佳方式,在数据段和bss段都提供定义数据元素的方式。
a.数据段:是最常见的定义数据元素的位置。
b.使用.data命令声明数据段在这个段声明的任何数据元素都保留在内存中并且可以被汇编语言程序中的指令读取和写入。
c.另一种类型的数据段,称为.rodata。在这种数据段中定义的任何数据元素只能按照只读(read-only)模式访问(因此使用ro前缀)。
d.数据段定义元素需要用到两个语句:一个标签和一个命令。标签用作引用数据元素所使用的标记,很像C程序中的变量名称。标签对处理器是没有意义,它只是汇编器试图访问内存位置时用作引用指针的一个位置;除了标签之外,还必须定义为数据元素保留多少字节,是一个汇编命令完成,这个命令指示汇编器为通过标签引用的数据元素保留特定数量的内存,保留的内存数量取决于定义的数据的类型,以及要声明的这个类型的项目的数量。声明命令之后,定义一个(或者多个)默认值,这样把保留的内存位置中的数据设置为特定值。
命令 | 数据类型 |
---|---|
.ascii | 文本字符串 |
.asciz | 以空字符串结尾的文本字符串 |
.byte | 字节值 |
.double | 双精度浮点数 |
.float | 单精度浮点数 |
.int | 32位整数 |
.long | 32位整数(和.int同) |
.octa | 16字节整数 |
.quad | 8字节整数 |
.short | 16位整数 |
.short | 单精度浮点数(和.float同) |
f.数据段声明数据元素的一个例子:
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
- 这个代码片段留出42字节的内存,把定义的字符串顺序地存放到内存字节中,并且把标签output赋值为第一个字节。以后当程序中引用内存位置output时,汇编器知道要转到文本字符串开头的内存位置。
g.例如此方法可以用与数字例子:
pi:
.float 3.14159
并不限制在一个命令语句行中只能定义一个值。可以在一行里定义多个值,按照每个值出现在命令中的顺序在内存中存放他们,例如:
标签必须在定义数据的命令的前面
sizes:
.long 100,150,200,250,300
定义数据元素,然后在程序中使用他们时需要小心。因为程序不会知道是否正确地处理了数据,如果你定义了两个16位整数数据值,但是把其中一个作为32位整数引用,汇编器仍然会读取必须的4字节内存,尽管这个值是错误的。
- 定义静态符号:.equ命令用于把常量值设置为可以在文本段中使用的符号。
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80
经过设置后,数据符号值是不能在程序中改动的。.equ命令可以出现在数据段中的任何位置,但是为了使需要阅读你的程序的其他人更加方便,最好在定义其他数据之前或者之后集中定义所有数据符号
a.引用静态数据元素,必须在标签名称之前使用$符号,例如:把赋值给LINUX_SYS_CALL符号的值传送给EAX寄存器
movel $LINUX_SYS_CALL, %eax
- bss段:bss段中定义数据元素和在数据段中定义有些不同。无需声明特定的数据类型,只需声明为所需目的保留的原始内存部分即可。
a.GNU汇编器使用两个命令声明缓冲:
命令 | 描述 |
---|---|
.comm | 声明未初始化的数据的通用内存区域 |
.lcomm | 声明未初始化的数据的本地通用内存区域 |
本地通用内存区域是为不会从本地汇编代码之外进行访问的数据保留的:
.comm synmbol, length
- 其中symbol是赋给内存区域的标签,length是内存区域中包含的字节数量
.section .bss
.lcomm buffer. 10000
- 这些语句把10000字节的内存区域赋值给buffer标签。在声明本地通用内存区域的程序之外的函数是不能访问他们的(不能在.globl命令中使用他们)。
- 在bss段中声明数据的一个好处是数据不包含在可执行程序中。在数据段中定义数据时,它必须被包含在可执行在程序中,因为必须使用特定值初始化它。因为不使用程序数据初始化bss段中声明的数据区域,所以内存区域被保留在运行时使用,并且不必包含在最终的程序中。
二. 传送数据元素:定义数据后,需要处理它们。因数据元素位于内存中,并且处理器的很多指令要利用寄存器,所以处理器元素的第一个步骤是在内存和寄存器之间传送他们。
1. MOV指令格式:MOV指令用作通用的数据传送指令。
a.MOV指令的基本格式:
movx source, destination
- source和destination的值可以是内存地址、存储在内存中的数据值、指令语句中定义的数据值、或者是寄存器。
- GNU汇编器为MOV指令添加了另一个唯独,在其中必须声明要传送的数据元素的长度。通过把一个附加字符添加到MOV助记符来声明这个长度,则指令变为:movx,其中x可以是下面字符
x | 描述 |
---|---|
l | 用于32位的长字值 |
w | 用于16位的字值 |
b | 用于8位的字节值 |
b.把32、16、8位的EAX寄存器值传送给32位的EBX寄存器值:
#32位
movl %eax, %ebx