保护模式下的内存访问_1

写在前面

本文讨论了在保护模式下访问内存的准备工作以及具体访问流程,还点出了一些细节问题。由于笔者水平有限,文中难免出现纰漏,恳请各位读者指正。

IA-32架构下段寄存器的变化

我们知道,在x86处理器中,段寄存器是16位的,里面存放了段地址。在IA-32架构下,段寄存器仍然是16位的,但是每个段寄存器都配备了一个长度为64位的描述符高速缓存器,这个缓存器对于我们来说是不可见的。这时的段寄存器存放的已经不再是段地址,而是段选择子。此时的段寄存器也称为段选择器。

段选择器

段描述符

在保护模式下,对内存打访问仍然使用段地址和偏移地址的形式,只不过增加了更多的限制。
我们定义一个数据结构来保存段的限制信息:段描述符,段描述符的大小是8字节也就是64位的。这时我们前面所说的描述符高速缓存器的作用就体现出来了:用于存放段描述符,便于我们使用。
接下来,我们看看段描述符中究竟有什么

段描述符结构

描述符中的具体内容先不讲解,以后用到哪个再拿出来讲一讲。

引入段描述符表

一个程序可能有很多个段,这时段描述符高速缓存器就不够用了。所以我们可以把程序的段描述符集中放在内存中,在需要访问对应的段的时候再把段描述符的内容复制到描述符高速缓存器中。这块存放着许多段描述符的内存空间,就是所谓的段描述符表。描述符表又分为全局描述符表(GDT)和局部描述符表(LDT)。全局说明这张表可以为整个软硬件所用,局部说明这张表是用户程序私有的。

段描述符表

编写段描述符表

在保护模式下想要访问一个内存段,必须要先在段描述符表中定义这个段,也就是说我们应该先把这个段的段描述符安装到表中。下面以全局段描述符表为例进行说明。
请牢记,此时我们仍然处于实模式下。想要在实模式下安装段描述符,我们就得把段描述符表的32位线性地址转换为段地址和偏移地址,我们使用除法指令完成这一转换。

写入描述符高速缓存器

但是问题又来了,前文提到过描述符高速缓存器是不可见的,也就是说我们不能操作它,那么我们该如何复制段描述符到其中呢?这时段选择器的作用就体现出来了。因为段描述符表在内存中是连续存放的,我们可以把段描述符表看作一个数组,段选择器中存储的段选择子,就相当于数组的下标。我们使用下标就可以将描述符表中的描述符复制到描述符高速缓存器中。
现在还有一个问题需要解决,CPU怎么知道这张表在内存中的什么位置。在CPU内部,有两个48位寄存器:GDTR和LDTR。它们分别存放了GDT、LDT在内存中的位置和大小。下面以GDTR为例进行说明。

GDTR

从图中我们可以知道一个段描述符表的最大大小为2^16=65536byte=64KB。有因为一个描述符的大小为8个字节,所以一个描述符表最多有8192个描述符,也就是说最多能有8192个段。
GDTR的高32位指明了GDT在内存中的起始地址,也就是编号为0的段描述符的第一个字节的地址。IA-32规定,0号全局段描述符是空的,只是占用8个字节但不保存段描述符。但是这个规定对于局部描述符表(LDT)来说不适用。
我们需要明确,全局段描述符表不是用户程序可以修改的,它一般由操作系统维护。
理论上我们可以把全局段描述符表写在内存的任何地方,但是在进入保护模式之前,我们必须先进入实模式,在实模式下最多只能访问2^20=1MB的内存,所以GDT一般安装在内存起始的1MB范围内。
我们使用lgdt指令来把内存中的内容写入到GDTR中。指令格式如下:

lgdt m  ;m为需要写入GDTR中的内容的有效地址

中途总结一下

以上所说的操作,均是在实模式下完成的。是的,我们仍然处于实模式,以上的操作不过是为进入保护模式所做的准备工作。接下来,我们将让CPU从实模式切换到保护模式。

进入保护模式

经过大量的前期准备工作之后,我们已经十分接近保护模式的大门了,打开这个大门的钥匙就是CR0控制寄存器。
在使用钥匙之前,我们需要关闭原来的中断。保护模式下的中断机制和实模式不同,因此,原有的中断向量表不再适用,而且,必须要知道的是,在保护模式下,BIOS中断都不能再用,因为它们是16位的代码。在重新设置保护模式下的中断环境之前,必须关中断。为此,我们使用如下指令关闭中断:

cli

在CLI指令生效后,EFLAG寄存器中的IF位将被清零,所有外部中断都会被屏蔽,从而保证当前运行的代码不被打断,起到保护代码运行的作用。
接着,我们需要设置CR0寄存器的PE(Protection Enable)位为1,从而正式切换到保护模式。PE位即为CR0寄存器的第0位。

mov eax, cr0
or eax, 1
mov cr0,eax

执行上述指令后,CPU就会进入保护模式。

保护模式下的内存访问

在保护模式下,我们使用一个段中的数据,或者执行一个段中的代码时,就会触发保护模式下的内存访问机制。以使用GDT为例,具体有如下过程。
我们通过段寄存器中存储的段选择子来索引到段描述符表中的具体内存段。我们来看看段选择子结构。

段选择子

第一部分是描述符的索引号,用来在描述符表中选择一个段描述符。TI是描述符表指示器(Table Indicator),TI=0时,表示描述符在GDT中;TI=1时,描述符在LDT中。RPL是请求特权级,表示想要访问这个内存段的程序的级别。
随后,CPU会把段选择子中的索引乘以8,在加上GDTR中的段描述符表基地址,得出段描述符的地址。如果这个地址没有超过GDTR中的界限大小,并且请求访问该内存段的程序权限足够大的话,CPU就自动将找到的描述符加载到不可见的描述符高速缓存部分。
此后,每当有访问内存的指令时,就不再访问GDT中的描述符,直接用当前段寄存器描述符高速缓存器提供线性基地址。有了这个线性基地址,再加上汇编代码中给出的偏移地址,我们就可定位到我们想要的内存地址中去了。

最后

至此,我们已经大致了解了保护模式下的内存访问基本机制。当然,还有诸如特权检查等内容未详细展开。此外,我们还尚未引入分页机制,也没有讨论任务切换的情况。这些内容,我会在后续的文章中展开说明。谢谢大家的观看。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全面预算体系+报表自动化,实现财务数字化

财务需求 1、经营背景 在公司近几年产业高速发展、外部市场环境快速变化的大背景下,决策层对公司的经营管理、分析调度、决策规划需求日益增加,公司内部管理与行业外部监管对财务数据效率与质量要求更为严格。因此,财务部急需通过数字化转型重塑财务工作流程、提升数据处理效…

【MC】脆骨症整合包开服记录

2024年12月,我们伟大的午睡千秋同志租了一台服务器来玩MC,于是一群CS转MC的人出现了。 然而,令人悲伤的是,2025年1月21日,一群从ins来的野蛮匪徒入侵了服务器,并摧毁了这个存档沟槽的匪徒,初升东曦而午睡千秋先生并没有定期备份,也没有写过自动备份脚本,因此这个服务器…

ACM寒假集训第一次专题任务

ACM寒假集训第一次专题任务 一、 题目:Long Loong解题思路: 因为o出现次数由输入的x所决定,可以想到使用一个循环解决。 AC代码: #include<iostream> using namespace std; int main() {int X;cin>>X;cout<<"L";for(int i=1;i<=X;i++){cout…

《CPython Internals》阅读笔记:p336-p352

《CPython Internals》学习第 17天,p336-p352 总结,总计 17 页。 一、技术总结 1.GDB GDB 是 GNU Dbugger 的缩写。 (1)安装 sudo apt install gdb(2)创建 .gdbinit 文件 touch ~/.gdbinitvim ~/.gdbinit(3)配置 .gdbinit 文件 add-auto-load-safe-path /project/cpython注:…

【python脚本】怎么解密navicat的密码(附代码)

1. 平台检查 import platformif platform.system().lower() != windows:print(Please run this script in Windows.)exit(-1)此部分借助platform.system()函数来判断当前操作系统是否为Windows。若不是,就输出提示信息并终止程序。 2. 导入必要的库 import sys, winreg from C…

### 深入敏捷之道:PSM认证与高效实践的结合

深入敏捷之道:PSM认证与高效实践的结合​ 在敏捷开发的世界中,Scrum因其灵活性和高效性成为全球最受欢迎的框架之一。而PSM(Professional Scrum Master)认证则是验证敏捷实践者专业能力的重要指标,不仅能提升个人职业竞争力,还能帮助团队更高效地实现目标。 Professional…

9. SpringCloud Alibaba Sentinel 流量控制、熔断降级、系统负载,热点规则的部署设置讲解

9. SpringCloud Alibaba Sentinel 流量控制、熔断降级、系统负载,热点规则的部署设置讲解 @目录9. SpringCloud Alibaba Sentinel 流量控制、熔断降级、系统负载,热点规则的部署设置讲解1. Sentinel 是什么?2. Sentinel 控制台3. Sentinel 下载&安装&运行4. Sentine…

MySQL训练营-慢查询诊断问题

慢查询相关参数和建议配置 slow_query_log + long_query_time 日志开关,是否记慢查询日志以及超过多长时间判定为慢查询。 查看参数设置:SHOW VARIABLES LIKE slow_query_log; SHOW VARIABLES LIKE long_query_time;实践建议:set global long_query_time=1; 分析型业务,set…

并发编程 - 线程同步(一)

线程同步确保多线程环境下共享资源安全使用,避免竞争条件和数据不一致。实现方式有避免资源共享、用户模式同步、内核模式同步和混合模式同步。经过前面对线程的尝试使用,我们对线程的了解又进一步加深了。今天我们继续来深入学习线程的新知识 —— 线程同步。01、什么是线程…

API接口开发设计

写接口看似是一个很简单的事情,但是往往越简单的事情越不容易做好,让我们看看如何写好一个接口。 01. 什么是接口 接口其实是一种规范,在生活中随处可见,比如:不同厂商的水管使用统一的水管接口对接、电脑厂商和配件厂商按照统一的 USB 接口标准进行生产完成配对、应用程序…

FZU ACM寒假集训专题一

只有前四题是自己做的,都ac。 做题思路: 前三题比较简单。第四题想法是,一个一个读字母,按照asc码值分别存储个数,用轮数减个数得出还缺几个,最后加在一起。 中间因为不清楚scanf,让getchar读到换行符出错了。 学习总结: 本专题学习了时空复杂度的计算,c++语法糖,还有…

谷歌泰坦:Transformer之后的AI时代?

介绍 2017年,谷歌发布了一篇具有革命性意义的论文,题为《Attention is All You Need》(注意力是你所需要的一切)。这篇论文引发了我们今天所经历的AI革命,并引入了Transformer模型。Transformer已经成为如今几乎所有顶级大型语言模型(LLM)的核心架构。 Transformer的优势…