CPUID implementations in C++
I would like to know if somebody around here has some good examples of a C++ CPUID implementation that can be referenced from any of the managed .net languages.
Also, should this not be the case, should I be aware of certain implementation differences between X86 and X64?
I would like to use CPUID to get info on the machine my software is running on (crashreporting etc...) and I want to keep everything as widely compatible as possible.
Primary reason I ask is because I am a total noob when it comes to writing what will probably be all machine instructions though I have basic knowledge about CPU registers and so on...
Before people start telling me to Google: I found some examples online, but usually they were not meant to allow interaction from managed code and none of the examples were a开发者_Python百科imed at both X86 and X64. Most examples appeared to be X86 specific.
Accessing raw CPUID information is actually very easy, here is a C++ class for that which works in Windows, Linux and OSX:
#ifndef CPUID_H
#define CPUID_H
#ifdef _WIN32
#include <limits.h>
#include <intrin.h>
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
class CPUID {
uint32_t regs[4];
public:
explicit CPUID(unsigned i) {
#ifdef _WIN32
__cpuid((int *)regs, (int)i);
#else
asm volatile
("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
: "a" (i), "c" (0));
// ECX is set to zero for CPUID function 4
#endif
}
const uint32_t &EAX() const {return regs[0];}
const uint32_t &EBX() const {return regs[1];}
const uint32_t &ECX() const {return regs[2];}
const uint32_t &EDX() const {return regs[3];}
};
#endif // CPUID_H
To use it just instantiate an instance of the class, load the CPUID instruction you are interested in and examine the registers. For example:
#include "CPUID.h"
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
CPUID cpuID(0); // Get CPU vendor
string vendor;
vendor += string((const char *)&cpuID.EBX(), 4);
vendor += string((const char *)&cpuID.EDX(), 4);
vendor += string((const char *)&cpuID.ECX(), 4);
cout << "CPU vendor = " << vendor << endl;
return 0;
}
This Wikipedia page tells you how to use CPUID: http://en.wikipedia.org/wiki/CPUID
EDIT: Added #include <intrin.h>
for Windows, per comments.
See this MSDN article about __cpuid.
There is a comprehensive sample that compiles with Visual Studio 2005 or better. For Visual Studio 6, you can use this instead of the compiler instrinsic __cpuid:
void __cpuid(int CPUInfo[4], int InfoType)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
xor ecx, ecx
cpuid
mov dword ptr [esi + 0], eax
mov dword ptr [esi + 4], ebx
mov dword ptr [esi + 8], ecx
mov dword ptr [esi + 12], edx
}
}
For Visual Studio 2005, you can use this instead of the compiler instrinsic __cpuidex:
void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
{
__asm
{
mov esi, CPUInfo
mov eax, InfoType
mov ecx, ECXValue
cpuid
mov dword ptr [esi + 0], eax
mov dword ptr [esi + 4], ebx
mov dword ptr [esi + 8], ecx
mov dword ptr [esi + 12], edx
}
}
Might not be exactly what you are looking for, but Intel have a good article and sample code for enumerating Intel 64 bit platform architectures (processor, cache, etc.) which also seems to cover 32 bit x86 processors.
精彩评论