8086的地址线为20位,最大寻址空间为220=1MB。8086内部的寄存器都是16位,对地址的运算也是16位,而16位的最大寻址范围为220=64KB。
为了能在1MB空间内进行全范围寻址,即可访问到1MB存储器的任何一个存储单元,把lMB存储器分成若干段(segment),每一段最大为64KB,如图2.3所示。在分段时,要求段的起始单元的物理地址是16的整数倍,写成十六进制,最后一位应是0,即xxxXOH(x为任一个十六进制数码,H为十六进制后缀)。
把段的起始单元的物理地址除以16的结果称为段地址,它为16位,写成十六进制是4位:XXXXH。显然,段地址决定了段在lMB空间中的位置。段内各存储单元相对段的起始单元都有一个距离,称为段内偏移量。
在对内存进行操作时,段地址先确定下来,然后给出不同的段内偏移量,就可以实现段内的寻址。段地址也是可以改变的,即段在1MB空间中的位置是可变的,因而可实现1MB的全范围寻址。
由于采用了分段结构,因此可以把每一个存储单元看成是具有两种类型的地址:物理地址和逻辑地址。物理地址就是实际地址,它具有20位的地址值,它惟一地标识1MB存储空间的某一存储单元。CPU与存储器之间的信息交换都是使用这个物理地址。逻辑地址是编程时所使用的地址,它由段地址和段内偏移量组成。逻辑地址和物理地址的关系为:物理地址=段地址16+段内偏移量。由逻辑地址形成物理地址是由总线接口部件中的电路实现的,如图2.4所示。
对图中的转换关系可理解为:
物理地址=(段地址+段内偏移量高12位16*)16**+段内偏移量低4位
=段地址16+段内偏移量高12位+段内偏移量低4位
=段地址16+段内偏移量
*:段内偏移量高12位送加法器的低12位,相当于右移了4位,即除以16,再参加加法运算。
**:相加结果送地址总线的高16位,相当于将相加结果先按最低位对齐再左移了4位。这把相加结果扩大了16倍。
一个8086程序可以同时使用4个段:代码段、数据段、堆栈段和附加段。代码段用来存放程序代码,数据段用来存放程序中用到的数据,堆栈段作为堆栈,附加段也用来存放数据。
存放这些段的段地址的寄存器分别是:
代码段寄存器:CS(CodeSegment);
数据段寄存器:DS(DataSegment);
堆栈段寄存器:ss(stackSegment);
附加段寄存器:ES(ExtraSegment)。
这4个段寄存器都是16位的。一个完整的程序在存储器中的存储分布如图2.5所示。当然,不是每一个程序都要求包括4个段,可根据实际需要确定。
例如,一个程序使用的数据不多,程序代码也不长,这时可以只建立代码段和堆栈段,在代码段中开辟一个区域作为数据区。此外,如果数据量很大,超过了一个段的最大容量(64KB),这时可以开辟几个数据段,程序中要用到某个数据段,只需将该数据段的段地址送到DS寄存器中。