linux0.11中jmpi 0,8解析

        系统在执行该行代码时已经为保护模式, jmpi 0,8会将段选择子(selector)载入cs段寄存器,并计算出逻辑地址。

段选择子的结构如下:

段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。

  • index(描述符索引)部分表示对应的段描述符在描述符表(GDT或者LDT)中的位置。然后GDTR或者LDTR中存储的描述符表基址 + index * 段描述符长度 就能得到对应描述符的地址
  • TI表示描述符表的类型,0=GDT,1=LDT
  • RPL--请求等级,有0,1,2,3四个取值,权限从大到小

在jmpi 0,8中,段选择子的值为8。按照二进制表示即为1000,那么

TI = 0          --GDT表
RPL = 0         --内核级访问权限
INDEX = 1       --GDT表第二个元素,从0开始

而段寄存器的格式如下:

Struct SegMent{
WORD	Selector段选择子;//16位selector
WORD	Attribute;//16位的Attribute
DWORD	Base;//32位的Base
DWORD	Limit	//32位的Limit
};

 那么上述的selector会被加载到段寄存器cs的selector部分,而段寄存器的不可见部分相当于缓存,它会将查询到的段的信息(段基值,段限长,可读可写等属性)缓存起来,当下次仍然用同样的段选择子去查询时就不用再查表,就直接用缓存的部分,相当于提高了执行效率,当然这与该文主题没有半毛钱关系,仅仅记录。

接下来就要去GDT表中查找段的信息,那GDT表到底长什么样子?以下是GDT表中元素的排列情况,可以看到内核代码段和数据段描述符分别为GDT表的第二(index=1)和第三(index=2)个元素。

GDT表中每个元素定义如下:

                                                                  图1

 G表示段界限粒度,为0时表示粒度为1字节,为1时表示粒度为4KB,一般置为1

 S表示是否为系统段,为1时表示系统段,为0时表示非系统段

可以看出每个段描述如占用8字节,即4个字

有了以上定义,只要知道其中的数据排列就能得出每个段的段基值和段界限,在源码中找到如下定义:

;// 全局描述符表开始处。描述符表由多个8 字节长的描述符项组成。
;// 这里给出了3 个描述符项。第1 项无用,但须存在。第2 项是系统代码段
;// 描述符(208-211 行),第3 项是系统数据段描述符(213-216 行)。每个描述符的具体
;// 含义参见列表后说明。
gdt:
	dw	0,0,0,0		;// 第1 个描述符,不用。
;// 这里在gdt 表中的偏移量为08,当加载代码段寄存器(段选择符)时,使用的是这个偏移值。
	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9A00h		;// code read/exec
	dw	00C0h		;// granularity=4096, 386
;// 这里在gdt 表中的偏移量是10,当加载数据段寄存器(如ds 等)时,使用的是这个偏移值。
	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9200h		;// data read/write
	dw	00C0h		;// granularity=4096, 386

那么jmpi 0,8中的index=1所指向的段描述符的内容如下:

	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9A00h		;// code read/exec
	dw	00C0h		;// granularity=4096, 386

 按照图1中进行排列,注意按照小端格式排列:

经过组合

                     段基值为  0x00000000 = 0

                     段限长为 0x007FF = 2047, 即2048 * 4KB = 8M

此处为什么要+1,应该是一种约定。另外G=1,就表示段界限单位为4KB.  另外也可以得出段界限的最大空间为

(0xFFFFF + 1) * 4KB = 4GB

那么最后可以得出jmpi 0,8所要跳转到的物理地址为

                 base(0) + ip(0) = 0

此地址处就是操作系统核心的head.s文件存放在内存中的地址。此处的地址需要经过MMU转换吗?系统在现在的执行阶段,其实还没有开启分页机制,那么该0其实就是真实的物理地址。这些都是由CR0寄存器决定的, 可以把它认为是操作系统的动态配置。CR0寄存器格式如下:

 PE(Protection Enable)保护使能是CR0寄存器的第0位(bit 0)。当设置了PE标志时,启用保护模式;当清除PE标志时,启用实地址模式。该标志位并不直接启用分页机制,它仅启用段级别的保护。要启用分页,必须同时设置PE和PG标志。

Paging(分页)标志位是CR0寄存器的第31位。当该位被设置时(为1时),启用分页机制;当该位被清除时(为0时),禁用分页机制。当分页被禁用时,所有线性地址都被视为物理地址。也就是说没有分页机制,段机制通过段基址加偏移后就是真实物理地址,如果PE标志(寄存器CR0的第0位)未设置,PG标志则没有影响;在PE标志被清除时设置PG标志会导致通用保护异常。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

拯救者Legion R9000X 2021(82HN)原装出厂Win10系统镜像ISO下载

lenovo联想拯救者笔记本R9000X 2021款原厂Windows10系统安装包,恢复出厂开箱状态预装OEM系统 链接:https://pan.baidu.com/s/1tx_ghh6k0Y9vXBz-7FEQng?pwd7mih 提取码:7mih 原装出厂系统自带所有驱动、出厂主题壁纸、系统属性联机支持标…

《QT实用小工具·十》本地存储空间大小控件

1、概述 源码放在文章末尾 本地存储空间大小控件,反应电脑存储情况: 可自动加载本地存储设备的总容量/已用容量。进度条显示已用容量。支持所有操作系统。增加U盘或者SD卡到达信号。 下面是demo演示: 项目部分代码如下: #if…

2024 蓝桥打卡Day31

递归与辗转相除法 递归(Recursion)辗转相除法(Euclidean Algorithm)总结 递归(Recursion) 递归是指一个函数在执行过程中调用自身的过程。在编程中,递归函数在遇到满足某个条件时会停止调用自身…

Servlet原理Servlet API

目录 一、Servlet运行原理 1.1、问题 1.2、Servlet的具体执行过程 1.3、Tomcat初始化流程小结 1.4、Tomcat处理请求流程 二、Servlet API详解 2.1、HttpServlet类 2.1.1、处理Get请求 2.2、HttpServletRequest类 2.3、HttpServletResponse类 2.3.1、设置状态码 ​2.…

wsl.conf在windows的什么路径

结论 全局的.wslconfig找不到。 局部的wsl.conf在ubuntu中的/etc/wsl.conf。 官网 https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config .wslconfig 使用 .wslconfig 为 WSL 上运行的所有已安装的发行版配置全局设置。 默认情况下,.wslconfig 文件不存在。…

Hadoop MapReduce

MapReduce分为两个阶段,分为Map阶段和Reduce阶段,可以自定义map函数和reduce函数, map函数的输入是行在文件的字节偏移量,value是文件的一行数据。 reduce函数的输入是key和对应key的value组,然后reduce函数可以对这…

【Linux】SSH协议应用

SSH协议 SSH简介实现OpenSSH ssh中的四个文件~/.ssh文件路径实验解析 SSH 简介 SSH(secure shell)只是一种协议,存在多种实现,既有商业实现,也有开源实现。本文针对的实现是OpenSSH,它是自由软件&#xf…

面试题:RabbitMQ 消息队列中间件

1. 确保消息不丢失 生产者确认机制 确保生产者的消息能到达队列,如果报错可以先记录到日志中,再去修复数据持久化功能 确保消息未消费前在队列中不会丢失,其中的交换机、队列、和消息都要做持久化消费者确认机制 由spring确认消息处理成功后…

字符分类函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h 这些函数的使用方法非常类似,我们就讲解⼀个函数的事情,其他的非常类似: int i…

蓝桥杯速成5-AD/DA模数转换

一、原理图 上图可知该芯片使用的是iic时序,而不是51单片机的xpt2046时序,iic我们都很熟悉了吧 并且大赛还提供了我们iic底层驱动代码 左上角有AIN0-4四个转换输入通道,和AOUT一个输出通道,由控制字节选择 地址字节:0x…

Linux性能分析工具-perf并生成火焰图

1 简介 perf 是一个非常实用且深入的性能分析工具,适用于从底层硬件交互到上层应用程序逻辑的全方位性能剖析。 perf 工具的设计目的是为了帮助开发者和系统管理员分析应用程序以及内核本身的性能,寻找潜在的性能瓶颈,并据此进行针对性的优…

向上转型与向下转型

首先,一个对象在new的时候创建是哪个类型的对象,它从头至尾都不会变。即这个对象的运行时类型,本质的类型用于不会变。但是,把这个对象赋值给不同类型的变量时,这些变量的编译时类型却不同。 7.6.1 为什么要类型转换 …

实景三维技术在推进城市全域数字化转型的作用

4月2日,国家数据局发布《深化智慧城市发展推进城市全域数字化转型的指导意见(征求意见稿)》(下称:《指导意见》),向社会公开征求意见。 《指导意见》作为推进城市数字化转型的重要文件&#xf…

蓝桥杯刷题day09——霓虹【算法赛】

一、问题描述 晚上,小蓝正无聊的走在大路上,小蓝所在的街区是—个带有赛博朋克风格的街区。 他抬头—看,看到了很多霓虹灯牌。在其中的某一个店铺前,挂着一排的数字灯牌,每一个数字的显示都依靠7段LED管,亮着的灯管组成数字,具体来说如下图所示: 小蓝刚学过数字电路,他…

Makefile:调用shell脚本和嵌套调用多项目编译(九)

1、Makefile中调用shell脚本 Makefile中可以通过使用$(shell 指令)的方式调用shell脚本a指令:输出当前文件夹下的所有文件b指令:输出当前路径c指令:如果当前目录下不存在abc文件那么创建一个abc的文件 a$(shell ls ./) b$(shell pwd) filen…

神经网络与深度学习(二)

一、深度学习平台 张量(Tensor) 是一个物理量,对高维(维数 ≥ 2) 的物理量进行“量纲分析” 的一种工具。简单的可以理解为:一维数组称为矢量,二维数组为二阶张量,三维数组为三阶张量 计算图 用“结点”…

Transformer模型-用jupyter演示逐步计算attention

学习transformer模型-用jupyter演示如何计算attention,不含multi-head attention,但包括权重矩阵W。 input embedding:文本嵌入 每个字符用长度为5的向量表示: 注意力公式: 1,准备Q K V: 先 生…

官宣!一文掌握2024百度CreateAI开发者大会最新议程

4月16日上午9:00,以“创造未来”为主题的2024百度Create AI开发者大会将在深圳国际会展中心(宝安)开幕。此次大会将是近十年来,粤港澳大湾区规格最高的AI大会,将聚焦炙手可热的AI话题,在大会主论坛、分论坛…

【JVM】如何定位、解决内存泄漏和溢出

目录 1.概述 2.堆溢出、内存泄定位及解决办法 2.1.示例代码 2.2.抓堆快照 2.3.分析堆快照 1.概述 常见的几种JVM内存溢出的场景如下: Java堆溢出: 错误信息: java.lang.OutOfMemoryError: Java heap space 原因:Java对象实例在运行时持…

Python快速入门系列-10(Python进阶与扩展)

第十章:Python进阶与扩展 10.1 Python与其他语言的整合10.1.1 使用Python的C API示例:使用C API创建一个简单的Python扩展10.1.2 使用Cython加速Python代码示例:使用Cython编写一个快速的矩阵乘法函数10.1.3 使用SWIG创建接口示例:使用SWIG为C++类生成Python接口10.2 Pytho…