对于8088来说,寄存器,内部数据总线,都为16位,可以很方便的表达16位的存储器地址:编号从0000H ~ FFFFH,即2^16 = 64KB 容量。但是,8088CPU的地址总线是20位的,这样他最大的寻址空间是2^20 = 1MB,物理地址范围为:00000H~FFFFFH。
于是,矛盾产生了:如何用16位的存储器来表示20位的地址呢?即如何用16位的寄存器空间来寻址20位的地址总线呢?
分析一下:如果用1个16位的寄存器来表示,显然是不行的,因为这样会有2^4个地址总线不能被表示,也就不能被访问。如果用两个存储器空间来表示,恩,这样空间是足够的,理论上可行。
我们来看看8088是如何处理这个问题的。8088也是用两个寄存器的空间来存放20位的地址,只是在实现的方式上还有特别之处。
8088的CPU将1MB的存储器空间分为许多个逻辑段来管理,每个段最大的限制为2^16 = 64KB,而且只能从模16地址开始一个逻辑段。每个存储器单元用“段基地址 : 段内偏移地址”表示其准确的物理地址。
我们来分析一下:
为什么要用模16作为段基地址呢? 这是为了能用16位的寄存器来表达,即XXXX0 H 模式,这时,我们把二进制低4位0(16进制最后一个0)省略,用XXXX H 来表示段基地址。xxxx可以认为是20位地址总线的高16位。
为什么要限制<=64KB的段大小呢?我们知道,64KB正好是2^16,而我们用来表示偏移的寄存器也是16位的,如果段大小比64KB大的话,我们16位的段偏移寄存器就不能把这个段表示了。所以要把段大小限定为64KB。
对于每个存储器单元,都有一个唯一的20位的地址,我们把它称为物理地址,而在8088内部或者用户编程的时候,我们所采用的是“段基地址 : 段内偏移地址”的方式,称为逻辑地址。下面我们来看看逻辑地址和物理地址之间的转换是如何进行的。
例如:物理地址单元 14700H = “1380H:F00H”
14700H是物理地址,用其后的逻辑地址表示时,1380H是段基地址,也就是这段空间的起始地址。F00H为偏移地址,用来表示该单元在这段存储器中的偏移。
我们可以计算一下:
14700H = 1380H * 2^4 + F00H
这样,只要我们知道段起始地址和段的偏移地址,我们就可以知道这个物理地址了。
接下来,我们知道,我们的地址空间可以分为很多个段,而段和段的关系可以是相互重叠,相互连接,互不相干的。这样,我们的一个物理地址,就可能位于多个逻辑的段空间中。那么,我们怎么知道这个物理地址到底该属于哪个段呢?
这个问题就要靠段偏移来解决了。还是刚才计算的例子:
在存储器空间中有一个单元位于一个段,该段基地址为1380H,偏移为F00H。现在又有一个段,段基地址为1470H,这个段中有一个单元,偏移量为0100H。
那么单元会是什么情况呢?
刚刚我们知道,14700H = 1380H * 2^4 + F00H,而14700H = 1470H *2^4 + 0100H。也就是说,这个单元位于两段空间中。我们如何判断这个单元是属于哪个段呢?偏移会告诉我们,如果偏移是F00H,那么他就会根据这个反推出段基地址,如果这个地址是段基地址,那么他就在这个段中,反之亦然。