此时已完成了MBR的任务,MBR将控制权交给了Loader
1.步骤
①打开A20 gate
②加载gdt
③将CR0 寄存器的PE位 置1
2.代码 Loader.S
%include "boot.inc"
section Loader vstart=LOADER_BASE_ADDR ; 0x900
LOADER_STACK_TOP EQU LOADER_BASE_ADDR
//栈顶设置为0x900
JMP Loader_Start
;/**********Init GDT***************/
align 2 //四字节对齐
//全局描述符表的第一个没用
GDT_BASE_ADDR : dd 0x00000000 ;Not Used
dd 0x00000000
//代码段 只有可执行权限
CODE_DESC : dd 0x0000ffff
dd DESC_CODE_HIGH4B
//栈段
DATA_STACK_DESC : dd 0x0000ffff
dd DESC_DATA_HIGH4B
//显存段
VIDEO_DESC : dd 0x80000007 ; limit = (0xbffff-0xb8000)/4K = 0x7
dd DESC_VIDEO_HIGH4B
GDT_SIZE EQU $-GDT_BASE_ADDR
GDT_LIMIT EQU GDT_SIZE - 1
TIMES 60 dq 0 ; prepare 60 GDT 定义了60个选择子
;/********SELECTOR***************/ 三个选择子
SELECTOR_CODE EQU (0x0001<<3) + TI_GDT + RPL0
SELECTOR_DATA EQU (0x0002<<3) + TI_GDT + RPL0
SELECTOR_VIDEO EQU (0x0003<<3) + TI_GDT + RPL0
;/**********gdt point****************/ gdt的指针
GDT_PTR dw GDT_LIMIT
dd GDT_BASE_ADDR
;/*******message*********/
loadermsg db '2 loader in real.';
;/*******Loader_Start***********/
Loader_Start:
//输出一段字符
MOV SP, LOADER_BASE_ADDR
MOV BP, loadermsg ; ES:BP 是字符串的地址
MOV CX, 17 ; 字符串的长度
MOV AX, 0x1301 ;AH=13 功能号 AL=1
MOV BX, 0x001f ;BH=0 页号 BL=1f 蓝色背景 粉红字
MOV DX, 0x1800;
INT 0x10
进入保护模式
;/******** protected mode*********/
;1.A20
;2.GDT
;3. CR0->PE
打开A20
IN AL, 0x92
OR AL, 0x02
OUT 0x92, AL
打开PE
MOV EAX, CR0
OR EAX, 0x01
MOV CR0, EAX
加载GDT
LGDT [GDT_PTR]
刷新流水线
JMP dword SELECTOR_CODE:p_mode_start ; flush Pipeline
//32位的指令
[BITS 32]
p_mode_start:
MOV AX, SELECTOR_DATA
MOV DS, AX
MOV ES, AX
MOV SS, AX
MOV ESP, LOADER_STACK_TOP
MOV AX, SELECTOR_VIDEO
MOV GS, AX
MOV byte [gs:160], 'P'
JMP $
3.打开A20
博客地址
这种方式 打开A20线很危险, 可能会引发硬件冲突
4. 刷新流水线
当我们进入到保护模式下的时候, 此时的流水线上的指令都是16位数,而保护模式下是32位的指令, 并且此时的段寄存器中 存储的是 偏移4位后的段基址, 所以我们要重新用段选择子+段偏移给他赋值
JMP 指令可以刷新流水线,因为jmp跳转 代表后面的指令没用了,要重新取指令
5.代码段和数据段的保护
①CPU每访问一个地址,就要确认该地址不能超过其所在内存段的范围
实际段界限的值
(描述符中段界限+1)*(段界限的粒度 4K/1)-1
②CPU保证一个指令的任何一个部分 完全的在当前代码段中。
满足EIP中的偏移地址+指令长度-1 <= 实际段界限大小
6.栈段的保护
①对于向上拓展的段,实际的段界限是 段内最后一个可以访问的字节
②对于向下拓展的段,实际的段界限是段内不可以访问的第一个字节
实际段界限+1 <= ESP-操作数大小 <= 0xFFFFFFFF
7.程序的运行结果