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变量)

声明内嵌所需要的寄存器与变量内存地址。

注解:

cpp 复制代码
__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 寄存器,需要在此处进行声明
);

具体实现:

cpp 复制代码
#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
相关推荐
进击的丸子5 分钟前
虹软人脸服务器版SDK(Linux/ARM Pro)多线程调用及性能优化
linux·数据库·后端
Johny_Zhao1 天前
OpenClaw安装部署教程
linux·人工智能·ai·云计算·系统运维·openclaw
RuoZoe2 天前
重塑WPF辉煌?基于DirectX 12的现代.NET UI框架Jalium
c语言
blasit2 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_3 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
chlk1233 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑3 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件3 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
不想写代码的星星3 天前
虚函数表:C++ 多态背后的那个男人
c++
深紫色的三北六号3 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移