段描述符是GDT和LDT表中的一个数据结构项,用于向处理器提供有关一个段的位置和大小信息以及访问控制的状态信息。每个段描述符的长度是8字节,含有3个主要字段:段基地址、段限长和段属性。段描述符通常由编译器、链接器、加载器或者操作系统来创建,但绝不是应用程序。图4-13给出了所有类型段描述符的一般格式。
(点击查看大图)图4-13 段描述符通用格式 |
一个段描述符中各字段和标志的含义如下:
(1)段限长字段Limit(Segment limit field):用于指定段的长度。处理器会把段描述符中两个段限长字段组合成一个20位的值,并根据颗粒度标志G来指定段限长Limit值的实际含义。如果G=0,则段长度Limit范围可从1B~1MB,单位是1B;如果G=1,则段长度Limit范围可从4KB~4GB,单位是4KB。
根据段类型中的段扩展方向标志E,处理器以两种不同方式使用段限长Limit。对于向上扩展的段(简称上扩段),逻辑地址中的偏移值范围可以从0到段限长值Limit。大于段限长Limit的偏移值将产生一般保护性异常。对于向下扩展的段(简称下扩段),段限长Limit的含义相反。根据默认栈指针大小标志B的设置,偏移值范围可从段限长Limit到0xFFFFFFFF或0xFFFF。而小于段限长Limit的偏移值将产生一般保护性异常。对于下扩段,减小段限长字段中的值会在该段地址空间底部分配新的内存,而不是在顶部分配。80x86的栈总是向下扩展的,因此这种实现方式很适合扩展堆栈。
(2)基地址字段Base(Base address field):该字段定义在4GB线性地址空间中一个段字节0所处的位置。处理器会把3个分立的基地址字段组合形成一个32位的值。段基地址应该对齐16字节边界。虽然这不是要求的,但通过把程序的代码和数据段对齐在16字节边界上,可以让程序具有最佳性能。
(3)段类型字段TYPE(Type field):用行指定段或门(Gate)的类型、说明段的访问种类以及段的扩展方向。该字段的解释依赖于描述符类型标志S指明是一个应用(代码或数据)描述符还是一个系统描述符。TYPE字段的编码对代码、数据或系统描述符都不同,如图4-14所示。
(点击查看大图)图4-14 代码段、数据段和系统段描述符格式 |
(4)描述符类型标志S(Descriptor type flag):用于指明一个段描述符是系统段描述符(当S=0)还是代码或数据段描述符(当S=1)。
(5)描述符特权级字段DPL(Descriptor privilege level):用于指明描述符的特权级。特权级范围从0到3。0级特权级最高,3级最低。DPL用于控制对段的访问。
(6)段存在标志P(Segment present):用于指出一个段是在内存中(P=1)还是不在内存中(P=0)。当一个段描述符的P标志为0时,那么把指向这个段描述符的选择符加载进段寄存器将导致产生一个段不存在异常。内存管理软件可以使用这个标志来控制在某一给定时间实际需要把那个段加载进内存中。这个功能为虚拟存储提供了除分页机制以外的控制。图4-15给出了当P=0时的段描述符格式。当P标志为0时,操作系统可以自由使用格式中标注为可用(Available)的字段位置来保存自己的数据,例如有关不存在段实际在什么地方的信息。
(点击查看大图)图4-15 当存在位P=0时的段描述符格式 |
(7)D/B(默认操作大小/默认栈指针大小和/或上界限)标志(Default operation size/default stack pointer size and/or upper bound):根据段描述符描述的是一个可执行代码段、下扩数据段还是一个堆栈段,这个标志具有不同的功能。(对于32位代码和数据段,这个标志应该总是设置为1;对于16位代码和数据段,这个标志被设置为0。)
可执行代码段。此时这个标志称为D标志并用于指出该段中的指令引用有效地址和操作数的默认长度。如果该标志置位,则默认值是32位地址和32位或8位的操作数;如果该标志为0,则默认值是16位地址和16位或8位的操作数。指令前缀0x66可以用来选择非默认值的操作数大小;前缀0x67可用来选择非默认值的地址大小。
栈段(由SS寄存器指向的数据段)。此时该标志称为B(Big)标志,用于指明隐含堆栈操作(如PUSH、POP或CALL)时的栈指针大小。如果该标志置位,则使用32位栈指针并存放在ESP寄存器中;如果该标志为0,则使用16位栈指针并存放在SP寄存器中。如果堆栈段被设置成一个下扩数据段,这个B标志也同时指定了堆栈段的上界限。
下扩数据段。此时该标志称为B标志,用于指明堆栈段的上界限。如果设置了该标志,则堆栈段的上界限是0xFFFFFFFF(4GB);如果没有设置该标志,则堆栈段的上界限是0xFFFF(64KB)。
(8)颗粒度标志G(Granularity):该字段用于确定段限长字段Limit值的单位。如果颗粒度标志为0,则段限长值的单位是字节;如果设置了颗粒度标志,则段限长值使用4KB单位。(这个标志不影响段基地址的颗粒度,基地址的颗粒度总是字节单位。)若设置了G标志,那么当使用段限长来检查偏移值时,并不会去检查偏移值的12位最低有效位。例如,当G=1时,段限长为0表明有效偏移值为0~4095。
(9)可用和保留位(Available and reserved bits):段描述符第2个双字的位20可供系统软件使用;位21是保留位并应该总是设置为0。