段寄存器
概述
段寄存器:
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为0x000
FFFFF
如果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位作用)。