0.ring0-PAE-(虚拟地址转换成物理地址详细示例)
2015-09-16 15:43
155 查看
PAE是Physical Address Extension的缩写,即物理地址扩展。简单来说,就是把IA-32处理器的寻址能力从原来的4GB扩展到64GB。寻址4GB空间,要求物理地址的宽度为32位。类似的,要寻址64GB空间,那么物理地址的宽度就是36位。因为这个原因,PAE又被称为PAE-36bit。
一般电脑都可以轻松看出是不是使用了PAE,最简单是看系统属性:
![](http://img.blog.csdn.net/20140308143636562?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如果不启用PAE机制,每个进程的DirBase 的低12位应该是0,启用PAE机制低5位是0。在lkd模式下,!pte显示是不正确的
以下是PAE启用的显示:
![](http://img.blog.csdn.net/20140308144248671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
以下为示例:
代码:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
char *g_test = "123456789";
int main()
{
printf(g_test);
1.找到g_test的地址
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
00498004 test!g_test = 0x00486c6c "123456789"
2.启用内核调试,观察test进程:
![](http://img.blog.csdn.net/20140308145142500?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
上面标红的即为CR3的值,即PDPTR的内容
我们再查看下虚拟地址分解:
![](http://img.blog.csdn.net/20140308154054640?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
==》
最高两位是页目录表指针表的索引(00)
接下来9位是页目录索引即2
接下来9位为页表索引即0x86
最后12位是页内偏移为0Xc6c
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
</pre><p></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">可以这样理解,三张表:</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页目录指针表-->页目录表基地址</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页目录表-->页表基地址</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页表+页内偏移即为物理地址</span></span></p><p>3.首先通过02b40320观察指针表,因为是物理地址,所以用!dq</p><p></p><pre code_snippet_id="224619" snippet_file_name="blog_20140308_4_3950583" name="code" class="cpp">kd> !dq 02b40320
# 2b40320 00000000`0313a801 00000000`1fdfb801
# 2b40330 00000000`1fc3c801 00000000`03579801
# 2b40340 00000000`10c5e801 00000000`10bdf801
# 2b40350 00000000`10ce0801 00000000`10d5d801
# 2b40360 00000000`111bb801 00000000`1123c801
# 2b40370 00000000`1143d801 00000000`1137a801
# 2b40380 00000000`115dd801 00000000`1151e801
# 2b40390 00000000`1145f801 00000000`1165c801
每个指针对共有4个表项,每个表项是8字节(64位),上面2分析为0号表项,即00000000`0313a801
4.把00000000`0313a801砍去低12位,高32位,就是页目录表的基地址为0313a000,观察它的第2项:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
kd> !dq 313a000+8*2
# 313a010 00000000`03425867 00000000`00000000
5.把00000000`03425867砍去低12位,高32位,就是页表基地址为:03425000,观察它的0x86项:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
kd> !dq 03425000+0x86*8
# 3425430 00000000`03f80025 00000000`03301025
# 3425440 00000000`00000000 00000000`00000000
# 3425450 00000000`1fc2e025 00000000`00000000
# 3425460 00000000`00000000 00000000`00000000
# 3425470 00000000`00000000 00000000`00000000
# 3425480 00000000`031b7025 00000000`00000000
# 3425490 00000000`00000000 00000000`00000000
# 34254a0 00000000`00000000 00000000`0362c025
6.把00000000`03f80025砍去低12位,高32位,即内存页基地址为03f8000,加上页内偏移c6c:
![](http://img.blog.csdn.net/20140308154559015?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
下面再发张全图加深下理解:
注意PAE是扩展,所以都是64位的:
![](http://img.blog.csdn.net/20140308154831234?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGd5NDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
一般电脑都可以轻松看出是不是使用了PAE,最简单是看系统属性:
如果不启用PAE机制,每个进程的DirBase 的低12位应该是0,启用PAE机制低5位是0。在lkd模式下,!pte显示是不正确的
以下是PAE启用的显示:
以下为示例:
代码:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
char *g_test = "123456789";
int main()
{
printf(g_test);
1.找到g_test的地址
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
00498004 test!g_test = 0x00486c6c "123456789"
2.启用内核调试,观察test进程:
上面标红的即为CR3的值,即PDPTR的内容
我们再查看下虚拟地址分解:
==》
最高两位是页目录表指针表的索引(00)
接下来9位是页目录索引即2
接下来9位为页表索引即0x86
最后12位是页内偏移为0Xc6c
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
</pre><p></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">可以这样理解,三张表:</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页目录指针表-->页目录表基地址</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页目录表-->页表基地址</span></span></p><p><span style="font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"><span style="font-size:14px">页表+页内偏移即为物理地址</span></span></p><p>3.首先通过02b40320观察指针表,因为是物理地址,所以用!dq</p><p></p><pre code_snippet_id="224619" snippet_file_name="blog_20140308_4_3950583" name="code" class="cpp">kd> !dq 02b40320
# 2b40320 00000000`0313a801 00000000`1fdfb801
# 2b40330 00000000`1fc3c801 00000000`03579801
# 2b40340 00000000`10c5e801 00000000`10bdf801
# 2b40350 00000000`10ce0801 00000000`10d5d801
# 2b40360 00000000`111bb801 00000000`1123c801
# 2b40370 00000000`1143d801 00000000`1137a801
# 2b40380 00000000`115dd801 00000000`1151e801
# 2b40390 00000000`1145f801 00000000`1165c801
每个指针对共有4个表项,每个表项是8字节(64位),上面2分析为0号表项,即00000000`0313a801
4.把00000000`0313a801砍去低12位,高32位,就是页目录表的基地址为0313a000,观察它的第2项:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
kd> !dq 313a000+8*2
# 313a010 00000000`03425867 00000000`00000000
5.把00000000`03425867砍去低12位,高32位,就是页表基地址为:03425000,观察它的0x86项:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
kd> !dq 03425000+0x86*8
# 3425430 00000000`03f80025 00000000`03301025
# 3425440 00000000`00000000 00000000`00000000
# 3425450 00000000`1fc2e025 00000000`00000000
# 3425460 00000000`00000000 00000000`00000000
# 3425470 00000000`00000000 00000000`00000000
# 3425480 00000000`031b7025 00000000`00000000
# 3425490 00000000`00000000 00000000`00000000
# 34254a0 00000000`00000000 00000000`0362c025
6.把00000000`03f80025砍去低12位,高32位,即内存页基地址为03f8000,加上页内偏移c6c:
下面再发张全图加深下理解:
注意PAE是扩展,所以都是64位的:
相关文章推荐
- Objective-C 【格式化日期时间字符串】
- 集成支付宝钱包支付iOS SDK的方法与经验
- THINKPHP 验证码不显示
- Winform获取应用程序的当前路径的方法集合(转)
- iOS学习 很有用的链接
- zz Android studio NDK JINI
- Comparable 和 Comparator
- calculate sorted y of function y = ax^2 + bx + c given sorted x array
- IOS视频压缩
- oracle修改密码永不过期(默认180天过期)
- CodeForce 505C Mr. Kitayuta(DP+DFS)
- 页面效果简单做(一)
- C++实现split,若有问题,请指正。(有用C实现过的,欢迎贴代码)
- 单个php页面实现301重定向
- Html5 Canvas 实现滚动的图片
- Android 自定义列表指示器
- Kth Largest Element in an Array
- iptrafic and tcpdump
- job.waitForCompletion(true)空指针问题
- 微信支付成功,不回调的问题