您的位置:首页 > 其它

操作系统开发之——进入保护模式

2017-06-07 20:19 176 查看
依旧直接贴代码:

%macro Descriptor 3
dw	%2 & 0FFFFh				; 段界限 1				(2 字节)
dw	%1 & 0FFFFh				; 段基址 1				(2 字节)
db	(%1 >> 16) & 0FFh			; 段基址 2				(1 字节)
dw	((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)	; 属性 1 + 段界限 2 + 属性 2		(2 字节)
db	(%1 >> 24) & 0FFh			; 段基址 3				(1 字节)
%endmacro ; 共 8 字节
SA_RPL0		EQU	0	; ┓
SA_RPL1		EQU	1	; ┣ RPL
SA_RPL2		EQU	2	; ┃
SA_RPL3		EQU	3	; ┛

DA_32		EQU	4000h	; 32 位段
DA_LIMIT_4K	EQU	8000h	; 段界限粒度为 4K 字节

DA_DPL0		EQU	  00h	; DPL = 0
DA_DPL1		EQU	  20h	; DPL = 1
DA_DPL2		EQU	  40h	; DPL = 2
DA_DPL3		EQU	  60h	; DPL = 3

DA_DR		EQU	90h	; 存在的仅仅读数据段类型值
DA_DRW		EQU	92h	; 存在的可读写数据段属性值
DA_DRWA		EQU	93h	; 存在的已訪问可读写数据段类型值
DA_C		EQU	98h	; 存在的仅仅运行代码段属性值
DA_CR		EQU	9Ah	; 存在的可运行可读代码段属性值
DA_CCO		EQU	9Ch	; 存在的仅仅运行一致代码段属性值
DA_CCOR		EQU	9Eh	; 存在的可运行可读一致代码段属性值
; GDT ----------------------------------------------------------------------------------------------------------------------------------------------------
;                                                段基址            段界限     , 属性
LABEL_GDT:			Descriptor            		   0,                    0,       0						; 空描写叙述符
LABEL_DESC_FLAT_C:		Descriptor                 0,              0fffffh,  DA_CR  | DA_32 | DA_LIMIT_4K			; 0 ~ 4G
LABEL_DESC_FLAT_RW:		Descriptor               0,          0fffffh,  DA_DRW | DA_32 | DA_LIMIT_4K			; 0 ~ 4G
LABEL_DESC_VIDEO:		Descriptor	             0B8000h,          0ffffh,   DA_DRW | DA_DPL3	; 显存首地址
; GDT ----------------------------------------------------------------------------------------------------------------------------------------------------

GdtLen		EQU	$ - LABEL_GDT
GdtPtr		DW	GdtLen - 1				; 段界限
DD	0x80000 + LABEL_GDT
; GDT 选择子 ----------------------------------------------------------------------------------
SelectorFlatC		EQU	LABEL_DESC_FLAT_C	- LABEL_GDT
SelectorFlatRW		EQU	LABEL_DESC_FLAT_RW	- LABEL_GDT
SelectorVideo		EQU	LABEL_DESC_VIDEO	- LABEL_GDT + SA_RPL3
; GDT 选择子 ----------------------------------------------------------------------------------
;准备切换到保护模式
MOV	EAX,CR0 ;获取CR0配置
OR	EAX,1 ;改动CR0的第0位(PE位),进入保护模式
MOV <span style="white-space:pre">	</span>CR0,EAX ;将改动过的配置送回CR0

JMP dword SelectorFlatC:(0x80000 + Protect_Mode)
[bits 32]
Protect_Mode:
MOV AX,SelectorFlatRW
MOV DS,AX
MOV SS,AX
MOV ES,AX
MOV FS,AX
MOV AX,SelectorVideo
MOV GS,AX
JMP $


嗯哼,读者朋友一定会问:前面那一大段干虾米的?

答:那但是著名的段选择子,那但是要载入到各个段里面的,在这里不细说,我们将在下一篇文章来讨论段选择子。当然,前面另一个数据结构,类似于C语言中的struct,这是为了简化程序,用最简便的方法来完毕传递參数。

废话不多说,直接进入正题。在这里介绍一下CR0

CR0,用于控制和确定处理器的操作模式以及当前运行任务的特性,(事实上CR0——CR3都是),我们在这里不介绍其它位,仅仅介绍PE位(保护模式位)。

我们先取出CR0的配置。然后用OR运算符把PE位(第0位)置1。接着把CR0的配置送回。

(完了?)当然没有。我们另一个历史性的JMP。

在这里笔者建议读者朋友看《X86汇编语言:从实模式到保护模式》(假设没有学习过长跳转)。为什么要看呢?由于接下来讲的可能读者朋友有些吸收不了。

JMP dword SelectorFlatC:(0x80000 + Protect_Mode)


如今我列出几个读者可能会问的问题。

一:为什么要加上那个0x80000:

答:由于Nasm和C语言的标识符默认没有加上当前的物理地址,(即把当前程序的開始地址当做0)

二:为什么要加上一个dword

答:我们先做一个实验,”JMP 8:0x12345678“。这一句没有加dword把。可是他执行出来的结果是”JMP 8:0x5678“。如今能明确为什么要加上dword了吧。

三:为什么前面有SelectorFlatC标识符呢?

答:我们在后面会讲到,这是个段选择子。

四:为什么一定要有这个JMP呢?

答:由于这个JMP(事关重大太严重了。嘻嘻)一要更新CS,二要跳转到32位段。三。

。。。

就这么简单。

假设还有问题能够联系我:Email:2608184397@qq.com

假设读者朋友也有开发操作系统的想法,能够联系我。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐