Linux C/C++ 获取CPUID
实现方式:
INTEL CC 格式
AT^T CC 格式
GCC/C库 __cpuid 宏
大致讲义:
AT^T 格式汇编很反人类,GCC可以改编译器选项为INTEL内嵌汇编,但一般在GCC还是按照默认的AT^T汇编来拽写把,不想用也可以让AI工具把INTEL内嵌汇编转换为AT^T汇编(让 bard、gpt、bing 干这种反人类的活很好用),AT^T汇编格式没有学的必要,这是一个反人类的东西。
__asm__ __volatile__(
"movl $0x00, %%eax\n\t"
"xorl %%edx, %%edx\n\t"
"cpuid\n\t"
"movl %%eax, %0\n\t"
"movl %%edx, %1\n\t"
: "=m" (s1), "=m" (s2)
:
: "%eax", "%edx"
);
汇编是一种面向地址标识符及通用寄存器编程的低级语言。
IL: 把立即数0移动到EAX寄存器,CPU参数(LEVEL,CPU内置指令函数取值范围0~1)
IL: 把EDX寄存器XOR(亦或)重置为0
IL: cpuid 指令(会推送值到EAX、EBX、ECX、EDX 四个寄存器之中,SN[4])
IL: 把EAX寄存器的值复制给内链参数一(注意是压入是内存地址,%0 = s1变量)
IL: 把EDX寄存器的值复制给内链参数二(注意是压入是内存地址,%1 = s2变量)
声明内嵌所需要的寄存器与变量内存地址。
注解:
__asm__ __volatile__ (
"movl $0x00, %%eax\n\t" // 将立即数 0x00 移动到 eax 寄存器中
"xorl %%edx, %%edx\n\t" // 将 edx 寄存器与自身进行异或操作,相当于将 edx 清零
"cpuid\n\t" // 执行 cpuid 指令,用于获取 CPU 的信息
"movl %%eax, %0\n\t" // 将 eax 寄存器的值移动到 s1 变量中
"movl %%edx, %1\n\t" // 将 edx 寄存器的值移动到 s2 变量中
: "=m" (s1), "=m" (s2) // 输出操作数列表,将 s1 和 s2 分别与 %0 和 %1 关联起来
: // 输入操作数列表为空
: "%eax", "%edx" // 使用了 eax 和 edx 寄存器,需要在此处进行声明
);
具体实现:
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
ppp::string CPUID() noexcept {
int s1, s2, s3, s4;
// int sn[4]; /* #include <cpuid.h> */
// __cpuid(0, sn[0], sn[1], sn[2], sn[3]);
// s1 = sn[0];
// s2 = sn[3];
// __cpuid(1, sn[0], sn[1], sn[2], sn[3]);
// s3 = sn[0];
// s4 = sn[3];
// INTEL CC:
// __asm
// {
// mov eax, 00h
// xor edx, edx
// cpuid
// mov dword ptr[s1], eax
// mov dword ptr[s2], edx
// }
// __asm
// {
// mov eax, 01h
// xor ecx, ecx
// xor edx, edx
// cpuid
// mov dword ptr[s3], eax
// mov dword ptr[s4], edx
// }
// AT&T CC
__asm__ __volatile__(
"movl $0x00, %%eax\n\t"
"xorl %%edx, %%edx\n\t"
"cpuid\n\t"
"movl %%eax, %0\n\t"
"movl %%edx, %1\n\t"
: "=m" (s1), "=m" (s2)
:
: "%eax", "%edx"
);
__asm__ __volatile__(
"movl $0x01, %%eax\n\t"
"xorl %%ecx, %%ecx\n\t"
"xorl %%edx, %%edx\n\t"
"cpuid\n\t"
"movl %%eax, %0\n\t"
"movl %%edx, %1\n\t"
: "=m" (s3), "=m" (s4)
:
: "%eax", "%ecx", "%edx"
);
// You can query all CPU processor instances using WQL in wbemtest,
// View the ProcessorId attribute of the processor instance MOF,
// And clarify the rules for the operating system CPUID to obtain and format as text.
char buf[40];
snprintf(buf, sizeof(buf), "%016llX %016llX",
(long long unsigned int)((int64_t)s4 << 32 | (int64_t)s3),
(long long unsigned int)((int64_t)s2 << 32 | (int64_t)s1));
return buf;
}
#endif