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
相关推荐
CSDN_RTKLIB8 分钟前
错进错出得到正确的字节序列
c++
Lw老王要学习24 分钟前
CentOS 7.9达梦数据库安装全流程解析
linux·运维·数据库·centos·达梦
闻缺陷则喜何志丹32 分钟前
【前后缀分解 排序】B4274 [蓝桥杯青少年组省赛 2023] 数字游戏|普及+
c++·蓝桥杯·排序·洛谷·前后缀分解
m0_7369191032 分钟前
C++中的享元模式变体
开发语言·c++·算法
集芯微电科技有限公司38 分钟前
15V/2A同步开关型降压单节/双节锂电池充电管理IC支持输入适配器 DPM 功能
c语言·开发语言·stm32·单片机·嵌入式硬件·电脑
CRUD酱1 小时前
CentOS的yum仓库失效问题解决(换镜像源)
linux·运维·服务器·centos
zly35001 小时前
VMware vCenter Converter Standalone 转换Linux系统,出现两个磁盘的处理
linux·运维·服务器
Albert Edison1 小时前
【Python】函数
java·linux·python·pip
zho_uzhou1 小时前
c++ imgui implot绘图使用示例 visual studio
开发语言·c++·visual studio
dyyx1112 小时前
C++中的过滤器模式
开发语言·c++·算法