3.4.2.4 段描述符

在保护模式下,段寄存器有另一个名字,叫段选择子,因为它保存的信息主要是该段在段表里索引值,用这个索引值可以从段表中“选择”出相应的段描述符。

先看看ds选择子的内容,还是用“sreg”命令:

cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1

ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3

ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1

es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1

fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1

gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1

ldtr:s=0x0068, dl=0x52d00068, dh=0x000082fd, valid=1

tr:s=0x0060, dl=0x52e80068, dh=0x00008bfd, valid=1

gdtr:base=0x00005cc8, limit=0x7ff

idtr:base=0x000054c8, limit=0x7ff

可以看到,ds的值是0x0017。段选择子是一个16位寄存器,它各位的含义如下图:

其中RPL是请求特权级,当访问一个段时,处理器要检查RPL和CPL(放在cs的位0和位1中,用来表示当前代码的特权级),即使程序有足够的特权级(CPL)来访问一个段,但如果RPL(如放在ds中,表示请求数据段)的特权级不足,则仍然不能访问,即如果RPL的数值大于CPL(数值越大,权限越小),则用RPL的值覆盖CPL的值。而段选择子中的TI是表指示标记,如果TI=0,则表示段描述符(段的详细信息)在GDT(全局描述符表)中,即去GDT中去查;而TI=1,则去LDT(局部描述符表)中去查。

看看上面的ds,0x0017=0000000000010111(二进制),所以RPL=11,可见是在最低的特权级(因为在应用程序中执行),TI=1,表示查找LDT表,索引值为10(二进制)= 2(十进制),表示找LDT表中的第3个段描述符(从0开始编号)。

LDT和GDT的结构一样,每项占8个字节。所以第3项“0x00003fff 0x10c0f300”就是搜寻好久的ds的段描述符了。用“sreg”输出中ds所在行的dl和dh值可以验证找到的描述符是否正确。

接下来看看段描述符里面放置的是什么内容:

可以看到,段描述符是一个64位二进制的数,存放了段基址和段限长等重要的数据。其中位P(Present)是段是否存在的标记;位S用来表示是系统段描述符(S=0)还是代码或数据段描述符(S=1);四位TYPE用来表示段的类型,如数据段、代码段、可读、可写等;DPL是段的权限,和CPL、RPL对应使用;位G是粒度,G=0表示段限长以位为单位,G=1表示段限长以4KB为单位;其他内容就不详细解释了。

3.4.2.4段基址和线性地址

费了很大的劲,实际上我们需要的只有段基址一项数据,即段描述符“0x00003fff 0x10c0f300”中加粗部分组合成的“0x10000000”。这就是ds段在线性地址空间中的起始地址(ds段的段基址)。用同样的方法也可以算算其它段的基址,都是这个数。

段基址+段内偏移,就是线性地址了。所以ds:0x3004的线性地址就是:

0x10000000 + 0x3004 = 0x10003004

用“calc ds:0x3004”命令可以验证这个结果。

3.4.2.5 页表

从线性地址计算物理地址,需要查找页表。线性地址变成物理地址的过程如下:

首先需要算出线性地址中的页目录号、页表号和页内偏移,它们分别对应了32位线性地址的10位+10位+12位,所以0x10003004的页目录号是64,页号3,页内偏移是4。

IA-32下,页目录表的位置由CR3寄存器指引。“creg”命令可以看到:

CR0=0x8000001b: PG cd nw ac wp ne ET TS em MP PE

CR2=page fault laddr=0x10002f68

CR3=0x00000000

PCD=page-level cache disable=0

PWT=page-level writes transparent=0

CR4=0x00000000: osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme

说明页目录表的基址为0。看看其内容,“xp /68w 0”:

0x00000000 : 0x00001027 0x00002007 0x00003007 0x00004027

0x00000010 : 0x00000000 0x00024764 0x00000000 0x00000000

0x00000020 : 0x00000000 0x00000000 0x00000000 0x00000000

0x00000030 : 0x00000000 0x00000000 0x00000000 0x00000000

0x00000040 : 0x00ffe027 0x00000000 0x00000000 0x00000000

0x00000050 : 0x00000000 0x00000000 0x00000000 0x00000000

0x00000060 : 0x00000000 0x00000000 0x00000000 0x00000000

0x00000070 : 0x00000000 0x00000000 0x00000000 0x00000000

0x00000080 : 0x00ff3027 0x00000000 0x00000000 0x00000000

0x00000090 : 0x00000000 0x00000000 0x00000000 0x00000000

0x000000a0 : 0x00000000 0x00000000 0x00000000 0x00000000

0x000000b0 : 0x00000000 0x00000000 0x00000000 0x00ffb027

0x000000c0 : 0x00ff6027 0x00000000 0x00000000 0x00000000

0x000000d0 : 0x00000000 0x00000000 0x00000000 0x00000000

0x000000e0 : 0x00000000 0x00000000 0x00000000 0x00000000

0x000000f0 : 0x00000000 0x00000000 0x00000000 0x00ffa027

0x00000100 : 0x00faa027 0x00000000 0x00000000 0x00000000

页目录表和页表中的内容很简单,是1024个32位(正好是4K)数。这32位中前20位是物理页框号,后面是一些属性信息(其中最重要的是最后一位P)。其中第65个页目录项就是我们要找的内容,用“xp /w 0+64*4”查看:

0x00000100 : 0x00faa027

其中的027是属性,显然P=1,其他属性实验者自己分析吧。页表所在物理页框号为0x00faa,即页表在物理内存的0x00faa000位置。从该位置开始查找3号页表项,得到(xp /w 0x00faa000+3*4):

0x00faa00c : 0x00fa7067

其中067是属性,显然P=1,应该是这样。

3.4.2.6 物理地址

最终结果马上就要出现了!

线性地址0x10003004对应的物理页框号为0x00fa7,和页内偏移0x004接到一起,得到0x00fa7004,这就是变量i的物理地址。可以通过两种方法验证。

第一种方法是用命令“page 0x10003004”,可以得到信息:“linear page 0x10003000 maps to physical page 0x00fa7000”。

第二种方法是用命令“xp /w 0x00fa7004”,可以看到:

0x00fa7004 : 0x12345678

这个数值确实是test.c中i的初值。

现在,通过直接修改内存来改变i的值为0,命令是: setpmem 0x00fa7004 4 0,表示从0x00fa7004地址开始的4个字节都设为0。然后再用“c”命令继续Bochs的运行,可以看到test退出了,说明i的修改成功了,此项实验结束。

附录:

调试汇编代码

用Bochs在汇编级调试操作系统很简单,只需要运行“dbg-asm”,然后就得到了如下图所示的调试界面。

图1 Bochs调试操作系统的界面

此时是暂停在BIOS中。而我们的代码是从0x7C00位置开始的,所以先要在那里设一个断点,然后继续运行到断点:

break 0x7c00

continue

(0) Breakpoint 1, 0x00007c00 in ?? ()

Next at t=4967728

(0) [0x00007c00] 0000:7c00 (unk. ctxt): mov ax, 0x07c0       ; b8c007

接下来可以用命令help来查看调试系统的各种基本命令,这里给出了一些常用的命令

1 执行控制指令

c/cont/continue 连续执行

s/step/stepi [count] 执行count条指令,默认为1条,会跟进到函数和中断调用的内部

p/n/next [count] 执行count条指令,默认为1条,但跳过函数和中断调用

Ctrl+C 停止执行,并回到命令行提示符下

q/quit/exit 退出调试和执行

2 断点设置命令

vb/vbreak seg:offset 在虚拟地址上设置指令断点,其中seg和offset可以是以0x开始的十六进制数,或十进制,或者是以0开头的八进制数

lb/lbreak addr 在线性地址上设置断点,addr同上面的seg和offset

b/break/pb/pbreak addr 在物理地址上设置断点

info break 显示当前所有断点的信息

d/del/delete n 删除一个断点

3 内存操作指令

x /nuf addr 检查位于线性地址addr处的内存内容

xp /nuf addr 检查位于物理地址addr处的内存内容

其中参数n、u、f分别表示:

n为要显示内存单元的计数值,默认为1

u表示单元大小,默认值为w

b(bytes) 1字节

h(halfwords) 2字节

w(words) 4字节

g(giantwords) 8字节

f为显示格式,默认为x

x(hex) 显示为十六进制数

d(decimal) 显示为十进制数

u(unsigned) 显示为无符号十进制数

o(octal) 显示为八进制数

t(binary) 显示为二进制数

c(char)   显示为对应的字符

4 信息显示和CPU寄存器操作命令

r/reg/regs/registers 列表显示CPU寄存器及其内容

set $reg=val 修改某寄存器的内容。除段寄存器和标志寄存器以外的寄存器都可以

修改,如set $eax=0x01234567

creg 列出所有的CR0-CR4寄存器

sreg 列出CPU全部状态信息,包括各个段选择子(cs,ds等)以及ldtr

和gdtr等。

print-stack        打印堆栈情况。

info tab 显示页表

地址映射与共享———2相关推荐

  1. 操作系统实验七 地址映射与共享(哈工大李治军)

    实验七 地址映射与共享 实验目的 深入理解操作系统的段.页式内存管理,深入理解段表.页表.逻辑地址.线性地址.物理地址等概念: 实践段.页式内存管理的地址映射过程: 编程实现段.页式内存管理上的内存共 ...

  2. 操作系统实验一到实验九合集(哈工大李治军)

    操作系统实验 作者寄语 操作系统实验的学习是一个循序渐进的过程,初次看linux-0.11中的代码,看着满屏的汇编语言,确实头疼.但通过学习赵炯博士的Linux内核0.11完全注释,结合着王爽老师的汇 ...

  3. C | 进程间通信的方式

    C | 进程间通信的方式 1.无名管道 无名管道是实现亲缘间进程通信的一种方式,属于半双工通信. 无名管道的实现是队列,不能使用lseek对读写指针偏移. 无名管道有两个端:数据流入端和数据流出端,也 ...

  4. 哈工大操作系统实验总结

    实验地址, https://www.lanqiao.cn/courses/115/learning/?id=374, 在现做实验, 好处是环境提前都配好了, 不足之处是敲代码有网络延迟, 环境无法保存 ...

  5. RocketMQ源码级别面试题板块

    目录 事务消息篇 消费者端 Broker端 面试题版块 Kafka版块 Kafka生产消息为什么快之PageCache kafka的生产者和消费者如何借助Pagecache实现快速读和快速写 Kafk ...

  6. 1. 定义、功能和目标

    1. 计算机系统 计算机系统的层次结构: 硬件:处理器.寄存器.内存储器(内存).外存储器(外存)及各种I/O设备 操作系统: 负责协调硬件.软件等计算机资源工作 为上层提供接口和服务 封装硬件的复杂 ...

  7. 最快69秒逆向DRAM地址映射,百度设计的这款逆向工具如何做到快速可靠?

    来源 | 百度安全实验室 出品 | AI科技大本营(ID:rgznai100) 导读:近日,国际顶级设计自动化大会DAC大会公布DAC 2020会议议程和论文名单,由百度安全发表的<DRAMDi ...

  8. linux进程间通讯-共享内存

    文章目录 共享内存概述 共享内存的特点 共享内存操作 在ubuntu 12.04中共享内存限制值如下 获得一个共享存储标识符 创建共享内存 共享内存映射(attach) 解除共享内存映射(detach ...

  9. cuda合并访问的要求_在 CUDA C / C ++ 中使用共享内存

    在 上一篇文章 中,我研究了如何将一组线程访问的全局内存合并到一个事务中,以及对齐和跨步如何影响 CUDA 各代硬件的合并.对于最新版本的 CUDA 硬件,未对齐的数据访问不是一个大问题.然而,不管 ...

最新文章

  1. WINCE5 s3c2440_SD驱动知识补充
  2. Python操作excel文件创建workbook和批量创建Sheet
  3. matlab中nsamp,matlab用于数字调制,几个函数的使用问题
  4. [转]使用DBX分析AIX 下的 CoreDump
  5. 既生Flash,又何生EEPROM?
  6. 麦芒装饰装修小程序源码V3.2.59
  7. KMP算法的next数组通俗解释
  8. MyEclipse中将项目的编码从默认GBK改变为默认UTF-8
  9. VB禁用CTRL +ALT + DEL (2)
  10. 高中信息技术——进制与编码刷题点整理
  11. 64位电脑 装32位oracle,64位Windows可以安装32位的Oracle吗
  12. 使用iMazing将图书应用程序的ePub文件导出至电脑
  13. 德标螺纹规格对照表_螺栓螺母德标、欧标、国标对照表
  14. SpreadJS:一款类Excel开发工具,功能涵盖Excel的 95% 以上
  15. python解析pdf乱码,python pdfkit 中文乱码问题的解决方案
  16. 谷歌浏览器翻译显示服务器失败,谷歌浏览器翻译失败怎么办
  17. 简述多媒体计算机的特点,多媒体课件的特点和作用
  18. python学生成绩管理系统实验报告心得_学生成绩管理系统心得体会
  19. 基于MATLAB的数字图像处理系统设计
  20. vue 中嵌入iframe页面

热门文章

  1. 企业微信入群欢迎语最全使用指南
  2. leetcode 2256. 最小平均差
  3. 2021年茶艺师(初级)最新解析及茶艺师(初级)新版试题
  4. PLUSE论文阅读笔记
  5. 刷脸支付全面普及到车站地铁等公共场所
  6. 怎样使用JPG转PDF转换器转换图片
  7. 假设u~N(0, 1), X|u ~ N(u, 1)$,我们一起来推导 u的 posterior(p(u|X))
  8. Win10系统安装VUE及环境配置解析
  9. 英文文本情感分析textblob模块sentiment方法
  10. 暑期结束了我的实习,可我的大学也过半了 | 暑期实习总结