版权归原作者所有,如有侵权,请联系我们

[科普中国]-x86内存分段

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

x86架构中,存储器分段(英语:Memory Segmentation)是在不改变16位段选择符时,使用单个索引寄存器(保存了段内地址偏移值)所能够寻址的的存储器范围部分。也指在英特尔x86指令集体系结构下存储器分段的实现方式。1

历史1978年的Intel 8086开始引入了内存分段。这使得16位CPU可以访问超过64 KB (65,536字节)的内存,实际上8086 CPU到内存的地址总线是20位,即可访问2=1MB内存。在16位模式,要让应用程序使用多个存储器分段(为了访问比任一64K分段还要大的存储器)是相当复杂。这个问题的根源在于没有适当的适合做整个存储器范围的平面寻址的地址算术指令。平面寻址方式也可以乘法指令来完成,但这会导致较慢的程序运行速度。

1982年面世的80286处理器的实模式与保护模式,以及80386及其后的处理器的虚拟86模式,一个分段的大小是64KiB(使用16位索引寄存器)。在Intelx86的实模式下的分段架构的内存空间会有所重叠,这是一种不好的设计。 80286的保护模式下,16位的段寄存器中的13位(称作段选择符segment selector)是描述符表的条目(descriptor table entry)的索引;该条目包含了24位的段开始地址以及16位的段长度;段开始地址与段内偏移地址相加即为内存物理地址。16位段寄存器中的剩余3位分别是全局/局部描述符表指示位、请求特权级(request privilege level)。

1985年面世的80386及其后续处理器的32位保护模式下,一个分段长度上限是2个粒度单位,粒度可以是1字节或4K字节,因此分段长度上限可以是4GB,这与索引寄存器是32位相配合。

随着32位操作系统的推出,以及更舒适的32位平面存储器模式,到1990年末期几乎淘汰了使用分段寻址。然而,使用32位平面存储器模式产生的最多只能访问4GB地址空间的限制并没有远离日常的使用。分段允许操作系统对每个进程虚拟寻址空间的限制,最大可利用64GB的系统存储器,但这种最终回归到分段的尴尬,经常被引述为朝着64位处理器发展的动机。

2003年问世的x86-64架构下,强制实现了平面内存模型,但保留了使用段寄存器FS或GS的64位下的分段寻址。

实模式实模式与虚拟86模式下,一个段总是长64,536字节(16位段内偏移地址)。在段寄存器内的16位段选择符(segment selector)被解释为20位线性地址空间的高16位,称为段地址;其余的低4位全为0。段地址与16位段内偏移地址相加产生线性地址,同时也是这种内存模式下的物理地址。 任何程序都可以访问全部内存空间。没有对内存的访问权限保护。

80286保护模式Intel 80286处理器仍然使用16位段寄存器与16位的段内偏移地址,但保护模式下支持访问2(16M)字节的内存。16位段寄存器内不再是段地址,16位段寄存器的高13位被称作段选择符(segment selector),其值是到段描述符表的索引值。段描述符中包含了24位的段开始的基地址,20位的段长度。段开始地址与段内偏移地址相加即为内存物理地址。段的长度上限为2=1M字节。

80386保护模式Intel 80286处理器继续使用286的分段保护模式,但段描述符中包含了32位的段开始的基地址。段内偏移地址也是32位。在分段转址与物理地址之间又增加了一层分页(paging)转址。分段寻址是不能关闭的。分页可以使能或关闭(enabled or disabled),如果关闭就与286保护模式一样。如果使用分页机制,则由段开始的基地址与段内偏移地址相加得到的是线性地址(虚地址),线性地址还需要分页转址才得到内存物理地址。

386处理器增加了两个段寄存器FS、GS,这两个寄存器并无硬件绑定的用途。Windows操作系统在地址FS:0中保存了当前线程信息块。Linux中GS指向了线程局部存储。

通过清除控制寄存器CR0中的最低位,可由386保护模式转为实模式。

Linux操作系统在386保护模式下把段基址设为0,段长度设为4GiB,从而模拟了平面内存模型。

x86-64的64位模式在x86-64体系结构64位的long mode,段寄存器CS, SS, DS, ES强制为0。段长度强制为2。形式上还有内存分段,但实际上所有内存都在唯一的一个分段中。段寄存器FS、GS可以有非0值,被操作系统用于其它用途。即硬件支持如“FS:[RAX]”这样的寄存器间接寻址。

本词条内容贡献者为:

王沛 - 副教授、副研究员 - 中国科学院工程热物理研究所