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。比如说,对于intel的cpu,会返回一个“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做参数,返回ecx和edx按从低位到高位的顺序存储前4个WORD;
具体程序如下: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,返回值放在edx和ecx,
//通过验证edx或者ecx的某一个bit,可以获得CPU的一个特性是否被支持。
//比如说,edx的bit32代表是否支持MMX,edx的bit28代表是否支持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为低位的4个WORD
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;
}