在《JIURL玩玩Win2k内存篇 分页机制 (三)》中提到计算虚拟地址对应PTE地址的公式,如下:
代码:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
其实很简单,因为1024个页表被映射在0xC0000000 - 0xC03FFFFF地址中,暂且不理会页目录被映射到哪,只要知道页目录里的1024个页目录项分别指向0xC0000000 - 0xC03FFFFF地址中的1024个页表就行了(其实这是因为页目录和一个页表完全重合的原因,见 《JIURL玩玩Win2k内存篇 分页机制 (四)》),这样就可以得到一个关系,页目录索引n指向的页表就等于0xC0000000 + n * 页表大小,一个页表的大小是1024 * 4 = 4096 = 2的12次方,得到了页表,在加上页表索引就可以得到页表项(PTE)的地址了,用公式表示就是如下:
代码:
//为了缩短表达式,用VA表示虚拟地址 // 页目录索引 页表索引 PTE_Addr=((VA&0xffc00000)>>22)*4096+((VA&0x3ff000)>>12)*4+0xc0000000 =(((VA&0xffc00000)>>22)<<12)+(((VA&0x3ff000)>>12)<<2)+0xc0000000 =((VA&0xffc00000)>>10)+((VA&0x3ff000)>>10)+0xc0000000 =((VA&0xffc00000)+(VA&0x3ff000)>>10)+0xc0000000 =((VA&(0xffc00000|0x3ff000))>>10)+0xc0000000 =((VA&0xfffff000)>>10)+0xc0000000 =(((VA&0xfffff000)>>12)<<2)+0xc0000000 =((VA&0xfffff000)>>12)*4+0xc0000000
代码:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
代码:
PTE = ((VA >> 12) << 2 ) & 0x3FFFC + 0xc0000000;
代码:
PTE = ((VA >> 12) << 2 ) & 0x3FFFFC + 0xc0000000;
代码:
PTE = (VA >> 12) * 4 + 0xc0000000;
上面说的都是在32位 x86 非PAE的情况下,PAE情况下略有不同,有时间再整理