|
MOV 指令用来传送数据,基本格式是:source 和 destination 的值可以是内存地址、存储在内存中的数据值、指令语句中定义的数据值,或者是寄存器。
movx 中的 x 用来要传送的数据元素的长度,可以是下面的字符:
如:
movl %eax, %ebx #32 位寄存器 EAX 中的内容送往 32 位寄存器 EBX
movw %ax, %bx #16 位寄存器
movb %al, %bl # 8 位寄存器
1、把立即数传送到寄存器和内存movl $0, %eax # 0 送往 EAX 寄存器
movl $0x80, %ebx # 16 进制 80 送往 EBX 寄存器
movl $100, height # 100 送往 height 所标识的内存位置处
2、在寄存器之间传送数据
数据在寄存器与寄存器间的传递是最快的,尽可能把数据保存在处理器寄存器中通常是明智的,这样可以减少试图访问内存位置所花费的时间。
需要注意的是,专用寄存器(控制、调试和段寄存器) 中的内容只能传给通用寄存器,或者接收从通用寄存器传来的内容。8 个通用寄存器是 (EAX, EBX, ECX, EDX, EDI, ESI, EBP 与 ESP) 。
例如:movl %eax, %ecx
movw %ax, %cx
下面这条指令是错误的:因为这条指令试图把 AL 寄存器中的 8 位传送给 BX 寄存器中的低 8 位。
3、在内存和寄存器之间传送数据
把数据从内存传送到寄存器value 是个引用内存位置的标签,如下这么定义:
value:
.int 1
把数据从寄存器传送给内存
使用变址的内存位置
像 C 中定义数组一样,汇编里可以在一个命令中指定把多个值存放到内存中:values:
.int 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 这创建了存放在内存中的连续一系列数据值。每个数据都占用内存的一个单元 (这里是 int 整型,占4字节)。引用这些数据中其中的一个时,需要使用变址的方法来确定要访问的那个数据。完成这种操作的方式称为变址内存模式 (indexed memory mode)。内存位置由下列因素确定:
表达式的格式是:base_address (offset_address, index, size)
获取的数据位于:base_address + offset_address + index * size 如果其中的任何值为零,则可以忽略它们,但是仍然需要用逗号作为占位符。
offset_address 和 index 的值必须是寄存器,但 size 的值可以是数字值。例如,为了引用上面给出的 values 数组中的值 20,可以使用下面的命令:movl $2, %edi
movl values(, %edi, 4), %eax 这条指令把从 values 标签开始的第 3 个 4 字节的变址值加载到 EAX 寄存器中 (注意,数组从变址 0 开始)。大多数情况下,将使用一个寄存器计数器作为变址值,并且改变这个值来匹配要处理的数组元素。
测试程序:
.section .data
output:
.asciz "The value is %d\n"
values:
.int 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60
.section .text
.globl _start
_start:
nop
movl $0, %edi
loop:
movl values(, %edi, 4), %eax
pushl %eax
pushl $output
call printf
addl $8, %esp
inc %edi
cmpl $11, %edi
jne loop
movl $0, %ebx
movl $1, %eax
int $0x80 运行输出:$ ./movetest3
The value is 10
The value is 15
The value is 20
The value is 25
The value is 30
The value is 35
The value is 40
The value is 45
The value is 50
The value is 55
The value is 60 程序中也可以使用 offset_address ,那么在程序中可修改为: movl values(%edi), %eax
pushl %eax
pushl $output
call printf
addl $8, %esp
addl $4, %edi
cmpl $44, %edi
jne loop
4、使用寄存器间接寻址
当使用标签引用内存位置中包含的数据值时,可以通过指令中的标签前面加上 $ 符号获得数据值的内存位置的地址,如:用于把 values 标签引用的内存地址传送给 EDI 寄存器。
又如:上面指令是把 EBX 中的值送到 EDI 中包含的内存地址处,也就是说 EDI 寄存器中的值是一个内存地址;如果 EDI 不加括号,则是把 EBX 中的值送到 EDI 寄存器中。
GNU 汇编器不允许把值与寄存器相加,必须把值放在括号之外,如下所示:movl %ebx, 4(%edi)
movl %ebx, -4(%edi) |
|