进入保护模式
进入保护模式
进入保护模式的步骤:
- 关闭中断,打开地址线A20GATE,使得CPU可以访问1M以上的内存空间。
- 设置CR0寄存器,进入保护模式。
- 加载临时GDT
- 进入保护模式后,首先执行jmp指令。因为内存寻址方式改变,需要刷新指令流水线
打开A20Gate
1. A20Gate的作用
在实模式下,A20Gate是关闭的,意味着只能使用20根地址线,需要通过打开A20Gate,访问第21根以上的总线。
A20Gate关闭时侯的内存访问:
A20Gate关闭式,只能使用20根总线,所以寻址范围位 0x00000 ~ 0xFFFFF,总共1M的地址范围。
当访问的地址大于这个范围,高位的值将被截取掉,导致超出1M的地址访问会使得CPU回滚到1M内地址范围的现象
例如
当使用 [0xFFFF :0xFFFF ] 内存地址,得到的地址位 0x10FFEF 。但是在实模式下,由于20根总线的限制,最高位的1是无效的,实际的访问地址
回绕到
[0x0FFEF]。
A20Gate打开后的内存访问:
打开A20Gate, 可以使用到32位的地址总线,内存地址访问也达到了1<<32 的4G范围。
实际上开启A20Gate,总线的寻址能力达到了4G,但是cpu的内存访问能力因为16位段寄存器,和16位偏移地址的限制,并不能协调工作。
所以需要进入保护模式突破cpu的内存访问限制。
2. 开启A20Gate
开启A20Gate,只要设置io端口0x92的第一位为1就可以了。
;------------------
;打开A20
cli ;禁止CPU级别的中断
in al,0x92
or al,0000_0010B ;设置第1位为1
out 0x92,al
设置CR0寄存器,进入保护模式
CR0寄存器
CR0寄存器是一个32位的寄存器
设置CR0寄存器的最高位为0,最低位为1,则可以进入保护模式。
CR0寄存器的作用
- 改变段寻址方式,使用段描述符方式寻址。
- 实模式指令的操作数默认为16位,保护模式指令的操作数默认为32位。
代码:
;------------------
;进入保护模式
mov eax,CR0
or eax,0x00000001 ;设置第0位为1
mov CR0,eax
loader.asm完整代码如下
;Rats OS
;Tab=4
[bits 16]
section loader vstart=LOADER_BASE_ADDR ;指明程序的偏移的基地址
;----------- loader const ------------------
LOADER_BASE_ADDR equ 0x9000 ;内存地址0x9000
;---------------------------------------
jmp Entry
;程序核心内容
Entry:
;------------------
;禁止CPU级别的中断
cli
;------------------
;打开A20
in al,0x92
or al,0000_0010B ;设置第1位为1
out 0x92,al
;------------------
;进入保护模式
mov eax,cr0
or eax,0x00000001 ;设置第0位为1
mov cr0,eax
;程序挂起
jmp $ ;让CPU挂起,等待指令?
使用bochs调试
在0x7c00打断点,输入c跳转执行
$ pb 0x7c00
$ c
输入显示切换模式命令
$ show mode
输入c继续执行
$ c
可以看到控制他输出:
00017609546: switched from 'real mode' to 'protected mode'
说明系统成功的从实模式切换到保护模式
查看CR0的PE位
$ creg