如果支持,您可以使用CPUID.80000008H:EAX[7:0]
。
算法如下:
- 检查
cpuid
的最大扩展E值,使用CPUID.80000000h.EAX
。
- 如果E >= 80000008h,则使用
CPUID.80000008H:EAX[7:0]
作为物理地址位数。
CPUID.80000008H:EAX[15:8]
作为线性地址位数。
- 否则,如果
CPUID.1:EDX.PAE
(第6位)为真,则CPU具有36个物理地址位和32个线性地址位。
- 否则,CPU具有32个物理和逻辑地址位。
来自Intel的符号CPUID.X:R B
表示
- X 在
cpuid
之前要放入eax
的值。
- R 感兴趣的输出寄存器。
- B 一个形式为[upper:lower]或形式为.bitname的命名位域。
AMD将虚拟:物理地址的最大限制设置为63:52。
当前实现通常为48:40,但物理地址空间的大小可能不同。
以下是可以使用NASM编译的示例代码:
BITS 64
GLOBAL max_phy_addr
GLOBAL max_lin_addr
SECTION .text
max_phy_addr:
push rbx
mov eax, 80000000h
cpuid
cmp eax, 80000008h
jae .fromCpuid
mov eax, 1
cpuid
mov eax, 32
shr edx, 4
and edx, 4
add eax, edx
pop rbx
ret
.fromCpuid:
mov eax, 80000008h
cpuid
movzx eax, al
pop rbx
ret
max_lin_addr:
push rbx
mov eax, 80000000h
cpuid
cmp eax, 80000008h
jae .fromCpuid
mov eax, 1
cpuid
mov eax, 32
pop rbx
ret
.fromCpuid:
mov eax, 80000008h
cpuid
movzx eax, ah
pop rbx
ret
并且可以与C程序一起使用,例如:
#include <stdio.h>
long max_phy_addr();
long max_lin_addr();
int main()
{
printf("Phy: %llu\nLin: %llu\n", max_phy_addr(), max_lin_addr());
return 0;
}
我刚刚发现我的Haswell是48:39!
注:Haswell是英特尔公司推出的一款处理器系列。