如何检测运行时使用的CPU?c ++代码需要区分AMD/Intel架构吗?使用gcc 4.2.
的cpuid
指令,与用于EAX=0
将在返回12个字符的供应商字符串EBX
,EDX
,ECX
,的顺序.
对于Intel,此字符串为"GenuineIntel".对于AMD来说,它是"AuthenticAMD".已经创造了x86芯片的其他公司也有自己strings.The 维基百科页面为cpuid
具有列出的字符串,以及检索内容的一例ASM上市的很多(所有?).
您真的只需要检查ECX是否与最后四个字符匹配.你不能使用前四个,因为一些Transmeta CPU也以"正版"开头
对于英特尔来说,这是 0x6c65746e
对于AMD来说,这是 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; }
编辑:另一件事 - 只需更改中的幻数即可轻松将其更改为IsAMD
函数,IsVIA
函数,IsTransmeta
函数等if
.
如果你在Linux上(或在Cygwin下运行的Windows上),你可以通过阅读特殊文件/proc/cpuinfo
并查找以...开头的行来解决这个问题vendor_id
.如果是字符串GenuineIntel
,则表示您正在使用英特尔芯片.如果你得到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; }