什么是物理地址?

注意,本篇中数字后的D和H表示十进制和十六进制,注意区别

物理地址不是真实地址。CPU访问的是虚拟地址空间,每一个内存单元在空间中都有个唯一的地址。

CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在 CPU向地址总线上发出物理地址之前,必须要在内部先形成这个物理地址。不同的CPU可以有不同的形成物理地址的方式。

8086是16位结构的CPU ,这也就是说,在8086内部,能够一次性处理、传输、暂时存储的信息的最大长度是16位的。内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放,对于16位CPU ,能一次性处理、传输、暂时存储16位的地址。

  • 运算器一次最多可以处理16位的数据;
  • 寄存器的最大宽度为16位;
  • 寄存器和运算器之间的通路为16位。

重要

8086CPU有 20位地址总线,可以传送20位地址,达到1MB寻址能力。即能表示2^20个不同的地址,一共是2^20^=1048576byte=1024k=1M。(一个地址指向一个内存单元,8bit)。但是8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。从8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。

8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。

(所以,内存的大小关键在于地址总线的宽度。)

逻辑结构

当8086CPU要读写内存时:

  1. CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
  2. 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
  3. 地址加法器将两个16位地址合成为一个20位的物理地址;
  4. 地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
  5. 输入输出控制电路将20位物理地址送上地址总线;
  6. 20位物理地址被地址总线传送到存储器。

地址加法器采用物理地址=段地址X16D+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086CPU要访问地址为123C8(H)的内存单元,此时

十六位地址A 十六位地址B
第一步 1230(段地址) 00C8(偏移地址)
第二步 送入地址加法器 送入地址加法器
第三步 1230H*16D 00C8
第四步 12300+00C8=123C8
第五步 送到地址总线

“段地址*16D”更好的说法是左移4位。 一个数据的二进制形式左移N位,相当于该数据乘以2 的N次方。

一个数据的十六进制形式左移1位,相当于乘以16;—个数据的十进制形式左移1位,相当于乘以10;一个X进制的数据左移1位,相当于乘以X。

注意:在内存中全是二进制的,对于乘多少的数字最好不要关注太多,非常容易混乱,每次算的时候还是用位移运算。

“段地址x16D+偏移地址=物理地址”的本质含义

“段地址X16+偏移地址=物理地址”的本质含义是:CPU在访问内存时,用一个基础地址(段地址X16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
更一般地说,8086CPU的这种寻址功能是“基础地址+偏移地址=物理地址”寻址模式的一种具体实现方案。8086CPU中,段地址X16可看作是基础地址。

注意:16是十进制的。在乘的时候要乘10H,因为段地址是十六进制的。

下面,我用两个与CPU无关的例子做进一步的比喻说明。
第一个比喻说明“基础地址+偏移地址=物理地址”的思想。
比如说,学校、体育馆、图书馆同在一条笔直的单行路上, 学校位于路的起点(从路的起点到学校距离是0米)。

位置

你要去图书馆,问我那里的地址,我可以用两种方式告诉你图书馆的地址:
(1) 从学校走2826m到图书馆。这 2826m可以认为是图书馆的物理地址。

(2) 从学校走2000m到体育馆,从体育馆再走826m到图书馆。第一个距离2000m, 是相对于起点的基础地址,第二个距离826m是相对于基础地址的偏移地址(以基础地址为起点的地址)。

第一种方式是直接给出物理地址2826m ,而第二种方式是用基础地址和偏移地址相加来得到物理地址的。
第二个比喻进一步说明“段地址X16D+偏移地址=物理地址”的思想。
我们为上面的例子加一些限制条件,比如,只能通过纸条来互相通信,你问我图书馆的地址我只能将它写在纸上告诉你。显然,我必须有一张可以容纳4 位数据的纸条,才能写下2826这个数据。

纸条

不巧的是,我没有能容纳4 位数据的纸条,仅有两张可以容纳3 位数据的纸条。这样我只能以这种方式告诉你2826这个数据。

纸条

在第一张纸上写上200D(段地址),在第二张纸上写上826D(偏移地址)。假设我们事前对这种情况又有过相关的约定:你得到这两张纸后,做这样的运算:200D(段地址)*10D+826D(偏移地址)=2826D(物理地址)。
8086CPU就是这样一个只能提供两张3位数据纸条的CPU。当然,现在的许多计算机都是32位的,即字长是4字节,8字节的也很多。

段的概念

其实,内存并没有分段,段的划分来自于CPU ,由于8086CPU用 “基础地址(段地址*16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。如图所示,我们可以认为:地址10000H100FFH的内存单元组成一个段,该段的起始地址(基础地址)为 10000H,段地址为1000H,大小为100H;我们也可以认为地址10000H1007FH、10080H~100FFH的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和10080H,段地址为:1000H和 1008H,大小都为80H。

段

以后,在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址X16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。有两点需要注意:段地址X16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB。

注意,因为只要加起来是那个物理地址,所以可以用不同的段地址和偏移地址构成同一个物理地址。

段寄存器

段地址由段寄存器提供,8086CPU有4个段寄存器:CS,DS,SS,ES.这里先看看CS和另一个指令指针寄存器IP.在8086PC机中,任意时刻,设CS中的内容为M, IP中的内容为N, 8086CPU将从内存M*16+N单元开始,读取一条指令并执行.