看《汇编语言》(王爽)这本书,里面提到CPU对内存的访问寻址问题,关于段地址和偏移地址那一节,有些没看明白。于是百度了一下,结合自己的思考,发现其实并不复杂。
该书所使用的CPU是8086,字长16位,数据总线宽度为20位。字长如果是16的话,那么CPU寻址范围是2^16 = 64k,而数据总线宽度是20位的话,那么通过数据总线寻址范围就是2^20 = 1M(这就是为什么32位机器2^32=4G只能使用4G内存空间的原理),这里就出现矛盾了,一边是64k,一般是1m,而cpu设计数据总线宽度为20的目的也很明显,增大寻址范围,增大可用内存,所以cpu就得变换一下寻址方式来使用这20位的数据总线。
那么是怎么解决的呢?其实也简单,既然一个寄存器存不下20位地址,那就用两个寄存器,而这两个寄存器其实存的数据不一样,分别就是段地址和偏移地址。2^20刚好是2^16的四倍大小,也就是二进制左移4未,16进制左移1位,也就是要用1的长度来访问16的长度。
书上说内存无分段,也别按照内存分段的思路理解,其实是正确的,一块内存区域,从头至尾,很平滑,并无分段,但是为了兼容字长和地址总线宽度的问题,我们大概可以想象成内存是分了段的,用偏移量达标一段的长度,为64k,那么2^20就能分2^4=16段,所以内存就分为16段,每一段长度64k。这种理解对吗?答案是不对。原因在于:我们用16位来表示20位,相当于是扩大了16倍,那么如果16位的地址 x 16就刚好可以表示20位地址。所以在任何时候16位那一头的地址 x 16就能够完全表示20位这一头,于是:
物理地址 = 段地址 x 16 + 偏移地址 这个公式就是成立的,假如段地址和物理地址都是从0开始,那么任何一个段地址 x 16 +偏移地址就能够完全表示物理地址。如果段地址最大值 x 16的值 + 偏移地址最大值 = 物理地址的最大值。