《oranges:一个操作系统的实现》阅读笔记 二

第三章 保护模式

1. 描述符和选择子的结构

先把这两个结构放在上面,下面讨论的时候好方便对照着看。
高地址                                                                                                                                                                                                                  低地址

                                                                                                                                                                                                                             高地址
描述符结构
31                                                        23                                                       15                                                        7                                                       0
段基址(8-15位)(第2字节)
段基址(0-7位)(第1字节) 段界限(8-15位)(第2字节) 段界限(0-7位)(第1字节)
段基址(24-31位)(第4字节)
G| D/B| 0AVL段界限(16-19位)
7 |  6  |5 |     4 | 3 2 1 0
P|    DPL  |  S |   TYPE  
7|   6 5    |  4 |  3 2 1 0
段基址(16-23位)(第3字节)
63                                                      55                                                      47                                                       39                                                   31  

选择子结构
描述符索引 13位                TI 1位      RPL 2位

2. 为什么由实模式跳入保护模式的程序必须要在GDT第一项有一个空描述符?

这个问题一直困扰着我,把那项描述符去掉后,程序无法正常显示进入保护模式后显示的'P'字,然后我就开始debug程序观察前后有什么差别吗,结果也还是没有找到答案。
后来我在网上看到一位网友提到这样一个问题:
程序加载完gdtr,打开A20地址线,设置保护模式PE位后已经位于保护模式了, 那么也就是说执行完 mov cr0, ax这句后,程序已经位于保护模式了,但这个时候cs段寄存器中仍然存放的是实模式下的段地址而不是保护模式下的选择子, 执行完后一句 jmp dword SelectorCode32:0 后cs才会变成选择子的值,那既然已经位于保护模式,程序是通过实模式下的cs, eip取得下句执行代码的地址呢?也就是如何定位到该执行 jmp dword SelectorCode32:0这句呢?
举个例子吧,加入mov cr0,ax这句实模式下地址cs:eip=0000:7c00h,按实模式下的寻址机制下条指令的地址就是cs:eip=0000:7c03h也就是jmp dword SelectorCode32:0的地址,但现在已经位于保护模式下了,按照保护模式下的寻址机制下条指令的物理地址应该是: cs选择子所指描述符中的段基址 + eip,这样的话就指不到指令
jmp dword SelectorCode32:0 了。
那个问题中提到了描述符缓存寄存器,所以我就在网上搜索相关内容,然后就找到了这个解释了上面提到的两个问题,感谢!
描述符表和描述符高速缓存寄存器
这里面的主要意思是:
CPU有一组用于存储描述符的描述符告诉缓存寄存器,这些寄存器主要是为了CPU快速得到一个段的信息,不用经由gdtr寄存器,再去描述符表里取,而且段具有计算机科学中常见的局部性,不经常变动,这样可以提高效率。当段寄存器发生变化时比如jmp,call操作,CPU才从描述符表中将新值同步到缓存寄存器中。
不管是在实模式还是在保护模式下,CPU在实际寻址时都会使用这个高速缓存。所不同的是,在实模式下,在段寄存器的值发生变化时,仅仅把段寄存器的值×16(左移4位)放到高速缓存的的基地址位置,段界限和存取权限总是一个固定不变的值(按照Intel的说法,PC机加电后工作在实模式,高速缓存中将被置入缺省值,在实模式下,其中的段界限和存取权限将一直保持不变);而在保护模式下,当段寄存器发生变化时,CPU要从描述符表中加载数据到高速缓存中。
而GDT第一项必须为空描述符的原因请参考这篇文章:http://blog.csdn.net/ruyanhai/article/details/7181270
下面我们在mov cr0, eax和jmp dword SelectorCode32:0之间添加几条指令,然后在执行完mov cr0, eax后,通过debug设置cs eip,让程序转到保护模式下的代码
mov cr0, eax
mov eax, 0
mov eax, 0
jmp dword SelectorCode32:0
1)执行到mov eax, 0这条指令
《oranges:一个操作系统的实现》阅读笔记 二_第1张图片

2) 设置cs=8, eip=0,即保护模式下32位段的逻辑段地址
《oranges:一个操作系统的实现》阅读笔记 二_第2张图片
3)然后用s单步执行,别用n因为n会跳过函数直接显示结果了
《oranges:一个操作系统的实现》阅读笔记 二_第3张图片

这就证明了上面的叙述,只有更改了告诉缓存寄存器中的信息,寻址模式才会更改。实模式下cs高速缓存寄存器下存储的就是段寄存器左移4位,段界限和段属性用默认值,而保护模式下CPU将描述符加载到缓存寄存器中,所以寻址模式是根据告诉缓存寄存器中的信息来决定的。

3. 为什么从保护模式跳回实模式需要一个Normal描述符和一个16位代码段?

这个问题其实都是问题2中描述的,因为高速缓存寄存器的存在,实模式和保护模式下高速缓存寄存器存储值的不同,并且影响了寻址机制造成的。
Normal描述符就是为了将ds, es等寄存器的高速缓存寄存器设置为实模式下正确的段界限和段属性,16位代码段的存在是为了cs寄存器切换时高速缓存寄存器中界限和属性符合实模式下的规范。

你可能感兴趣的:(操作系统,保护模式,oranges,汇编)