操作系统:浅析全局描述符表GDT

以下内容都是我阅读《从x86实模式到保护模式》一书的总结笔记,大约在11章~13章,主要记录一下有关GDT的内容。

GDT的引入

在实模式下最大可以访问1M大小的地址,进入保护模式后,由于需要内存保护,必须一五一十的记录段的权限–哪个段是系统级别的权限,哪个段时应用级别的权限,这样就可以使得系统可以对所有硬件进行直接访问,限定应用程序对硬件的直接访问,以免怀有恶意的应用程序对计算机破坏。

负责记录段权限的就是GDT,全称全局描述符表,它由64位比特组成,也就是两个字,下图是GDT的示意图
GDT

  • Base:段的基地址,由一个字大小组成,意味着它可以是保护模式下4G内存中任意一个地址。
    Base
  • LimitG:Limit 是段的大小范围也叫段界限,由20个比特组成,也就是1M大小,G是段界限的单位。另外,如果G位为0就以字节为单位,如果为1就以4KB为单位。假设G位为0,那么Limit+1是多少,此段大小就为多少字节,范围为1B~1M;设G位位1,那么此段大小为(Limit+1)*4KB大小,范围为4KB~4G
    Limit&G
  • P:存在标志位,为0就说明段不存在内存中,为1就存在内存中。这里可以引发一个中断,当CPU检查到这一位为0,后面指令又要使用此段的时候,可以引发一个缺段中断,然后跳转到加载段的中断程序以加载此段到内存中。
  • DPL: 此段的特权等级,由两位比特组成,最高特权等级为00,最低特权等级为11,一共有三个特权等级。
  • STYPE: S 位用于指定描述符的类型。当该位是0时,表示是一个系统段;为“1时,表示是一个代码段或者数据段(栈段也是特殊的数据段)。当S为1时,也就是为代码段或数据段时,TYPE的情况如下:
    TYPE
    也就是说,X为0时候就是数据段,X为1时候就是代码段,而关于依从的概念是关系到切换任务时候特权的更变的,后面再说。当S为0时也就是此段是一个系统段,而系统段也有好几种,TYPE里所代表的就是系统段的种类。(目前据我所知,TYPE是0010的为 LDT描述符、是1011或1001的为TSS描述符、是1100的为调用门描述符等)
  • D/B:默认的操作数大小或者默认的栈指针大小,该标志位主要是为了能够在32位处理器上兼容运行16 位保护模式的程序。该标志位对不同的段有不同的效果。对于代码段,此位为D位,用于指示指令中默认的偏移地址和操作数尺寸。D=0 表示指令中的偏移地址或者操作数是16 位的;D=1,指示32 位的偏移地址或者操作数。对于数据段,此位为B位…
  • L:是64 位代码段标志,保留此位给64位处理器使用。如果还是32位保护模式,我们将此位置0即可。
  • AVL:此位是保留位,留给操作系统用的,用也可以不用也可以。

段界限

这里重点关注一下段界限,有两点:

  • 段界限的计算
  • 栈段界限和栈的范围

段界限的计算

有一点需要注意段界限在数值上,是比实际大小少1的,为什么呢?比如内存单元的0~7,这里的0也是可以作为一个内存单元的,因此0~7实际的大小为8比特,而不是7比特。

实际段界限值 = (描述符中段界限值+1)*(段界限的颗粒大小:4KB或1B)-1
实际段界限值 = 0xffffffff或0xffff(段界限的颗粒大小:4KB或1B) - 需要设置的栈的大小

这里假设描述符中段界限值为0xFFFFF
G为0,颗粒大小为1字节,根据公式实际段界限值就是描述符中段界限值
G为1,颗粒大小为4KB字节,实际段界限值=0x100000*0x1000-1=0xFFFFFFFF

4KB=4*1024B=4096B
4096为十进制
4096B的十六进制为1000

栈段界限与栈的范围

我当时也一脸懵逼,但是后来慢慢理解上了。

普通的数据段,偏移量是从0x00000000开始,一直到段界限值,因为数据段是向上增长的,是增加的;而作为栈的数据段就不一样了,栈是向下减少的,方向和数据段相反,所以偏移量的起点应该也要相反,也就是说偏移量应该是从0xFFFFFFFF开始,一直减少到段界限值。

总的来说,数据段的范围为:0x00000000 ~ Limit,栈段的范围为:0xFFFFFFFF ~ Limit

而栈基址的作用是啥?我认为是一种定位的作用,比如我设置一个栈段界限为0xFFFFE,栈段基地址为0x7c00,会发生什么呢?看下图就懂了:
栈段范围
原本栈段基地址为0时候,栈段范围为0xFFFFFF ~ 0xFFFFEFFF ,有了基地址,两头分别加上栈段基地址0x7c00,由于底部和顶部两端是相连的(0xFFFFFF + 1 = 0x000000),所以栈段的范围变成了0x00006C00~0x00007BFF

而关于ESP的值的问题,原本不加栈段基地址设置为0,那就可以自动从0落到0xFFFFFF ~ 0xFFFFEFFF 范围,如果加了栈段基地址,就会落到0x00006C00~0x00007BFF范围里。

一旦CPU访问此栈段时候,实际访问的物理地址超过0x00006C00~0x00007BFF这个范围,就会触发异常中断,以保护其他段的数据安全。

有关GDT的第一部分完成,第二部分是有关保护模式下的特权保护相关内容,会记录一下选择子的笔记,也就是GDT里的DPL以及CPL,还有选择子的RPL

你或许也想写一个简单的操作系统,没错我也是,欢迎来一起讨论操作系统相关问题,这是我的QQ:2197651308

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值