03 段描述符和段选择子

时间:2024-05-31 08:26:56

前面篇章我们说过段寄存器有96位,而且写一个段寄存器的时候是写96位,那么我们只给了16位,其他的80位从哪里来呢?

下面我们来认识两张表,一张是GDT(全局描述符表),一张是LDT(局部描述符表),当我们执行MOV DS, AX的时候,CPU会根据AX的值来查表,由AX的值来决定是查找GDT还是LDT,并且决定查找什么位置,并根据查找的值来填充其他的80位,这也是可见部分称为段选择子的原因吧。

下面我们来看一下GDT这表在哪里,这里我们需要用windbg来调试虚拟机里面的xp系统来查看这张表。

首先,我们登录我们虚拟机中的XP系统,按windows键+R键,在输入框中输入msconfig命令,弹出如下图窗口:03 段描述符和段选择子
接着我们点击BOOT.INI选项,出现如下图窗口:
03 段描述符和段选择子

我们选择高级选项,出现下图窗口并按照下图配置端口及波特率:

03 段描述符和段选择子
确定保存后会提示我们重启,这时我么选择稍后重启,然后再直接关机。

然后,在XP系统关机状态下,我们对其硬件进行设置,我们先将打印机设备删除并添加一个串行端口如下图:
03 段描述符和段选择子
接下类我们 对串行端口进行设置,包括管道名称,XP端作为服务器,我们本机作为客户应用程序,设置如下:

03 段描述符和段选择子
然后打开windbg,选择文件–>内核调试,或者直接快捷键Ctrl+K弹出如下对话框,设置并确定。

03 段描述符和段选择子
波特率跟我们的XP系统内高级设置一致,端口名填写硬件设置处的端口管道名。
打开windbg后我们开启虚拟机XP系统,中间如果有选择选项选择跟调试相关的,当windbg中出现如下图界面,我们就可以开始我们的实验了。
03 段描述符和段选择子
我们要找到GDT这张表,我们就要知道它在哪能找到,这时我们需要认识一下一个叫gdtr的寄存器,这里存放了GDT表的地址以及其大小。接下来我们在windbg里输入命令r gdtr(注:r这个命令跟很久以前的debug程序用法类似,用于查看寄存器值),然后回车如图:
03 段描述符和段选择子
这个寄存器有48位,用r命令能查看其32位,也就是GDT所在地址,我们要查看这张表的大小我们可以用r gdtl来查看,如下图:
03 段描述符和段选择子
其也是查看gdtr寄存器,查看的是gdtr的另外16位,表示GDT这张表的大小.

我们用dd指令查看内训单元值,来看看GDT这张表:
03 段描述符和段选择子
到这里我们就知道GDT表是什么了,我们的段寄存器的其他值是从这个表里查出来的,那么每次查多少?

每次查8个字节也就是64位,所以这张表是以8字节为一个元素存放的一张表,而这8字节元素就是我们所说的段描述符。接下来我们先看一下段描述符的结构:
03 段描述符和段选择子
我写的硬编码博客里找到Intel架构手册的下载地址,在这个手册的2295页,有这个结构,这图从这里截图而来。

那么我们从这张表的哪里索引到我们要的段描述符,这个就要用到段选择子了。

段选择子:是我们段寄存器可见的16位值,该值指向了定义该段的段描述符;当然,不是直接按它的值作为索引的,段选择子也有自己的结构,该结构可以在手册的2292页找到,如下:
03 段描述符和段选择子
从图我们可以看出,这16位分三个部分,3~15位就是查找段描述符的索引,第2位为表示查找的是GDT表还是LDT表,RPL为请求特权级别。

除了mov之外,我们还可用如下几个指令加载段寄存器:

LES LSS LDS LFS LGS

CS不能通过上述指令进行修改,CS的改变会导致EIP的改变,要改CS,一定要确保CS与EIP一起修改。