02.加载GDT表,进入保护模式
加载GDT表,进入保护模式
加载GDT表,实现操作系统从实模式进入保护模式
参考
操作系统学习 — 启动操作系统:进入保护模式
保护模式与实模式
GDT、GDTR、LDT、LDTR
调用门与特权级
趣谈 Linux 操作系统
在01.硬盘启动盘,加载操作系统中BIOS在0x7c00处加载MBR,并让程序跳转到该处。MBR只是一个中转站,其他功能如加载GDT表、切换保护模式,需要loader完成。
1.实模式
概念:
在程序中用到的地址都是真实的物理地址,“段基址:段内偏移地址”产生的逻辑地址就是物理地址,即程序员可见的地址完全是真实的内存地址。
物理地址(physicaladdress)=段值(segment) * 16 + 偏移(offset)
缺点:
- 没有权限划分,实模式下操作系统和用户程序属于同一特权级
- 程序中用到的地址都是真实的物理地址,逻辑地址等于物理地址
- 访问超过 64KB 的内存区域时要切换段基址,16位寄存器,2^16 = 64KB
- 共 20 条地址线,最大可用内存为 1MB
- 平坦模型,无法支持多任务,安全性无法保证
2.保护模式
概念:
保护模式下,全部32条地址线有效,可寻址高达4G字节的物理地址空间。保护模式下,地址表示方式:段(segment):偏移(offset),虽然段值仍然由原来的cs、ds等寄存器表示,但此时它仅仅变成了一个索引,这个索引指向了一个数据结构的一个表项(段描述符),表项中详细定义了段的起始地址、界限、属性等内容。这个数据结构就是全局描述符表GDT(LDT是局部的)。

在实模式下,段地址并非真实的物理地址,在计算物理地址时,还要左移 4 位(乘以 16)。和实模式不同,在 32 位保护模式下,段地址是 32 位的线性地址,如果未开启分页功能,该线性地址就是物理地址。
- 段基址:指定了这个段的起始地址,它是一个32位的值,用于计算线性地址。
- 段界限:段界限符 = 该段的大小。
- G位:G表示段界限粒度大小,假如 G = 1,粒度 = 4kb(最大段界限 = 2 20 ∗ 4 K B = 2 32 2^{20} * 4KB=2^{32} 220∗4KB=232),G = 0,粒度 = 1字节( 2 20 ∗ 1 = 2 20 2^{20} * 1=2^{20} 220∗1=220)。超过段界限,就会触发内存段保护。
- 段类型:需要看两个字段:type和S位。
- S位:S位的作用在于,指示这个段是不是系统段。只有知道了S位,type段才有意义。系统段就是说,这个段由硬件CPU运行,非系统段是由软件(OS/用户)运行。
- S = 1 代码段或数据段的描述符

- S= 0 系统段的描述符

- S = 1 代码段或数据段的描述符
3.分段机制
段描述符表
每个段都需要一个段描述符。这些描述符存储在内存的一段空间中,即全局描述符表GDT(或LDT)。
GDT与LDT的区别:
- 范围不同:GDT 是全局段描述符表,包含系统中所有进程所需的所有段描述符,而 LDT 是局部段描述符表,只有在需要更多段描述符时才使用。
- 使用限制不同:每个进程只能使用一个 GDT,但可以同时使用多个 LDT。
- 加载方式不同:GDT 的基地址和限长保存在 GDTR 寄存器中,由 CPU 加载,而 LDT 的基地址和限长保存在相应进程的 LDTR寄存器中,由操作系统加载,与进程的虚拟地址空间独立。
- 访问速度不同:由于 GDT 存储所有段描述符,因此访问 GDT 通常比访问 LDT 更快。
描述符表的长度可变,最多可以包含8K个这样的描述符(因为段选择子是16位的,其中的13bit用来作index,2^13=8K)。
段选择器
实模式下的 6 个段寄存器 CS、 DS、 ES、 FS、 GS 和 SS,在保护模式下叫做段选择器。
其结构如下图所示

- 第0-1位:请求特权级(Requestor Privilege Level, RPL),用于表示当前代码的特权级别。RPL可以取值0、1、2、3,其中0表示最高特权级,3表示最低特权级。
- 第2位:表指示器(TableIndicator, TI),用于指示该段描述符存储在全局描述符表(GDT)还是局部描述符表(LDT)中。TI的值为0表示描述符存储在GDT 中,为1表示描述符存储在 LDT 中。
- 第3-15位:索引(Index),用于标识段描述符在 GDT 或 LDT中的位置,索引的值必须是 8 的倍数。
段选择子的结构可以通过一个 16 位的寄存器来存储和传递,如 CS(代码段选择子)、DS(数据段选择子)和 SS(堆栈段选择子)等。当 CPU 访问某个段时,它会根据段选择子来确定所需的段描述符的位置,并加载该段描述符以获取相应的段基址、权限和限长等信息,从而实现对这个段的正确访问。

GDT表可以很大,存放在内存中,由 GDTR寄存器 存储它的地址。同理,LDT存储在LDTR中。其中:
- GDTR全局描述符寄存器:48位,高32位存放GDT基址,低16为存放GDT限长。
- 通过 lgdt xxxx 将xxxx存储到 GDTR 寄存器,xxxx包含GDT内存起始地址和GDT界限。
- 通过 sgdt xxxx获得当前 GDTR 寄存器的内容存储到 xxxx 当中。
- LDTR局部描述符寄存器:16位,高13为存放LDT在GET中的索引值。
以此构建GDT表:
[SECTION .gdt]
DATA_SEG_BASE equ (0x1000)
DATA_SEG_LIMIT equ 0xfffffCODE_SEG_BASE equ (0x0)
CODE_SEG_LIMIT equ 0xfffff
; 索引<<3位 = 地址相减 。2^3 = 8字节
CODE_SELECTOR equ (gdt_code - gdt_base) ; 代码段选择子
DATA_SELECTOR equ (gdt_data - gdt_base) ; 数据段选择子gdt_base:dd 0, 0
gdt_code:dw CODE_SEG_LIMIT & 0xffff ; 段界限dw CODE_SEG_BASE & 0xffff ;db CODE_SEG_BASE >> 16 & 0xff; P_DPL_S_TYPE; 其中1表示有效,00表示特权级0,1表示的代码段,1000表示代码段不可读写,可执行db 0b1_00_1_1000; G_DB_AVL_LIMIT; 其中0表示段界限以字节为单,1表示此段是32位的,后四位表示段界限高4位。db 0b0_1_00_0000 | (CODE_SEG_LIMIT >> 16 & 0xf)db CODE_SEG_BASE >> 24 & 0xf
gdt_data:dw DATA_SEG_LIMIT & 0xffffdw DATA_SEG_BASE & 0xffffdb DATA_SEG_BASE >> 16 & 0xff; P_DPL_S_TYPE; ,其中1表示段描述符有效,00表示特权级0,1表示数据段,0010表示数据段可读写。db 0b1_00_1_0010; G_DB_AVL_LIMIT; 其中1表示段界限以4KB作为单位,1表示此段是32位的,后四位表示段界限高4位。db 0b1_1_00_0000 | (DATA_SEG_LIMIT >> 16 & 0xf)db DATA_SEG_BASE >> 24 & 0xfgdt_ptr:dw $ - gdt_base - 1dd gdt_base
寻址流程
寻址流程图下图所示:

分段机制下的虚拟地址由两部分组成,段选择子和段内偏移量。段选择子保存段寄存器里面。段选择子里面最重要的是段号,用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。虚拟地址中的段内偏移量应该位于 0 和段界限之间。如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。
- 1.根据段选择子在段描述表中找到对应的段描述符号。
- 2.根据段描述符获取段基址、段界限、特权等级等。
- 3.根据段基地址和段内偏移量得到物理地址。
根据GDT寻址
当 TI=0时表示段描述符在GDT中

① 先从GDTR寄存器中获得GDT基址。
② 然后再GDT中以段选择符高13位位置索引值得到段描述符。
③ 段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址(程序给出)才得到最后的线性地址。
根据LDT寻址
当TI=1时表示段描述符在LDT中

① 还是先从GDTR寄存器中获得GDT基址。
② 从LDTR寄存器中获取LDT所在段的位置索引(LDTR高13位)。
③ 以这个位置索引在GDT中得到LDT段描述符从而得到LDT段基址。
④ 用段选择符高13位位置索引值从LDT段中得到段描述符。根据位置索引在GDT中得到LDT段描述符从而得到LDT段基址。
⑤ 段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址(程序给出)才得到最后的线性地址。
4.进入保护模式流程
进入保护模式的代码却是千奇百怪的,形式可不统一。比如进入保护模式需要三个步骤。
- 打开 A20
- 加载 gdt
- 将 cr0 的 pe 位置 1
打开 A20
打开A20,避免地址回绕

打开方式:
- 通过键盘控制器
- 调用BIOS功能
- 使用系统端口
in al, 92hor al, 00000010bout 92h, al
加载 gdt
GDT 有两个相关的指令:
- lgdt xxxx:xxxx有6字节,前2字节是一个gdt界限,后4字节是gdt起始地址。将 xxxx 存储到 gdtr
- sgdt xxxx:获得gdtr的值,存储到 xxxx
进入保护模式一定需要加载gdt,首先在loader建立一个GDT,然后将 GDT 的地址、界限存储到 GDTR 寄存器当中。
lgdt [gdt_ptr]
将 cr0 的 pe 位置 1
CR0 寄存器的第0位是 pe位,Protection Enable,用来启动保护模式,是保护模式的开关。所以这一步一般都是最后一步。

PE 为 0 表示在实模式下运行,PE 为 1 表示在保护模式下运行。
mov eax, cr0or eax, 0x00000001mov cr0, eax
5.验证
进入保护模式流程图:

验证方法:
protected_mode:; 设置段寄存器mov ax, DATA_SELECTOR ; 设置数据段选择子为DATA_SELECTORmov ds, ax ; 将数据段寄存器设置为DATA_SELECTOR; 转换为逻辑地址:ds:0xB7000; ds 绑定数据段,基地址为0x1000, 对应的线性地址(物理地址)0xB7000+0x1000 = 0xB8000; 0xB8000对应显存的物理地址,若能超过写入字符; 说明CPU 能够正确地处理地址映射,并且成功进入了保护模式mov byte [0xB7000], 'A'; 测试是否成功进入保护模式.如果没有,写入内存是失败的; 同理逻辑地址为: ds:0x100000; 对应的线性地址(物理地址) 0x101000xchg bx, bxmov byte [0x100000], 0xABjmp $


当前未开启分页,线性地址=物理地址。
相关文章:
02.加载GDT表,进入保护模式
加载GDT表,进入保护模式 加载GDT表,实现操作系统从实模式进入保护模式 参考 操作系统学习 — 启动操作系统:进入保护模式 保护模式与实模式 GDT、GDTR、LDT、LDTR 调用门与特权级 趣谈 Linux 操作系统 在01.硬盘启动盘,加载操作系…...
MySQL(进阶篇3.0)
锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算机资源(CPU、RAM、I/O)的争用之外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...
2023.6.8小记——嵌入式系统初识、什么是ARM架构?
今天还挺充实的,早上在图书馆本来想学一下notion,结果看李沐老师的动手深度学习看到十点半,在电脑上配置了李沐老师的d2l和jupyter,等后续有时间的时候再继续学。 下午看了一下notion的使用方法,这玩意初学者用起来是…...
分布式运用之ELK企业级日志分析系统
1.ELK的相关知识 1.1 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案,将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用, 完成更强大的用户对日志的查询、排序、统计需求。 ElasticSearch: 是基于Lucene(…...
【华为OD机试真题 C语言】8、停车场车辆统计 | 机试真题+思路参考+代码解析
文章目录 一、题目🎃题目描述🎃输入输出🎃样例1🎃样例2 二、思路参考三、代码参考🏆C语言 作者:KJ.JK 🍂个人博客首页: KJ.JK 🍂专栏介绍: 华为OD机试真题汇…...
c++ MES 对接(XML、JSON、SOAP)
🗑️ 清空 //MES系统对接可以使用多种协议,包括XML、JSON和SOAP等。 //以下是使用C语言进行MES系统对接的示例代码: //1. XML协议对接: //c #include <iostream> #include <string> #include <vector> #incl…...
idea导入java web项目带jar
可参考:idea导入Javaweb项目_小黑cc的博客-CSDN博客 配置tomcat 加载项目jar依赖 最后点ok,tomcat启动 jsp页面的项目,必须要加载这两个jar包...
【第55天|● 392.判断子序列 ● 115.不同的子序列 】
392.判断子序列 class Solution { public:bool isSubsequence(string s, string t) {if(s.size()0)return true;if(t.size()0) return false;vector<bool> dp(t.size()1, true);for(int i0; i<s.size(); i){for(int jt.size(); j>0; j--){if(s[i]t[j-1]&&…...
Dockerfile创建镜像
一、Docker镜像的创建 创建镜像有三种方法,分别为【基于已有镜像创建】、【基于本地模板创建】以及【基于Dockerfile创建】。 1.1 基于现有镜像创建 (1)首先启动一个镜像,在容器里做修改docker run -it centos:7 /bin/bash …...
基于 opencv 的人脸识别上课考勤系统,附源码,可作为毕业设计
一、简介 这个人脸识别考勤签到系统是基于大佬的人脸识别陌生人报警系统二次开发的。 项目使用Python实现,基于OpenCV框架进行人脸识别和摄像头硬件调用,同时也用OpenCV工具包处理图片。交互界面使用pyqt5实现。 该系统实现了从学生信息输入、人脸数据…...
.editorconfig 配置
有人会问:既然项目已经使用了 eslint 和 prettier,为什么还需要 EditorConfig? 为什么需要 EditorConfig? .editorconfig 是一个用于定义和维护跨不同编辑器和开发环境的一致编码样式的文件。它可以确保整个团队在使用不同编辑器…...
Spring 高级依赖注入 —— Bean的延迟依赖查找功能,ObjectFactory 和 ObjectProvider
介绍 首先明确一下什么是延迟查找,一般来说通过Autowired注解注入一个具体对象的方式是属于实时依赖查找,注入的前提是要保证对象已经被创建。而使用延迟查找的方式是我可以不注入对象的本身,而是通过注入一个代理对象,在需要用到…...
VSCode--Config
1. basic 1.1 调整字体 1.2 调整 remote login 输入框都在 TERMINAL 中实现 1.3 界面设置成中文 安装插件: 然后配置即可。 2.Linux 2.1 Install 2.1.1 offline Install vscode server 问题描述 内网开发,vscode 自身通过代理安装完 remote 插件后…...
代码随想录刷题第48天|LeetCode198打家劫舍、LeetCode213打家劫舍II、LeetCode337打家劫舍III
1、LeetCode198打家劫舍 题目链接:198、打家劫舍 1、dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。 2、递推公式: 如果偷第i房间,那么dp[i] dp[i - 2] nums[i] …...
C# NTS 获取MuliiLineString中的所有线
/// <summary>/// 获取多段线的所有线/// </summary>/// <param name"ml"></param>/// <returns></returns>public static List<LineString> GetLineStrings(this MultiLineString ml){List<LineString> lineString…...
CodeWhisperer插件使用体验
官方教程点击跳转 使用工具 1.vscode 2.插件(AWS Toolkit),免费使用 安装以后如何使用 1.首先要有一个aws账号 2.插件下载好以后登录aws账号,我们主要用这款插件的CodeWhisperer这个功能,其它的自行看官方教程了解。 注意事项:我们在从vs…...
机器学习笔记 - 多实例学习(MIL)弱监督学习
一、多实例学习概述 多实例学习(MIL)是一种弱监督学习形式,其中训练实例被排列在称为袋的集合中,并为整个袋提供标签。这种方式越来越受到人们的关注,因为它自然适合各种问题,并允许利用弱标记数据。因此,它被应用于计算机视觉和文档分类等不同的应用领域。 多实例学习(…...
SQL Server 2008 定时自动备份和自动删除方法
SQL Server 2008 数据定时自动备份和自动删除方法,同一个计划兼备数据备份数数据删除的操作方法 工具/原料 SQL Server 2008 方法/步骤 1、 点击实例名下的【管理】-【维护计划】-点击鼠标右键,点击【维护计划向导】,填写计划名称&…...
代码生成器实现
代码生成器实现 实现封装元数据的工具类实现代码生成器的代码编写掌握模板创建的 构造数据模型 需求分析 借助Freemarker机制可以方便的根据模板生成文件,同时也是组成代码生成器的核心部分。对于Freemarker而 言,其强调 数据模型 模板 文件 的思…...
【Python基础】Python函数(基本函数)
文章目录 Python函数1、函数多返回值2、函数多种传参方式(1)位置参数(2)关键字参数(3)缺省参数(4)不定长参数位置传递关键字传递 3、小结 Python函数 1、函数多返回值 Q:如果一个函数要有多个返回值,该如何书写代码? # 使用多个变量&#…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...
