段寄存器历史来源

来源:互联网 发布:java绝对路径 编辑:程序博客网 时间:2024/04/30 14:18
段寄存器的产生源于Intel 8086 CPU体系结构中数据总线与地址总线的宽度不一致。数据总线的宽度,也即是ALU(算数逻辑单元)的宽度,平常说一个CPU是“16位”或者“32位”指的就是这个。8086CPU的数据总线是16位。
地址总线的宽度不一定要与ALU的宽度相同。因为ALU的宽度是固定的,它受限于当时的工艺水平,当时只能制造出16位的ALU;但地址总线不一样,它可以设计得更宽。地址总线的宽度如果与ALU相同当然是不错的办法,这样CPU的结构比较均衡,寻址可以在单个指令周期内完成,效率最高;而且从软件的解决来看,一个变量地址的长度可以用整型或者长整型来表示会比较方便。但是,地址总线的宽度还要受制于需求,因为地址总线的宽度决定了系统可寻址的范围,即可以支持多少内存。如果地址总线太窄的话,可寻址范围会很小。如果地址总线设计为16位的话,可寻址空间是2^16=64KB,这在当时被认为是不够的;Intel最终决定要让8086的地址空间为1M,也就是20位地址总线。地址总线宽度大于数据总线会带来一些麻烦,ALU无法在单个指令周期里完成对地址数据的运算。有一些容易想到的可行的办法,比如定义一个新的寄存器专门用于存放地址的高4位,但这样增加了计算的复杂性,程序员要增加成倍的汇编代码来操作地址数据而且无法保持兼容性。
    Intel想到了一个折中的办法:把内存分段,并设计了4个段寄存器,CS,DS,ES和SS,分别用于指令、数据、其它和堆栈。把内存分为很多段,每一段有一个段基址,当然段基址也是一个20位的内存地址。不过段寄存器仍然是16位的,它的内容代表了段基址的高16位,这个16位的地址后面再加上4个0就构成20位的段基址。而原来的16位地址只是段内的偏移量。这样,一个完整的物理内存地址就由两部分组成,高16位的段基址和低16位的段内偏移量,当然它们有12位是重叠的,它们两部分相加在一起,才构成完整的物理地址。
Baseb15 ~ b12b11 ~ b0
Offset
o15 ~ o4o3 ~ o0Addressa19 ~ a0这种寻址模式也就是“实地址模式”。在8086中,段寄存器还只是一个单纯的16位寄存器,而且操作寄存器的指令也不是特权指令。通过设置段寄存器和段内偏移,程序就可以访问整个物理内存,无安全性可言。

    总之一句话,段寄存器的设计是一个权宜之计,现在看来可以说是一个临时性的解决方案,设计它的目的是为了把地址空间从64KB扩展为1MB,仅此而已。

段寄存器的种类

16位CPU有四个段寄存器,所以,其程序可同时访问四个不同含义的段。段寄存器及其偏移量的引用关系如图所示。

8086CPU有4个段寄存器:CS、DS、SS、ES。
CS(Code Segment) :代码段寄存器;
DS(Data Segment) :数据段寄存器
SS(Stack Segment):堆栈段寄存器;
ES(Extra Segment):附加段寄存器。
当8086CPU要访问内存时,由这四个寄存器提供内存单元的段地址

CS+IP:段寄存器CS指向存放程序的内存段,IP是用来存放下条待执行的指令在该段的偏移量,把它们合在一起可在该内存段内取到下次要执行的指令。

SS+SP:段寄存器SS指向用于堆栈的内存段,SP是用来指向该堆栈的栈顶,把它们合在一起可访问栈顶单元。另外,当偏移量用到了指针寄存器BP,则其缺省的段寄存器也是SS,并且用BP可访问整个堆栈,不仅仅是只访问栈顶。

DS/ES+有效地址:段寄存器DS指向数据段,ES指向附加段,在存取操作数时,二者之一和一个偏移量合并就可得到存储单元的物理地址。该偏移量可以是具体数值、符号地址和指针寄存器的值等之一,具体情况将由指令的寻址方式来决定。

通常,缺省的数据段寄存器是DS,只有一个例外,即:在进行串操作时,其目的地址的段寄存器规定为ES。当然,在一般指令中,我们还可以用强置前缀的方法来改变操作数的段寄存器。
0 0