保护模式-段描述符

  • Post author:
  • Post category:其他



目录


1 段描述符的结构


1.1 Segment Limit


1.2 G


1.3 Base Address


1.4 S


1.5 Type


1.5.1 应用描述符(S=1)


1.5.1.1 数据段


1.5.1.2 代码段


1.5.1.3 一致段与非一致段的区别


1.5.2 系统描述符(S=0)


1.6 DPL


1.7 P


1.8 D/B


1.9 AVL、L


1 段描述符的结构

在x86架构中,段描述符是用于定义内存段属性的数据结构。每个段描述符占8字节(64位模式下为16字节),包含了以下字段:

在64位模式下,段描述符的结构与上图述描述类似,但是字段大小和位数会有所不同。例如,段限长变为了占48位的字段,段基址变为了占64位的字段,而特权级、描述符类型、P标志等字段的位数和定义方式也会有所不同。

1.1 Segment Limit

段限长域,指定了段的大小,处理器将两个段限长域组合成一个20位的段限长值。等等,之前在讲解段寄存器的时候不是说段限长有32位么,怎么现在只有20位了呢?那是因为CPU会根据标志位G的不同,按照两种不同的方式处理段限长

1.2 G

粒度标志,若G标志位为0,Segment Limit的单位为字节,则在20位的Segment Limit前面补3个0即可;若G标志位为1,Segment Limit的单位为字节4K字节,所以还需要在20位的Segment Limit后面补充3个F才是真正的段限长。例如两个段限长域拼接后的值为0xFFFFF,如果G位为0则段限长为0x000FFFFF,反之为0xFFFFFFFF。

这个标志位不会影响段基址的粒度,段基址的粒度永远是字节。

1.3 Base Address

基地址域,确定段的第0字节在4GB线性地址空间中的位置。CPU将这3个基地址域组合在一起构成了一个32位地址值。

1.4 S

描述符类型标志,若S标志位为0,则表示该描述符是一个系统段描述符;若S标志位为1,则表示该描述符是一个代码段或数据段描述符。

1.5 Type

类型域,如何解释这个域,取决于该描述符是应用描述符(代码段或数据段)还是系统描述符,这由S标志位所确定。

1.5.1 应用描述符(S=1)

当段描述符中的S标志(描述符类型)为1时,该描述符为代码段描述符或者数据段描述符,类型域的解释如下图:

类型域的最高位(段描述符的第二个双字的第11位)将决定了该描述符为数据段描述符(为0时)或代码段描述符(为1时) 。

1.5.1.1 数据段



对于数据段而言,描述符的类型域的低3位(位8,9,10)分别被解释为访问位(A-accessed),是否可写(W-write),扩展方向(E-expand)。

访问位(A)表示该段是否被访问过,每当CPU将该段的段选择符置入到某个段寄存器时,就将访问位置为1。

可写位(W)表示该段是否可写,ds段可以是只读(为0时)或可读写(为1时)的段,这取决于是否可写标志。ss段必须是可读写的数据段。

扩展方向位(E)表示该段的扩展方向,若是向上扩展(为0时),则该段的有效区域是Base Address到Base Address + Segment Limit之间;若是向下扩展(为0时),则该段的有效区域为非Base Address到Base Address + Segment Limit之间的区域,也就是Base Address到Base Address + Segment Limit之间是无效的。注意这个位针对数据段有效。

1.5.1.2 代码段

对于代码段而言,描述符的类型域的低3位(位8,9,10)分别被解释为访问位(A-accessed),可读位(R-read),一致位(C-conforming)。

访问位(A)与数据段一样,表示该段是否被访问过,每当CPU将该段的段选择符置入到某个段寄存器时,就将访问位置为1。

可读位(R)表示该段是否可读,cs段可以可以是仅执行(为0时)或可执行可读(为1时)。

一致位(C)。如果该标志位被设置为0,则该代码段为非一致代码段;如果该标志位被设置为1,则该代码段为一致代码段。

1.5.1.3 一致段与非一致段的区别

一致代码段是指可以被当前特权级别或更低特权级别的代码段调用,且在被调用时,该代码段会自动切换到与调用方相同的特权级别。非一致代码段是指仅允许具有相同特权级别的代码段访问和执行。


无论目标段是否为一致代码段,进程都不能因为call或jmp而转入一个低特权级别(特权值较大)的代码段执行。


所有的数据段都是非一致的,也就意味着数据段不能被更低特权级别的进程访问(特权值较大的执行代码)。但是和代码段不同,低特权级别的数据段可以被更高特权级别的进程所访问。

特权级低->高 特权级高->低 相同特权级
非一致代码段 × ×
一致代码段 ×
数据段

(总是非一致)
×

1.5.2 系统描述符(S=0)

当段描述符中的S标志(描述符类型)为0时,该描述符为系统描述符。系统描述符又可以分为两类:系统段描述符和门描述符。在后面的章节中会给出详细的介绍,这里先给出Intel白皮书中对系统描述符的类型域的译码:

1.6 DPL

描述符特权级别(Descriptor Privilege Level)域,指明该段的特权级。特权级从0~3,0为最高特权级。DPL用来控制访问该段的所需的特权级别。

1.7 P

段存在标志,指出该段当前是否在内存中(1表示在内存中,0表示不在)。当P位被设置为1时,表示该段可用;当P位被设置为0时,表示该段不可用。如果一个程序试图访问一个不可用的段,则会触发一个异常,通常是”段不存在”异常。因此,操作系统或者应用程序可以通过设置和清除P位来控制哪些段可以被程序访问和使用。

P位的存在主要是为了支持虚拟内存机制。在虚拟内存机制下,操作系统可以将进程的虚拟地址空间映射到物理地址空间中的任意位置。当CPU访问一个虚拟地址时,操作系统会根据该地址的映射关系,将其转换为物理地址,并检查被访问的页面是否存在于内存中。如果该页面不存在于内存中,操作系统会从磁盘中加载该页面,并将其放入内存中,然后将虚拟地址重新映射到该页面的物理地址上。在这个过程中,P位会被动态地设置和清除,以反映该段是否存在于内存中。

1.8 D/B

默认操作数大小/默认栈指针大小/上限标志,对于cs段、ss段、向下扩展的数据段,这个标志完成不同的功能(对32位的代码和数据段,这个标志总是被置为1,而16为的代码和数据段,这个标志总是被置为0)

cs段:这个标志被称为D标志,用于指示代码段中默认的操作数大小。如果D标志位被设置为1,则默认操作数大小为32位;如果D标志位被设置为0,则默认操作数大小为16位。

ss段:这个标志被称为B标志,B = 1时隐式堆栈访问指令(如:PUSH POP CALL)使用32位堆栈指针寄存器ESP,B = 0时则使用16位寄存器SP。如果该ss段为一个向下扩展的数据段,B标志位还确定了该ss段的地址上界。

向下扩展的数据段:这个标志称为B标志,它确定了该段的地址上限。如果该标志位为1,段地址上限为4GB;若该标志为0,段地址上限为64KB。

1.9 AVL、L

AVL(第二个双字节中的第20位)可以被系统软件使用,L(第二个双字节中的第21位)位被保留,并且应该设置为0。



版权声明:本文为weixin_43074760原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。