其他分享
首页 > 其他分享> > 保护模式(段描述符与段选择子3)

保护模式(段描述符与段选择子3)

作者:互联网

要点回顾:

上一篇段属性探测2中,我知道了当一个段寄存器的时候,只给了16位的数,但段寄存器有96位,那剩下的80位从哪里来的?,这16位数是随便写的码?

GDT(Global Descriptor Table)全局描述符表和LDT(局部描述符表)

当我们执行类似MOV DS,AX指令时,CPU会查表,根据AX的值来决定查找GDT还是LDT,查找表的什么位置,查出多少数据。
window并没有使用LDT,我们主要是查询的是gdtr,这里需要虚拟机和windbg调试环境。

用来查看gdtr寄存器的位置:

r gdtr 用来查看寄存器(48位=32(表的起始地址)+16(表的大小))
r gdtl 用来查看表的大小
dd dd 8003f000 用来查看表的数据


2.段描述符:

我们都知道段寄存器有96位但是我们只给16位剩余的值就是从这张表里面查出来的数据放进去,每次需要查询8个字节(64位),因为GDT里面存放的每一个元素称为段描述符


因为段描述符占8个字节(64位),dq命令可以帮助我们一次读取8个字节的数据(低位在前,高位在后)

段选择子

当我们执行 MOV DS,AX指令时就是查找GDT这张表,查GDT表的那个位置由源操作数(AX)来决定,一旦查到它就会把段描述符8个字节放到段寄存器中,每个原操作数使用的段描述符都不一样所以我们要学习段选择子。
段选择子共有16位,该描述符指向了定义该段的描述符

第0-1位:RPL(请求特权级别,段权限检查)
第2位:TI位 分为两种情况 TI=0 查GDT表 ,TI = 1查找LDT表(一般TI=0代表windows)windows没有使用LDT表
第3-15位:就是一个索引,我们到底查找那个段描述符就是由第3位到第15位
比如 段选择子 1B = 001B = 0000 0000 00001 1011(对这十六位按段选择子的位数进行拆分)
RPL = 11 =3(最后两位)
TI = 0(第最后末三位)(gdt表)
最后剩下的为:0000 0000 00001 1 = 3 查找的就是第三个字节的

加载段描述符至段寄存器

除了MOV指令,我们还可以使用LES、LSS、LDS、LFS、LGS指令修改寄存器(其中l为加载的意思)
CS不能通过上述的指令进行修改,CS为代码段,CS的改变会导致EIP的改变,要改变CS,必须保证CS和EIP一起改,后面再说。

char buffer[6];
__asm
{
 les ecx,fword ptr ds:[buffer]//高两个字节给了es,低四个字节给ecx
}
注意RPL<=DPL(DPL在高四个字节的第13-14位上,一定要熟练段描述表)(在数值上)

总结

1.记住段描述符与段选择子(必须要记住)
2.使用LES、LDS等指令修改段寄存器
思考:段描述符共有64位,但是需要填充80位,怎么填呢
段寄存器(96位) = 16位的Selector+64位的段描述符+?

标签:保护模式,GDT,字节,16,LDT,选择,描述符,寄存器
来源: https://www.cnblogs.com/doubleconquer/p/15514516.html