寻址是X86系列CPU中最大的一个特色,也是从8086CPU中继承下来的。现在就来谈谈8086中的寻址方式。
1.地址加法器
一开始就提到了,8086是一个16位系统,寄存器是16位的,但是他的地址总线却有20位,那么16位的寄存器如何表示20位的地址?
段地址+偏移地址,这种形式就自然而然的出现了,CS这个寄存器就是保存着代码段的段地址,IP这个寄存器就是保存着代码的偏移地址,这样,通过CS:IP所表示的地址就能寻找到执行代码的地方。
那么两个16位寄存器怎么表示20位的地址?段地址*16+偏移地址,这就是段地址+偏移地址的真实含义,为什么要乘以16?这就是把段地址左移4位,加上原来的16位偏移地址,就可以得到一个20位的地址。
2.DS,BX,DI,SI
那么如何定位内存中的数据?形式是一样的,不过数据段的段地址保存在DS中,偏移地址需要由[BX]给出,前面也提到过了DI,SI是来帮助BX来完成对数据的寻址的,具体形式如下:
mov [BX+SI],AX ;把AX的值放入DS:[BX+SI]这个地址中。
BX,DI,SI三个都是变量,这就提供了更加丰富的寻址方式,这也为高级语言的数组提供了具体实现,例如,把BX的当成数组首地址,变动DI,就可以对一个一维数组中的各个元素进行逐个寻址,同理二维数组也是一样,只是增多一个变量。
那么数据只能是存放在数据段中吗?换句话说,一定要用[BX]的形式来表示数据吗?不,只要显示的给出段前缀(DS,CS,SS)就可以,如下:
mov CS:[BX],AX ;把AX的值放入CS:[BX]这个地址中。
那么直接用[BX]表示和显示给出段前缀有什么区别?其实很简单,直接用[BX]表示的段地址默认存在DS中。
3.prt
在存储数据中,数据字长是一个问题,计算机如何知道应该存储一个Byte的大小还是一个Word的大小?一般来说,通过你给出的寄存器来判断,如给出的是AX寄存器,那么这个数据大小就是16位,但是有时候没有这种暗示,那么怎么判断存储字长?例如我要向一个内存地址中直接写入10这个数据,那么这个10到底是8位?还是16位?这时就需要显示的指出数据字长,例如:
mov [BX],AX ;把AX的值当成一个Word存入DS:[BX]中。
mov byte ptr [BX],10 ;这就是将10看成一个Byte存入DS:[BX]中。