04 段描述符属性P位与G位

在前面篇章里我们知道,写段寄存器是通过段选择子查GDT表中段描述符来填充剩余的80位,但是段描述符只有64位,这就涉及到怎么填充的问题;
下面重新贴出段描述符属性结构,如下图:
在这里插入图片描述
这篇讲的P位位于高四字节的15位,G位位于高四字节的23位;
P位的作用:P位说明当前段描述符是否有效,P为1时说明段描述符是有效的;
P位为0时说明当前段描述符是无效的。我们通过指令将一个段描述符加载到段寄存器时,CPU首先检查P位是否有效,若有效则继续后续操作;若无效则不进行后续操作。
下面我们再来回顾一下段寄存器的结构:

struct SegmentRegister{
	W	ORD Selector; //16为段选择子
	W	ORD Attribute; //16为段选择子
	DWORD Base;  //32位Base
	DWORD Limit; //32位Limit
};

段选择子是我们给定的16位值,那后续80位则需要用段描述符来填充。
Attribute:由段描述符的第8~23位来填充,刚好16位,无压缩;
Base:由三部分组成,第一部分为高四字节的24~31位,第二部分为高四字节的0到7位,第三部分为底四字节的16到31位,由这三部分组成了四字节的Base地址。
Limit:由两部分组成,第一部分是高四字节的第16到19位,第二部分是第四字节的0到15位;这两部份加起来是20位,而Limit为32位,我们就还差12位,那么为了补全这12位,我们就需要来了解一下段描述符中位于高四字节中第23位的属性位G位;如果G位为0则表示Limit单位是字节,所以当G位为0的时候段描述符中的20位填Limit的底20位,高12位补0即可,当G位为1的时候,Limit的单位是2的12次方也就是4KB而不再是字节(有点类似IP报文中4位首部长度规定为字节的思想),所以当G为1的时候段描述符的20位填Limit高20位,其他12位补1;我们用OD打开一个程序,就可以直观的感受到Limit的值,如下图红色小框中的0xFFFFFFFF

在这里插入图片描述
下面我们通过上篇跟本篇的知识来填一个段选择子为0x002B的段寄存器;
首先:
我们将0x002B转换为二进制为0000 0000 0010 1011,从上篇我们知道段选择子分三部分,第3位TI为说明查找的是GDT表还是LDT表,这里我们看到第三位为1,所以我们需要查GDT表,我们在windbg中用指令查看gdtr的地址值如下图:
在这里插入图片描述
接着我们用dq 8003f000查GDT表如下图:
在这里插入图片描述
从上图我们用2作为索引找到段描述符为:00cf9300`0000ffff
对应的高四字节二进制为:0000 0000 1100 1111 1001 0011 0000 0000
对应的底四字节为:0000 0000 0000 0000 1111 1111 1111 1111
我们先来看一下高四字节的第15位P位为1,说明这个段描述符是有效的。
通过段描述符的结构我们可以拆分出属性Attribute:0xcf93对应二进制为:1100 1111 1001 0011
Base:为0
我们看一下高四字节的23位G位为1,说明Limit单位为4KB,所以后面12位补1,则我们这里的Limit为:0xFFFFFFFF

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/86520488
04