頁表項(PTE)地址計算公式的解釋

轉自: http://www.pediy.com/kssd/pediy10/62497.html


《JIURL玩玩Win2k內存篇 分頁機制 (三)》中提到計算虛擬地址對應PTE地址的公式,如下:


代碼:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
從虛擬地址轉換到物理地址的過程來看,計算PTE需要虛擬地址的高10位做頁目錄索引,還需要第12 - 21位做頁表索引,上面的公式晃眼看起來,貌似是錯的,但是偏偏它又是對的,爲什麼捏?
其實很簡單,因爲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
由於VA的低位被清零,所以上面的移位操作化簡是成立的。最後的一個表達式已經很明顯了,VA & 0xfffff000完全是多餘的,因爲始終要>>12,所以最終公式就是:

代碼:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
combojiang兄在《透過MmIsAddressValid看Windows分頁機制》中也提到PTE的計算公式,如下:

代碼:
PTE = ((VA >> 12) << 2 ) & 0x3FFFC + 0xc0000000;
估計combojiang兄深夜發帖,意識模糊 :-),少寫了個F,誤導了不少羣衆,還沒人指出,正確的應該是:

代碼:
PTE = ((VA >> 12) << 2 ) & 0x3FFFFC + 0xc0000000;
這裏的& 0x3FFFFC也是不必要的,& 0x3FFFFC只是將低2位清零,而<< 2後低2位本來就是0,所以等價於:

代碼:
PTE = (VA >> 12) * 4 + 0xc0000000;

上面說的都是在32位 x86 非PAE的情況下,PAE情況下略有不同,有時間再整理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章