zoukankan      html  css  js  c++  java
  • MIT-JOS系列1:实模式和保护模式下的段寻址方式

    实模式下的段寻址

    以8086为例

    8086 段寄存器16位(段地址/基地址),寄存器16位(偏移地址),地址总线20位(寻址1M:2^20)

    实际物理地址 = (段寄存器 << 4) + 偏移地址

    1554258444489

    访问到的是实地址。

    段内最大64K(2^16),但一个段可以小于64K:

    在编程时可以根据需要,将若干个地址连续的内存单元看做一个段,用段地址×16定位段的起始地址(基地址),用偏移地址定位段中的内存单元

    如下图所示,我们可以认为:地址10000H~100FFH的内存单元组成一个段,该段的起始地址(基础地址)为10000H,段地址为1000H,大小为100H;我们也可以认为地址10000H~1007F、10080H~100FHH的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和10080H,段地址为:1000H和1008H,大小都为80H

    1554258609212

    寻址方式:

    MOV AX, [SI] : PA(物理地址) = DS:SI

    MOV AX, [1234H] : PA = 段地址 + 直接地址

    默认段地址都使用DS,也可以指定为CS、SS、ES:

    MOV AX, ES:[1234H] : 段地址使用ES

    注意!!

    在实模式下(包括32位等),内存寻址方式与8086相同,基地址16位移4位后加上偏移地址形成20位物理地址,最大寻址空间为1MB,与32位的保护模式基地址不需要左移不一样

    1. 在实模式下最大寻址空间时1M,1M以上的内存空间在实模式下不会被使用
    2. 在实模式所有的内存数据都可以被访问。不存在用户态、内核态之分
    3. 在BIOS加载、MBR、ntdlr启动阶段都处在实模式下

    保护模式下的段寻址

    80286时代地址总线位数增加到24位,可访问16MB,80386为4GB

    引入保护模式

    • 保护模式:在执行多任务操作时,对不同任务使用的虚拟存储器空间进行完全的隔离,保护每个任务顺利执行

    在保护模式下,分段机制是利用一个称作段选择子的偏移量到全局描述符表中找到需要的段描述符,而这个段描述符中就存放着真正的段的物理首地址,然后再加上偏移地址量便得到了最后的物理地址

    • 在32位平台上,段物理首地址和偏移址都是 32 位的,实际物理地址的计算不再需要将段首地址左移 4 位了,直接相加即可,如果发生溢出的情况,则将溢出位舍弃

    段描述符:段物理首地址(32位)、段界限(20位)、段属性(12位)

    全局描述符表:(数组)维护段描述符结构体

    段选择子:对应段描述符结构体在全局描述符表中的下标

    保护模式寻址:xxxx(16位的索引): yyyyyyyy(32位的偏移量)

    80386及其以后的处理器用寄存器 GDTR专门存储全局描述符表在内存中的位置

    GDTR共48位:32位记录描述符表的物理地址,16位记录描述符表的长度(字节数)

    1554270606818

    1554259183673

    段描述符结构如下图:

    1554260331081

    段基址为 2,3,4,7 字节,共 32 位。段限长为 0,1 以及 6 字节的低四位,共 20 位

    G:段限长粒度,G = 0 时,粒度为 1B,G = 1 时,粒度为 1 页(4KB)

    D/B:对于不同类型段含义不同。在可执行代码段中,这一位叫做 D 位,D = 1 使用 32位地址和 32/8 位操作数,D = 0 使用 16 位地址和 16/8 位操作数。在向下扩展的数据段中,这一位叫做 B 位,B = 1 段的上界为 4GB,B = 0 段的上界为 64KB。在描述堆栈段的描述符中,这一位叫做 B 位,B = 1 使用 32 位操作数,堆栈指针用 ESP,B = 0 使用 16 位操作数,堆栈指针用 SP。

    • 个人理解: G、D/B的存在以及段地址、段限长的奇妙分布是为了兼容80286和80386,因为80286的段地址24位,寄存器16位。G、D/B为0时表示80286

    实模式下 PA = ES:偏移 = ES存放的段基址 + 偏移地址

    保护模式下 PA = ES:偏移,ES存放的是段选择子(16位的索引),根据段选择子从GDT表中找到段描述符的段基址,然后偏移

    保护模式下的地址形成

    1554273035637

    1. 将48位逻辑地址xxxx(16位的索引): yyyyyyyy(32位的偏移量)转化为32位的线性地址(称为分段,由分段部件SU完成)
    2. 将32位的线性地址转化为32位的物理地址(称为分页,由分页部件PU完成)
    • 索引*8:一个段描述符八字节,GDT中存放的是完整的段描述符,索引只是给出它的序号

    CR0:0位PE,是否进入保护模式(1进入);31位PG,是否启动分页(1启动)

    • 逻辑地址:程序中给出的地址,如 MOV EAX, [12345678],逻辑地址为 DS:[12345678],DS存放段选择子(16位的索引)

    • 线性地址:由段转换得到的地址 4GB

    • 物理地址:地址总线上的实际物理内存地址 4GB

    段选择子(段寄存器DS的值):

    1554271672069

    • RPL:请求特权级(2位),构成选择子的特权,0最高,3最低

    • TI:描述符表指示器,0选择全局描述符表(GDT),1选择局部描述符表(LDT)

    • 索引:描述符所在地址(13位),可指示2^13=8K个描述符

      因此虚拟地址空间最大为2^13 *2*2^32=64TB

    例1:

    1554273646611

    已知:GDT和LDT的首地址分别为55600000H和00013000H,FS=000BH,CR3=00013000H , ESI=0000125AH,内存有关数据如图所示。执行指令MOV EAX,FS:[ESI],求:

    1. PE=0时源操作对应的物理地址及EAX中的值
    2. PE=1且PG=0时源操作对应的物理地址及EAX中的值
    3. PE=1且PG=1时源操作对应的物理地址及EAX中的值

    CR0:0位PE,是否进入保护模式(1进入);31位PG,是否启动分页(1启动)

    (1)PE=0,工作在实模式下,因此物理地址=基地址×16+偏移地址=FS<<4+ESI=00B0H+0000125AH=0130AH,故读出数据EAX=49102512H

    (2)PE=1且PG=0,工作在保护模式,不开启分页,FS=000BH=0000 0000 0000 1011,PRL=3,TI=0,索引=1,因此从GDT中寻找段描述符首地址=GDT首地址+索引×8=55600000H+1×8H=55600008H,**读出段描述符内容(共8字节) ** 01444900700001FFH,根据图1-4,第2,3,4,7个字节为基地址,因此基地址=01007000H,物理地址=基地址+偏移地址=01007000H+0000125AH=0100825AH,故读出数据EAX=12009966H

    (3)详解见例2

    保护模式下中断的管理

    中断向量表的基地址存放在IDTR寄存器中

    页式存储器地址映像与变换

    页式存储器将地址转换得到的线性地址**(虚拟地址)转化为物理地址**,即上文所说的分页过程

    CR0的31位PG置1表示开启分页模式

    • 主存和辅存空间都分别划分为多个相同尺寸的定长块,每块称为一页,并按顺序编号。微处理器把页面尺寸定为4KB(2^12)

    • 页式存储器中,每个任务都有页表作为虚拟空间映射到物理空间的中介,如图中程序由4页组成

      1554275965550

    • 组成页表的行称作页表项,页表项包括页面基址和控制位,页式存储器通过页表项对页面进行管理。页表本身也是一页,存储在主存中

    二级页表

    • 第一级页表为页表目录,其页表项指明第二级页表中各页表的地址

      • 页目录表页面的物理地址存放在CR3中,仅高20位有效,低12位必须设置为0(因为页面4K对齐)

    • 第二级页表的页表项将线性地址(虚拟地址)映射到物理地址(实地址)

    1554276523224

    重新理清一下各种地址的概念:

    • 逻辑地址:程序中给出的地址,如 MOV EAX, [12345678],逻辑地址为 DS:[12345678],DS存放段选择子(16位的索引)逻辑地址包括 基地址: 偏移地址

    • 线性地址:由段转换得到的地址

    • 物理地址:地址总线上的实际物理内存地址

    一般好像线性地址称为虚拟地址,图中的”(虚地址)“标注有些不准确

    上一节保护模式下段寻址最终得到的地址即为图中的线性地址,页式存储器将其转化为物理存储器的物理地址

     

    Q:页目录表基址(保存在CR3)为物理地址,但GDT表基址(保存在GDTR)为线性地址,为什么?

    A:在开启了分页后,除了cr3,所有地址都要经过MMU自动进行虚拟地址到物理地址的转换,这个是无法绕过的。而对于cr3,是指明物理页面的地址,用来在物理内存中找物理页表的,就必须使用物理地址,也是不可避免的,所以cr3是特例。

     

    页表项(页描述符)

    1554277525097

    • 页表项共32位,其中高20位是页面基址,在页表中表示实页号,在页目录表中页面基址*2^12=相应页表的首地址

      乘2^ 12:一个页面尺寸为4KB(2^ 12),和GDT表相同,页目录表的索引给出的是第二级页表的序号

    • 低12位说明页(页表)的控制状态信息

      • P:存在为,P=1时表示页表在主存中,若P=0表示需要立即访问的页不在主存,这种情形称为页面失效(页面故障)
    • 两级页表中的页表项作用不同,但格式完全一样

    例2:(续例1)

    已知:GDT和LDT的首地址分别为55600000H和00013000H,FS=000BH,CR3=00013000H , ESI=0000125AH,内存有关数据如图所示。执行指令MOV EAX,FS:[ESI],求:

    CR3:含有存放页目录表页面的物理地址,仅高20位有效,低12位必须设置为0

    • 听说GDTR存放的是线性地址!我目前还没搞懂。。
    1. PE=1且PG=1时源操作对应的物理地址及EAX中的值

    (3)在PG=1,即保护模式开启分页的情况下,由基地址+偏移地址=01007000H+0000125AH=0100825AH求得的值并不能作为物理地址直接读取EAX,而是作为线性地址(虚拟地址)。如下图:

    1554278527168

    线性地址二进制表示为 0000 0001 0000 0000 1000 0010 0101 1010

    • 从一级页表找二级页表地址:虚拟地址高10位0000 0001 00为页目录索引,从CR3=00013000H读出页目录表基址,每个页表项(页描述符)占四个字节,因此得到页目录表中的相应项地址=页表目录基址(CR3)+目录索引*4=00013000H+0000 0001 00B*4=00013000H+0010H=00130010H

      页表项占四个字节,从例1的图中地址00130010H读出四个字节55600040H为页表项内容

      根据图13,高20位为页面基址,因此页表首地址=页面基址*2^12 =00055600H*2^12=55600000H

    • 从二级页表找实页号:虚地址12-21位00 0000 1000为页索引,得到页中目录项地址=页表首地址+页索引*4=55600000H+0020H=55600020H,从例1的图中地址55600020H读出四个字节000060B6H为页表项内容

      虚地址低12位0010 0101 1010为页内偏移,根据图13,页表项高20位为实页号,因此物理地址=页面基址*2^12+页内偏移=00006000H+025AH=0000625AH

    • 从物理地址读出数据:EAX=061A9936H

  • 相关阅读:
    LVS+keepalived DR模式配置 实现高可用集群
    lamp+redis集群配置详解
    Centos7.4+Mariadb集群-主从配置介绍
    centos6.5 LVS-DR模式---全内网环境
    Cacti安装使用&流量监控详解
    纯CSS模拟安卓滑动开关
    Java静态泛型方法使用例子-工具类
    基于KaliLinux的GNOME美化
    ArchLinux安装笔记
    [笔记] SpringMVC+Mybatis搭建Web开发环境
  • 原文地址:https://www.cnblogs.com/sssaltyfish/p/10656781.html
Copyright © 2011-2022 走看看