分页机制总结

【0】写在前面(分页机制)

  • 0.0) source code from orange’s implemention of a os and text description from Zhaojiong’s perfect analysis of Linux kernel and for complete code ,please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/p67.asm
  • 0.1)本代码旨在演示 怎样开启分页机制 + 怎样构建页目录和页表
  • 0.3)本文 只对 与 分页机制的 代码进行简要注释,言简意赅;
  • 0.4) 为了让广大小白(像我一样对os分页机制不觉明里的小白)真真切切了解分页机制,即使这篇文章是转载自 “0.0” 中的两本,但我还是将本文归为原创以推荐到博客首页;(版权,我已在0.0中声明了)

; ==========================================
; pmtest6.asm
; 编译方法:nasm pmtest6.asm -o pmtest6.com
; ==========================================%include    "pm.inc"    ; 常量, 宏, 以及一些说明PageDirBase  equ    200000h ; 页目录开始地址: 2M
PageTblBase  equ    201000h ; 页表开始地址: 2M+4Korg 0100hjmp    LABEL_BEGIN[SECTION .gdt]
; GDT
;                            段基址,       段界限, 属性
LABEL_GDT:           Descriptor 0,              0, 0     ; 空描述符
LABEL_DESC_NORMAL:   Descriptor 0,         0ffffh, DA_DRW    ; Normal 描述符

; 页目录描述符 [add]

LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW;Page Directory

; 页表描述符 [add]

LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 1023, DA_DRW|DA_LIMIT_4K;Page TablesLABEL_DESC_CODE32:   Descriptor 0, SegCode32Len-1, DA_C+DA_32    ; 非一致代码段, 32
LABEL_DESC_CODE16:   Descriptor 0,         0ffffh, DA_C  ; 非一致代码段, 16
LABEL_DESC_DATA:     Descriptor 0,      DataLen-1, DA_DRW    ; Data
LABEL_DESC_STACK:    Descriptor 0,     TopOfStack, DA_DRWA + DA_32  ; Stack, 32 位
LABEL_DESC_VIDEO:    Descriptor 0B8000h,   0ffffh, DA_DRW    ; 显存首地址
; GDT 结束GdtLen   equ    $ - LABEL_GDT  ; GDT长度
GdtPtr   dw GdtLen - 1  ; GDT界限dd    0    ; GDT基地址; GDT 选择子
SelectorNormal   equ    LABEL_DESC_NORMAL   - LABEL_GDT
SelectorPageDir  equ    LABEL_DESC_PAGE_DIR - LABEL_GDT
SelectorPageTbl  equ    LABEL_DESC_PAGE_TBL - LABEL_GDT
SelectorCode32   equ    LABEL_DESC_CODE32   - LABEL_GDT
SelectorCode16   equ    LABEL_DESC_CODE16   - LABEL_GDT
SelectorData     equ    LABEL_DESC_DATA  - LABEL_GDT
SelectorStack    equ    LABEL_DESC_STACK    - LABEL_GDT
SelectorVideo    equ    LABEL_DESC_VIDEO    - LABEL_GDT
; END of [SECTION .gdt][SECTION .data1]     ; 数据段
ALIGN   32
[BITS   32]
LABEL_DATA:
SPValueInRealMode   dw  0
; 字符串
PMMessage:   db "In Protect Mode now. ^-^", 0   ; 进入保护模式后显示此字符串
OffsetPMMessage  equ    PMMessage - $$
DataLen  equ    $ - LABEL_DATA
; END of [SECTION .data1]; 全局堆栈段
[SECTION .gs]
ALIGN   32
[BITS   32]
LABEL_STACK:times 512 db 0TopOfStack  equ $ - LABEL_STACK - 1; END of [SECTION .gs][SECTION .s16]
[BITS   16]
LABEL_BEGIN:mov    ax, csmov    ds, axmov    es, axmov    ss, axmov    sp, 0100hmov    [LABEL_GO_BACK_TO_REAL+3], axmov    [SPValueInRealMode], sp; 初始化 16 位代码段描述符mov    ax, csmovzx  eax, axshl    eax, 4add    eax, LABEL_SEG_CODE16mov    word [LABEL_DESC_CODE16 + 2], axshr    eax, 16mov    byte [LABEL_DESC_CODE16 + 4], almov    byte [LABEL_DESC_CODE16 + 7], ah; 初始化 32 位代码段描述符xor    eax, eaxmov    ax, csshl    eax, 4add    eax, LABEL_SEG_CODE32mov    word [LABEL_DESC_CODE32 + 2], axshr    eax, 16mov    byte [LABEL_DESC_CODE32 + 4], almov    byte [LABEL_DESC_CODE32 + 7], ah; 初始化数据段描述符xor    eax, eaxmov    ax, dsshl    eax, 4add    eax, LABEL_DATAmov    word [LABEL_DESC_DATA + 2], axshr    eax, 16mov    byte [LABEL_DESC_DATA + 4], almov    byte [LABEL_DESC_DATA + 7], ah; 初始化堆栈段描述符xor    eax, eaxmov    ax, dsshl    eax, 4add    eax, LABEL_STACKmov    word [LABEL_DESC_STACK + 2], axshr    eax, 16mov    byte [LABEL_DESC_STACK + 4], almov    byte [LABEL_DESC_STACK + 7], ah; 为加载 GDTR 作准备xor    eax, eaxmov    ax, dsshl    eax, 4add    eax, LABEL_GDT   ; eax <- gdt 基地址mov    dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址; 加载 GDTRlgdt   [GdtPtr]; 关中断cli; 打开地址线A20in al, 92hor al, 00000010bout    92h, al; 准备切换到保护模式mov    eax, cr0or eax, 1mov    cr0, eax; 真正进入保护模式jmp    dword SelectorCode32:0  ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0  处;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LABEL_REAL_ENTRY:    ; 从保护模式跳回到实模式就到了这里mov    ax, csmov    ds, axmov    es, axmov    ss, axmov    sp, [SPValueInRealMode]in al, 92h  ; ┓and    al, 11111101b   ; ┣ 关闭 A20 地址线out    92h, al  ; ┛sti     ; 开中断mov    ax, 4c00h   ; ┓int    21h  ; ┛回到 DOS
; END of [SECTION .s16][SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS   32]LABEL_SEG_CODE32:

; 开启分页机制的初始化工作,该指令执行后,cpu即可开启分页机制[add]

 call   SetupPagingmov    ax, SelectorDatamov    ds, ax   ; 数据段选择子mov    ax, SelectorVideomov    gs, ax   ; 视频段选择子mov    ax, SelectorStackmov    ss, ax   ; 堆栈段选择子mov    esp, TopOfStack; 下面显示一个字符串mov    ah, 0Ch  ; 0000: 黑底    1100: 红字xor    esi, esixor    edi, edimov    esi, OffsetPMMessage    ; 源数据偏移mov    edi, (80 * 10 + 0) * 2  ; 目的数据偏移。屏幕第 10 行, 第 0 列。cld
.1:lodsbtest   al, aljz .2mov    [gs:edi], axadd    edi, 2jmp    .1
.2: ; 显示完毕; 到此停止jmp    SelectorCode16:0

; [add]启动分页机制 ————————————————————–

SetupPaging:

; 为简化处理, 所有线性地址对应相等的物理地址.
; 首先初始化页目录

 mov    ax, SelectorPageDir ; 此段首地址为 PageDirBasemov    es, axmov    ecx, 1024    ; 共 1K 个表项xor    edi, edixor    eax, eaxmov    eax, PageTblBase | PG_P  | PG_USU | PG_RWW ; PageTblBase equ 201000h 页表开始地址: 2M+4K

; 这里是在初始化页目录中项的内容,即对应页表的内存地址

.1: stosd 

;stosb, stosw, stosd 把al/ ax/ eax的内容存储到 es:edi 指向的内存单元中, 该指令执行后,edi自增1

 add    eax, 4096    

; 为了简化, 所有页表在内存中是连续的.,每个页表占用4k字节空间

 loop   .1

; 初始化页目录的项内容 over
; 再初始化所有页表 (1K 个, 4M 内存空间)的项内容,即页表的项存储的是内存地址的高20位地址;

 mov    ax, SelectorPageTbl ; 此段首地址为 PageTblBasemov    es, axmov    ecx, 1024 * 1024    ; 共 1M 个页表项, 也即有 1M 个页 (因为1k个页目录项,每个目录项映射到1k个页表项)xor    edi, edixor    eax, eaxmov    eax, PG_P  | PG_USU | PG_RWW
.2:stosdadd    eax, 4096    ; 每一页指向 4K 的空间loop   .2

; 初始化页表的项内容 over

 mov    eax, PageDirBase

; 加载页目录的基地址到 cr3

 mov    cr3, eax

; 设置cr0的PG位=1,开启分页机制

 mov    eax, cr0or eax, 80000000hmov    cr0, eaxjmp    short .3
.3:nopret

; 分页机制启动完毕 ———————————————————-

SegCode32Len    equ $ - LABEL_SEG_CODE32
; END of [SECTION .s32]; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式
[SECTION .s16code]
ALIGN   32
[BITS   16]
LABEL_SEG_CODE16:; 跳回实模式:mov    ax, SelectorNormalmov    ds, axmov    es, axmov    fs, axmov    gs, axmov    ss, axmov    eax, cr0and    eax, 7FFFFFFEh   ; PE=0, PG=0mov    cr0, eaxLABEL_GO_BACK_TO_REAL:jmp    0:LABEL_REAL_ENTRY  ; 段地址会在程序开始处被设置成正确的值Code16Len   equ $ - LABEL_SEG_CODE16; END of [SECTION .s16code]

3.3 页式存储总结

分段机制将逻辑地址转换成线性地址,线性地址通过分页机制转换成物理地址。
这里写图片描述
为什么使用分页?(干货)
分页管理机制的目的在于实现虚拟存储器,线性地址中的任意一个页都能映射到物理地址中的任何一个页,使得内存管理机制特别灵活。
分页和分段的最大不同之处在于?(干货)

  • 1)段的长度不固定: 段的长度通常与存放在其中的代码和数据结构具有相同的长度;
  • 2)页面长度固定:页面具有固定的长度;
  • 3)如果仅使用分段地址转换:那么存储在物理内存中的一个数据结构将包含所有的部分;
  • 4)如果使用了分页,那么一个数据结构就可以一部分存储在物理内存中,一部分存储在磁盘上(虚拟存储器);
  • 5)为了减少地址转换所要求的总线总起数量,最近访问的页目录和页表会被存放在处理器的缓冲器件中,该缓冲器件被称为TLB(translation lookaside buffer,翻译后备缓冲寄存器),提高访存效率;

3.3.1 分页机制概述

这里写图片描述
Why-为什么使用两极页表结构?

  • w1)页表含有2^20(1M)个表项,每项占4字节。如果用一个表来存储的话,将最多占用4M;为减少内存占用量,X86使用了两极页表;
  • w2)每个,仅有一个页目录占用4k, 每个页表占用4k,而要知道页目录一定常驻内存,而页表是在需要的时候才占用内容空间,当然常用的页表会存储在TLB中,这在一定程度上减少了
    页表机制进行线性地址与物理地址映射所占用内存空间;(干货)

  • 1)第一级页表——页目录(bit31~22):页目录项存储的内容是页表的基地址(高20位存储页表基地址,低12位存储所指向的页表属性)(干货); 它被存放在1页4k页面中, 含有1k个4字节长度的表项,通过线性地址的bit31~22进行索引页目录表项;

  • 2)第二级页表——页表(bit21~12):页表项存储的内容是物理页的基地址(高20位存储物理页基地址,低12位存储物理页属性)(干货); 它被存放在1页4k页面中,含有1k个4字节长度的表项,而该页表的表项由 bit21~12进行定位;

  • 3)偏移地址(bit11~0):它存储的是物理页的第12位地址(干货); 把页表项存储的高20位地址作为物理页的高20位地址,而偏移地址12位作为物理页的低12位地址,这样就得到了32位的物理地址;

  • 4)映射到的物理地址空间:页长4k,总共有1k个页目录项,每个页目录项映射一张页表,每张页表有1k个页表项;故总共1k * 1k =1M个页表项;所以物理地址空间=1M * 4k = 4G

(you should know):
Y1)页目录的基地址存储在cr3中;
Y2)开启分页机制,要设置cr0的最高位PG位=1;

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

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

相关文章

python程序填空题参照代码模板、完善代码_python二级考试操作题11.pdf

综合应用题参照代码模板完善代码&#xff0c;实现下述功能。文件ngchina.html 保持了网页源代码&#xff0c;请将该页面中图片的URL 提取出来,并输出所有图像的URL。习题讲解#P301#读取HTML 文件内容def getHTMLlines(htmlpath):f open(htmlpath,"r",encoding utf-…

Struts2学习笔记

文章目录Struts2 的核心开发包Struts2 配置文件Struts2 域对象Struts2 编程流程Action 组件使用通配符配置 ActionAction 中如何访问 Session通过 ActionContext 对象访问 Session 对象&#xff08;不推荐&#xff09;通过实现 SessionAware 接口访问 sessionAction 如何访问 r…

如何从文件系统中读取文件内容

【0】写在前面 0.0&#xff09; text description from orange’s implemention of a os &#xff0c;文末总结系个人臆测出的干货 【1】intro to FAT12&#xff08;file allocation table 12&#xff09;文件系统格式&#xff08;from Baidu Baike&#xff09; &#xff08;…

java微服务,微在哪_Java:ChronicleMap第3部分,快速微服务

java微服务,微在哪标准Java Maps需要在启动时进行初始化。 了解如何利用可从文件初始化的ChronicleMaps并显着减少微服务启动时间&#xff0c;以及如何在JVM之间共享Maps。 内置的Map实现&#xff08;例如HashMap和ConcurrentHashMap速度很快&#xff0c;但是必须先使用映射进…

excel离散度图表怎么算_Excel数据分析——离散值排除-excel直方图

今天举例的数据继续沿用昨天做出来的结果&#xff0c;至于这组数据还要接着用多久~~可能要混到我讲不下去为止吧~~~我们通过两个不同的拟合公式得到了两组不同的残差值&#xff0c;数据情况如下&#xff1a;有没有觉得看上面那张散点图有点糊啊&#xff1f;没错&#xff0c;问题…

drools dmn_Drools DMN最新开源引擎性能改进

drools dmn我们一直在寻求改善Drools DMN开源引擎的性能。 我们最近审查了DMN用例&#xff0c;其中输入数据节点的实际输入总体有所不同。 这突出显示了引擎的次佳性能&#xff0c;我们在最新版本中对此进行了改进。 我想分享我们的发现&#xff01; 基准制定 当我们开始为此用…

制作FAT12软盘以查看软盘的根目录条目+文件属性+文件内容

【-1】Before for specific info , please visit http://wiki.osdev.org/Loopback_Device 【0】我们先上干货&#xff0c;看到效果后&#xff0c;我们再说明每个步骤的缘由&#xff1b; 【1】进入挂载目录&#xff0c;添加相关文件&#xff08;依个人意愿&#xff09; Attenti…

如何取消高亮显示重复项_如何将重复数据突出显示?

将表格中一列数据中重复的&#xff0c;使用特殊颜色突出显示或者使用一些符号标记出来。例如&#xff1a;一个供应商&#xff0c;可以邀请别的供应商加入成为联合体&#xff0c;报表要显示所有供应商&#xff0c;然后供应商最后一列显示所有联合体&#xff0c;当联合体供应商跟…

Maven的maven-source-plugin插件详解

maven-source-plugin 这个插件专门负责将项目源文件打成包的&#xff0c;该插件在 pom.xml 中的配置如下&#xff1a; <build><plugins><plugin><artifactId>maven-source-plugin</artifactId><version>3.0.1</version><configu…

Maven Java Web Project打包详解/如何打包

文章目录打包部署构件&#xff08;Artifacts&#xff09;打源码包方式一&#xff1a; 命令行方式方式二&#xff1a;使用 IDE将源码包发布到本地 Maven 仓库中涉及到案例项目的结构&#xff1a; 打包部署构件&#xff08;Artifacts&#xff09; war 格式的部署构件可以直接放…

四位共阳极数码管显示函数_数码管模块.doc

数码管模块数码管1、概 述数码管模块采用四位共阳极数码管&#xff0c;用于显示数字和少数特殊字符。可以在机器人项目中使用该模块&#xff0c;用于显示速度、时间、分数、温度、距离等传感器的值。同时&#xff0c;Makeblock提供易于编程的Arduino库&#xff0c;使用户能够方…

java中的可检查和不检查_检查Java测试中发生了什么

java中的可检查和不检查有人想到了在Java单元测试中使用try和catch块的想法&#xff1a; Test public void test() { try { callSomeCode(); } catch (Exception e) { assertEquals( "foo" , e.getMessage()); } } 上面的内容很诱人&#xff0c;但不起作用 。 如果…

FAT12中,如何定位大于一个扇区(512B)的文件内容

【0】README 0.1&#xff09;本文旨在于 演示在FAT12中&#xff0c; 如何取定位大于 512B 的文件内容&#xff0c;和查看它&#xff1b;0.2&#xff09;如何制作FAT12文件系统&#xff0c;以及如何向文件中添加temp.txt文件&#xff0c;参见&#xff1a; { http://blog.csdn.n…

通过Struts2的拦截器实现文件上传/上传文件功能

struts.xml配置内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN""http://struts.apache.org/dtds/struts-2.3.dtd&qu…

java获取ram_Java:ChronicleMap第2部分,超级RAM映射

java获取ram诸如无处不在的HashMap类的标准Java Map最终受到可用RAM的限制。 阅读本文并了解如何创建几乎无限大小甚至超过目标计算机RAM大小的Java Map。 内置的Map实现&#xff0c;例如HashMap和ConcurrentHashMap &#xff0c;只要它们相对较小&#xff0c;就可以正常工作。…

lifi与wifi的论文_Wifi_(毕业论文).doc

Wifi_(毕业论文)绪论2第一章 Wi-Fi技术概述31.1 无线局域网络31.1.1 IEEE 802.11系列标准31.1.2 无线局域网络概述31.2 Wi-Fi概念的引入41.2.1 Wi-Fi技术41.2.2 怎样使用Wi-Fi41.2.3 谁可以使用Wi-Fi5第二章 Wi-Fi技术的分析62.1 Wi-Fi与其他技术的对比分析6参 考 文 献8绪论Wi…

os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)

【0】README 0.1&#xff09; 本代码旨在演示 在boot 代码中&#xff0c;如何 通过 loader文件所在根目录条目 找出该文件的 在 软盘所有全局扇区号&#xff08;簇号&#xff09;&#xff0c;并执行内存中的 loader 代码&#xff1b;0.2&#xff09; 此代码非常重要&#xff0…

Struts2的资源文件和国际化(i18n)

文章目录资源文件的命名资源文件基名的指定struts.xml 文件指定资源文件的基名struts.properties 文件指定资源文件的基名通过标签 i18n 指定资源文件的基名资源文件的位置包级资源文件类级资源文件全局级资源文件默认资源文件资源文件的加载顺序Action 中加载资源文件在 JSP 中…

java设计模式之装饰模式_Java中的装饰器设计模式

java设计模式之装饰模式装饰器设计模式允许在运行时将附加职责或行为动态附加到对象。 它是一种结构模式&#xff0c;利用聚合来组合这些行为。 在本教程中&#xff0c;我们将学习实现装饰器模式。 UML图&#xff1a; 让我们从装饰器模式的UML表示开始&#xff1a; Concrete…

qml 自定义消息框_Qt qml 自定义消息提示框

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/a844651990/article/details/78376767Qt qml 自定义消息提示框QtQuick有提供比较传统的信息提示框Mes…