Вопрос

Я хотел бы знать, есть ли у кого-нибудь здесь хорошие примеры реализации C++ CPUID, на которую можно ссылаться из любого управляемого языка .net.

Кроме того, если это не так, должен ли я знать об определенных различиях в реализации между X86 и X64?

Я хотел бы использовать CPUID для получения информации о машине, на которой работает мое программное обеспечение (отчеты о сбоях и т. д.), и я хочу, чтобы все было как можно более широко совместимым.

Основная причина, по которой я спрашиваю, заключается в том, что я полный нуб, когда дело доходит до написания того, что, вероятно, будет всеми машинными инструкциями, хотя у меня есть базовые знания о регистрах ЦП и так далее...

Прежде чем люди начнут говорить мне в Google:Я нашел несколько примеров в Интернете, но обычно они не предназначались для взаимодействия с управляемым кодом, и ни один из примеров не был нацелен одновременно на X86 и X64.Большинство примеров оказались специфичными для X86.

Это было полезно?

Решение

Получить доступ к необработанной информации CPUID на самом деле очень просто. Вот класс C++, который работает в Windows, Linux и 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

Чтобы использовать его, просто создайте экземпляр класса, загрузите интересующую вас инструкцию 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

РЕДАКТИРОВАТЬ: Добавлен #include <intrin.h> для Windows, согласно комментариям.

Другие советы

Видеть эта статья MSDN о __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  
  }
}

В 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  
  }
}

Возможно, это не совсем то, что вы ищете, но у Intel есть хорошая статья и пример кода для перечисления архитектур 64-битных платформ Intel (процессор, кэш и т. д.), которые, похоже, также охватывают 32-битные процессоры x86.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top