第11章:进入保护模式
描述符格式:
高32位 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
31 24 | 23 | 22 | 21 | 20 | 1916 | 15 | 1413 | 12 | 11 8 | 7 0 |
段基地址 24-31(8bit) | G | D/B | L | AVL | 段界限(19-16 = 4bit = 1个16位) | p | DPL | S | TYPE | 段基地址 23-16(8bit) |
低32位: | ||||||||||
31 | 16 | 15 | 0 | |||||||
段基地址 15-0 | 段界限15-0 |
G(粒度):
0=1 byte
1= 4k byte
D/B (操作数大小)
0=16bit
1=32bit
L:64bit处理器用的
AVL(空闲)
P 段是否存在内存中
0 = 不存在
1 = 存在
DPL 描述符的特权级别 : 指定访问该段需具有的最低特权级别
保护模式执行的代码特权级别都是 0
S: 段的类型
0=系统段
1=代码or数据段
type: 代码段or数据段的的类型
分析例子:
1 |
|
线性地址
高位(前1个字节+最后1个字节)+低位(前2个字节) =
0x00007c00
段界限 (20bit = 4+16 bit)
- 4bit恰好是1个16进制数
高位第4个16进制数(0) + 低位最后2个字节(
01ff
) =0x001ff
剩下 高位第3个(
3
)、第5个(9
)、第6个(4
)16进制数,每个位置对应看就行了
80486: 南桥的处理器接口的端口0x92:第0位INIT_NOW
用于初始化处理器,此端口=1,处理器复位,计算机重启,第1位控制A20,
2种模式的切换开关:CR0是 控制寄存器(Control register),并且第1位(位0)是保护模式允许位置(Protection Enable), =1则处理器进入保护模式,
32bit处理器下的段寄存器变成了段选择器(存描述符在table中的偏移位置),且cpu内部对应了一个用户不可见的描述符高速缓存寄存器, 并且新增了2个额外的段寄存器
Fs
,Gs
(注意:仍是16位)
32bit处理器实模式下,引用一个段,处理器自动将段地址左移4位,传送到描述符高速缓存器中,(32bit下向段寄存器传送16bit的逻辑段地址处理器不看做是描述符选择子)
保护模式访问内存的方式(段选择子的组成
传送到段寄存器的不是逻辑段地址而是在描述符表(局部或者全局)中的索引号(偏移地址)
- TL指出在GDT(=0)还是LDT(=1)中
- RPL:自己的特权级别
15 | 3 | 2 | 1 0 | |
---|---|---|---|---|
描述符索引(偏移地址) | TI | RPL |
在设置CR0的位0后进入保护模式的问题
处理器进入16位保护模式
操作数默认大小由描述符D位决定,此时段寄存器的描述符高速缓存器仍是实模式(低20有效,高12为0)内容,所以D位 = 0,此时处于16bit保护模式下
- 描述符高速缓存器低20位有效,高12位为0,应刷新段寄存器的内容
- 流水线中待执行的都是按照16bit操作数或者32bit编译后的字节,因为对地址的解释不同,可能导致执行结果不正确
通过jmp
刷新段寄存器和段寄存器描述符高速缓冲器,因为无条件转移,流水线被清空
JMP
执行时:将GDT()中描述符加载到cs寄存器描述符高速缓存器,偏移量送到EIP中
1 |
|
Bochs
调试:
- r:显示所有的通用寄存器
- sreg:段寄存器
- creg:控制寄存器内容: PE=1 进入保护模式
- lgdt加载gdt到gdtr后,用info gdt查看gdt
来源:《X86实模式到保护模式》
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!