linux cpuid指令,通过CPUID指令获取CPU信息

1.简介

在计算机领域中需要用到CPU信息的地方有很多。比如,在可信计算中,需要收集终端的软硬件的完整性信息,其中就包含CPU的信息;再比如,一些加密软件需要绑定CPU的某些信息,去生成加密密钥。本文就关于在Linux平台下CPU信息的获取展开阐述。

CPU信息获取的方式有两种方式:

1. 使用内嵌汇编调用CPUID指令

2. 读取/proc/cpuinfo文件

本文主要对第一种方式-“使用内嵌汇编调用CPUID指令”进行说明,在下一篇中重点对‘读取/proc/cpuinfo文件’的方式进行讲解。

以”使用内嵌汇编调用CPUID指令”的方式获取CPU信息。首先使用内嵌汇编调用CPUID指令来获取CPUID、CPU厂商、CPU Brand、CPU Family、CPU Model、CPU Stepping ID,然后采用MD5算法计算CPU信息的Hash值。

2.CPUID指令

CPUID指令的基本原理是,CPU根据传递给EAX 寄存器的值,将对应的CPU信息返回给 EAX、EBX、ECX 及 EDX 寄存器。通过对这些寄存器的值进行操作即可获取CPU各类信息。CPUID指令带代码如下:

#define cpuid(func,eax,ebx,ecx,edx)\

__asm__ __volatile__ ("cpuid":\

"=a" (eax),"=b" (ebx),"=c" (ecx),"=d" (edx):\

"a" (func));

本文使用了宏定义的方式封装CPUID指令函数。如对此处的宏定义不太清楚,请阅读。GCC内嵌汇编的格式是——

_asm__ _volatile__(“asm statements” : outputs : inputs : registers-modified);

对于上面的__cpuid

asm statements: “cpuid”。汇编代码为——调用cpuid指令

outputs:”=a” (eax), “=b” (ebx), “=c” (ecx), “=d” (edx)。表示有4个输出参数——参数0为eax(绑定到变量a)、参数1为ebx(绑定到变量b)、参数2为ecx(绑定到变量c)、参数3为edx(绑定到变量d)。

inputs:”a” (func)。表示有1个输入参数——将变量func赋给参数0(eax)。

registers-modified:(无)。

因此,上述cpuid函数执行过程为:

1. 将变量func的值赋给eax

2. 执行cpuid指令

3. 将返回的eax的值赋给a

4. 将返回的ebx的值赋给b

5. 将返回的ecx的值赋给c

6. 将返回的edx的值赋给d

3.获取CPU ID

功能号eax=0x80000004,返回CPU ID。执行cpuid指令后,返回值寄存器依次为eax,ebx,ecx,edx。具体代码如下:

void getCPUID(char *cpuId)

{

int a,b,c,d;

char cpuid_buf[HWI_BUFFER_SIZE];

memset((void*)cpuid_buf,0,HWI_BUFFER_SIZE);

cpuid(0x80000004,a,b,c,d);

sprintf(cpuid_buf,"%#010x %#010x %#010x %#010x",a,b,c,d);

strcpy(cpuId,cpuid_buf);

}

4.获取CPU 厂商

功能号eax=0,返回CPU 厂商。执行cpuid指令后,返回值寄存器依次为ebx,ecx,edx。具体代码如下:

void getCPUCompany(char *cCom)

{

char ComName[13];

int a,b,c,d;

int i,k;

memset((void*)ComName,0,sizeof(ComName));

cpuid(0,a,b,c,d);

for(i = 0; b > 0; i++)

{

k = b;

k = (k>>8);

k = (k<<8);

ComName[i]=b-k;

b=(b>>8);

}

for(; d > 0; i++)

{

k = d;

k = (k>>8);

k = (k<<8);

ComName[i]=d-k;

d=(d>>8);

}

for(; c > 0; i++)

{

k = c;

k = (k>>8);

k = (k<<8);

ComName[i]=c-k;

c=(c>>8);

}

ComName[12]='\0';

strcpy(cCom,ComName);

}

5.获取CPU Brand

EAX=80000002h、80000003h、80000004h:返回处理器brand字符串。

void getCPUBrand(char *cBrand)

{

int a,b,c,d,i;

unsigned int cpu_brand_buf[13];

int k = 0;

memset((void*)cpu_brand_buf,0,sizeof(cpu_brand_buf));

/**

* eax == 0x800000000

* 如果CPU支持Brand String,则在EAX中返 >= 0x80000004的值。

*/

cpuid(0x80000000,a,b,c,d);

if(a < 0x80000004)

{

printf("the cpu is not support\n");

return;

}

for(i=0x80000002;i<=0x80000004;i++)

{

cpuid(i,a,b,c,d);

cpu_brand_buf[k++]=a;

cpu_brand_buf[k++]=b;

cpu_brand_buf[k++]=c;

cpu_brand_buf[k++]=d;

}

strcpy(cBrand,(char*)cpu_brand_buf);

printf("CPU Brand:%s\n", (char *)cpu_brand_buf);

}

6.获取CPU Family,Model,Stepping ID

EAX=0x01,返回Model、Family、Stepping信息.执行CPUID后,返回的EAX寄存器包含Model、Family、Stepping信息。

void getCPUBaseParam(char *baseParam)

{

char baseParamBuf[HWI_BUFFER_SIZE];

unsigned long CPUBaseInfo;

int a,b,c,d;

memset((void*)baseParamBuf,0,HWI_BUFFER_SIZE);

cpuid(1,a,b,c,d);

CPUBaseInfo = a;

sprintf(baseParamBuf,"Family:%d Model:%d Stepping ID:%d",

(CPUBaseInfo & 0x0F00)>>8,(CPUBaseInfo & 0xF0)>>4,CPUBaseInfo & 0xF);

strcpy(baseParam,baseParamBuf);

}

7.运行结果

程序运行结果:

0818b9ca8b590ca3270a3433284dd417.png

8.完整代码

主要包括获取CPU信息源文件,MD5源文件,Makefile文件。地址:完整代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值