30

我想知道这里是否有人有一些 C++ CPUID 实现的好例子,可以从任何托管的 .net 语言中引用。

另外,如果不是这种情况,我应该知道 X86 和 X64 之间的某些实现差异吗?

我想使用 CPUID 来获取运行我的软件的机器上的信息(崩溃报告等...),并且我想保持一切尽可能广泛兼容。

我问的主要原因是,尽管我对 CPU 寄存器等有基本的了解,但在编写可能是所有机器指令的内容时,我是一个完全的菜鸟……

在人们开始告诉我 Google 之前:我在网上找到了一些示例,但通常它们并不意味着允许来自托管代码的交互,而且这些示例都不是针对 X86 和 X64 的。大多数示例似乎是特定于 X86 的。

4

3 回答 3

51

访问原始 CPUID 信息实际上非常容易,这里有一个适用于 Windows、Linux 和 OSX 的 C++ 类:

#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

要使用它,只需实例化一个类的实例,加载您感兴趣的 CPUID 指令并检查寄存器。例如:

#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;
}

这个维基百科页面告诉你如何使用 CPUID:http ://en.wikipedia.org/wiki/CPUID

编辑:根据评论为 Windows添加#include <intrin.h>

于 2011-01-28T01:23:32.090 回答
8

请参阅有关 __cpuid 的 MSDN 文章

有一个使用 Visual Studio 2005 或更高版本编译的综合示例。对于 Visual Studio 6,您可以使用它来代替编译器固有的 __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  
  }
}

对于 Visual Studio 2005,您可以使用它来代替编译器固有的 __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  
  }
}
于 2012-01-20T13:05:33.813 回答
2

可能不是您正在寻找的,但英特尔有一篇很好的文章和示例代码,用于枚举英特尔 64 位平台架构(处理器、缓存等),这似乎也涵盖了 32 位 x86 处理器。

于 2009-11-03T09:18:10.620 回答