段描述符
IA-32架构的处理器访问内存都是采用“段基址:段内偏移地址”的形式,即使到了保护模式也不例外。其次,实模式脆弱的安全性也是保护模式推出的重要原因。为了内存安全性,必须为内存段添加一些额外的安全属性,如特权级、段界限、段类型等。描述内存段属性的数据结构就叫段描述符。其结构定义如下所示:
一个段描述符是8字节大小,它描述了一个内存段的地址范围和各种属性。
保护模式下地址总线宽度是32位,因此段基址需要用32位地址来表示。从上图看出段基址字段一共有2个部分,分别在第2~4字节和第7字节。这样划分的目的是为了兼容旧式的16位CPU(段界限字段也是如此)。
段界限表示段边界的扩展极值,即最大扩展到多少或最小扩展到多少。扩展方向只有上下两种,对于数据段和代码段,段的扩展方向是向上,即从低地址向高地址扩展,此时的段界限用来表示段内偏移的最大值(上界);对于栈段,段的扩展方向是向下,即从高地址向低地址扩展,此时的段界限表示段内偏移的最小值(下界)。无论是向上还是向下,段界限都表示段的边界。段界限字段给出的只是数值,其单位(或称粒度)则在G位中给出,G位为0则粒度为B,为1则为4KB。因此段界限边界值的计算公式为:
(段界限字段值+1)*(粒度大小)- 1
内存访问需要用到“段基址:段内偏移地址”,段界限其实是用来限制段内偏移地址的,段内偏移地址必须位于段描述符给出的范围之内,否则CPU会抛出异常。任何超范围的偏移地址都被认为是非法的,CPU会捕获这个异常。
属性字段中的type字段用来指定段描述符的类型,而S位的数值决定了type字段中不同位的含义。一个段描述符首先分为两大类,要么是系统段(S位置0),要么是非系统段(S位置1),或称数据段。对于CPU而言,凡是硬件运行需要用到的东西都可称之为系统(如硬件在内存中的映射),凡是软件需要用到的东西(操作系统也是软件,对CPU而言在这一层面它与用户程序无区别)都是数据。无视是代码还是数据,都是作为硬件的输入,因此我们常说的代码段在段描述符中也属于数据段(非系统段)。type字段要和S字段配合才能确定段描述符的确切类型,只有S字段的值确定后type字段的值才有意义。
系统段 | 系统段类型 | 第3~0位 | 说明 | |||
3 | 2 | 1 | 0 | |||
未定义 | 0 | 0 | 0 | 0 | 保留 | |
可用的80826 TSS | 0 | 0 | 0 |