前面我们尝试过在VC中获取CPUID信息。现在再来试试GCC编译器。
一、调用CPUID指令
怎么调用CPUID指令呢?有三种办法——
1. 用汇编语言编写一个cpuid函数,然后调整链接器配置,在C语言中调用该函数。
2. 使用内嵌汇编调用CPUID指令。
3. 使用编译器提供的Intrinsics函数来调用CPUID等特定平台指令。
我们一般优先使用第3种办法,代码量少、可读性高、编译维护简单。例如VC(VC2005或更高)在“intrin.h”中声明了 __cpuid函数。
当编译器没有提供Intrinsics函数时,就只有使用前两种办法了。
1.1 查找函数
首先,应该先检查编译器是否提供CPUID指令的Intrinsics函数。
我装的是Fedora 17,首先尝试了——
1. 使用“man”命令查阅手册,搜索“__cpuid”等关键字。没有找到。
2. 在“/usr/include”目录中的头文件中搜索“cpuid” 。也没有找到。
手册中没有,include中也没有,难道真的没有?
别着急,试一试“locate cpuid”,其中可以发现“/usr/lib/gcc/i686-redhat-linux/4.7.0/include/cpuid.h”。打开该文件,发现果然有“__cpuid”等声明。
再看一下MinGW(20120426版)。发现“cpuid.h”也是放在“\lib\gcc\mingw32\4.6.2\include”目录中,而不是“\include”目录。
1.2 代码解读
虽然手册上没有__cpuid的说明,但我们可以通过阅读代码分析其用法。
打开“cpuid.h”,找到__cpuid的声明——
#if defined(__i386__) && defined(__PIC__)
/*%ebx may be the PIC register.*/
#if __GNUC__ >= 3
#define __cpuid(level, a, b, c, d) \__asm__ ("xchg{l}\t{%%}ebx, %1\n\t"\"cpuid\n\t"\"xchg{l}\t{%%}ebx, %1\n\t"\
:"=a" (a), "=r" (b), "=c" (c), "=d"(d) \
:"0"(level))#define __cpuid_count(level, count, a, b, c, d) \__asm__ ("xchg{l}\t{%%}ebx, %1\n\t"\"cpuid\n\t"\"xchg{l}\t{%%}ebx, %1\n\t"\
:"=a" (a), "=r" (b), "=c" (c), "=d"(d) \
:"0" (level), "2"(count))#else
/*Host GCCs older than 3.0 weren't supporting Intel asm syntax
nor alternatives in i386 code.*/
#define __cpuid(level, a, b, c, d) \__asm__ ("xchgl\t%%ebx, %1\n\t