2009-11-03 7 views
20

Me gustaría saber si alguien por aquí tiene algunos buenos ejemplos de una implementación de CPUID C++ a la que se puede hacer referencia desde cualquiera de los lenguajes .NET administrados.Implementaciones de CPUID en C++

Además, de no ser así, ¿debería tener en cuenta ciertas diferencias de implementación entre X86 y X64?

Me gustaría utilizar CPUID para obtener información sobre la máquina en la que se ejecuta mi software (informe de fallos, etc.) y quiero que todo sea lo más compatible posible.

razón primaria que pido es porque soy un novato total cuando se trata de escribir lo que probablemente será todas las instrucciones de la máquina aunque no tengo conocimientos básicos sobre registros de la CPU y así sucesivamente ...

Antes de empezar la gente que me dice a Google: encontré algunos ejemplos en línea, pero generalmente no estaban destinados a permitir la interacción del código administrado y ninguno de los ejemplos estaba dirigido tanto a X86 como a X64. La mayoría de los ejemplos parecían ser específicos de X86.

Respuesta

38

Acceso a la información CPUID prima es realmente muy fácil, aquí es una clase de C++ porque lo que funciona en Windows, Linux y 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 

Para usarlo sólo se crea una instancia de la clase, cargar el CPUID instrucción que le interesa y examinar los registros. Por ejemplo:

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

Esta página de Wikipedia se explica cómo utilizar CPUID: http://en.wikipedia.org/wiki/CPUID

EDIT: Agregado #include <intrin.h> para Windows, por los comentarios.

+4

Excelente respuesta. Solo una nota: debe incluir el '#include ' en Windows para usar la función __cpuid(). –

+1

Es un error extremadamente leve y una solución fácil, pero también olvidó '#include '; 3 – Gurgadurgen

+0

@Gurgadurgen '' '' '' está incluido en '' '' 'en la mayoría de los sistemas, pero está bien, Lo agregaré – jcoffland

1

Puede que no sea exactamente lo que está buscando, pero Intel tiene un good article and sample code para enumerar arquitecturas de plataforma Intel de 64 bits (procesador, caché, etc.) que también parece abarcar procesadores x86 de 32 bits.

+0

vi éste ya , hay algunos más en intel.com y MSDN. Pero particularmente para el que mencionaste: por mi vida, no podría encontrar la manera de compilar esto correctamente en algunos dll nativos que podría llamar desde mi código C# ... Estoy ocupado tratando de aprender todas las cosas programación más allá de los entornos administrados, pero las curvas de aprendizaje son pronunciadas :) – Kris

+2

IA64 es en realidad Itanium, mientras que ese artículo se refiere a "Intel 64" que es más comúnmente llamado x86_64. – kdt

+1

Intel 64 corresponde a AMD64, no IA64 que es Itanium –

6

Ver this MSDN article about __cpuid.

Hay una muestra completa que compila con Visual Studio 2005 o superior. Para Visual Studio 6, puede utilizar esto en vez del compilador __cpuid intrínseca:

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

para Visual Studio 2005, puede utilizar esto en vez del compilador __cpuidex intrínseca:

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 
    } 
} 
+3

La definición de '__cpuid' y' __cpuidex' le da como resultado un comportamiento indefinido ya que los identificadores están reservados. – rightfold

Cuestiones relacionadas