《Orange's 一个操作系统的实现》读书手记3(3)--- [ 保护模式(Protect Mode)]

来源:互联网 发布:微信视频录像软件 编辑:程序博客网 时间:2024/05/21 21:38

 保护模式(Protect Mode) (3)


    3.1.2 GDT(Global Descriptor Table)

    在Intel Architecture 32 下, CPU包括两种工作模式: 实模式和保护模式

    计算机刚打开的时候CPU是工作在实模式下的,经过某种机制之后(还记得那次辉煌的鲤鱼跳龙门吗?),才进入保护模式。在保护模式下,CPU有着巨大的寻址能力,并为强大的32位操作系统提供了更好的硬件保障。

    为了让我们容易明白一些,作者举了一个例子,大意是这样:

    刚开机时,实模式是CPU的当朝皇帝,他有他的一套冶理计算机资源的政策,我们的程序得按他的规则来编写,否则就有可能让你的机器一命呜呼。后来经过我们艰苦卓绝的革命斗争, 保护模式被推上了CPU的宝座,保护模式自有他一套新政,在新的政策下,CPU的国土更加的辽阔,可以使用的资源空前丰富(寻址空间达到4G),编写程序更加的自由和民主,甚至成就了CPU的多党轮流执政(多进程)。

    旧政下是什么样的情形?始皇帝时期的Intel8086是16位的,它的寄存器、数据总线都是16位的,地址总线是20位的,仅有2的20次方即1M的寻址能力。要得到这个20位的物理地址需要这样做:

   物理地址(Physical Address) = 段值(Segment) X 16 +偏移(Offset)

   从80386开始,Intel 家族的CPU进入了32时代。80386有32位地址线,寻址空间达到了2的32次方即4G。

   如今我们有了32位的寄存器,一个寄存器就能把4G的空间寻完,但是,这一次的革命不够彻底,仍然保留了"段:偏移"的旧的寻址形式。不过,在新的历史舞台上,”段“具有了双重身份:在实模式时,它仍然是直接做为地址的一部分的;而在保护模式下,它仅仅是一个索引,这个索引正是指向了前面我们讲到的现在即将解剖的变态的GDT中的一个表项的(还记得前面的SelectXXX吗?想一想它是怎么发挥选择作用的)。

   从现在起我要为GDT的表项正名----描述符,不再叫它变态的了,因为那也不是自己愿意的,是有历史原因的,饶了他吧!他是有功劳的,听我为你讲来:

   GDT提供了保护模式下段式存储机制,这种机制是由段寄存器(还是16位)和GDT中的描述符共同完成的 。(GDTR不高兴了:怎么把我给忘了?)

   让我们走近一点,看看“臭名昭著”的GDT的描述符吧:

    这是一个代码段和数据段的描述符,将来我们还会遇到系统段描述符和门描述符(应该跟现在这个差不多吧?)。

    不知你看到没有,32位的段基址被分成两部分:31...24位放在了BYTE7和BYTE6,23..0 位放在BYTE4、BYTE3和BYTE2;20位的段界限 也被分成两部分:19..16位放在属性的BYTE6的BIT3-0,15..0位放在BYTE1和BYTE0。属性里面还有其他的一些东西,我们暂时不理它。

    还记得前面讲的Descriptor这个宏吧?它隐藏了设置描述符的复杂性,将段基址、段界限和段属性安排在了GDT中描述符的一个合适位置。

   GDT中的每一个描述符定义一个段,前面说过,在保护模式下,仍然保留了"段:偏移"的旧的寻址形式,段寄存器仅仅是保存了一个指向GDT中表项的索引,这个索引值就是通过SelectXXX取得的。SelectXXX专门名称叫选择子,它实际上就是一个对应描述符相对GDT基址的偏移,只不过因为GDT中描述符是8字节对齐的,选择子中的低3位对地址没有什么贡献,另作他用了。 

    在这里我总结一下我对保护模式下段式寻址过程的理解, 有不对的地方,欢迎指正:

    在程序中给出一个逻辑地址 SEG:OFFSET,CPU首先通过GDTR取得GDT表首的地址,又通过段寄存器SEG (cs,ds,gs等)得到了GDT中对应表项的地址偏移,由此定位了一个段描述符,我们知道,描述符里面包括了所描述段的基址和界限,将这个基址与逻辑地址中的OFFSET相加就得到了所要的线性地址,在前面的例程中,这个线性地址与物理地址是一致的,其他视情况而定。

  

 

原创粉丝点击