c++获取cpu信息方法

PS:此文章是从本人sina博客搬移过来;

此文章好像是我之前 参照一个博客做的测试程序。是谁我找不到作者了。对此。表示对作者表示抱歉;



intelIA32架构下,通过cpuid命令,获得CPU信息的汇编指令,可以得到CPU类型,型号,制造商信息,商标信息,序列号,缓存等一系列CPU相关的东西。当然有的也不支持索引CPU序列号;

cpuid使用eax作为输入参数;eax,ebx,ecx,edx作为输出参数;

具体汇编实现:

__asm

{

mov,eax,param

cpuid

mov,vrai_a,eax

mov,vrai_b,ebx

mov,vrai_c,ebx

mov,vrai_d,ecx

}

 

param作为输入参数,不同的参数会有不同的输出结果;eax,ebx,ecx,edx所保存的值意义都不一样,具体参考各型号CPU;由于eax,ebx,ecx,edx这四个寄存器是32位的,所以vrai_a,vrai_b,vrai_c,vrai_d,类型是DWORD双字节;

1.eax=0作为输入参数,可以得到CPU的制造商信息。
    cpuid
指令执行以后,会返回一个12字符的制造商信息,前四个字符的ASC码按低位到高位放在ebx,中间四个放在edx,最后四个字符放在ecx。比如说,对于intelcpu,会返回一个“GenuineIntel”的字符串,返回值的存储格式为:

           31      23      15      07      00
        EBX|u (75)| n (6E)| e (65)| G (47)
        EDX|I (49)| e (65)| n (6E)| i (69)
        ECX|l (6C)| e (65)| t (74)| n (6E)

 

2.获得CPU商标信息(BrandString)

  由于商标的字符串很长(48个字符),所以不能在一次cpuid指令执行时全部得到,所以intel把它分成了3个操作,eax的输入参数分别是0x80000002,0x80000003,0x80000004,每次返回的16个字符,按照从低位到高位的顺序依次放在eax,ebx, ecx, edx。因此,可以用循环的方式,每次执行完以后保存结果,然后执行下一次cpuid

 

3.获得序列号需要两个步骤,首先用eax= 1做参数,返回的eax中存储序列号的高两个WORD。用eax= 3做参数,返回ecxedx按从低位到高位的顺序存储前4WORD

 

具体程序如下:c++

 

 

#include
#include
usingnamespace std;

classCPUID
{
public:
 char * GetVID();
 char *GetBrand();
 char * GetSerialNumber();
 boolIsHyperThreading();
 bool IsEST();
 boolIsMMX();
 
private:
 void Executecpuid(DWORDveax);//
获取信息
 DWORDm_eax;      //
私有成员变量来保存寄存器值;
 DWORDm_ebx;
 DWORD m_ecx;
 DWORD m_edx;
};


voidCPUID::Executecpuid(DWORD veax)
{
 DWORD deax;
 DWORDdebx;
 DWORD decx;
 DWORDdedx;
 __asm        //
混合编程。c++直接插入汇编代码;
 {
  moveax,veax;    //
将参数压入eax;
  cpuid;      //
可以得到CPU类型,型号,制造商信息,商标信息,序列号,缓存等一系列CPU相关的东西。
  movdeax,eax;    //
将寄存器中变量赋予临时变量。因为是32位寄存器,所以用dword类型;
  movdebx,ebx;    //
这里用临时变量而不直接使用类成员变量原因是因为汇编不认识类的成员变量
  movdecx,ecx; 
  movdedx,edx; 
 }
 m_eax=deax;
 m_ebx=debx;
 m_ecx=decx;
 m_edx=dedx;
 
}

char* CPUID::GetVID()
{
 char *VID=newchar[13];    //
申请13字节空间;
 memset(VID,0,13);       //
初始化
 Executecpuid(0);    //
传入指令1
 memcpy(VID,&m_ebx,4);   //
m_ebx值(一共4字节),复制给VID[0]--VID[3];
 memcpy(VID+4,&m_edx,4);
 memcpy(VID+8,&m_ecx,4);
 returnVID;
}

char*CPUID::GetBrand()
{
 const DWORDBRAND=0x80000002;  //
0x80000002开始到0x80000004结束
 char*Brand=new char[49];
 memset(Brand,0,49);
 for(DWORDi=0;i<3;i++)
 {
  Executecpuid(BRAND+i);
  memcpy(Brand+i*16,&m_eax,16);//
每次执行结束后,保存四个寄存器里的asc码到数组,
          //
由于在内存中,m_eax,m_ebx, m_ecx, m_edx是连续排列,每个都是4字节
          //
所以可以直接以内存copy的方式进行保存

 }
 returnBrand;

}

boolCPUID::IsHyperThreading()
{
 Executecpuid(1);
 returnm_edx&(1<<28);   //CPU
的特性可以通过cpuid获得,参数是eax=1,返回值放在edxecx
         //
通过验证edx或者ecx的某一个bit,可以获得CPU的一个特性是否被支持。
         //
比如说,edxbit32代表是否支持MMXedxbit28代表是否支持Hyper-Threading
         //ecx
bit7代表是否支持speedsted
}

boolCPUID::IsEST()
{
 Executecpuid(1);
 return m_ecx &(1<<7);
}

boolCPUID::IsMMX()
{
 Executecpuid(1);
 return m_edx &(1<<23);
}

char*CPUID::GetSerialNumber()
{
 Executecpuid(1);
 boolisSupport=m_edx & (1<<18);// edx
是否为1代表CPU是否存在序列号

 if(isSupport)
 {
  char* SerialNumber=new char[12];
  memcpy(SerialNumber,&m_eax,4);//eax
为最高位的两个WORD

  Executecpuid(3);//执行cpuid,参数为eax= 3

  memcpy(SerialNumber+4,&m_ecx,8);//ecx edx为低位的4WORD

  returnSerialNumber;
 }
 else
 {
  returnNULL;
 }
 return NULL;
}

intmain(int argv,char *argc[])
{
    CPUIDcpu;
 char*test;
 test=cpu.GetBrand();
 cout<<test<<endl;
 
 test=cpu.GetSerialNumber();
 if(test)
 {
 cout<<test<<endl;
 }
 else
 {
  cout<<"thecpu cann't support theserisenumber"<<endl;
 }
 
 test=cpu.GetVID();
 cout<<test<<endl;
 //
以下是随意的一些测试;
 boolisornot=cpu.IsEST();//
判断是否支持speedstep

 
 cout<<isornot<<endl;
 
 isornot=cpu.IsMMX();//
判断是否支持MMX

 cout<<isornot<<endl;
 
 isornot=cpu.IsHyperThreading();//
判断是否支持hyper-threading

 cout<<isornot<<endl;
  system("pause");
    return0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值