《一个操作系统的实现》笔记一,GDT(全局描述符)

     最近在研究操作系统,然后看见了《oange‘s,一个操作系统的实现》,觉得不错,感谢作者大笑。说实话,关于GDT这部分我看了几天了,不是很懂,今天又仔细看了一遍,突然茅塞顿开啊,要理解GDT,先要理解什么是实模式,什么是保护模式。
     我们知道,Intel的8086是一个16位的CPU,寻址使用《段寄存器 :偏移地址》的方式来寻址,8086有20根地址线,但是寄存器是16位的,怎样才能寻址1MB呢,很简单,就是将段寄存器左移4位,然后加上偏移地址,即可得出20位的物理地址,此地址就可以直接寻址1MB了,但是8086里面没有内存保护机制,这样一个程序就可以修改任意内存的值了,现代操作系统显然不允许这样做,如果一个程序可以修改任意内存空间的值,那随便一个程序就把系统搞死机了,然后出现了80286,80286地址线有24根,可以寻址16MB,并且有内存保护机制,我今天要说的是80386以及后来出现的X86系列,80386地址线有32根,可以寻址4GB的内存,那是不是就可以不用段寄存器了呢,Intel为了向下兼容,保留了这些段寄存器,那这些段寄存器用来干嘛呢?在保护模式下,它用来保存一个索引,这个索引值就是GDT/LDT相对于GDTR的位置,80386启动时处于实模式下,寻址还是采用段寄存器左移4位加上偏移值来实现,寻址能力还是1MB,启动时,CS:IP=0xF000:0xFFF0,计算得出物理地址为0xFFFF0,这个地址是存放BIOS程序的地址。进入保护模式是通过设置某一个寄存器来实现的,进入保护模式之后,段寄存器还是16位的,不能表示32位的段地址,所以段寄存器的意义就发生了变化。

     以一个设计者的角度来讲,我要寻址内存某一个地址,首先要给出物理地址对吧,并且还要用上段寄存器,那么这个物理地址如何来呢,我给出一个16位的段寄存器值,和一个偏移值,如0x0012:0x00000000,那么0x0012就是一个段选择符(选择子),如下图所示:

                                                                                                      

     进入保护模式之后,CPU不会将它左移4位加上偏移值形成物理地址了,CPU先查看0x0012的信息,第0,1位是特权级,第2位表示GDT还是LDT,第3-15位就表示描述符在描述符表中的第几个,0x0012=0000_0000_0001_0010,表示特权级2级,GDT,索引号为2,然后CPU就会到内存的某一个地址出开始找到索引号为2的描述符,这个描述符里面就保存了32位的地址,然后将这个地址加上给出的偏移地址0x00000000得出物理地址(如果没有分页的话),那么问题来了,CPU到哪个位置查找描述符呢,所以就有一个寄存器GDTR保存了GDT的首地址,后面就跟着以8个字节为单位的段描述符,一个8字节表示一个段,这8个字节表示了这个段的基地址,属性,大小,权限等信息,这8个字节如下图所示,那么要进入保护模式,就要先设置好GDT表和GDTR寄存器的值了,不然进入保护模式直接就会出错。

                                                             

     所以总结一下,进入保护模式下后CPU的寻址方式用下图来描述:

     

猜你喜欢

转载自blog.csdn.net/u014783685/article/details/53258336