利用bochs将逻辑地址转化为物理地址理解操作系统的分段分页机制
来源:互联网 发布:朝鲜 知乎 编辑:程序博客网 时间:2024/05/24 06:57
在步入正题前,我们先来了解几个概念:逻辑地址、线性地址、虚拟地址、物理地址。逻辑地址(logical address):Intel为了兼容,将远古时代的段式内存管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个操作数或者是一条指令的地址。线性地址/虚拟地址(linear address/virtual address):跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。物理地址(physical address):用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。相关概念可以参考:[逻辑地址、线性地址、物理地址和虚拟地址](http://www.cnblogs.com/diyingyun/archive/2012/01/03/2311327.html)下面我们利用bochs说说操作系统的段页式转换:(本文程序在windows下进行)关于Bochs的配置这里就不赘述,网上有很多教程!首先在Bochs-2.1.1/linux-0.11-devel-040329下运行run.bat得到
内存调试窗口:
程序运行窗口:
(1)在内存调试窗口中输入c后
在程序运行窗口中写main.c文件,gcc –o main main.c编译 执行main
程序代码如下:
#include <stdio.h>int main(){ static int a = 1; int b = 6; int c = 10; printf("&a:0x%x\n",&a); while(a); printf("Program exit!\n"); return 0;}
执行结果为:
此时,程序阻塞到while(a);处。
我们的目标是将a的值修改为0,从而可以使程序运行通过。
(2)将内存调试窗口 ctrl+c跳出:
(3)info cpu(dump_cpu)查看cpu寄存器内容
变量a的值存在数据段,因此通过cpu的数据段寄存器ds的当前值作为段式映射的“选择码”,也就是用它作为段描述表中下标。
ds:s=0x17 转化为二进制:0000 0000 0001 0111
我们可以看出index = 2,TI = 1(LDT 局部描述符表),RPL = 3
ldtr:0x68 转化为二进制:0000 0000 0110 1000
同上 index = 13,TI = 0(GDT 全局描述符表),RPL = 0
gdtr:base=0x5cb8(段基址)
(4)xp /2wx 0x5cb8+13*8通过段基址+下标找出LDT(局部描述符表)的地址
段描述符表的结构图如下:
根据段描述符表的结构分析可知LDT的入口地址是:0x00fad2d0
(5)xp /2wx 0x00fad2d0+2*8 通过段基址+偏移量得到线性地址
根据段描述符表的结构得到线性地址的基地址0x10000000,而a的地址0x3004,因此可得到a的线性地址为:0x10003004
calc ds:0x3004查看a的实际线性地址:
由此可确认a的线性地址确实为:0x10003004
至此,分段结束。
(6)分页开始,分页机制如下图所示:
将线性地址0x10003004,二进制为0001 0000 0000 0000 0011 0000 0000 0100
按10、10、12位划分, 0001000000 0000000011 000000000100可得
Director = 64 Table = 3 Offset = 4
首先查看cr0:0x80000001b最高位为1,说明支持分页机制;
再查看cr3: 0x0
xp /wx 0x0+64*4根据cr3和Director得到页目录索引:
页目录索引的有效位为高20位,即0x00faa000,与Table可得到页表索引:
页表索引的有效位也是高20位,即0x00fa9000,与Offset可得到实际的物理地址:
即a的物理地址为0x00fa9004
(7)最后setpmem 0x00fa9004 4 0x0将a的值修改为0,使得程序可以通过。
通过xp /wx 0x00fa9004查看a的值已被修改为0
(8)c 继续执行发现程序运行窗口的程序结束:
完!!!
顺便再说一下逻辑地址、线性地址、虚拟地址、物理地址的区别和联系
就针对本例子来说:
逻辑地址:0x3004
线性地址(虚拟地址):0x10003004
物理地址:0x00fa9004
未分段前,逻辑地址=线性地址=虚拟地址,通过MMU分页后转化为物理地址
Linux下,逻辑地址与线性地址保持一致,因为所有的线性地址都是从0x00000000开始的。
线性地址=0x00000000(相当于基址)+逻辑地址(相当于偏移量)
如果没有分页机制,物理地址=逻辑地址
这下真的说完了,如有偏颇,希望同仁批评指正,谢谢!
- 利用bochs将逻辑地址转化为物理地址理解操作系统的分段分页机制
- 操作系统的分段与逻辑地址和转换物理地址
- 分段 分页 虚拟内存空间 逻辑地址 物理地址
- 80386的分段机制、分页机制和物理地址的形成
- 80386的分段机制、分页机制和物理地址的形成
- 80386的分段机制、分页机制和物理地址的形成
- 80386的分段机制、分页机制和物理地址的形成
- 80386的分段机制、分页机制和物理地址的形成
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 为什么分页机制中逻辑地址空间是一维的,而分段机制中逻辑地址空间是二维的?
- 理解的逻辑地址、线性地址、物理地址和虚拟地址
- nandflash地址的物理地址,逻辑地址,spare地址等理解
- 关于 @mvc:annotation-driven @InitBinder
- 基于本地Ubuntu主机的Hadoop系统环境搭建
- 关于编译后文件取回 - Samba服务器
- 关于vector在堆上还是在栈上的思考与vector.push_back()究竟放入的是什么
- Java入门习题(五)——内部类
- 利用bochs将逻辑地址转化为物理地址理解操作系统的分段分页机制
- No2.认识图片---机房收费
- 匿名函数和字面量——JS学习
- 在Maven项目中加载spring中的bean的配置xml文件会提示找不到解决方法
- 二分图总结
- C++ primer plus 第十章课后习题,原创答案。
- cccc结构体
- Swift 学习1
- Android 面试题