IA-32e模式下无法读写4GB以上内存地址的问题求助
问题根源与修复方案
核心问题:页表覆盖范围不足
你的页表仅配置了PDPT索引0的项,只能映射0-1GB的虚拟地址。4GB以上的地址(如0x100000000)属于PDPT索引4的范围(每个PDPT项对应1GB),但你未为该索引配置页表项,导致访问时触发缺页异常,最终表现为读写无效果。同时,页表项标志位不完整也加剧了错误。
具体修复步骤
1. 扩展PDPT表,添加4GB对应索引的项
修改PAGE_DIRECTROIC_POINTER_TABLE0,补充索引4的项,指向新的PD表物理地址(需4KB对齐):
PAGE_DIRECTROIC_POINTER_TABLE0: dq 0000000000003003h ; 原索引0,指向0x3000的PD表,添加可写位(RW,第1位) times 4 dq 0 ; 填充索引1-3的空项 dq 0000000000005003h ; 索引4,指向0x5000的PD表,用于映射4GB-5GB PAGE_DIRECTROIC_POINTER_TABLE_END:
2. 创建新的PD表,用于映射4GB区域
新增PD表,指向对应PT表:
PAGE_DIRECTROIC_TABLE1: ; 4GB-5GB对应的PD表 dq 0000000000006003h ; 指向0x6000的PT表,标志位含存在位(P)+可写位(RW) PAGE_DIRECTROIC_TABLE1_END:
3. 创建对应PT表,映射4GB起始的4KB页
新增PT表项,将4GB起始虚拟地址映射到目标物理地址(需4KB对齐):
PAGE_L3_4GB: dq 0000000a00000003h ; 虚拟地址0x100000000 → 物理地址0xA00000000,含P+RW位 PAGE_L3_4GB_END:
4. 复制新增页表到物理内存
在16位初始化部分,添加复制新PD表和PT表的代码:
; 复制4GB区域的PD表 mov ax,0 mov ds,ax mov es,ax mov si,PAGE_DIRECTROIC_TABLE1 mov di,00005000h mov cx,PAGE_DIRECTROIC_TABLE1_END - PAGE_DIRECTROIC_TABLE1 cld rep movsb ; 复制4GB对应的PT表 mov ax,0 mov ds,ax mov es,ax mov si,PAGE_L3_4GB mov di,00006000h mov cx,PAGE_L3_4GB_END - PAGE_L3_4GB cld rep movsb
5. 修改测试代码,访问正确的4GB虚拟地址
调整test4gb块,访问4GB起始的虚拟地址:
test4gb: mov al,'w' mov byte [0x100000000],al ; 访问4GB以上的虚拟地址 mov bl,byte [0x100000000] mov byte [0x20],bl ; 将读取的值显示到屏幕 jmp $
额外注意事项
- 页表对齐:所有页表(PML4、PDPT、PD、PT)必须在4KB(
0x1000)地址边界对齐,你的代码已满足此要求。 - 标志位设置:页表项低12位为控制标志,至少需设置
P(存在位,第0位)和RW(可写位,第1位),否则无法正常读写。若需用户态访问,还需设置US位(第2位)。 - 物理地址有效性:确保映射的物理地址实际存在,建议先用虚拟机(如QEMU)测试,避免硬件限制导致的问题。
内容的提问来源于stack exchange,提问作者sanzenyou
相关产品推荐
相关产品推荐

