深度探索Go语言:对象模型与runtime的原理特性及应用
上QQ阅读APP看书,第一时间看更新

1.2.2 数据传输指令

x86有多种数据传输指令,这里只简单介绍最常用的MOV指令。MOV指令主要用来在寄存器之间及寄存器和内存之间传输数据,也可以用来把一个立即数写到寄存器或内存中。第1个操作数称为目的操作数,第2个操作数是源操作数,MOV指令用于把源操作数的值复制到目的操作数中。

把ECX寄存器的值复制到EAX寄存器中,指令如下:

把数值1234复制到EDX寄存器中,指令如下:

因为涉及从内存中读写数据,所以接下来有必要了解一下x86常用的几种内存寻址方式,实际上很多指令会涉及内存寻址,不过跟数据传输放在一起讲解更容易理解。

指令中可以直接给出内存地址的偏移量,又称为位移,也可以通过一项或多项数据计算得到一个地址。

(1)Displacement:位移,是一个8位、16位或32位的值。

(2)Base:基址,存放在某个通用寄存器中。

(3)Index:索引,存放在某个通用寄存器中,ESP不可用作索引。

(4)Scale:比例因子,用来与索引相乘,可以取值1、2、4、8。

经过计算得到的地址称为有效地址,计算公式如式(1-1)所示。

Base、Index和Displacement可以随意组合,任何一个都可以不存在,如果不使用Index也就没有Scale。Index和Scale主要用来寻址数组和多维数组,这里不继续展开。下面简单介绍基于Base和Displacement的寻址。

(1)位移(Displacement):一个单独的位移表示距离操作数的直接偏移量。因为位移被编码在指令中,所以一般用于编译阶段静态分配的全局变量之类。

(2)基址(Base):将内存地址存储在某个通用寄存器中,寄存器的值可以变化,所以一般用于运行时动态分配的变量、数据结构等。

(3)基址+位移(Base+Displacement):基址加位移,尤其适合寻址运行时动态分配的数据结构的字段,以及函数栈帧上的变量。

如下3条汇编指令分别使用位移、基址和基址+位移这3种寻址方式,指令如下: