上一篇文章学习了段描述符与段描述符各个标志位的含义:段描述符
本篇文章学习如何进入保护模式,并学习如何在保护模式下进行内存访问。
1、如何进入保护模式
假设我们已经用汇编语言将段描述符安装到GDT中(具体的汇编代码在后面的文章中会给出),并且也已经将GDTR的线性地址与界限值加载到了GDTR中。现在前期的准备已经准备好了,可以直接进入到保护模式了。那么如何进入到保护模式呢?
控制实模式与保护模式切换的一个控制器是CR0寄存器。CR0是处理器内部的一个控制寄存器。
CR0是32位寄存器。如下图:
它的第一位(位0)是保护模式允许位(PE位)。如果把该位置1,则处理器进入保护模式的规则下运行。其他位暂时不用,所以显示的空白。以后学习过程中会继续学习。
好了,只要我们再汇编代码中将CR0寄存器的PE位置1,则进入保护模式的规则。现在假设我们已经进入了保护模式。
2、进入保护模式后如何访问内存
2.1、32位处理器的段寄存器
我们很清楚16位的8086处理器的是如何通过段寄存器来访问内存的。
在保护模式下,32位的处理器中。段寄存器有所变化。如下图是32位处理器的段寄存器:
每个段寄存器的前16位于8086的寄存器一样,在实模式下,他们用传统的方式访问1M内存,使用方法没有变化。
同时每个段寄存器还包括一个不可见的部分,如上述图的红色部分,称为描述符高速缓存器,用来存放所要访问的段的线性地址、段界限和属性。
说它不可见是因为只有处理器可以访问,只能是处理器来使用。
那么保护模式下,是如何听过上述的段寄存器访问内存的呢?
在保护模式中,前16位的段寄存器称为段选择器。将段描述符在GDT中的索引号传送给段选择器。
如下图所示,是段选择器里的内容。
在保护模式下访问一个段时,传送到段选择器的是段选择子。它由上述三部分组成。
描述符索引: 用来在描述符表(GDT)中找到一个段描述符。TI :描述符表指示器。TI=0时,表示描述符在GDT中。TI=1时表示描述符在LDT中。LDT是局部描述符表,在后面会有所介绍。RPL :请求特权级,表示给出当前选择字的能程序的特权级,正式该程序要访问这个内存段。
2.2、开始访问内存
到了这里,我们知道了段选择器的作用,就是用来索引段描述符的。现在还不知道描述符高速缓存器的作用呢??? 不着急,马上就来。
假设现在我们要访问的是数据段。
DS寄存器的段选择器中存放的是数据段描述符在GDT中的索引号,而GDTR寄存器又保存的是GDT的基地址。GDT中每一个描述符的大小是8字节。那么访问数据段的内容,就如下图所示了:
在第一次访问数据段的时候,首先将之前传送到段选择器的段选择子部分的描述符的索引号乘以8,得到描述符在GDT中的偏移地址。再用这个偏移地址加上GDT的基地址GDTR指向的内容,就可以访问到内存中的段。
如果没有发现什么问题,就自动的找到数据段描述符,将它加载到段寄存器的描述符高速缓存部分。加载的部分包括数据段的线性地址、段界限、与访问属性。
此后,如果再有访问数据段的内存操作,处理器直接访问段寄存器的描述符高速缓存部分的内容,而不用像开始那样还用段选择子部分的描述符索引号乘以8加上GDTR指向的GDT基地址。不用那么麻烦了,以后如果还访问数据段,直接在数据段的描述符高速缓存中查找段的地址以及访问属性即可。
比如接下来如果有一条指令mov byte [0x00],'P'
假设现在的DS中的描述符高速缓存存的数据段的线性地址是 0x000B8000,那么上述指令的访问就如下图所示:
不只是访问数据段。访问代码段也是与上述过程类似。只不过指令的偏移地址一般是由EIP寄存器指定。那么访问一个内存中的指令大概就是下面的过程:
到了这里,我们已经很明白段寄存器中的描述符高速缓存的作用。它其实就是一个cache的作用。
3、总结
本篇文章有点绕。但是只要很用心的看,多看几遍,肯定会看明白保护模式下的内存访问机制。
笔记记得不是很全,如果有不懂的可以加我联系方式一起交流。
学习探讨加个人:
qq:1126137994
微信:liu1126137994