Linux C/C++ 获取CPUID

2024-01-03 15:54:53

实现方式:

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

文章来源:https://blog.csdn.net/liulilittle/article/details/135361541
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。