C++ 中的 CPUID 实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1666093/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:49:45  来源:igfitidea点击:

CPUID implementations in C++

c++assemblycpux86-64

提问by Kris

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.

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

Also, should this not be the case, should I be aware of certain implementation differences between X86 and X64?

另外,不应该是这样吗,我应该知道 X86 和 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.

我想使用 CPUID 获取有关运行我的软件的机器的信息(崩溃报告等),并且我希望尽可能广泛地保持所有内容的兼容性。

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...

我问的主要原因是因为我在编写可能是所有机器指令的方面完全是个菜鸟,尽管我对 CPU 寄存器等有基本的了解......

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 aimed at both X86 and X64. Most examples appeared to be X86 specific.

在人们开始告诉我谷歌之前:我在网上找到了一些示例,但通常它们不允许来自托管代码的交互,并且没有一个示例同时针对 X86 和 X64。大多数示例似乎是特定于 X86 的。

回答by jcoffland

Accessing raw CPUID information is actually very easy, here is a C++ class for that which works in Windows, Linux and OSX:

访问原始 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

To use it just instantiate an instance of the class, load the CPUID instruction you are interested in and examine the registers. For example:

要使用它,只需实例化类的一个实例,加载您感兴趣的 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;
}

This Wikipedia page tells you how to use CPUID: http://en.wikipedia.org/wiki/CPUID

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

EDIT:Added #include <intrin.h>for Windows, per comments.

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

回答by Jabberwocky

See this MSDN article about __cpuid.

请参阅有关 __cpuid 的这篇 MSDN 文章

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:

有一个综合示例,可以使用 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  
  }
}

For Visual Studio 2005, you can use this instead of the compiler instrinsic __cpuidex:

对于 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  
  }
}

回答by Stephen Doyle

Might not be exactly what you are looking for, but Intel have a good article and sample codefor enumerating Intel 64 bit platform architectures (processor, cache, etc.) which also seems to cover 32 bit x86 processors.

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