现在的位置: 首页 > 综合 > 正文

PAE物理地址扩展

2013年12月01日 ⁄ 综合 ⁄ 共 6536字 ⁄ 字号 评论关闭

启用物理地址扩展 (PAE) X86
1.打开 Windows 资源管理器。
2.在“工具”菜单上,单击“文件夹选项”。
3.在“查看”选项卡上,单击“显示所有文件和文件夹”,清除“隐藏受保护的操作系统文件”复选框,然后单击“确定”。如果显示警告对话框,单击“是”以继续。
4.在根文件夹(如 C:)下查找 Boot.ini 文件并删除它的只读属性。
5.打开 Boot.ini 文件,然后将 /PAE 参数添加到 ARC 路径中,如以下 Windows Server 2003 Datacenter Edition 示例所示:
multi(0)disk(0)rdisk(0)partition(2)/%systemroot%="Windows Server 2003, Datacenter Edition" /PAE
6.在“文件”菜单上,单击“保存”。
7.还原 Boot.ini 文件的只读属性。
8.为使更改生效,请重新启动计算机。

禁用PAE模式方法
右击桌面“我的电脑”属性,选择“高级”,再点击“启动与恢复”下面的“设置”,再点击框中的“编辑”键,此时会打开BOOT.INI文件,
然后将文件的此行“multi(0)disk(0)rdisk(0)partition(1)/WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect”中的/noexecute=optin改成/execute 改完后保存该文件,然后重启电脑便OK。

注意
? 要执行该过程,您必须是本地计算机上 Administrators 组的成员,或者您必须被委派了适当的权限。如果计算机已加入某个域,则 Domain Admins 组的成员可能会执行该过程。作为安全性最佳操作,请考虑使用“运行方式”执行此过程。
在采用支持非执行页面保护功能的处理器的计算机上启用 DEP 时,在运行装有 Service Pack 1 的 Windows Server 2003 和装有 Service Pack 2 的 Windows XP 的计算机上将自动启用 PAE。

在装有 SP1 的标准版 Windows Server 2003 和装有 SP2 的 Windows XP 上启用 PAE 模式时,物理地址空间将限制在 4 GB。将物理地址空间限制在 4 GB 有助于防止 PAE 模式出现驱动程序兼容性问题。
也可以用程序实现:
void DeactivateAll_NoPAE(){
        DWORD current;
         current = Bpx.StartRange;
        while (current < Bpx.StartRange + Bpx.Size){
                 __asm{
                         mov      eax, current
                         shr      eax, 22
                         test     dword ptr[eax*4+0C0300000h], 1
                         jz       __next_danp
                         mov      eax, current
                         shr      eax, 12
                         lea      eax, [eax*4+0C0000000h]
                         test     dword ptr[eax], 1
                         jz       __next_danp
                         or       dword ptr[eax], 04h               ;set user bit in pte

__next_danp:                       
                 }
                 current += 0x1000;
         }
        return;      
}       

void DeactivateAll_PAE(){
        DWORD current;
         current = Bpx.StartRange;
        while (current < Bpx.StartRange + Bpx.Size){
                 __asm{
                         mov      eax, current
                         shr      eax, 21
                         test     dword ptr[eax*8+0C0600000h], 1
                         jz       __next_da
                         mov      eax, current
                         shr      eax, 12
                         lea      eax, [eax*8+0C0000000h]
                         test     dword ptr[eax], 1
                         jz       __next_da
                         or       dword ptr[eax], 04h               ;set user bit in pte

__next_da:                       
                 }
                 current += 0x1000;
         }
        return;      
}

void ActivateAll_NoPAE(){
        DWORD current;
         current = Bpx.StartRange;
        while (current < Bpx.StartRange + Bpx.Size){
                 __asm{
                         mov      eax, current
                         shr      eax, 22
                         test     [eax*4+0C0300000h], 1
                         jz       __next_aanp
                         mov      eax, current
                         shr      eax, 12
                         lea      eax, [eax*4+0C0000000h]
                         test     dword ptr[eax], 1
                         jz       __next_aanp
                         and      dword ptr[eax], 0FFFFFFFBh               ;wipe user bit from PTE

__next_aanp:       
                 }
                 current += 0x1000;
         }
         __asm    mov      eax, cr3                         ;flush TLB... make sure that translation goes trough PTE
         __asm    mov      cr3, eax                         ;which will force cpu to see supervisor page...       
        return;      
}

void ActivateAll_PAE(){
        DWORD current;
         current = Bpx.StartRange;
        while (current < Bpx.StartRange + Bpx.Size){
                 __asm{
                         mov      eax, current
                         shr      eax, 21
                         test     [eax*8+0C0600000h], 1
                         jz       __next_aa
                         mov      eax, current
                         shr      eax, 12
                         lea      eax, [eax*8+0C0000000h]
                         test     dword ptr[eax], 1
                         jz       __next_aa
                         and      dword ptr[eax], 0FFFFFFFBh               ;wipe user bit from PTE

__next_aa:       
                 }
                 current += 0x1000;
         }
         __asm    mov      eax, cr3                         ;flush TLB... make sure that translation goes trough PTE
         __asm    mov      cr3, eax                         ;which will force cpu to see supervisor page...       
        return;      
}

void DeactivateAll(){
        if (PaeEnabled)
                 DeactivateAll_PAE();
         else
                 DeactivateAll_NoPAE();
        return;
}

void ActivateAll(){
        if (PaeEnabled)
                 ActivateAll_PAE();
         else
                 ActivateAll_NoPAE();
        return;
}

一个虚拟地址转换成物理地址的计算过程是:
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位
还得分两种情况:
非PAE分页模式.PDE,PTE的计算公式为:
PDE = ((VA >> 22) << 2 ) & 0xffc + 0xc0300000;
PTE = ((VA >> 12) << 2 ) & 0x3FFFFC + 0xc0000000;

PAE模式,PDE,PTE地址的计算公式是:
int    PDE = ((lVirtualAddress>>21)<<3) & 0x3FF8 + 0xC0600000;
int    PTE = ((lVirtualAddress>>12)<<3) & 0x7FFFF8 + 0xC0000000;

在PAE模式下PDE和PTE为64位,而不是原来的32位
实验代码:虚拟地址假设为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;
}

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

转自:http://hi.baidu.com/charme000/blog/item/40d75f72775b17158701b0b1.html

抱歉!评论已关闭.