一 CPUID介绍
CPUID 是一个用于获取中央处理单元(CPU)相关信息的指令。它通常在 x86 架构的计算机上使用,通过读取 CPU 寄存器中的特定值来提供关于 CPU 特性、制造商、型号和支持的功能的信息。CPUID 指令返回的信息对于操作系统、编程、性能优化以及硬件识别非常有用。以下是有关 CPUID 的详细信息:
- 指令执行和寄存器: CPUID 指令通常是一个特定的汇编指令,它向 CPU 请求信息,并将结果存储在一组特殊寄存器中。在 x86 架构中,CPUID 指令的操作码为 0x0F A2。执行这个指令会将 CPU 的一些关键信息加载到通用寄存器中,通常是 EAX、EBX、ECX 和 EDX 寄存器。
- 返回的信息: CPUID 指令返回的信息包括:
- EAX 寄存器:包含一些通用信息,如最大支持的 CPUID 值。
- EBX 寄存器:包含制造商相关信息,如 "GenuineIntel"(英特尔)或 "AuthenticAMD"(AMD)。
- ECX 寄存器:包含一些功能和特性的标志位,例如是否支持虚拟化、AES 指令集等。
- EDX 寄存器:包含其他功能和特性的标志位,如 MMX、SSE 等。
- 获取的信息: 使用 CPUID 指令,可以获取以下信息:
- CPU 制造商:通过 EBX 寄存器中的字符串值来识别制造商,如 Intel、AMD 等。
- CPU 型号和系列:这些信息可以帮助确定 CPU 的型号,从而更好地优化代码。
- 支持的指令集:了解 CPU 是否支持特定的指令集(如 MMX、SSE、AVX 等),以便在编程中使用。
- 缓存大小和配置:获取 CPU 的缓存层次、大小和配置,以优化内存访问模式。
- 支持的扩展特性:了解 CPU 是否支持虚拟化、64 位操作系统等。
二 常见的CPUID介绍
常见的一些CPUID参数及其返回信息:
- EAX=0:获取最大参数值和厂商标识符。
- EAX=1:获取CPU型号、系列号、步进和特性信息。
- EAX=2:获取高级处理器缓存描述符。
- EAX=3:获取处理器序列号。
- EAX=4:获取确定处理器类型的确定位。
- EAX=0x80000000:获取最大扩展参数值和厂商标识符。
- EAX=0x80000001:获取扩展处理器信息和特性位。
- EAX=0x80000002-4:获取处理器品牌字符串。
通过组合调用,可以获取CPU的全部信息,如厂商、品牌、型号、缓存、指令集等,用来检测和识别CPU非常有用。现在编程中通过CPUID已经成为一种标准的获取CPU信息的方式。
三 编程实现CPUID的读取
以下是DOS下的程序,可以读取CPUID
#include <stdio.h>
void main()
{
unsigned long DBaseIndex, DFeInfo, DFeInfo2, DCPUBaseInfo;
unsigned long DFeIndex, DCPUExInfo, i;
unsigned long DOther[4], DTLB[4], DProceSN[2];
char cCom[13];
char cProStr[49];
unsigned int j;
_asm
{
xor eax, eax
cpuid
mov DBaseIndex ,eax
mov dword ptr cCom ,ebx //基本CPU信息,品牌名
mov dword ptr cCom+4 ,ecx //AMD CPU要把ecx改为edx
mov dword ptr cCom+8 ,edx //AMD CPU要把edx改为ecx
mov eax, 1 //EAX版本信息:类型、系列、型号和步进ID
cpuid
mov DCPUBaseInfo, eax
mov DFeInfo, ebx
mov DFeInfo2, edx //功能标志的一些信息传输到edx
mov eax, 0x80000000 //当cpuid在eax设置为80000000H的情况下执行时,处理器返回扩展处理器信息
cpuid
mov DFeIndex, eax
mov eax, 0x80000001 //准备返回EAX扩展处理器签名和功能位
cpuid
mov DCPUExInfo, eax
mov eax, 0x80000002 //准备返回处理器品牌字符串
cpuid
mov dword ptr cProStr , eax
mov dword ptr cProStr + 4 , ebx
mov dword ptr cProStr + 8 , ecx
mov dword ptr cProStr + 12 ,edx
mov eax, 0x80000003 //准备返回处理器品牌字符串
cpuid
mov dword ptr cProStr + 16 , eax
mov dword ptr cProStr + 20 , ebx
mov dword ptr cProStr + 24 , ecx
mov dword ptr cProStr + 28 , edx
mov eax, 0x80000004 //准备返回处理器品牌字符串
cpuid
mov dword ptr cProStr + 32 , eax
mov dword ptr cProStr + 36 , ebx
mov dword ptr cProStr + 40 , ecx
mov dword ptr cProStr + 44 , edx
}
if( DBaseIndex >= 2 )
{
_asm
{
mov eax, 2 //CPUID在EAX设置为02H情况下
cpuid //返回有关处理器内部TLB、缓存和预取硬件的信息
mov DTLB[0], eax
mov DTLB[2], ebx
mov DTLB[3], ecx
mov DTLB[4], edx
}
}
if(DBaseIndex == 3)
{
_asm
{
mov eax, 3
cpuid
mov DProceSN[0], ecx
mov DProceSN[1], edx
}
}
// cCom[12] = '/0'; //加一个结尾符
printf( "CPU Manufacturer:%s\n", cCom );
printf( "CPU String:%s\n", cProStr );
printf( "CPU Basic Parameters: Family:%X Model:%X Stepping ID:%X\n", (DCPUBaseInfo & 0x0F00) >> 8,
(DCPUBaseInfo & 0xF0) >> 4, DCPUBaseInfo & 0xF );
printf( "CPU Extended Parameters: Family:%X Model:%X Stepping ID:%X\n", (DCPUExInfo & 0x0F00) >> 8,
(DCPUExInfo & 0xF0) >> 4, DCPUExInfo & 0xF );
printf( "CPU String Index:0x%X\n", DFeInfo & 0xFF );
printf( "CLFLUSH Size:0x%X\n", ( DFeInfo & 0xFF00 ) >> 8 );
printf ( "APIC number:0x%X\n", ( DFeInfo & 0xF000 ) >> 24 );
if( DBaseIndex == 3 )
{
printf( "CPU Serial Number:%X%X\n", DProceSN[0], DProceSN[1] );
}
printf( "FPU: %d\t\t", DFeInfo2 & 0x00000001 ); //下面是调用某BLOG上面的代码,懒得写了 ^^
printf( "VME: %d\t\t", (DFeInfo2 & 0x00000002 ) >> 1 );
printf( "DE: %d\n", (DFeInfo2 & 0x00000004 ) >> 2 );
printf( "PSE: %d\t\t", (DFeInfo2 & 0x00000008 ) >> 3 );
printf( "TSC: %d\t\t", (DFeInfo2 & 0x00000010 ) >> 4 );
printf( "MSR: %d\n", (DFeInfo2 & 0x00000020 ) >> 5 );
printf( "PAE: %d\t\t", (DFeInfo2 & 0x00000040 ) >> 6 );
printf( "MCE: %d\t\t", (DFeInfo2 & 0x00000080 ) >> 7 );
printf( "CX8: %d\n", (DFeInfo2 & 0x00000100 ) >> 8 );
printf( "APIC: %d\t", (DFeInfo2 & 0x00000200 ) >> 9 );
printf( "SEP: %d\t\t", (DFeInfo2 & 0x00000800 ) >> 11 );
printf( "MTRR: %d\n", (DFeInfo2 & 0x00001000 ) >> 12 );
printf( "PGE: %d\t\t", (DFeInfo2 & 0x00002000 ) >> 13 );
printf( "MCA: %d\t\t", (DFeInfo2 & 0x00004000 ) >> 14 );
printf( "CMOV: %d\n", (DFeInfo2 & 0x00008000 ) >> 15 );
printf( "PAT: %d\t\t", (DFeInfo2 & 0x00010000 ) >> 16 );
printf( "PSE-36: %d\t", (DFeInfo2 & 0x00020000 ) >> 17 );
printf( "PSN: %d\n", (DFeInfo2 & 0x00040000 ) >> 18 );
printf( "CLFSN: %d\t", (DFeInfo2 & 0x00080000 ) >> 19 );
printf( "DS: %d\t\t", (DFeInfo2 & 0x00200000 ) >> 21 );
printf( "ACPI: %d\n", (DFeInfo2 & 0x00400000 ) >> 22 );
printf( "MMX: %d\t\t", (DFeInfo2 & 0x00800000 ) >> 23 );
printf( "FXSR: %d\t", (DFeInfo2 & 0x01000000 ) >> 24 );
printf( "SSE: %d\n", (DFeInfo2 & 0x02000000 ) >> 25 );
printf( "SSE2: %d\t", (DFeInfo2 & 0x04000000 ) >> 26 );
printf( "SS: %d\t\t", (DFeInfo2 & 0x08000000 ) >> 27 );
printf( "TM: %d\n", (DFeInfo2 & 0x20000000 ) >> 29 );
printf("\nOther Info:\n");
printf("----------------------------------------\n");
printf("In \t\tEAX \t\tEBX \t\tECX \t\tEDX");
for( i = 0x80000004; i <= DFeIndex; ++i )
{
DOther[0] = DOther[1] = DOther[2] = DOther[3] = 0;
_asm
{
mov eax, i
cpuid
mov DOther[0], eax
mov DOther[1], ebx
mov DOther[2], ecx
mov DOther[3], edx
}
printf( "\n0x%.8X\t0x%.8X\t0x%.8X\t0x%.8X\t0x%.8X", i, DOther[0], DOther[1], DOther[2], DOther[3] );
}
printf( "\n" );
}
运行结果:
标签:DFeInfo2,读取,mov,eax,printf,CPUID,CPU From: https://blog.51cto.com/u_16204156/7068228