启用PAE机制下虚拟地址到物理地址的转换
2009-12-18 16:55
351 查看
启用PAE机制下虚拟地址到物理地址的转换
最近突然想起用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机制下的线性地址转换和各种表项如下:
最近突然想起用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机制下的线性地址转换和各种表项如下:
相关文章推荐
- 启用PAE机制下虚拟地址到物理地址的转换
- 0.ring0-PAE-(虚拟地址转换成物理地址详细示例)
- 【软件安全】PAE下虚拟地址到物理地址的转换
- [Linux内存管理-分页机制]—把一个虚拟地址转换为物理地址
- 0.ring0-PAE-(虚拟地址转换成物理地址详细示例)
- 分段管理机制(虚拟地址转换到线性地址)
- 在用户态进行虚拟空间地址向物理空间地址的转换
- 【解答】关于内核中没开MMU之前的虚拟地址物理地址转换问题
- 物理地址扩展(PAE)分页机制
- 32位ubuntu物理地址扩展(PAE)分页机制及如何开启PAE支持4G以上内存(有时grub里面会让你选择)
- 【Linux内存管理】虚拟地址、逻辑地址、线性地址、物理地址之间的转换
- 用户虚拟地址转换成物理地址
- 在用户态进行虚拟空间地址向物理空间地址的转换
- 利用/proc/pid/pagemap将虚拟地址转换为物理地址
- 虚拟地址到物理地址的转换步骤【转】
- 【Operating System】内存管理/分页机制,虚拟内存到实际物理地址的转换
- 分页管理机制(线性地址转换到物理地址)
- 深入理解计算机系统-之-内存寻址(一)--存储管理机制(虚拟地址,线性地址,物理地址)
- 虚拟地址、线性地址和物理地址的转换
- 虚拟地址转换成物理地址