首页
社区
课程
招聘
[求助]页表问题(在线等)
发表于: 2008-2-15 15:08 7529

[求助]页表问题(在线等)

2008-2-15 15:08
7529

:addr notepad
:dd (7ffe0000>>12)*4+c0000000
0010:C0007FFC ????????  1F083025  80000000  1F148025      ....%0......%...
0010:C000800C 00000000  1F113025  00000000  1F114025      ....%0......%@..

在softice 中做页表的实验.为什么这样做出来显示的不是 页表呢 很奇怪!


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 424
活跃值: (1879)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
如果启用了PAE,应该是这样算

(7ffe0000>>12)*8+c0000000
2008-2-15 15:32
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
操作系统没有任何特殊性,都是默认值,刚装的
2008-2-15 16:06
0
雪    币: 424
活跃值: (1879)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4


查看系统盘根目录下的boot.ini文件,如果当前系统有/noexecute=optin(/alwayson、/optout)或者/pae这样的参数话,就说明启用了PAE,市面上很多系统安装盘都是默认有/noexecute=optin的
2008-2-15 16:28
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
5
你的这个方法是不对的。 对于4k分页,32位线性地址中最高10位是页目录索引,中间10位才是页表索引。
2008-2-17 00:45
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
6
PDE,PTE.

看看操作系统的内存管理. 嘿嘿

网上也有相关知识~
2008-2-17 08:49
0
雪    币: 424
活跃值: (1879)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
如果没启用PAE,算法是对的



启用了PAE后,就是这样,地址被扩展到64位



晕,楼主的表达式有问题,SoftICE的数字默认好像是16进制,(7ffe0000>>12)*4+c0000000这个表达式有问题,应该是(7ffe0000>>c)*4+c0000000
(7ffe0000>>c)*4+c0000000=C01FFF80才对,楼主的C0007FFC不对
上传的附件:
2008-2-17 09:45
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
8
注参数说明:BaseAddress是页目录pde基地址,通常是0xc0300000 ,64位对应0x00000000c0600000.  

addr: 线性地址

返回值:物理地址

PVOID LinearToPhys(PULONG BaseAddress, PVOID addr)
{
    ULONG VAddr = (ULONG)addr;
        ULONG PGDE,PTE,PAddr;
    PGDE = BaseAddress[VAddr>>22]; //页目录 ,BaseAddress是页目录的首地址

    if (0 == (PGDE&1)) //判断present位
        return 0;

    ULONG tmp = PGDE & 0x00000080;  //判断page size.

    if (0 != tmp)
    {
                //高10位 + 低22位
        PAddr = (PGDE & 0xFFC00000) + (VAddr & 0x003FFFFF); //如果是4M分页
                  
    }
    else  //4K分页
    {
                //得到二级页目录地址
        PGDE = (ULONG)MapViewOfFile(g_hMPM, 4, 0, PGDE & 0xfffff000, 0x1000);

                //找到pte
        PTE = ((PULONG)PGDE)[(VAddr&0x003FF000)>>12];  //页表
        
        if (0 == (PTE&1)) //判断present位
            return 0;

                //取PTE高20位 + 线性地址12位得到物理地址
        PAddr=(PTE&0xFFFFF000)+(VAddr&0x00000FFF);

        UnmapViewOfFile((PVOID)PGDE);
    }

    return (PVOID)PAddr;
}
2008-2-18 11:17
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
9
嘿嘿,简单打几个字,给这个优秀帖丰富点儿内容.

#define PTE_BASE 0xC0000000
#define PDE_BASE 0xC0300000


根据虚拟地址得到PTE的地址和PDE的地址:

#define GetPteAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
#define GetPdeAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))


------------------------------------------------------------------------------------------------------

再看看pte的结构:

lkd> dt nt!_hardware_pte
nt!_HARDWARE_PTE
+0x000 Valid : Pos 0, 1 Bit
+0x000 Write : Pos 1, 1 Bit
+0x000 Owner : Pos 2, 1 Bit
+0x000 WriteThrough : Pos 3, 1 Bit
+0x000 CacheDisable : Pos 4, 1 Bit
+0x000 Accessed : Pos 5, 1 Bit
+0x000 Dirty : Pos 6, 1 Bit
+0x000 LargePage : Pos 7, 1 Bit
+0x000 Global : Pos 8, 1 Bit
+0x000 CopyOnWrite : Pos 9, 1 Bit
+0x000 Prototype : Pos 10, 1 Bit
+0x000 reserved : Pos 11, 1 Bit
+0x000 PageFrameNumber : Pos 12, 20 Bits


PTE和PDE的格式实际上是一样的

PTE
+---------------+---------------+---------------+---------------+
|3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1     |                |
|1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
+---------------------------------------+-----------------------+
|                                        |T P C U R D A P P U R P|
|   Base address 20 bits                  |R P W          C W S W   |
|                                        |N T            D T       |
+---------------------------------------+-----------------------+

还有个概念是pfn:

lkd> !pfn
    PFN 00000000 at address 8178A000
    flink       00000000  blink / share count 00000000  pteaddress 00000000
    reference count 0000   NonCached  color 0
    restore pte 00000000  containing page        000000  Zeroed  

...

这些东西在俄罗斯一大牛05年写的"内存与进程管理器"有部分介绍. 把内容传上来了,见附件

另外给篇资料供大家参考 -->

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(转载,原始出处:http://stonefish99.spaces.live.com/blog/cns!8D0306EAAFBB673C!118.entry)

关于PTE/PDE
上节课老师讲了关于PDE,PTE的虚拟地址计算的一些内容,当时有点晕,主要是两个问题:1 虚拟地址到物理地址的转换必须用到PDE,PTE的虚拟地址吗?是怎么转换的?2 计算PDE,PTE的虚拟地址有什么用?回来做了一些实验,终于明白了,下面是一些实验结果

一  虚拟地址如何转换到物理地址?必须用到PDE,PTE的虚拟地址吗?

按照以前学习的分页机制,一个虚拟地址转换成物理地址的计算过程应该是:
1 处理器通过CR3找到当前页目录所在的物理页地址a
2 计算PDE的物理地址:a+ 虚拟地址高十位左移两位 (因为每个页目录项四个字节),取出该地址处的PDE,PDE的前20位+低12位0是这个虚拟地址对应页表的物理地址b
3 计算PTE的物理地址:b+ 虚拟地址的中间10位左移两位,取出该地址处的PTE,PTE的前20位是这个虚拟地址+低12位0是所对应物理页的地址c
4 计算该虚拟地址对应的物理地址:c + 虚拟地址最低12位

是这样的吗?
实验代码://和老师上课给的代码相同,只是把虚拟地址改成了60010020
int main()
{
      char buf[100] = "Hello world";                              
      VirtualAlloc( (void  *)0x60010020, 0x3000, MEM_RESERVE, PAGE_READWRITE );   //保留三页
      VirtualAlloc( (void *)0x60010020, 0x2000, MEM_COMMIT, PAGE_READWRITE );   //提交两页
      printf( "Accessing memory...\n" );                           
      getchar();
      memcpy( (void *)0x60010020, buf, 100 );
      printf( "Releasing memory...\n");
      getchar();
      VirtualFree( (void *)0x60010020, 0, MEM_RELEASE );
      printf( "Exiting memory...\n" );
      getchar();
      return 0;
}

1 查寄存器CR3中的值

kd> r cr3

cr3=0e238000
2 计算PDE的物理地址:0e238000 + 00000600= 0e238600

取出该地址处的PDE

kd> !dd 0e238600

# e238600 0dfc9867 00000000 00000000 00000000

# e238610 00000000 00000000 00000000 00000000

# e238620 00000000 00000000 00000000 00000000

# e238630 00000000 00000000 00000000 00000000

# e238640 00000000 00000000 00000000 00000000

# e238650 00000000 00000000 00000000 00000000

# e238660 00000000 00000000 00000000 00000000

# e238670 00000000 00000000 00000000 00000000

3计算PTE的物理地址:0dfc9000 + 00000040 = 0dfc9040
取出该地址处的PTE

kd> !dd 0dfc9040

# dfc9040 0dece867 00000080 00000080 00000000

# dfc9050 00000000 00000000 00000000 00000000

# dfc9060 00000000 00000000 00000000 00000000

# dfc9070 00000000 00000000 00000000 00000000

# dfc9080 00000000 00000000 00000000 00000000

# dfc9090 00000000 00000000 00000000 00000000

# dfc90a0 00000000 00000000 00000000 00000000

# dfc90b0 00000000 00000000 00000000 00000000
4 计算虚拟地址对应的物理地址:0dece000 + 00000020 = 0dece020
取出该物理地址处的数据:

kd> !db 0dece020

# dece020 48 65 6c 6c 6f 20 77 6f-72 6c 64 00 00 00 00 00 Hello world.....

# dece030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

# dece090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
实验结果表明:虚拟地址0x60010020对应的物理地址为:0dece020,并不需要用到PDE,PTE的虚拟地址,上面的计算方法是正确的

二 通过基址c0300000和c0000000计算出的PDE和PTE的虚拟地址有什么用?

cpu在转换地址的过程中,并不需要页表,页目录的虚拟地址,那为什么还需要计算PDE,PTE的虚拟地址呢?是因为在分页标志设置后,cpu把指令中的虚拟地址转换成物理地址,程序中只能使用虚拟地址,因此要把页目录和页表映射到虚拟地址空间中,页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间,页目录被映射到了0xC0300000开始处的4K地址空间

因此PDE的虚拟地址为: c0300000 + 00000600 = c0300600
取出该虚拟地址处的PDE,可以看到和上面用PDE的物理地址取出来的结果相同

kd> dd c0300600

c0300600  0dfc9867 00000000 00000000 00000000

c0300610  00000000 00000000 00000000 00000000

c0300620  00000000 00000000 00000000 00000000

c0300630  00000000 00000000 00000000 00000000

c0300640  00000000 00000000 00000000 00000000

c0300650  00000000 00000000 00000000 00000000

c0300660  00000000 00000000 00000000 00000000

c0300670  00000000 00000000 00000000 00000000

PTE的虚拟地址为:  c0000000 + 00180040 = c0180040
取出该虚拟地址处的PTE,和上面用PTE的物理地址取出来的结果相同

kd> dd c0180040

c0180040  0dece867 00000080 00000080 00000000

c0180050  00000000 00000000 00000000 00000000

c0180060  00000000 00000000 00000000 00000000

c0180070  00000000 00000000 00000000 00000000

c0180080  00000000 00000000 00000000 00000000

c0180090  00000000 00000000 00000000 00000000

c01800a0  00000000 00000000 00000000 00000000

c01800b0  00000000 00000000 00000000 00000000
上传的附件:
2008-2-18 12:43
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
查看系统盘根目录下的boot.ini文件,如果当前系统有/noexecute=optin(/alwayson、/optout)或者/pae这样的参数话,就说明启用了PAE,市面上很多系统安装盘都是默认有/noexecute=optin的

重点感谢 StarsunYzL  
确实发现系统启动了PAE
2008-2-18 12:49
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
11
只感谢 StarsunYzL 一个人啊. LZ不厚道啊

另外,kanxue里面已经有人问过了.提问题前应该先搜索:
http://bbs.pediy.com/showthread.php?p=370581

问题解决了.在标题上加个 [已解决]  字样,别人也就知道了啊.
2008-2-18 12:52
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
我犯的最大的一个错误就是 把c写成了12
只有他一个人指出来 让我少走了很多弯路
2008-2-18 13:23
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
13
高傲的人...

奉劝大家以后不要帮助这种 XX 的小人啊
2008-2-18 13:35
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
感谢大家的支持帮助!!
2008-2-19 13:49
0
游客
登录 | 注册 方可回帖
返回
//