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


    依旧直接贴代码:

    %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

    假设读者朋友也有开发操作系统的想法,能够联系我。


  • 相关阅读:
    AC_9. 分组背包问题
    AC_8. 二维费用的背包问题
    AC_7混合背包问题
    AC_5. 多重背包问题 II
    AC_4. 多重背包问题 I
    AC_3. 完全背包问题
    小郡肝火锅点餐系统——测试部署发布
    Vue脚手架搭建
    归并排序-总结
    小郡肝火锅点餐系统——项目文档
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6958903.html
Copyright © 2020-2023  润新知