30-TLB(实验)
2016-11-02 11:15
176 查看
还是老办法,实践出真知。
上一篇已经介绍了 TLB 的有关概念。你已经知道,它无非就是位于 CPU 内部的一个数组,它保存了线性地址和物理地址的直接对应关系,以及页属性等信息。
CPU 在做线性地址转换的时候,首先会去 TLB 中查找它对应的物理地址,如果找不到,才会根据 CR3 寄存器去查找页目录、页表。
本篇的实验,主要是为了验证 TLB 本身的存在。为什么说是验证?因为 CPU 本身并未提供给我们访问 TLB 的指令。与其说验证,说感知 TLB 的存在,可能会更恰当。
给 0 地址挂上0x50000000对应的物理页,并从 0 地址读取数据。
申请一个线性地址 0x60000000,写入4字节整数 0x87654321
给 0 地址重新挂上0x6000000对应的物理页
读 0 地址的数据
可以自行思考下,上述步骤两次读取数据分别得到什么样的结果?
如果两次读取到的 0 地址的数据,都是 0x12345678,那么说明 TLB 是存在的。
继续接上前面的步骤
刷新 TLB
再次读取 0 地址数据
思考下,此时读取 0 地址的数据是多少?
如果没出意外,读取到的应该是 0x87654321
构造中断门描述符 0040ee00`00081030
中断到 WinDbg 中去,执行以下命令安装中断门
在 WinDbg 中执行命令
继续执行 VC6.0 中的程序。
![](http://img.blog.csdn.net/20161102110310838)
上一篇已经介绍了 TLB 的有关概念。你已经知道,它无非就是位于 CPU 内部的一个数组,它保存了线性地址和物理地址的直接对应关系,以及页属性等信息。
CPU 在做线性地址转换的时候,首先会去 TLB 中查找它对应的物理地址,如果找不到,才会根据 CR3 寄存器去查找页目录、页表。
本篇的实验,主要是为了验证 TLB 本身的存在。为什么说是验证?因为 CPU 本身并未提供给我们访问 TLB 的指令。与其说验证,说感知 TLB 的存在,可能会更恰当。
1. 实验步骤
申请一个线性地址 0x50000000,写入数字 0x12345678给 0 地址挂上0x50000000对应的物理页,并从 0 地址读取数据。
申请一个线性地址 0x60000000,写入4字节整数 0x87654321
给 0 地址重新挂上0x6000000对应的物理页
读 0 地址的数据
可以自行思考下,上述步骤两次读取数据分别得到什么样的结果?
如果两次读取到的 0 地址的数据,都是 0x12345678,那么说明 TLB 是存在的。
继续接上前面的步骤
刷新 TLB
再次读取 0 地址数据
思考下,此时读取 0 地址的数据是多少?
如果没出意外,读取到的应该是 0x87654321
2. 实验过程
2.1 代码
#include <windows.h> DWORD zero, one, two; __declspec(naked) void MountPageOnNull() { __asm { push ebp mov ebp, esp sub esp, 0x100 push ebx push esi push edi } DWORD* pPTE; // 保存目标线性地址的 PTE 线性地址 DWORD* pNullPTE; // 0 地址的 PTE 线性地址 pNullPTE = (DWORD*)0xc0000000; // 挂上 0x50000000 所在位置 pPTE = (DWORD*)(0xc0000000 + ((0x50000000 >> 9) & 0x7ffff8)); *pNullPTE = *pPTE; zero = *(DWORD*)0; // 挂上 0x60000000 所在位置 pPTE = (DWORD*)(0xc0000000 + ((0x60000000 >> 9) & 0x7ffff8)); *pNullPTE = *pPTE; one = *(DWORD*)0; // 刷新 TLB __asm { mov eax, cr3 mov cr3, eax } // 再次读取 0 地址位置的数据 two = *(DWORD*)0; __asm { pop edi pop esi pop ebx mov esp, ebp pop ebp iretd } } // 外壳包裹函数 __declspec(naked) void MyMountPageOnNull() { __asm { int 0x20 ret } } int main(int argc, char* argv[]) { DWORD* x = (DWORD*)VirtualAlloc((LPVOID)0x50000000, 4, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); DWORD* y = (DWORD*)VirtualAlloc((LPVOID)0x60000000, 4, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); *x = 0x12345678; *y = 0x87654321; if (x != (DWORD*)0x50000000 || y != (DWORD*)0x60000000) { printf("Error alloc!\n"); return -1; } MyMountPageOnNull(); printf("1. 读 0 地址数据:\n"); printf("*NULL = 0x%08x\n\n", zero); printf("2. 给 0 地址重新挂上物理页\n\n"); printf("3. 重新读取 0 地址数据:\n"); printf("*NULL = 0x%08x\n\n", one); printf("4. 刷新 TLB \n\n"); printf("5. 再次读取 0 地址数据:\n"); printf("*NULL = 0x%08x\n", two); return 0; }
2.2 在 WinDbg 中安装中断门
在 main 函数起始位置下断点,在 VC6.0 中观察到函数 MountPageOnNull的函数地址,在我的环境里是 0x00401030。构造中断门描述符 0040ee00`00081030
中断到 WinDbg 中去,执行以下命令安装中断门
kd> eq 8003f500 0040ee00`00081030
在 WinDbg 中执行命令
g回到 xp 系统中。
继续执行 VC6.0 中的程序。
2.3 运行结果
3. 总结
该实验中,主要遵从前面的几个步骤,并且和前面预测的结果一样,足以说明 TLB 是存在的。本篇实验,使用的是 PAE 分页方法。当然,有兴趣的小伙伴,也可以使用 10-10-12 分页。相关文章推荐
- NA-NP-IE系列实验30:CHAP 认证
- HP 路由交换之NAT实验
- linux dhcp服务器配置及小实验
- 实验十 SCVMM创建虚拟机
- 数据结构上机实验之二分查找
- 04-树8. Complete Binary Search Tree (30)
- 实验3
- 数据结构实验之数组三:快速转置
- 数据压缩实验三——霍夫曼编解码算法实现
- SDUT 2054-数据结构实验之链表九:双向链表
- 模数转换AD 实验
- 实验1-1 VC6.0的使用
- 一片糟糕的实验报告
- 数据结构实验:连通分量个数
- C++实验3-1-个人所得税计算器
- 数据结构实验之二叉树六:哈夫曼编码
- 架构设计:系统存储(30)——分布式文件系统Ceph(RADOS结构)
- 数据结构实验之排序七:选课名单