您的位置:首页 > 其它

30-TLB(实验)

2016-11-02 11:15 176 查看
还是老办法,实践出真知。

上一篇已经介绍了 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 分页。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  保护模式 TLB