【火哥学习笔记】段寄存器

段寄存器和其他寄存器不同,类似EAX,EBX,EBP,ESP,都只有32位可读可写。而段寄存器只有16位可读,但是有96位可写,即除开可见的16位之外,还有隐藏的80位。以下是段寄存器的结构

1
2
3
4
5
6
7
struct  Segment{
   short Select;         //16位的段选择子 可见部分
   short Atrribute;      //不可见缓冲 16位的段属性
   int Base;         //不可见缓冲 32位的段基地址
   int Limit;           //不可见缓冲 32位的段的限长
// 值得注意的是,这里的Limit指的是最大可取的下标 而不是一个范围 比如我可以使用 fs:[Limit]
}

段选子

Select 是段选择子(段选择符),关于段选子的构造如下

高13为是在GDT表或者是LDT表中查找内容的索引(index),公式为 offset = index*8

低两位是使用该段寄存器时候的的特权级(RPL)11(b)=3 时为R3特权,00(b)=0 时为R0特权

第3位(index为2)是指示位,为0的时候去GDT表中查,为1的时候去LDT表中查

段描述符

剩下的80位不可见的缓存就是根据段选子,在GDT or LDT内查找8 byte的段描述符得到的,以下是段描述符的构造

段描述符结构

这个构造如此复杂,是因为这个结构是从16位系统拓展过来的(可以发现如果是16位,就只有``baselimit`)

基地址

如图,Base 由高32位中的首尾各8位(共2 byte),加上低32位中的高16位(共2 byte)构成一个dword,储存在段寄存器的Base变量中。

Limit

如图,可以发现Limit拼凑起来只有20位,但是为了对齐补齐,使用32位的dword储存,放在段寄存器的Limit变量中

DPL 位

如图,高32位中的第13,14位是DPL位,该位描述了访问特权级,需要满足RPL<=DPL才可以访问到该段(之后DPL,RPL,CPL的关系会单独说明)

P 位

表示该段是否可用,但是实验。。。(待做实验)

S 位

S位为0表示该段是系统段(调用门,任务门,陷阱门,中断门等),为1表示该段为普通段(一般是代码数据段)

TYPE 位

这里仅针对S位为1 即代码数据段做解释 S位为0时候的作为门描述符的后文再提

TYPE位一共有4位

第11位没有很大的用处,可以理解为:为0的时候是Data段,为1的时候是Code段(值小于8,或者大于等于8)

E位是扩展方向位,为0表示向上扩展—-Base~Limit内部可访问,外部不可访问;为1表示向下扩展,Base~Limit内部不可访问,外部可访问(左侧为向上扩展,右侧为向下扩展,红色为可以访问的部分)

W位是读写权限位,为0表示只读,为1表示可读可写

A位是访问位,如果访问过该段描述符,则把该位置为1

G 位

粒度(单位1)表示位,为0表示粒度为字节byte,为1表示粒度为一个页4096byte(2^12,加上Limit 2^20 刚好4GB,可以覆盖所有线性地址)

D/B 位

当该段是代码段的时候,是D位;当该段为数据段的时候,是B位

1.对于硬编码的操作宽度的影响:

​ D = 1 采用32位宽度;D = 0,采用16位宽度(比如push压栈,call寻址方式)

​ 如果D = 1 ,想要采用16位宽度 需要在指令的操作数前面加上前缀67 比如push 67:0x1234

​ 如果D = 0 ,想要采用32位宽度 需要在指令的操作数前面加上前缀66 比如push 66:0x12345678

2.对于向下扩展(E位为1)的数据段的影响:(这里可能写的有错误)

​ B = 1 ,向下扩展的上限为4GB,也就是说FS.Base + Limit之后的内容全部可以访问

​ B = 0 ,向下扩展的上限为64kb,也就是说只有FS.Base + Limit~ FS.Base + Limit + 64kb 的内容可以访问

RPL、DPL、CPL之间的关系

RPL:存在于每个段寄存器的可见部分的低两位,表示了当前段的权限

CPL:一般来说我们称CS段的RPL为CPL,也有说SS段的RPL也成为CPL,大概就是当前线程空间(代码空间和栈空间)的权限

DPL:当我们要申请一个段的时候(更新一个段寄存器),将要申请的目标段所具备的权限称为DPL(by 源哥)

如果要访问 / 申请另一个段,需要满足权限上RPL>=目标.DPL 即当前CS代码段需要有比目标段相同或者更高的权限,符合实际

程序在执行每一条汇编语句的时候都要检查 权限上 CS.CLP >= CS.DPL 相当于我代码段访问我自己,权限上 RPL>=目标.DPL