8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力。8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。
从8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。
8086CPU采用一种在内部用两个16位地址合成方法,来形成一个20位的物理地址。
8086CPU相关部件的逻辑结构图如下:
8086CPU相关部件的逻辑结构
如上图所示,当8086CPU要读写内存时:
(1)CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
(2)段地址和偏移地址通过内部总线,送入一个称为地址加法器的器件的部件;
(3)地址加法器将两个16位的地址合成为一个20位的物理地址;
(4)地址加法器通过内部总线,将20位物理地址送入输入输出控制电路;
(5)输入输出控制电路,将20位物理地址送上地址总线;
(6)20位物理地址被地址总线传送到存储器。
地址加法器采用物理地址=段地址×16+偏移地址的方法,用段地址和偏移地址合成物理地址。
列如,8086CPU要访问地址为123C8H的内存单元,此时,地址加法器的工作过程如下图所示(图中数据皆为16进制表示):
地址加法器的工作过程
“段地址×16”有一个更为常用的说法是左移4位。计算机中的所有信息,都是以二进制的形式存储的,段地址当然也不列外。机器只能处理二进制信息, “左移4位”中的位,指的是二进制位。
我们看一个例子,一个数据为2H,二进制形式为10B,对其进行左移运算:
左移位数 | 二进制 | 十六进制 | 十进制 |
0 | 10B | 2H | 2 |
1 | 100B | 4H | 4 |
2 | 1000B | 8H | 8 |
3 | 10000B | 10H | 16 |
4 | 100000B | 20H | 32 |
观察上面移位次数和各种形式的数据的关系,我们可以发现:
(1)一个数据的二进制形式左移1位,相当于该数据乘以2;
(2)一个数据的二进制形式左移N位,相当于该数据乘以2的N次方;
(3)地址加法器如何完成段地址×16的运算?就是将以二进制形式存放的段地址左移4位。
进一步思考,我们可以看出:一个数据的十六进制形式左移1位,相当于乘以16。一个数据的十进制形式左移1位,相当于乘以10。一个X进制的数据左移一位,相当于乘以X。
问:为什么段地址要乘以16?
答:
这是历史遗留问题
intel 8088时代,计算机的地址总线是20位的,即可以寻址能力可以达到1M字节,但是它的ALU和寄存器都只有16位,也就是表示数的能力只能达64k,再大就逾锅了。
那怎么办呢?INTEL想了一个办法,让两个寄存器对来表示一个物理地址,比如说DS:BX,前者叫段寄存器,后者叫偏址寄存器。
由于这两个寄存器都是16位,直接相加还是不能匹配20位的地址线的访问能力,因此,INTEL公司变通了一下,人为地将这个组合寻址设计成:在它们组合时,让段寄存器左移四位(假设DS是1234H,左移4位就变成了12340H,至于它内部怎么实现我们不用管它。
注意,对于16进制的数来说,乘以16就相当于在原数后面补个0,因为它是逢16进1啊;与10进制数乘10就是后面补0同样道理。)然后与偏址寄存器相加,这样得到的地址最大可以到0FFFFFH。这样行了。
现在都32位机了,甚至64位了,所以上面的寻址方法在保护模式下不再用了。
问:为什么要学习16位的汇编,而不是直接学习32位或者64位了?
答:只有先把基础打好,地基打好,才能进一步盖房子。