#include <windows.h>
#include <cstdio>
#define REG_EAX reg[0]
#define REG_EBX reg[1]
#define REG_ECX reg[3]
#define REG_EDX reg[2]
// В inline-ассемблере числа в [] означают байты
#define ASM_EAX reg[0]
#define ASM_EBX reg[1*4]
#define ASM_ECX reg[3*4]
#define ASM_EDX reg[2*4]
int reg[5];
char *vendor;
//Функция проверяет установлен ли бит номер flag в reg
void check_flag(int reg, int flag){
int mask = 1;
mask <<= flag;
if(reg & mask) printf("FOUND\n"
;
else printf("NOT FOUND\n"
;
}
//Функция выполняет инструкцию CPUID, и сохраняет после нее
//регистры в REG_EAX, REG_EBX, REG_ECX и REG_EDX
void cpuid(int arg){
try{
__asm{
push ebx
mov eax, arg
cpuid
mov ASM_EAX, eax
mov ASM_EBX, ebx
mov ASM_ECX, ecx
mov ASM_EDX, edx
pop ebx
}
} catch(...){
MessageBox(GetDesktopWindow(),
"
Error while CPUID. Maybe you have earlier version of x486 processor",
"
Error!", MB_ICONERROR);
exit(-1);
}
}
int main(){
reg[5] = 0;
//Если выполнить cpuid с EAX=0, то:
//EAX - максимальное значение, с которым можно выполнять cpuid
//EBX:EDX:ECX - строка - 12-байтный идентификатор производителя
cpuid(0);
//vendor = (char *)REG_EBX;
printf("Vendor: %s\n", ®_EBX);
int max_cpuid_arg = REG_EAX;
//Если в EAX=1, то cpuid установит регистры в соответствии с
//с возможностями процессора.
cpuid(1);
//В EAX находится информация о типе ,модели, семействе
// и модификации процессора
printf("Family: %i\n", (REG_EAX & 0xF00) >> 8); //EAX bits 11-8
printf("Model: %i\n", (REG_EAX & 0xF0) >> 4); //EAX bits 7-4
printf("Stepping: %i\n", REG_EAX & 0xF); //EAX bits 3-0
printf("
Type: "
;
switch((REG_EAX & 0x3000) >> 12){
case 0:
printf("OEM\n"
;
break;
case 1:
printf("Overdrive\n"
;
break;
case 2:
printf("
ual\n"
;
break;
}
//Проверяем установлены ли определенные биты в регистре EDX
//от них зависит, присутствуют ли некоторые возможности
//процессора
printf(" FPU : "
; check_flag(REG_EDX, 0);
printf(" VMode Extensions : "
; check_flag(REG_EDX, 1);
printf(" Debugging Extensions : "
; check_flag(REG_EDX, 2);
printf(" 4-Megabyte Pages : "
; check_flag(REG_EDX, 3);
printf(" RDTSC Instruction : "
; check_flag(REG_EDX, 4);
printf(" Machine-Specific Registers : "
; check_flag(REG_EDX, 5);
printf(" Extended Physical Addressing : "
; check_flag(REG_EDX, 6);
printf(" Machine-Check Exception : "
; check_flag(REG_EDX, 7);
printf(" CMPXCHG8B Instruction : "
; check_flag(REG_EDX, 8);
printf(" APIC : "
; check_flag(REG_EDX, 9);
printf(" SYSENTER, SYSEXIT Instructions : "
; check_flag(REG_EDX, 10);
printf(" Memory
Type Range Registers (MTRR): "
; check_flag(REG_EDX, 12);
printf("
Global Pages : "
; check_flag(REG_EDX, 13);
printf(" Machine Check Architecture : "
; check_flag(REG_EDX, 14);
printf(" CMOVcc, FCMOV Instructions : "
; check_flag(REG_EDX, 15);
printf(" Page Attributes Table : "
; check_flag(REG_EDX, 16);
printf(" MMX : "
; check_flag(REG_EDX, 23);
printf(" FXSAVE, FXRSTOR Instructions : "
; check_flag(REG_EDX, 24);
printf(" SSE : "
; check_flag(REG_EDX, 25);
printf(" SSE2 : "
; check_flag(REG_EDX, 26);
char buff[128];
int t;
cpuid(0x80000002);
t = reg[2]; reg[2] = reg[3]; reg[3] = t;
memcpy(buff, reg, sizeof(int) * 4);
cpuid(0x80000003);
t = reg[2]; reg[2] = reg[3]; reg[3] = t;
memcpy(&buff[16], reg, sizeof(int) * 4);
cpuid(0x80000004);
t = reg[2]; reg[2] = reg[3]; reg[3] = t;
memcpy(&buff[32], reg, sizeof(int) * 4);
buff[48] = 0;
printf("Processor Brand
String: %s\n", buff);
return 0;
}