zoukankan      html  css  js  c++  java
  • C语言调用Intel处理器CPUID指令的实例

    C语言调用Intel处理器CPUID指令的实例

    来源 https://blog.csdn.net/subfate/article/details/50789905

    在Linux环境下,使用C语言内嵌汇编的手段使用CPUID指令,进而在高级语言层面上看到获取的信息。

    实现文件cpuid.c代码如下:

    struct cpuid_result {
        uint32_t eax;
        uint32_t ebx;
        uint32_t ecx;
        uint32_t edx;
    };
    
    /*
    * Generic CPUID function
    */
    static inline struct cpuid_result cpuid(unsigned int op)
    {
        struct cpuid_result result;
        __asm volatile(
            "mov %%ebx, %%edi;"
            "cpuid;"
            "mov %%ebx, %%esi;"
            "mov %%edi, %%ebx;"
            : "=a" (result.eax),
            "=S" (result.ebx),
            "=c" (result.ecx),
            "=d" (result.edx)
            : "0" (op)
            : "edi");
        return result;
    }
    
    static inline unsigned int cpuid_eax(unsigned int op)
    {
        //unsigned int eax, ebx, ecx, edx;  
        struct cpuid_result regs;
    
        regs = cpuid(op);
    
        return regs.eax;
    }
    
    void get_cpu_vendor(char* cpu_vendor, unsigned int* cpuid_level)
    {
        unsigned int cpuid_op = 0x00000000;
        char vendor_name[16] = {''};
        struct cpuid_result result;
        unsigned int level = 0;
    
        vendor_name[0] = ''; /* Unset */
        result = cpuid(cpuid_op); // eax为0表示读取vendor id,一共12字节,依次在ebx、edx、ecx。
        level = result.eax;
        vendor_name[0] = (result.ebx >> 0) & 0xff;
        vendor_name[1] = (result.ebx >> 8) & 0xff;
        vendor_name[2] = (result.ebx >> 16) & 0xff;
        vendor_name[3] = (result.ebx >> 24) & 0xff;
        vendor_name[4] = (result.edx >> 0) & 0xff;
        vendor_name[5] = (result.edx >> 8) & 0xff;
        vendor_name[6] = (result.edx >> 16) & 0xff;
        vendor_name[7] = (result.edx >> 24) & 0xff;
        vendor_name[8] = (result.ecx >> 0) & 0xff;
        vendor_name[9] = (result.ecx >> 8) & 0xff;
        vendor_name[10] = (result.ecx >> 16) & 0xff;
        vendor_name[11] = (result.ecx >> 24) & 0xff;
        vendor_name[12] = '';
    
        strcpy(cpu_vendor, vendor_name);
        *cpuid_level = level;
    }
    
    void get_cpu_id(char* cpu_id, unsigned int* cpu_sign)
    {
        unsigned int cpuid_op = 0x00000001;
        struct cpuid_result result;
        unsigned int sign = 0, id = 0;
        unsigned int tmp = 0;
    
        result = cpuid(cpuid_op);
        sign = result.eax;
        id = result.edx;
    
        sprintf(cpu_id, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", (sign >> 0) & 0xff, (sign >> 8) & 0xff, (sign >> 16) & 0xff, (sign >> 24) & 0xff,
            (id >> 0) & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff, (id >> 24) & 0xff);
        *cpu_sign = sign;
    }
    
    struct cpuinfo_x86 {
        uint8_t    x86;        /* CPU family */
        uint8_t    x86_vendor;    /* CPU vendor */
        uint8_t    x86_model;  /* CPU model */
        uint8_t    x86_step;  /* CPU stepping */
    };
    
    // 参考IA32开发手册第2卷第3章。CPUID exa==0x01的图3-6
    static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
    {
        c->x86 = (tfms >> 8) & 0xf;
        c->x86_model = (tfms >> 4) & 0xf;
        c->x86_step = tfms & 0xf;
        if (c->x86 == 0xf)
            c->x86 += (tfms >> 20) & 0xff;
        if (c->x86 >= 0x6)
            c->x86_model += ((tfms >> 16) & 0xF) << 4;
    }
    
    void get_cpu_fms(unsigned int* family, unsigned int* model, unsigned int* stepping)
    {
        unsigned int cpuid_op = 0x00000001;
        struct cpuinfo_x86 c;
        unsigned int ver = 0;
    
        ver = cpuid_eax(cpuid_op);
        get_fms(&c, ver);
    
        *family = c.x86;
        *model = c.x86_model;
        *stepping = c.x86_step;
    }
    
    void get_cpu_name(char* processor_name)
    {
        unsigned int cpuid_op = 0x80000002;
        struct cpuid_result regs;
        char temp_processor_name[49];
        char* processor_name_start;
        unsigned int *name_as_ints = (unsigned int *)temp_processor_name;
        unsigned int i;
    
        /*
        用cpuid指令,eax传入0x80000002/0x80000003/0x80000004,
        共3个,每个4个寄存器,每个寄存器4字节,故一共48字节。
        参考IA32开发手册第2卷第3章。
        */
        for (i = 0; i < 3; i++) {
            regs = cpuid(cpuid_op + i);
            name_as_ints[i * 4 + 0] = regs.eax;
            name_as_ints[i * 4 + 1] = regs.ebx;
            name_as_ints[i * 4 + 2] = regs.ecx;
            name_as_ints[i * 4 + 3] = regs.edx;
        }
    
        temp_processor_name[49] = ''; // 最后的字节为0,结束
    
        /* Skip leading spaces. */
        processor_name_start = temp_processor_name;
        while (*processor_name_start == ' ')
            processor_name_start++;
    
        memset(processor_name, 0, 49);
        strcpy(processor_name, processor_name_start);
    }
    
    void get_address_bits(unsigned int* linear, unsigned int* physical)
    {
        unsigned int cpuid_op = 0x80000008;
        unsigned int tmp = 0;
        tmp = cpuid_eax(cpuid_op);
        *linear = (tmp >> 8) & 0xff;
        *physical = (tmp >> 0) & 0xff;
    
    }

    主函数实现代码如下:

    void get_hw_cpu(void)
    {
        char buffer[49] = { '' };
        unsigned int num = 0;
        unsigned int f = 0, m = 0, s = 0;
        unsigned int phy_bits = 0, vir_bits = 0;
    
        memset((void *)buffer, '', sizeof(buffer));
        num = 0;
        get_cpu_vendor(buffer, &num);
        fprintf(stdout, "vendor_id 	: %s
    ", buffer);
        fprintf(stdout, "cpuid level 	: %u
    ", num);
    
        memset((void *)buffer, '', sizeof(buffer));
        num = 0;
        get_cpu_id(buffer, &num);
        fprintf(stdout, "cpu_id serial 	: %s
    ", buffer);
        fprintf(stdout, "cpuid sign 	: %u
    ", num);
    
        memset((void *)buffer, '', sizeof(buffer));
        get_cpu_name(buffer);
        fprintf(stdout, "model name 	: %s
    ", buffer);
    
        get_cpu_fms(&f, &m, &s);
        fprintf(stdout, "cpu family 	: %u(0x%0X)
    ", f, f);
        fprintf(stdout, "cpu model 	: %u(0x%0X)
    ", m, m);
        fprintf(stdout, "cpu stepping 	: %u(0x%0X)
    ", s, s);
    
        get_address_bits(&vir_bits, &phy_bits);
        fprintf(stdout, "address sizes 	: %u bits physical - %u bits virtual
    ", phy_bits, vir_bits);
    
    }

    Intel处理器的CPUID远不止上文所述,详情请参考Intel IA32软件开发手册。

    在GCC中获取CPUID信息(兼容VC) https://www.cnblogs.com/zyl910/archive/2012/08/06/getcpuid_gcc.html

    =========================== End

  • 相关阅读:
    [恢]hdu 2098
    [恢]hdu 2049
    [恢]hdu 2027
    [恢]hdu 2111
    [恢]hdu 1202
    [恢]hdu 2131
    Windows Phone 7 文件下载进度和速度显示
    深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例
    深入WPF中的图像画刷(ImageBrush)之2——ImageBrush的铺设方式
    textblock设置属性
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/9553404.html
Copyright © 2011-2022 走看看