《Linux0.11源码解读》理解(五) head之开启分页

news2024/10/6 18:27:53

先回顾一下地址长度以及组合的演变:16位cpu意味着其数据总线/寄存器也是16位,但是地址总线(寻址能力)与此无关,可能是20位。可以参考:cpu的位宽、操作系统的位宽和寻址能力的关系_cpu位宽_brahmsjiang的博客-CSDN博客

也就因为寄存器和地址总线位数的不对等,于是16位cpu的寻址方式是: 物理地址=段地址×16+偏移地址。这叫做实模式。但随着历史的演进,cpu已经支持32位(地址总线可以36位)、甚至64位(地址总线可以40位)。为了提升寻址能力和安全性,也为了兼容16位系统,在setup阶段就开始准备从16位实模式往32位保护模式做准备。

在32位保护模式下,段寄存器中存储是段选择子。根据段选择子的索引去查询全局描述符表以获得段描述符,其中存储着基地址物理地址=基地址+偏移地址

一旦开启了分段机制,还要多一步: 

 

程序员写代码时给出的地址叫逻辑地址,其中包含段选择子和偏移地址两部分。通过分段后得到的叫线性地址,线性地址通过分页后得到的叫物理地址。比如我们得到的线性地址是32位,分页机制大概是这样运作的:

线性地址被分为高 10 位、中间 10 位、后 12 位。高 10 位在页目录表中找到一个页目录项,这个页目录项的值加上中间 10 位拼接后的地址去页表中去寻找一个页表项,这个页表项的值,再加上后 12 位偏移地址,就是最终的物理地址。这个过程是由硬件MMU(内存管理单元)完成的。

现在我们继续上一节,将head程序跳转至setup_paging开启分页:

setup_paging:
    mov ecx,1024*5    ;用来计数
    xor eax,eax
    xor edi,edi
    pushf             ;保存所有标志, 这里主要为了DF(方向标志位)
    cld               ;让DF=0,用于串操作指令中。决定内存地址递增
    rep stosd         ;重复执行后面的指令stos。每次执行时从ecx-1,直到ecx=0则结束重复
    mov eax,_pg_dir   ;设置页目录中的项,仅需4个。_pg_dir为页表目录标号(0地址开始)
    mov [eax],pg0+7   ;pg0+7表示:0x00001007,是页目录表中的第1项
    mov [eax+4],pg1+7 
    mov [eax+8],pg2+7
    mov [eax+12],pg3+7
    mov edi,pg3+4092
    mov eax,00fff007h ;16Mb-4096+7 (r/w user,p)
    std
L3: stosd             ;将eax的内容复制到edi,复制4字节,并将edi加/减4个字节
    sub eax,00001000h
    jge L3
    popf
    xor eax,eax
    mov cr3,eax
    mov eax,cr0
    or  eax,80000000h
    mov cr0,eax
    ret

上述代码的意义就是在内存中一次写好页目录表和页表,之后开启cr0寄存器的分页开关。

首先按当前分页机制:

页目录项有10位,最多可以指示1K项的页表
页表项也有10位,最多可以指示1K项的页起始地址
线性地址低12位,最多可以指示4K偏移地址,4K为一个页。
分页后总共可访问的虚拟内存空间为:1024*1024*4K=4G。但当时Linux 0.11认为,总共可使用的内存不会超过16M。于是4(页表数)* 1024(页表项数) * 4KB(一页大小)= 16MB,即1个页目录表 + 4个页表就可搞定。这也就是ecx计数器设为1024*5的原因,意在通过rep stosd将5个页结构全部清0。

接着填写页目录中的项,共有4个页表只需设置4项(页目录和每个页表项本身也占据4K,每项4byte,一共可以设置1k个项/条目)。来看mov [eax],pg0+7
回顾下在实模式下,ds基地址,eax偏移地址所代表的内存单元:ds×16+eax
在保护模式下,ds段选择子,如0x10指向的是全局描述符表中的第二个段描述符(数据段描述符),里面内容中的段基址是 0。exa偏移地址所代表的内存单元:0+eax (这里+4/+8/+12是因为每一项4字节,32位)。
而页目录项结构与页表中项结构一样,"pg0+7"表示:0x00001007,是页目录表中的第1项。则
第1个页表所在的地址 = 0x00001007 & 0xfffff000 = 0x1000
第1个页表的属性标志 = 0x00001007 & 0x00000fff = 0x07,表示该页存在、用户可读写。
于是我们用此方法把所需4个页目录项的地址、属性给设置了。

接着填写页表(非页目录)中的项,共有:4(页表)*1024(项/页表)=4096 项(0 - 0xfff),也即能映射物理内存4096*4K = 16M。
每项内容是:当前项映射的实际物理内存地址+该页的标志。我们从最后一个页表的最后一项始按倒退填写。一个页表的最后一项在页表中的偏移地址是1023*4 = 4092(表项从0到1023,偏移地址=序号*4)。因此最后一页页表的最后一项的位置就是$pg3+4092。这里edi作为stosd的目的地址被写入,充当了地址变量的作用。然后作为16M内存的最后一页的物理地址是16Mb - 4096 = 0xfff000,加上属性标志7,即为0xfff007。这里eax作为stosd的写入内容,每次写入递减0x1000。

等上述内容全部写入完毕,设置页目录基址寄存器cr3的值,即在0x0000处。然后开启分页(cr0 的PG 标志,位31)。大功告成!大概整个内存效果图是这样:

接下来终于可以进入main.c了! 

 

 

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

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

相关文章

C++——map和set(multimap和multiset)

目录 1.关联式容器 2.键值对 3.树形结构的关联式容器 3.1 set 3.1.1 set的介绍 3.1.2 set的使用 3.2 multiset 3.2.1 multiset的介绍 3.2.2 multiset的使用 3.3 map 3.3.1 map的介绍 3.3.2 map的使用 3.4 multimap 3.4.1 multimap的介绍 3.4.2 multimap的使用 …

抖音小店选品攻略:10个技巧助你选择助轻松学会选品技巧

抖音小店是目前非常火爆的电商平台之一,许多商家都希望能在抖音上开设自己的小店。而在开设抖音小店之前,选品是一个非常重要的环节。下面是不若与众总结的一些抖音小店选品技巧,希望能帮助到你。 1. 确定目标受众:在选品之前&…

数据库应用:MySQL高级语句

目录 一、理论 1.常用查询 2.函数 3.进阶查询 二、实验 1.普通查询 2.函数 3.进阶查询 三、问题 1.MySQL || 运算符不生效 四、总结 一、理论 1.常用查询 常用查询包括:增、删、改、查; 对 MySQL 数据库的查询,除了基本的查询外…

(学习笔记-TCP连接断开)建立了连接,但是客户端或服务端出现问题,会怎么样?

客户端突然出现故障 客户端出现故障指的是客户端的主机发生了宕机或者断电的场景。发生这种情况的时候,如果服务端一直不会发送数据给客户端,那么服务端是永远无法感知到客户端宕机这件事的,也就是服务端的TCP连接将一直处于ESTABLISH 状态&…

两巨头强强联手!美国EB-5投资移民新项目侨外出国首发

7月15日,在侨外出国“见证辉煌历史 重启明日新章”的主题活动中,一个全新乡村EB-5投资移民项目——峰堡长岭天然气开发项目正式扬帆起航。 这一项目,由两大行业巨头——侨外出国和CanAm基金强强联手。众所周知,侨外出国是EB-5投资…

并发编程中常见的锁策略

本文介绍一些常见的锁策略。 锁策略是多线程编程中相对进阶的内容,它不仅仅局限于Java,任何和“锁”相关的话题,都可能会涉及到这些内容;即使是别的语言,只要涉及到“锁”,也都会涉及到锁策略。 锁策略的…

px4上传数据waiting for bootloader

输入make px4_fmu-v6c_default upload,出现waiting for bootloader 原因,可能是启动了QGC占用了端口,把QGC关掉,重新上电,就OK了。

C++ 继承与多态的基本用法

目录 1.继承 1.1访问等级 1.2函数遮蔽 2.多态 2.1虚函数 1.继承 有父类,有子类,这种层次关系就叫继承,也就说说子类能从父类哪里继承很多东西,继承这种概念或性质是面向对象程序设计的核心思想之一。 这种继承需要先定义一个父…

TS类型断言、函数重载踩过的坑

任意属性 interface Person {name: string;age?: number;[propName: string]: string;//报错 } let tom: Person {name: Tom,age: 25,gender: male }; 任意属性需要包含确定属性和可选属性的类型:[propName: string]: string|number; 类型断言 👉在…

zabbix企业级监控(监控第二台linux服务器安装部署)接上篇单台监控文章操作

zabbix企业级监控监控linux主机 目录 【agent端配置】(监控第二台linux服务器) 1、源码安装zabbix(解包、编译、配置、安装) 2、改agent配置文件 3、启动服务 图形操作: 【agent端配置】(监控第二台l…

批处理判断目录是否存并且删除非空目录

这个功能很常用,但是偶尔总是忘记写法,这里贴一个亲测通过的例子吧。 ECHO OFF CLS if exist DirName ( rmdir /q /s DirName ) ELSE ( echo dir NOT exist!)这个例子的功能非常简单,判断目录DirName是否存在,存在就删除&#x…

【Linux】多线程(上)

本文详细介绍了多线程的常见概念 生产者消费者模型将在多线程(下)继续讲解 欢迎大家指正 提起讨论进步啊 目录 多线程的理解 线程的优点 线程的缺点: 线程的用途 线程VS进程 用户级线程库 POSIX线程库 线程创建: 线程…

【管理设计篇】聊聊系统部署生产有哪些方式

背景 对于互联网应用来说,除了在服务端开发和服务治理之外,还需要保证的有高可用运维。所以很多时候我们不能仅仅局限于,实现需求这个层面,比如软件设计,工程质量,性能,运维、可测试、可观测性…

基于深度学习的高精度交通标志检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于CCTSDB数据集的高精度交通标志(指示、禁止和警告)检测系统可用于日常生活中来检测与定位交通标志目标,利用深度学习算法可实现图片、视频、摄像头等方式的交通标志目标检测识别,另外支持结果可视化与图片或视…

【react + antd】antd如何自定义请求使用antd的upload组件实现图片上传且可预览可删除

文章目录 1. 效果展示2. customRequest如何使用?特别注意: 3. 控制上传时什么时候使用customRequest,什么时候选择beforeUpload方法? 1. 效果展示 官网给出的案例无法使用封装好的请求方式上传图片,以及无法满足上传图…

使用模板创建【vite+vue3+ts】项目出现 “找不到模块‘vue‘或其相应的类型声明” 的解决方案

问题描述 项目前台需要使用Vue3Ts来写一个H5应用,然后我用模板创建 npm create vitelatest vue3-vant-mobile -- --template vue-ts创建完后进入HelloWorld.vue,两眼一黑 解决办法一 npm i --save-dev types/node然后在tsconfig.json的"compi…

【ARM Cortex-M 系列 1 -- Cortex-M0, M3, M4, M7, M33 差异】

文章目录 Cortex-M 系列介绍Cortex-M0/M0 介绍Cortex-M3/M4 介绍Cortex-M7 介绍Cotex-M33 介绍 下篇文章:ARM Cortex-M 系列 2 – CPU 之 Cortex-M7 介绍 Cortex-M 系列介绍 Cortex-M0/M0 介绍 Cortex-M0 是 ARM 公司推出的一款微控制器(MCU&#xff0…

Golang跨平台UI框架之Wails(二)

上一篇文章我们讲解了如何简单创建一个 wails 的项目,但是现在有很多前端框架我们可以选择,比如: AngularVueSvelteReactLitVanilla各个都是时代的弄潮儿,就看哪一个适合你了,后续的系列都是以Angular为例。 1. 创建Angular模板项目 由于 wails 是没有官方支持Angular的…

代码随想录算法训练营之JAVA|第六天| 454. 四数相加 II

今天是第6天刷leetcode,立个flag,打卡60天。 算法挑战链接 454. 四数相加 IIhttps://leetcode.cn/problems/4sum-ii/ 第一想法 理解题目:找到四个数相加等于0 ——> 找到两个互为相反的数 理解完题目之后,那么我们要做的就…

IP首部报文字段

一、IP首部报文字段 字段如下图所示 二、每个字段的含义 版本 表示 IP 协议的版本。通信双方使用的 IP 协议版本必须一致。目前广泛使用的IP协议版本号为 4,即 IPv4 首部长度 这个字段所表示数的单位是 32 位字长(1 个 32 位字长是 4 字节&#xff0…