如何在各个版本的VC及64位下使用CPUID指令

如何在各个版本的VC及64位下使用CPUID指令,第1张

、推荐使用__cpuid、__cpuidex等Intrinsics函数

32位模式我使用内嵌汇编调用cpuid指令64位模式VC编译器支持内嵌汇编

于微软提供Intrinsics函数——编译器Intrinsics函数编译应机器指令且同支持32位64位

例CPUID指令应Intrinsics函数——

[cpp] view plain copy

//

void __cpuid(

int CPUInfo[4],

int InfoType

);

void __cpuidex(

int CPUInfo[4],

int InfoType,

int ECXValue

);

__cpuidex函数InfoType参数CPUID指令eax参数即功能IDECXValue参数CPUID指令ecx参数即功能IDCPUInfo参数用于接收输eax, ebx, ecx, edx四寄存器

早期CPUID功能需要功能ID参数(eax)使用__cpuid函数

CPUID功能越越强功能ID参数(eax)参数够用于加功能ID(ecx)参数应该采用__cpuidex

二、用条件编译判断VC编译器Intrinsics函数支持性(_MSC_VER)

__cpuid、__cpuidex等Intrinsics函数遇问题——

1低版本VC编译器没intrinh文件注:VC2005(或更高)才拥intrinh支持__cpuid

2低版本VC编译器支持__cpuidex注:VC2008部版本及VS2011(或更高)intrinh才__cpuidex

使用条件编译判断VC编译器版本

_MSC_VER微软C/C++编译器——clexe编译代码预定义宏值表示cl版本类型int例——

#if _MSC_VER >=1200 // VC++60

#if _MSC_VER >=1300 // VC2003

#if _MSC_VER >=1400 // VC2005

#if _MSC_VER >=1500 // VC2008

#if _MSC_VER >=1600 // VC2011

例发现_MSC_VER于等于1400我#include 再利用_MSC_VER进步判断__cpuid、__cpuidex支持性

三、用条件编译判断64位模式(_WIN64)

使用_WIN64预处理宏用判断目标平台64位

虽编译x64平台程序编译器自推导_WIN64Visual Studio语高亮清楚些能仍按32位代码做语高亮所建议手项目预处理宏增加_WIN64

四、32位用内嵌汇编实现__cpuidex函数

32位模式我使用内嵌汇编实现__cpuidex函数代码——

[cpp] view plain copy

void __cpuidex(INT32 CPUInfo[4], INT32 InfoType, INT32 ECXValue)

{

if (NULL==CPUInfo) return;

_asm{

// load 读取参数寄存器

mov edi, CPUInfo; // 准备用edi寻址CPUInfo

mov eax, InfoType;

mov ecx, ECXValue;

// CPUID

cpuid;

// save 寄存器保存CPUInfo

mov [edi], eax;

mov [edi+4], ebx;

mov [edi+8], ecx;

mov [edi+12], edx;

}

}

五、全部代码

全部代码——

[cpp] view plain copy

#include

#include

#include

#if _MSC_VER >=1400 // VC2005才支持intrinh

#include // 所Intrinsics函数

#endif

char szBuf[64];

INT32 dwBuf[4];

#if defined(_WIN64)

// 64位支持内联汇编 应使用__cpuid、__cpuidex等Intrinsics函数

#else

#if _MSC_VER < 1600 // VS2011 据说VC2008 SP1才支持__cpuidex

void __cpuidex(INT32 CPUInfo[4], INT32 InfoType, INT32 ECXValue)

{

if (NULL==CPUInfo) return;

_asm{

// load 读取参数寄存器

mov edi, CPUInfo; // 准备用edi寻址CPUInfo

mov eax, InfoType;

mov ecx, ECXValue;

// CPUID

cpuid;

// save 寄存器保存CPUInfo

mov [edi], eax;

mov [edi+4], ebx;

mov [edi+8], ecx;

mov [edi+12], edx;

}

}

#endif // #if _MSC_VER < 1600 // VS2011 据说VC2008 SP1才支持__cpuidex

#if _MSC_VER < 1400 // VC2005才支持__cpuid

void __cpuid(INT32 CPUInfo[4], INT32 InfoType)

{

__cpuidex(CPUInfo, InfoType, 0);

}

#endif // #if _MSC_VER < 1400 // VC2005才支持__cpuid

#endif // #if defined(_WIN64)

// 取CPU厂商(Vendor)

//

// result: 功返字符串度(般12)失败返0

// pvendor: 接收厂商信息字符串缓冲区至少13字节

int cpu_getvendor(char pvendor)

{

INT32 dwBuf[4];

if (NULL==pvendor) return 0;

// Function 0: Vendor-ID and Largest Standard Function

__cpuid(dwBuf, 0);

// save 保存pvendor

(INT32)&pvendor[0] = dwBuf[1]; // ebx: 前四字符

(INT32)&pvendor[4] = dwBuf[3]; // edx: 间四字符

(INT32)&pvendor[8] = dwBuf[2]; // ecx: 四字符

pvendor[12] = '\0';

return 12;

}

// 取CPU商标(Brand)

//

// result: 功返字符串度(般48)失败返0

// pbrand: 接收商标信息字符串缓冲区至少49字节

int cpu_getbrand(char pbrand)

{

INT32 dwBuf[4];

if (NULL==pbrand) return 0;

// Function 0x80000000: Largest Extended Function Number

__cpuid(dwBuf, 0x80000000);

if (dwBuf[0] < 0x80000004) return 0;

// Function 80000002h,80000003h,80000004h: Processor Brand String

__cpuid((INT32)&pbrand[0], 0x80000002); // 前16字符

__cpuid((INT32)&pbrand[16], 0x80000003); // 间16字符

__cpuid((INT32)&pbrand[32], 0x80000004); // 16字符

pbrand[48] = '\0';

return 48;

}

int _tmain(int argc, _TCHAR argv[])

{

//__cpuidex(dwBuf, 0,0);

//__cpuid(dwBuf, 0);

//printf("%8X\t%8X\t%8X\t%8X\n", dwBuf[0],dwBuf[1],dwBuf[2],dwBuf[3]);

cpu_getvendor(szBuf);

printf("CPU Vendor:\t%s\n", szBuf);

cpu_getbrand(szBuf);

printf("CPU Name:\t%s\n", szBuf);

return 0;

}

六、兼容性说明

VC编译器32/64位支持性——

32位:VC6早支持编译32位Intrinsics函数

64位:VC2005早支持编译64位Intrinsics函数

本文32位编译器兼容性——

__cpuid:兼容VC6(或更高)

__cpuidex:兼容VC6(或更高)

本文64位编译器兼容性——

__cpuid:兼容VC2005(或更高)

__cpuidex:兼容VC2011(或更高)

耐心看看啊,运行通过啦,希望对你有帮助啊!

#include<stdioh>

unsigned int veax;

unsigned int vebx;

unsigned int vedx;

unsigned int vecx;

//执行CPUID指令

void cpuid(unsigned int veax1)

{

_asm{

mov eax,veax1

cpuid

mov veax,eax

mov vebx,ebx

mov vecx,ecx

mov vedx,edx

}

}

//做移位 *** 作,把寄存器中的ASCII码,以字符形式输出

void LeftMove(unsigned int var)

{

printf("%c",var);

for(int i=0;i<3;i++)

{

var=(var>>;

printf("%c",var);

}

}

//做移位 *** 作,把寄存器中的值以“%d”形式输出

void LM(unsigned int var)

{

printf("%d",var);

for(int i=0;i<3;i++)

{

var=(var>>;

printf("%d",var);

}

}

//得到CPU的生产厂商(当EAX值为0时),依次存放在EBX,EDX,ECX中

void getCpuName()

{

cpuid(0);

LeftMove(vebx);

LeftMove(vedx);

LeftMove(vecx);

printf("\

";

}

//得到CPU的商标,当EAX中的值为0x80000003和0x80000004时分别返回16个字符,组成商标

//依次存放在EAX,EBX,ECX,EDX中

void getCpuBrand()

{

for(int j=0;j<2;j++)

{

cpuid(0x80000003+j);

LeftMove(veax);

LeftMove(vebx);

LeftMove(vecx);

LeftMove(vedx);

}

printf("\

";

}

//获得CPU的特性,参数是eax = 1,返回值放在edx和ecx,通过验证edx或者ecx的某一个bit,

//可以获得CPU的一个特性是否被支持。比如说,edx的bit 32代表是否支持MMX,

//edx的bit 28代表是否支持Hyper-Threading,ecx的bit 7代表是否支持speed sted。

void getCpuFeature()

{//由于特性太多,无法一一编写,需要的时候再写,方法是一样的。

}

//获得CPU序列号,获得序列号需要两个步骤,首先用eax = 1做参数,返回的eax中存储序列号的高两个WORD。

//用eax = 3做参数,返回ecx和edx按从低位到高位的顺序存储前4个WORD。

void getCpuSeris()

{

cpuid(1);

LM(veax);

cpuid(3);

LM(vecx);

LM(vedx);

printf("\

";

}

void main()

{

getCpuName();

getCpuBrand();

getCpuSeris();

}

以上就是关于如何在各个版本的VC及64位下使用CPUID指令全部的内容,包括:如何在各个版本的VC及64位下使用CPUID指令、C语言 编程实现获取cpu信息、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9458529.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存