手写操作系统--进入保护模式的开篇

news2024/9/29 7:26:32

之前我们讲的主引导扇区以及内核加载器等内容。都是在实模式下运行的。在实模式下寻址范围仅有1M,是远远不够我们用的。我们想要更大的内存空间,就得进入保护模式,实模式是一个历史遗留问题,本身是没有这个名字的。是因为有了保护模式才对原先的8086模式起个名字叫实模式。为何叫保护模式呢,顾名思义,是有些东西想要保护起来。我们回顾实模式,内核和用户程序都跑在同一个内存空间中。地址都是实际的物理地址。分分钟可以修改别人的程序甚至是内核程序。这样做是非常危险的。因此保护模式想在根源上杜绝这些问题因此就有了更多的保护措施。下面我们一一道来。

(1)首先,寄存器的扩展

 如上图所示,实模式下的16位寄存器都变成了32位(除了段寄存器)并且在原先的寄存器名字上多了个E,表示扩展。如果是64位的话扩展名就是R比如说RAX。我们只讨论32位的,64位只是顺带提一句。

下面我们介绍下段寄存器。在原先的实模式下,想访问超过64KB的内存就需要借助段寄存器才能把20跟地址线充分利用,也就是访问1M的内存,公式我们前面介绍过(段寄存器*16+偏移地址)

进入保护模式后,32位的CPU拥有着访问4GB内存的能力,远不是1M能比的,此时不再需要段寄存器来辅助寻址,那这么说段寄存器岂不是没用了?然而并不是,段寄存器在进入保护模式后,叫段选择子,386之后还扩展了两个段寄存器(fs,gs)段选择子如图所示:

这就是段选择子也就是我们实模式下的段寄存器。它的0-1比特位是表示特权级,就是访问权限。保护模式嘛必然加了很多安全的东西。我们知道在intel的架构提供了几种特权级别:

 这样的圈我们也称为环。比如最里面的level 0也叫0环。是权限最高的一个 给操作系统使用的。往外还有1环,2环,3环。但是在现代操作系统(windows,Linux)均没有使用1环2环权限。只使用了0环和3环也就是我们教科书上对应的内核态和用户态,这是权限级别。

讲完了特权级我们回到段选择子中,看到第三个比特位TI,这是表示访问的是GDT还是LDT,如果为1访问的是GDT,如果为0访问的是LDT。至于什么是GDT,LDT后面我们会介绍。,最后就是3-15位比特位。这是一个索引值。用于检索GDT表项。你可以把它理解为是数组的下标索引。GDT也称为全局描述符表,是一个类似于数组的这么一个表。这个表有多大呢,就是我们索引的最大值也就是13个1,也就是8192个(0也算,真实情况下第一个项是全0,能用的其实是8191个):

GDT中的每一项也叫段描述符。段选择子的最大功能就是索引到对应的段描述符。什么是段描述符呢?

 图示就是一个段描述符。这是一个64位的段描述符。里面记录了很多有用的信息。我们现在只需要关注一些重点就可以了。毕竟这么描述符挺复杂的。低32位的16-31比特位与高32位的0-7和24-31共同组成了一个32位的线性地址(这个地址不是真实的物理地址是需要转换的)。低32位的0-15位和高32位的16-19位组成一个20位的界限,记录了这个段的长度。这是最基本的信息,有了这些信息我们就能找到对应的段在什么位置以及它有多长。其次高32位的8-11这4个比特位标识一个类型。会把找到的段标识为数据段还是代码段还是系统段。先介绍这么多。以后有些位我们用到在细说。

可能会很好奇为什么这个段描述符长的这么怪,一个段地址分为三份。那是因为Intel能走到今天这么一个硬件大帝国。靠的就是它的兼容性。为了兼容之前的产品(中间出过一个80286,地址总线24根)那么它的描述符长的就很规范:

 

 这是80386的段描述符:

 段描述符就是这么进化而来的。我们写操作系统的时候用的是80386的段描述符,也就是最后一个图。

x86使用一个寄存器来指GDT表的首地址这个寄存器是GDTR:

我们能操作的指令是:

lgdt  [指针] ;加载GDT
sgdt  [指针] ;保存GDT

下面我们在讲讲A20线:

为了兼容8086,A20线默认是关闭的,想要访问超过实模式下1M的内存,我们必须把这个A20线打开,有兴趣的可以查查这A20的历史,我也不是很懂。

下面上代码:

memory_base equ 0   ;   内存基址=0
memory_limit equ ((1024*1024*1024*4)/(1024*4))-1  ;4G/4K -1
;第一步构建段描述符,相当于C语言定义一个结构体
gdt_base:              ;第1一个 也就是索引为0的是不可用的 全为0
    dd 0, 0
gdt_code:             ;构建代码段,数据段段描述符
    dw memory_limit & 0xffff ;段界限0-15位
    dw memory_base & 0xffff ;基地址的0-16位
    db (memory_base>>16)& 0xff ;基地址16-23位
    db 0b_1_00_1_1_0_1_0 ;存在 - dlp 0 - S _ 代码 - 非依从 - 可读 - 没有被访问过
    ; 4k - 32 位 - 不是 64 位 - 段界限 16 ~ 19
    db 0b1_1_0_0_0000 | (memory_limit >> 16) & 0xf;
    db (memory_base >> 24) & 0xff; 基地址 24 ~ 31 位
gdt_data:
     dw memory_limit & 0xffff; 段界限 0 ~ 15 位
    dw memory_base & 0xffff; 基地址 0 ~ 15 位
    db (memory_base >> 16) & 0xff; 基地址 16 ~ 23 位
    ; 存在 - dlp 0 - S _ 数据 - 向上 - 可写 - 没有被访问过
    db 0b_1_00_1_0_0_1_0;
    ; 4k - 32 位 - 不是 64 位 - 段界限 16 ~ 19
    db 0b1_1_0_0_0000 | (memory_limit >> 16) & 0xf;
    db (memory_base >> 24) & 0xff; 基地址 24 ~ 31 位
gdt_end:
;第二步 定义好gdtr寄存器 参考上图gdtr寄存器的比特位

gdt_ptr:
    dw (gdt_end - gdt_base)- 1
    dd gdt_base
;第三步 定义好段选择子 参考选择子的比特位

code_selector equ (1 << 3) ;这里很巧妙 将变成8 也就是1000 访问索引为1 ,访问的是GDT ,访问的权限是系统级
data_selector equ (2 << 3)   ;2左移3位是10000 10表示索引2 访问GDT , 访问权限是系统级
;第四步 打开A20 启动保护模式
  xchg bx, bx  ; 断点

    cli; 关闭中断

    ; 打开 A20 线
    in al,  0x92
    or al, 0b10
    out 0x92, al

    lgdt [gdt_ptr]; 加载 gdt

    ; 启动保护模式
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; 用跳转来刷新缓存,启用保护模式
    jmp dword code_selector:protect_mode
;第五步 进入保护模式 用保护模式输入超过1M的内存空间

[bits 32] ;告诉编译器进入32位
protect_mode:
    xchg bx, bx; 断点
    mov ax, data_selector
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax; 初始化段寄存器

    mov esp, 0x10000; 修改栈顶

    mov byte [0xb8000], "P"
    mov byte [0x200000], "P"

这些代码全部在内核加载器中实现,我们看看实际效果:

实模式下即将进入保护模式

打开A20 然后加载gdtr寄存器:

 已经进入保护模式:

 开始执行保护模式下的代码:

初始化段寄存器然后屏幕输出:

 原先的L已经被改为了P

接着往0x200000的地址写入一个P:

 我们的实验完成。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/730468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法集训之线性表篇】Day 01

文章目录 题目知识点补充思路分析代码实现运行结果 题目 01.从顺序表中删除具有最小值元素&#xff08;假设唯一&#xff09;并返回被删元素的值。空出位置由最后一个元素填补&#xff0c;若顺序表为空&#xff0c;则显示出错信息并退出运行。 知识点补充 顺序表的特点是逻辑…

CRM系统中AI如何进行销售线索评分?有什么好处(上)

每个公司的TOP销售都是精明的猎手。他们善于从大量潜在客户中挑出最可能购买的&#xff0c;把最好的时间、精力和资源给到高意向客户。意向度差一些的排在后面&#xff0c;在资源分配上也会降低。现在&#xff0c;您可以通过AI来进行线索评分&#xff0c;可以说CRM销售线索评分…

SIP 协议的主要流程

目录 SIP 协议的呼叫模型图 基本呼叫建立流程 基本呼叫拆除流程 经过代理的呼叫建立流程 经过代理的呼叫拆除流程 SIP 协议在软交换 SoftX3000&#xff08;华为推出的一个支持sip协议的交换机设备&#xff09; 流程图 SIP 协议的呼叫模型图 MGC 负责将 PSTN 前向信令映射…

ETHERNET/IP转MODBUS-TCP协议网关

远创智控YC-EIP-TCP 是自主研发的一款 ETHERNET/IP 从站功能的通讯网关。该产品主要功能是将各种 MODBUS-TCP 设备接入到 ETHERNET/IP 网络中。 本网关连接到 ETHERNET/IP 总线中做为从站使用&#xff0c;连接到 MODBUS-TCP 总线中做为主站&#xff08;客户端&#xff09;或从站…

淘上拼/拼上拼/抖上拼分别是什么意思(操作玩法是怎样的及数据采集代码举例)

拼多多店群玩法最常见的就是淘上拼、拼上拼、抖上拼这三种&#xff0c;但是很多的商家都不了解这三种玩法是什么意思&#xff0c;更别提操作了&#xff0c;本期小编就来为你们详细介绍一下。 淘上拼&#xff1a; 传统玩法&#xff1a;通过蓝海词&#xff0c;采集类目爆款商品数…

若依前端,菜单栏切换时刷新问题[页面菜单切换时,页面总是重新刷新,导致页面输入的查询参数重载清空]...

前端页面菜单切换时&#xff0c;页面总是重新刷新&#xff0c;导致页面输入的查询参数重载清空 这样切换时&#xff0c;页面就刷新了&#xff0c;解决方法在这里 1&#xff0c;页面代码&#xff0c;这里指定name name: "Item", 注意 name的首字母必须大写 2&#xff…

密盾科技即将推出同态加密隐私计算开源平台Pinsehub!

密盾科技预计将于8月底正式推出同态加密隐私计算平台Pinsehub-Platform。Pinsehub隐私计算平台将涵盖匿踪查询、隐私求交、联合建模、联合统计、算法容器管理、数据资源管理、数据确权与定价&#xff08;开发中&#xff09;、异构平台互联互通&#xff08;开发中&#xff09;等…

Spring中@Autowired和@Resource的区别:

文章目录 一、Autowired二、Resource三、Autowired和Resource的区别&#xff1a; 一、Autowired Autowired 这个注解呢&#xff0c;是由 Spring 提供的&#xff0c;它可以用来对构造方法、成员变量以及方法参数上进行标注&#xff0c;能够根据对象类型完成自动注入。 public …

Podman下载安装说明以及通过下载mysql镜像

Podman下载地址 Releases containers/podman GitHub csdn下载地址&#xff1a;https://download.csdn.net/download/u010479989/88010018 下载exe会自动添加到环境变量中&#xff0c;下载zip需要手动设置环境变量 初始化命令 podman machine init 这个时候会提示安装wsl&…

[工业互联-15]:Linux操作与实时Linux操作系统RT Linux( PREEMPT-RT、Xenomai)

目录 第1章 Linux操作系统 1.1 什么是Linux操作系统 1.2 Linux操作系统架构 1.3 常见Linux操作系统发行版本 第2章 实时Linux操作系统 2.1 实时性要求 2.2 实时性实现技术的基本思想 2.2 常见发行版方案 2.3 Xenomai和PREEMPT-RT比较 第3章 PREEMPT-RT 3.1 概述 3…

java调用python脚本,json传参方式。

使用python的json.loads()进行解析json数据&#xff0c;如果没有包含双引号&#xff0c;则会解析出错 解决方案1 使用demjson.decode()&#xff0c;安装方式直接百度&#xff0c;就不做过多的说明了 解决方案2 使用json.loads&#xff08;&#xff09;方式解析&#xff0c;…

Jetpack Compose与Accompanist:改变Android UI开发的方式

在Android开发中&#xff0c;UI开发一直是一个重要的部分。Google推出的Jetpack Compose库为开发者提供了一种全新的声明式UI工具&#xff0c;使得UI开发变得更加简单和直观。而Accompanist库则为Jetpack Compose提供了一系列有用的扩展&#xff0c;进一步提升了开发效率。 Jet…

jQuery节点操作

jQuery常用技术 1.jQuery获取元素 2.jQuery与js对象转换 3.jQuery中的遍历方式 4.jQuery中的事件绑定 1. jQuery介绍 1.1 jQuery概述 在JavaScript的使用过程中&#xff0c;存在很多问题&#xff0c;例如&#xff1a;兼容问题(咱不考虑)&#xff0c;元素获取方式单一(只能用基…

抖音矩阵号管理系统源码开发及布局流程

“账号矩阵”运营是一种账号运营的高阶玩法&#xff0c;指一个运营主体同时开设多个平台多个账号利用品牌联动的形式来实现账号之间的相关引流&#xff0c;以账号组的形式实现企业营销价值最大化。那么运营多个账号&#xff0c;短视频平台内容是核心&#xff0c;势必要招募多个…

前端Vue自定义精美宫格菜单按钮组件 可设置一行展示个数 可设置成九宫格 十二宫格 十五宫格

前端Vue自定义精美宫格菜单按钮组件 可设置一行展示个数 可设置成九宫格 十二宫格 十五宫格 &#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13315 效果图如下&#xff1a; # cc-categoryMenu #### 使用方法 使用方法…

js实现 无限层级 树形数据结构

创建数据 const list []; for (let i 0; i < 1000; i 200) {if (i 0) {list.push({ id: i - 1, age: 年龄- (i - 1) });list.push({ id: i, age: 年龄- i, parentId: -1 });} else {for (let index i - 199; index < i; index) {list.push({ id: index, age: 年龄…

LED显示屏出现花屏故障怎么办

LED显示屏出现花屏故障时&#xff0c;可以尝试以下几个步骤来解决问题&#xff1a; 检查电源连接&#xff1a;确保LED显示屏的电源连接正常并牢固。检查电源线、插头和插座&#xff0c;确保它们没有松动或损坏。 检查信号源&#xff1a;检查LED显示屏的信号源&#xff0c;如视频…

现在低代码平台推进阻力那么大,有没有最好的解决办法?

前言 低代码是一种快速设计和开发软件应用程序并且手动编码最少的方法。通过在图形界面中使用可视化建模来组装和配置应用程序&#xff0c;开发人员可以跳过所有基础架构让开发速度提升起来。 一、发现问题 1.“在踏出一步之前&#xff0c;首先考虑能否退回去” 现在低代码平…

ACWing算法基础课

y总说 java不能用Scanner读入,要用Buffer.read();快十倍二十倍; 第一讲 基础算法 包括排序、二分、高精度、前缀和与差分、双指针算法、位运算、离散化、区间合并等内容。 快速排序 一定要先移动end(就是把大数移到右边),后移动start; 否则 先找小数,会出现end start重合…

Python capitalize()函数使用详解,Python首字母大写

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 capitalize 1、返回的是新字符串2、转换规则3、转换列表的元素4、指定位置转换 c…