《操作系统真象还原》第四章——保护模式入门

2024-03-19 19:28

本文主要是介绍《操作系统真象还原》第四章——保护模式入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前置知识

段描述符格式

  • 段界限:表示段边界的扩展最值
    • 此段界限是一个单位量,其单位要么是字节,要么是4KB,具体可由G位进行指定
    • 最终段界限=此段界限值*单位
    • 实际段界限计算公式:(此段界限值+1)*(G位)-1
  • G:粒度位,用于解释段界限的单位
    • 为0:表示段界限的单位表示为字节
    • 为1:表示段界限的单位表示为4KB
  • S描述符类型
    • 为0,表示系统段
    • 为1,表示非系统段(代码段或者数据段)
  • type:用于指示描述符的子类型
  • DPL:Descriptor Privilege Level,即描述符特权级
    • 特权级共有0、1、2、3,用于解释段界限的含义
  • P段存在位,用于指示描述符所对应的段是否存在
    • P位是由处理器负责检查的。每当通过描述符访问内存中的段时,如果P位是“0”,处理器就会产生一个异常中断
    • 该中断处理过程是由操作系统提供的,该处理过程的任务是负责将该段从硬盘换回内存,并将P位置1
  • D/B:标志位,为了能够在32位处理器上兼容运行16位保护模式的程序。该标志位对不同的段有不同的效果。
    • 对于代码段,此位称作“D”位,用于指示指令中默认的有效地址和操作数尺寸;
      • D=0表示指令中的有效地址或者操作数是16位的;
      • D=1,指示32位的有效地址或者操作数。
    • 对于栈段和向下扩展的数据段来说,该位被叫作“B”位,用于指定在进行隐式的栈操作时,是使用寄存器SP还是寄存器ESP,隐式的栈操作指令包括push、pop和call等。
      • 如果该位是“0”,在访问那个段时,使用寄存器SP;
      • 否则就是使用寄存器ESP。
  • AVL:表示软件是否可以使用(Available),通常由操作系统来用,处理器并不使用它。
  • L:用于设置是否是64位代码段
    • 为1,表示64位代码段
    • 为0,表示32位代码段

选择子

  • RPL:请求特权级
  • TI(table indicator):表示在GDT(全局描述符表)还是在LDT(局部描述符表)中索引描述符
    • 为0,在GDT中进行索引
    • 为1,在LDT中进行索引 
  • 3~15位,具体描述符的索引值,2^13=8192,故最多可以索引8192个段 

 GDT寄存器GDTR

  • 作用:用于指向GDT的内存地址
  • 访问格式:lgdt 48位内存数据

由上述GDTR寄存器的格式可以看出,GDT的大小占16位,也就是65536个字节,而每个描述符占8个字节,因此GDT最多可以容纳的描述符数量是65536/8=8192个 

控制寄存器CR0

控制寄存器是CPU的窗口,既可以用来展示CPU的内部状态,也可以用于控制CPU的运行机制

其中CR0的PE位是保护模式的开关

  • 为0时,表示在实模式下运行
  • 为1时表示在保护模式下运行 

进入保护模式

boot.inc

原书勘误,显存描述符应该为的最后应该是0x0b,而不是0x00

DESC_VIDEO_HIGH4 equ (0x00<<24) + DESC_G_4K \+ DESC_D_32 + DESC_L + \DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + \DESC_S_DATA + DESC_TYPE_DATA + 0x0b

%include "boot.inc"SECTION loader vstart=LOADER_BASE_ADDR
;初始化栈指针地址
LOADER_STACK_TOP equ LOADER_BASE_ADDR
jmp loader_start;------------- 构建gdt及其内部的描述符 -------------GDT_BASE: dd 0x00000000dd 0x00000000;代码段描述符的低4字节部分,其中高两个字节表示段基址的0~15位,在这里定义为0x0000;低两个字节表示段界限的0~15位,由于使用的是平坦模型,因此是0xFFFFCODE_DESC:  dd 0x0000FFFFdd DESC_CODE_HIGH4;段描述符的高4字节部分DATA_STACK_DESC: dd 0x0000FFFFdd DESC_DATA_HIGH4;定义显存段的描述符;文本模式下的适配器地址为0xb8000~0xbffff,为了方便显存操作,显存段不使用平坦模型;因此段基址为0xb8000,段大小为0xbffff-0xb8000=0x7fff,;段粒度位4k,因此段界限的值为0x7fff/4k=7VIDEO_DESC: dd 0x80000007dd DESC_VIDEO_HIGH4GDT_SIZE equ $-GDT_BASEGDT_LIMIT equ GDT_SIZE-1times 60 dq 0 ;此处预留60个描述符的空位;------------- 构建选择子 -------------SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0;------------- 定义gdtr(指向GDT的寄存器) -------------gdt_ptr dw GDT_LIMITdd GDT_BASE;------------- 加载器的显式信息 -------------loadermsg db '2 loader in real .'loader_start:
;------------------------------------------
;INT 0x10 功能号:0x13 功能描述:打印字符串
;------------------------------------------
;输入:;AH:功能号;AL:显示输出方式;   0——字符串中只含显示字符,显示属性在BH中,显示后光标位置不变;   1——字符串中只含显示字符,显示属性在BH中,显示后光标位置改变;   2——字符串中含显示字符和显示属性,显示后光标位置不变;   3——字符串中含显示字符和显示属性,显示后光标位置改变;BH:页码;BL:属性;CX:字符串长度;(DH、DL):坐标(行、列);ES:BP 字符串地址
;无返回值mov sp,LOADER_BASE_ADDRmov bp,loadermsgmov cx,17mov ax,0x1301mov bx,0x001f;页号为0,蓝底粉红字mov dx,0x1800int 0x10;------------- 准备进入保护模式 -------------
;1.打开A20
;2.加载gdt
;3.置cr0的PE位为1;------------- 打开A20 -------------in al,0x92or al,0000_0010Bout 0x92,al;------------- 加载gdt -------------lgdt [gdt_ptr];------------- 置cr0的PE位为1 -------------mov eax,cr0or eax,0x00000001mov cr0,eaxjmp dword SELECTOR_CODE:p_mode_start;刷新流水线[bits 32]
p_mode_start:mov ax,SELECTOR_DATAmov ds,axmov es,axmov ss,axmov esp,LOADER_STACK_TOPmov ax,SELECTOR_VIDEOmov gs,axmov byte [gs:160],'p'jmp $

编译

nasm -I ./include/ -o mbr.bin mbr.S
nasm -I ./include/ -o loader.bin loader.S

磁盘写入

注意loader.S写入磁盘时count参数为2

dd if=./osCode/mbr.bin of=./bochs/hd60M.img bs=512 count=1 conv=notrunc
dd if=./osCode/loader.bin of=./bochs/hd60M.img bs=512 count=2 seek=2 conv=notrunc

运行

输出p说明GDT成功建立,如下调试所示

这篇关于《操作系统真象还原》第四章——保护模式入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/827012

相关文章

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Python实现Word转PDF全攻略(从入门到实战)

《Python实现Word转PDF全攻略(从入门到实战)》在数字化办公场景中,Word文档的跨平台兼容性始终是个难题,而PDF格式凭借所见即所得的特性,已成为文档分发和归档的标准格式,下面小编就来和大... 目录一、为什么需要python处理Word转PDF?二、主流转换方案对比三、五套实战方案详解方案1:

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习