迈入保护模式

此时已完成了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.程序的运行结果

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ZZHinclude/article/details/121241045
今日推荐