Bootstrap

内核_段寄存器|段描述符|段选择子(详解)

概述

段寄存器:
ES CS SS DS FS GS LDTR TR共8个。

可以通过MOV指令对寄存器进行读写(LDTR和TR除外)。

段寄存器结构分布

Struct SegMent{
WORD	Selector段选择子;//16位selector
WORD	Attribute;//16位的Attribute
DWORD	Base;//32位的Base
DWORD	Limit	//32位的Limit
}

段寄存器结构图
在这里插入图片描述
读一个段寄存器只读16位,写一个段寄存器写96位。

段寄存器属性

在这里插入图片描述注意:
红色数据在不同环境下,数值可能不一样。(如下图)

在这里插入图片描述

段描述符

详细设计参考_保护模式

GDT(全局描述符表) LDT(局部描述符表)
Windows里面并没有使用LDT,使用的都是GDT。
GDTR(48位寄存器,表中存放了GDT表 的起始地址(32位),外加存放GDT表的大小(16位))。

查表机制:
当我们执行类似MOV DS,AX(注:AX就是可见的Selector段选择子的内容)指令时,CPU会查表,根据AX的值来决定查找GDT还是LDT,查找表的什么位置,查出多少数据。

利用Windbg调试看看:
Windbg调试环境搭建
VBoxDbg调式内核方法:
VirtualBox内置调试器VBoxDBG入门 (推荐这种,方便简单)

 r gdtr 	//查看全局描述符表寄存器

在这里插入图片描述

GDTR(48位寄存器,表中存放了GDT表 的起始地址(32位),外加存放GDT表的大小(16位) )。(不知道这里VboxDbg显示的怎么前面位数超过了32位,后面知道了再补上解释)

gd	//查看GDT表

在这里插入图片描述

	dd [地址]	//每四字节查看数据
	dq [地址]	//每八字节查看数据

在这里插入图片描述

段描述符(8字节一组,64位)结构(记住结构)

高4字节+低4字节
在这里插入图片描述

段选择子(2字节,16位)

段选择子是一个16位的段描述符,该描述符指向了定义该段的段描述符。

在这里插入图片描述
说明:
MOV DS,AX指令时,
假如AX=1B,即001B,拆分为0000 0000 0001 1011

去掉TI和RPL值,后剩下Index值为11,即3,则查GDT表索引值为3 (GDT表中索引值从0开始,索引值为0处的段描述符为0)的段描述符。


加载段描述符至寄存器(dword 4个字节;fword 6个字节;qword 8个字节;)。
除了MOV指令,我们还可以使用LES,LSS,LDS,LFS,LGS指令修改寄存器。
CS不能通过上述的指令进行修改,CS为代码段,CS的改变会导致EIP的改变,要改CS,必须要保证CS与EIP一起改。
实例:

char buffer[6];
__asm{
les ecx,fword ptr ds:[buffer]//高2字节给es,低4个字节给ecx
}

注意:RPL<=DPL(在数值上)段权限检查

段描述符P位|G位

p=1段描述符有效

p=0段描述符无效(CPU后面就不检查别的位了)

段描述符与段寄存器的对应关系

Intel白皮书Volume III
在这里插入图片描述

  • Attribute //16位 对应段描述符(高四字节) 第8位~第23位

  • Base //32位 (高四字节)第24位 ~ 第31位 + (高四字节)第0位 ~ 第7位+(低四字节)第16位 ~ 第31位

  • Limit //32位 (高四字节)第16位 ~ 第19位 +(低四字节)第0位 ~ 第15位 总共20位 最大值也就是FFFFF,此时分情况
    1,如果G位为0,那么Limit单位是字节,此时高位填0,即最大值也就是0x000fffff
    2,如果G位为1,那么Limit单位是4KB,4x1024=4096,4096代表有多少个,但是地址计算都是从0开始的,那么需要减1,即上限为4096-1=4095,刚好转为0xfff,如果此时Limit此时界限为1的话,那么此时为0x1FFF,则最大可以为0xffffffff

总结:
如果G为0的话,那么Limit为0x000FFFFF
如果G为1的话,那么Limit为0xFFFFFFFF

注意:
FS对应的短描述符比较特殊,FS是与线程相关,查分后的值与段寄存器中的值不符合。
在这里插入图片描述

段描述符S位|Type域

S = 1 代码段或者数据段描述符
S = 0 系统段描述符

TYPE域

当S = 1 时,

A 访问位
R 可读位

C 一致位

  • C=1 ,一致代码段
  • C=0 , 非一致代码段

在这里插入图片描述
数据段补充:
在这里插入图片描述

段描述符DB位

三种情况:
在这里插入图片描述

在这里插入图片描述


当S=0时,

在这里插入图片描述

段权限检察

CPU分级拥有0~3环权限,OS只使用了0和3环。

查看程序处于第几环?(CPL-Current Privilege Level)

查看CS和SS中存储的段选择子后2位。(CS和SS永远一样)

  • 3环实例
    在这里插入图片描述
  • 0环实例
    在这里插入图片描述

是否允许访问(DPL-Descriptor Privilege Level)

在这里插入图片描述

RPL(Request Privilege Level)

在这里插入图片描述

数据段的权限检察(举例)

在这里插入图片描述原理参考操作系统设计:操作系统_保护模式和分段机制

为什么要有RPL存在?

在这里插入图片描述

段寄存器|段选择子|段描述符 三者关系

  • 段寄存器(96位)
    {
    WORD Selector段选择子;//16位selector
    WORD Attribute;//16位的Attribute
    WORD Base;//32位的Base
    DWORD Limit //32位的Limit
    }

段寄存器的值是通过段描述符填充的。

  • 段选择子(16位)。

  • 段描述符(64位) 映射 段寄存器里面属性

在这里插入图片描述

typedef struct Descriptor{
WORD	Attribute;//16位的Attribute
WORD	Base;//32位的Base
DWORD	Limit	//32位的Limit
}

16+32+32=80?
通过Limit和属性里面的G位获得80位(上面已解释G位作用)。

;