Реализация CPUID в С++
Я хотел бы знать, есть ли у кого-нибудь здесь примеры хороших примеров реализации CID CPUID, на которые можно ссылаться с любого из управляемых языков .net.
Также, если это не так, следует ли мне знать о некоторых различиях в реализации между X86 и X64?
Я хотел бы использовать CPUID для получения информации о компьютере, на котором работает мое программное обеспечение (crashreporting и т.д.), и я хочу, чтобы все было максимально совместимо, насколько это возможно.
Основная причина, о которой я прошу, заключается в том, что я являюсь полным noob, когда дело доходит до написания того, что, вероятно, будет всем машинным инструкциям, хотя у меня есть базовые знания о регистрах CPU и т.д....
Прежде чем люди начнут рассказывать мне в Google: я нашел несколько примеров в Интернете, но обычно они не предназначены для разрешения взаимодействия с управляемым кодом, и ни один из примеров не был нацелен на X86 и X64. Большинство примеров оказались специфичными для X86.
Ответы
Ответ 1
Доступ к исходной информации CPUID на самом деле очень прост, вот класс С++ для работы в 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 в соответствии с комментариями.
Ответ 2
См. эту статью 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
}
}
Ответ 3
Не может быть именно то, что вы ищете, но у Intel есть хорошая статья и образец кода для перечисления архитектур платформы Intel 64 бит ( процессор, кеш и т.д.), который также, похоже, охватывает 32-разрядные процессоры x86.