分类:
2010-08-13 13:19:18
参考于渊的《自己动手写操作系统》第三章中从实模式切换到保护模式
在由保护模式切换到实模式之前,用normal选择子对段寄存器进行填充。
原因:
在切换到实模式之前,把一个指向似乎没有用的数据段的描述符Normal的选择子装载到DS和ES。这是为什么呢?
实模 |
段寄存器 |
段基地址 |
段界限(固定) |
段属性(固定) | |||||||||
存在性 |
特权级 |
已存取 |
粒度 |
扩展方向 |
可读性 |
可写性 |
可执行 |
堆栈大小 |
一致特权 | ||||
CS |
当前CS*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
Y |
- |
N | |
SS |
当前SS*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
N |
W |
- | |
DS |
当前DS*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
N |
- |
- | |
ES |
当前ES*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
N |
- |
- | |
FS |
当前FS*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
N |
- |
- | |
GS |
当前GS*16 |
0000FFFFH |
Y |
0 |
Y |
B |
U |
Y |
Y |
N |
- |
- |
在分段管理机制中,每个段寄存器都配有段描述符高速缓冲寄存器,这些高速缓冲寄存器在实方式下仍发挥作用,只是内容上与保护模式下有所不同。如上表所示,其中“Y”表示“是”; “N”表示“否”;“B”表示字节;“U”表示向上扩展,“W”表示以字方式操作堆栈。段基地址仍是 32位,其值是相应段寄存器值(段值)乘以16,在把段值装载到段寄存器时刷新。由于其值是16位段值乘上16,所以在实模式下基地址实际上有效位只有20位。每个段的32位段界限都固定为0FFFFH,段属性的许多位也是固定的。所谓固定是指在实方式下不可设置这些属性值,只能继续沿用保护方式下所设置的值。因此,在准备结束保护模式回到实模式之前,要通过加载一个合适的描述符选择子(如实例代码中的Normal选择子)到有关段寄存器,以使得对应段描述符高速缓冲寄存器中含有合适的段界限和属性。
也就是说,在实模式下装载段寄存器并不会影响段告诉缓冲寄存器的值,比如段界限(其实在实模式也没有必要改变,应为段界限一直都是0ffffh),这也就是为甚麽所有讲保护模式的树在讲到有保护模式切换到实模式时都要加载一个normal选择子的原因了。
应为必须在保护模式下设置好段高速缓冲寄存器的值,因为一旦到了实模式下就不能在改变了。
经我试验,对于normal的描述符,其最重要是段界限一定要设置为0ffffh,如果不是这样,那莫在由保护模式跳转到实模式后会发生错误(对于上述代码如果把normal描述符的段界限改为别的的话,在跳转后会产生死循环的现象,具体是什么原因现在还不明确,哪位高人知道一定要告诉我啊~~)。其次就是属性的设置一定要设置为可读可写的,否则也会发生错误.
不能从32位代码段返回实模式,而只能从16位代码段返回。
原因:(书中说的)因为无法实现从32位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)