段寄存器是因为对内存的分段管理而设置的。计算机需要对内存分段,以分配给不同的程序使用(类似于硬盘
分页)。在描述
内存分段时,需要有如下段的信息:1.段的大小;2.段的起始地址;3.段的管理属性(禁止写入/禁止
执行/系统专用等)。需要用8个字节(64位)存储这些信息,但段寄存器只有16位,因此段寄存器中只能存储段号(segment selector,也译作“段选择符”),再由段号映射到存在内存中的GDT(global (segment) descriptor table,全局段号记录表),读取段的信息。
段寄存器的产生
段寄存器的产生源于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位是重叠的,它们两部分相加在一起,才构成完整的物理地址。
含义
8086CPU有20根地址线,最大可寻址内存空间为1MB。而8086的寄存器只有16位,指令指针(IP)和变址寄存器(SI、DI)也是16位的。用16位的地址寻址1MB空间是不可能的。所以就要把内存分段,也就是把1MB空间分为2^4,即16个段,每段不超过64KB(2^16,16位数据线就可以寻址)。在8086中设置4个16位的段寄存器,用于管理4种段:CS是
代码段,DS是
数据段,SS是
堆栈段,ES是附加段。把内存分段后,每一个段就有一个段基址,段寄存器保存的就是这个段基址的高16位,这个16位的地址左移四位(后面加上4个0)就可构成20位的段基址。
段寄存器CS指向存放程序的内存段,IP是用来存放下条待执行的指令在该段的
偏移量,把它们合在一起可在该内存段内取到下次要执行的指令。
段寄存器SS指向用于
堆栈的内存段,SP是用来指向该堆栈的栈顶,把它们合在一起可访问栈顶单元。另外,当
偏移量用到了
指针寄存器BP,则其缺省的段寄存器也是SS,并且用BP可访问整个
堆栈,不仅仅是只访问栈顶。
段寄存器
DS指向
数据段,ES指向附加段,在存取
操作数时,二者之一和一个
偏移量合并就可得到
存储单元的
物理地址。该
偏移量可以是具体数值、符号地址和指针寄存器的值等之一,具体情况将由指令的
寻址方式来决定。
通常,缺省的
数据段寄存器是DS,只有一个例外,即:在进行串操作时,其目的地址的段寄存器规定为ES。当然,在一般指令中,我们还可以通过改变前缀中的“段取代”字段来改变
操作数的段寄存器。
“可选用的段寄存器”即是可以用强置说明这些段寄存器的值来作为其
操作数地址的
段地址。
寄存器
寄存器(Register),是
中央处理器内的其中组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、
数据和
地址。在中央处理器的控制部件中,包含的寄存器有
指令寄存器(IR)和
程序计数器。在中央处理器的算术及逻辑部件中,包含的寄存器有
累加器。
在电脑架构里,处理器中的暂存器是少量且速度快的
电脑存储器,借由提供快速共同地访问数值来加速
电脑程序的运行:典型地说就是在已知时间点所作的之计算中间的数值。
暂存器是存储器层次结构中的最顶端,也是系统操作数据的最快速途径。暂存器通常都是以他们可以保存的
比特数量来估量,举例来说,一个8位暂存器或
32位暂存器。暂存器现在都以暂存器数组的方式来实现,但是他们也可能使用单独的正反器、高速的核心存储器、
薄膜存储器以及在数种机器上的其他方式来实现出来。
这个名词通常都用来意指由一个
指令之输出或输入可以直接索引到的暂存器组群。更适当的是称他们为“架构暂存器”。例如,
x86指令集定义八个32位暂存器的集合,但一个实现
x86指令集的
CPU可以包含比八个更多的暂存器。
组成
段寄存器:在8086系统中,访问
存储器的
地址码由
段地址和段内
偏移地址两部分组成。段寄存器用来存放各分段的逻辑基值,并指示当前正在使用的4个逻辑段,包括
代码段寄存器CS、
堆栈段寄存器SS、
数据段寄存器DS和附加段
数据寄存器ES。
分类
代码段寄存器CS(Code Segment)
存放当前正在运行的程序代码所在段的段基址,表示当前使用的指令代码可以从该段寄存器指定的
存储器段中取得,相应的偏移量则由IP提供。
数据段寄存器DS(Data Segment)
指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基址。
堆栈段寄存器SS(Stack Segment)
指出当前堆栈的底部地址,即存放堆栈段的段基址。
附加段寄存器ES(Extra Segment)
指出当前程序使用附加
数据段的段基址,该段是串操作指令中目的串所在的段。