如何在运行时检测使用的 CPU?C++ 代码需要区分 AMD/Intel 架构。使用 gcc 4.2。
cpuid
指令与EAX=0
一起使用时,将按顺序在EBX
、EDX
、ECX
中返回一个12个字符的供应商字符串。对于英特尔(Intel),此字符串为“GenuineIntel”。对于AMD,则为“AuthenticAMD”。其他创建x86芯片的公司也有自己的字符串。 Wikipedia页面列出了许多(全部?)的字符串,以及检索详细信息的示例ASM列表。
您只需要检查ECX是否与最后四个字符匹配。您不能使用前四个字母,因为一些Transmeta CPU也以“Genuine”开头。
0x6c65746e
0x444d4163
如果将这些字节转换为字符,则它们看起来是反向的。这只是x86的小端设计产生的结果。如果将寄存器复制到内存并将其作为字符串查看,则可以正常工作。
示例代码:
bool IsIntel() // returns true on an Intel processor, false on anything else
{
int id_str; // The first four characters of the vendor ID string
__asm__ ("cpuid":\ // run the cpuid instruction with...
"=c" (id_str) : // id_str set to the value of EBX after cpuid runs...
"a" (0) : // and EAX set to 0 to run the proper cpuid function.
"eax", "ebx", "edx"); // cpuid clobbers EAX, ECX, and EDX, in addition to EBX.
if(id_str==0x6c65746e) // letn. little endian clobbering of GenuineI[ntel]
return true;
else
return false;
}
编辑:还有一件事 - 只需更改if
中的魔术数字,就可以轻松将此代码更改为IsAMD
函数、IsVIA
函数、IsTransmeta
函数等。
IsAMD
function, IsVIA
function, IsTransmeta
function, etc. just by changing the magic number in the if
.如果您使用Linux(或在Cygwin下运行的Windows),您可以通过读取特殊文件/proc/cpuinfo
并查找以vendor_id
开头的行来确定。 如果字符串为GenuineIntel
,则表示您正在运行Intel芯片。 如果是AuthenticAMD
,则表示您正在运行AMD芯片。
void get_vendor_id(char *vendor_id) // must be at least 13 bytes
{
FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
; // handle error
char line[256];
while(fgets(line, 256, cpuinfo))
{
if(strncmp(line, "vendor_id", 9) == 0)
{
char *colon = strchr(line, ':');
if(colon == NULL || colon[1] == 0)
; // handle error
strncpy(vendor_id, 12, colon + 2);
fclose(cpuinfo);
return;
}
}
// if we got here, handle error
fclose(cpuinfo);
}
如果您知道您正在运行x86架构,一个不太便携的方法是使用CPUID指令:
void get_vendor_id(char *vendor_id) // must be at least 13 bytes
{
// GCC inline assembler
__asm__ __volatile__
("movl $0, %%eax\n\t"
"cpuid\n\t"
"movl %%ebx, %0\n\t"
"movl %%edx, %1\n\t"
"movl %%ecx, %2\n\t"
: "=m"(vendor_id), "=m"(vendor_id + 4), "=m"(vendor_id + 8) // outputs
: // no inputs
: "%eax", "%ebx", "%edx", "%ecx", "memory"); // clobbered registers
vendor_id[12] = 0;
}
int main(void)
{
char vendor_id[13];
get_vendor_id(vendor_id);
if(strcmp(vendor_id, "GenuineIntel") == 0)
; // it's Intel
else if(strcmp(vendor_id, "AuthenticAMD") == 0)
; // it's AMD
else
; // other
return 0;
}
你可能根本不应该去检查。相反,检查CPU是否支持你需要的功能,例如SSE3。两个英特尔芯片之间的差异可能比AMD和英特尔芯片之间的差异要大。
uname -p 2>&1
,然后使用#ifdef i386和# endif来处理不同的架构。
int Last4()
,返回最后四个字符作为整数,然后很容易地创建bool IsIntel() { return Last4() == 0x6c65746e; }
和bool IsAMD() { return Last4() == 0x444d4163; }
。这还避免了代码重复,并减少了所需的内联汇编总量。 - Chris Lutz