30-TLB(实验)

还是老办法,实践出真知。

上一篇已经介绍了 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 中安装中断门

  1. 在 main 函数起始位置下断点,在 VC6.0 中观察到函数 MountPageOnNull的函数地址,在我的环境里是 0x00401030。

  2. 构造中断门描述符 0040ee00`00081030

  3. 中断到 WinDbg 中去,执行以下命令安装中断门

    kd> eq 8003f500 0040ee00`00081030
    
  4. 在 WinDbg 中执行命令g 回到 xp 系统中。

  5. 继续执行 VC6.0 中的程序。

2.3 运行结果

这里写图片描述

3. 总结

该实验中,主要遵从前面的几个步骤,并且和前面预测的结果一样,足以说明 TLB 是存在的。本篇实验,使用的是 PAE 分页方法。当然,有兴趣的小伙伴,也可以使用 10-10-12 分页。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值