《汇编语言程序设计》Richard Blum著:5.2.4 在内存和寄存器之间传送数据
使用变址的内存位置:
可以在一个命令中指定把多个值存放到内存中:
values:
.int 10,15,20,25,30,35,40,45,50,55,60
这创建存放在内存中的连续的一系列数据值。每个数据值都占用内存的一个单元(在上面的例子中是长整型,即4个字节)。引用数组中的数据时,必须使用变址系统确定你要访问的是哪个值。
完成这种操作的方式称为变址内存模式(indexed memory mode)。内存位置由下列因素确定:
(1)基址
(2)添加到基址上的偏移地址
(3)确定选择哪个数据元素(第几个)的变址
(4)数据元素的长度
表达式的格式是:
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开始)。
使用寄存器间接寻址
除了保存数据之外,寄存器也可以用于保存内存地址。当寄存器保存内存地址时,它被称为指针(pointer)。使用指针访问存储在内存位置中的数据称为间接寻址(indirect addressing)。
使用标签引用内存位置中包含的数据值,通过在标签前面加上美元符号($)获得数据值的内存位置的地址。因此,下面这条指令
movl $values, %edi
用于把values标签引用的内存位置的地址传送给EDI寄存器。
间接寻址模式的另一半,如下面这条指令
movl %ebx, (%edi)
如果EDI寄存器外面没有括号,那么指令只是把EBX寄存器中的值加载到EDI寄存器中。如果EDI寄存器外面加上了括号,那么指令就把EBX寄存器中的值传送给EDI寄存器中包含的内存位置。
GNU汇编器不允许把值与寄存器相加,必须把值放在括号之外,就像这样:
movl %edx, 4(%edi)
这条指令把EDX寄存器中的值存放在EDI寄存器指向的位置之后4个字节的内存位置中。也可以把它存放到相反的方向:
movl %edx, -4(%edi)
这条指令把值存放在EDI寄存器指向的位置之前4个字节的内存位置中。
变址values(, %edi, 4)和间址4(%edi)