启用PAE机制下虚拟地址到物理地址的转换

来源:互联网 发布:排列组合公式算法c50 编辑:程序博客网 时间:2024/05/18 03:50

最近突然想起用softice手工计算一下虚拟地址到物理地址的转换,理论的东西如段表、页表等已经很熟悉了,但真正实际操作就碰到了大问题,特别是分页机制,根本不是从cr3到页目录表到页表再到物理地址这么简单,后来读了一下《Intel® 64 and IA-32 Architectures
Software Developer’s Manual》(Volume 3A: System Programming Guide, Part 1)的第三章“PROTECTED-MODE MEMORY MANAGEMENT”,才发现原先的认识还停留在80386的基础上,没有考虑PAE、PSE-36等机制,所以这里用一个实际例子简单解释一下, 具体的内容还得去看上述的那本手册(强烈推荐)。

先写一个简单的用于实验的例子,只要用vc++6.0建一个MFC的对话框程序(我把工程取名为“memory”),界面只要留下默认生成的“确认”按钮,该按钮的消息函数写成这样:

void CMemoryDlg::OnOK()
{
     // TODO: Add extra validation here
     int test = 0x12345;
     CDialog::OnOK();
}
生成一个应用程序memory.exe,就可以开始实验了。

 

开启softice后,用symbol loader转换memory.exe以实现源码调试。呼出softice窗口,键入file memorydlg.cpp(包含按钮消息函数的cpp),代码窗口即出现该cpp文件的源码,寻找代码中的CMemoryDlg::OnOk函数,对CDialog::OnOK()一句设断点。用ctrl-d隐藏窗口,即弹出memory.exe程序的对话框,单击“确定按钮”,即弹出sofice窗口。

1、输入 d test,察看数据窗口,发现test(即0x12345)在0023:0012f698处

2、键入 gdt,发现0023对应的段基址为0x00000000,因此test的线性地址为0012f698

3、如果是双核的机器,则如下操作:键入cpu,发现高亮行为cpu0(不一定,可能为cpu0,也可能为cpu1),再键入cpu0(若高亮行为cpu1,则键入cpu1),查找对应的CR4寄存器,发现有PSE、PAE标志,说明已启用了PAE机制(PSE被PAE屏蔽)。再看CR3,为0x06c80260。如果是单核的直接键入cpu即可。

 

4、因为启用了PAE,故如下分解线性地址:

0x0012f698 :

[00] (用于选择页目录指针表项)  [00 0000 000](用于选择页目录表项) [1 0010 1111](用于选择页表项) [0110 1001 1000](偏移)

或者:

[00] (用于选择页目录指针表项)  [00 0000 000](用于选择页目录表项) [1 0010 1111 0110 1001 1000](偏移)

到底取哪一种具体要看页目录表项的PS(Page Size)位。

5、页目录指针表项地址:06c80260(cr3按32byte对齐)+8(页目录指针表项为8字节长)*0(线性地址高2位) = 06c80260

peek  d 06c80260: 0x2a1d7801

peek  d 06c80264: 0x00000000

因此,页目录指针表项低字为0x2a1d7801,高字为0x00000000

6、页目录表项地址:2a1d7000(页目录指针表项按4k对齐)+8(页目录表项为8字节长)* 0(线性地址21-29位) = 2a1d7000

peek d 2a1d7000: 0x36a60867

peek d 2a1d7005: 0

因此,页目录表项低字为0x36a60867,高字为0x00000000

由于页目录表项的第7位(PS位)为0(......,1000,0000,0001),故页目录表项指向页表而非指向4M大小的页(即线性地址采用第一种分解方法)

7、页表项地址: 36a60000(页目录表项按4k对齐)+ 8(页目录表项为8字节长)* 0x12f(线性地址12-20) = 36a60978

peek d 36a60978: 0x25e25867

peek d 36a6097c : 0x80000000

(手册中说64页表项的高地址28被保留为零,但不知为何最高位是1,可能这几年最高位已被用作某种标志,我看的是06年的版本,知道的不吝赐教,这里暂且不管)

因此,页表项低字为0x36a60867,高字为0x00000000

8、物理地址:25e25000(页表项按4k对齐(63位的1暂且看作0吧)) +0x698(线性地址低12位) = 25e25698

于是我们得到了物理地址:0x25e25867

peek d 25e25698: 0x00012345

果然得到了在虚拟地址0023:0012f698处的变量test(0x12345) 的物理地址。

关于PAE机制下的线性地址转换和各种表项如下:

 

 

原创粉丝点击