Intel CPU 实地址模式

硬件资源:

  1. 20根地址总线,寻址能力为1MB
  2. 2个寄存器,均为16bit长度

目的:
充分利用20根地址总线的能力

问题:
1个16bit寄存器只能控制16根地址总线,寻址能力为64KB
2个寄存器就有32bit,但又超出20根地址总线的数量

未被采纳的解决方法:
高位寄存器只使用4bit,低位寄存器使用全部16bit。高位寄存器剩下的12bit闲置不用。
此时,高位寄存器的4bit相当于段。假设其内容为0101b,则其段基址就是
0101<<16
0101 0000 0000 0000 0000
确认段基址以后,低位寄存器16bit就是每个段的寻址空间,为64KB。
每个64KB空间中,我们就可以运行之前为8086处理器开发的16位程序了,大家都很开心。
这样整个20位即1MB的寻址空间就被等分为16个64KB。
好好的1MB内存被剁成16段,这就是"segment"这个词的由来。

缺点:

  1. 只有16个段,意味着最多只能同时运行16个16位程序。这个数量有点少。
  2. 如果某个程序只需要1KB空间,剩下63KB空间无法被其他程序使用,因为段与段之间不重叠的。在内存比金子贵得多的年代,这么做太奢侈了。
  3. 我们还有高位寄存器的12个bit闲置。在寄存器比车贵的年代,这也很奢侈。

同样未被采纳的方案:
我们已经看出来了,段的粒度取决于高位寄存器的bit数。
如果我们反过来高位寄存器使用全部16bit,低位寄存器使用4bit,那么我们就有64K(65536)个段,每个段16个字节。

缺点:

  1. 只能兼容4bit程序,无法兼容16bit程序。
  2. 每个程序16字节,这绝对是个馊主意。

Intel采用的方案:
高位寄存器采用全部16bit,可以有64K个段。
低位寄存器采用全部16bit,每个段64KB。
这样段与段之间就产生了重叠。
例如:
第1234个段的起始位置位于内存的第1234x16字节处,从这里往上64KB都是它的地盘。
第1235个段的起始位置位于内存的第1235x16字节处,从这里往上64KB都是它的地盘。
jietu20180804-052106
1234:16与1235:0是同一个字节。
在16位的时代,每个程序需要多少字节内存是可以大致计算出来的。假设你已知手上每个程序需要的内存都不超过10KB,那么你可以至少同时运行102个程序程序。相比区区16个程序来说,这极大地提升了生产力。

物理地址的计算:
2个寄存器一共有32个bit,显然不能直接把两个寄存器收尾拼接起来。
我们已知这样一个公式:
物理地址 = 高位寄存器 x 16 + 低位寄存器
乘以16就是逻辑左移4bit,也是16进制右边补0.

命名:
高位寄存器我们称为段寄存器,它的值叫段地址
高位寄存器 x 16称为"段基址",直接对应物理内存上这个段的起始位置。
低位寄存器称为偏移

练习:
假设CS寄存器为0xABCD,IP为0x1234
那么段基址为0xABCD0,物理地址为0xABCD0 + 0x1234 = 0xACF04