2009-11-03 3 views
20

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

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

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

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

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

ответ

38

Доступ к необработанной информации 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

EDIT: Добавлен #include <intrin.h> для Windows, в комментариях.

+4

Отличный ответ. Просто примечание: вам нужно включить '#include ' в Windows, чтобы использовать функцию __cpuid(). –

+1

Это очень незначительное несчастье и легкое исправление, но вы также забыли «#include »; 3 – Gurgadurgen

+0

@Gurgadurgen '' '' '' включен в '' '' '' на большинстве систем, но нормально, Я добавлю. – jcoffland

1

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

+0

Я видел этот уже , есть еще несколько на intel.com, а также MSDN. Но особенно для той, на которую вы ссылались: для моей жизни я бы не смог понять, как правильно ее скомпилировать в некоторых родных dll, которые я мог бы вызвать из своего кода на C# ... Я занят поиском всех вещей программирование за пределами управляемых сред, но кривые обучения круты :) – Kris

+2

IA64 - это Itanium, тогда как эта статья относится к «Intel 64», которая чаще называется x86_64. – kdt

+1

Intel 64 соответствует AMD64, а не IA64, который является Itanium –

6

См. this MSDN article about __cpuid.

Существует всеобъемлющий образец, который компилируется с помощью Visual Studio 2005 или выше. Для Visual Studio 6, вы можете использовать это вместо компилятора 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 
    } 
} 

для Visual Studio 2005, вы можете использовать это вместо компилятора 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 
    } 
} 
+3

Определение '__cpuid' и' __cpuidex' себя приводит к неопределенному поведению при сохранении идентификаторов. – rightfold