📄 cpuid.c
字号:
#include <windows.h>
#include "cpuid.h"
//#include "speed.h"
// Global Variable /////////////////////////////////////////////
int clone_flag; // Flag to show whether processor
// is an Intel clone
// Public DLL Functions ////////////////////////////////////////
/***************************************************************
* wincpuidsupport()
*
* Inputs: none
*
* Returns:
* 1 = CPUID opcode is supported
* 0 = CPUID opcode is not supported
***************************************************************/
WORD wincpuidsupport() {
int cpuid_support = 1;
_asm {
pushfd // Get original EFLAGS
pop eax
mov ecx, eax
xor eax, 200000h // Flip ID bit in EFLAGS
push eax // Save new EFLAGS value on
// stack
popfd // Replace current EFLAGS value
pushfd // Get new EFLAGS
pop eax // Store new EFLAGS in EAX
xor eax, ecx // Can not toggle ID bit,
jnz support // Processor=80486
mov cpuid_support,0 // Clear support flag
support:
}
return cpuid_support;
} // wincpuidsupport()
/***************************************************************
* wincpuid()
*
* Inputs: none
*
* Returns:
* 0 = 8086/88
* 2 = 80286
* 3 = 80386
* 4 = 80486
* 5 = Pentium(R) Processor
* 6 = PentiumPro(R) Processor
* 7 or higher = Processor beyond the PentiumPro6(R) Processor
*
* Note: This function also sets the global variable clone_flag
***************************************************************/
WORD wincpuid() {
WORD cpuid;
if ( wincpuidsupport() ) // Determine whether CPUID
// opcode is supported
cpuid=check_IDProc();
else {
clone_flag=check_clone();
cpuid=check_8086(); // Will return FFFFh or 0
if (cpuid == 0) goto end;
cpuid=check_80286(); // Will return FFFFh or 2
if (cpuid == 2) goto end;
cpuid=check_80386(); // Will return FFFFh or 3
if (cpuid == 3) goto end; // temporarily commented out.
cpuid=4; // If the processor does not support CPUID,
// is not an 8086, 80286, or 80386, assign
// processor to be an 80486
}
end:
if (clone_flag)
cpuid = cpuid | CLONE_MASK; // Signify that a clone has been
// detected by setting MSB high
return cpuid;
} // wincpuid ()
/***************************************************************
* wincpuidext()
*
* Inputs: none
*
* Returns:
* AX(15:14) = Reserved (mask these off in the calling code
* before using)
* AX(13:12) = Processor type (00=Standard OEM CPU, 01=OverDrive,
* 10=Dual CPU, 11=Reserved)
* AX(11:8) = CPU Family (the same 4-bit quantity as wincpuid())
* AX(7:4) = CPU Model, if the processor supports the CPUID
* opcode; zero otherwise
* AX(3:0) = Stepping #, if the processor supports the CPUID
* opcode; zero otherwise
*
* Note: This function also sets the global variable clone_flag
***************************************************************/
WORD wincpuidext(BOOL bUse)
{
int i=0;
WORD cpu_type=0x0000;
WORD cpuidext=0x0000;
BYTE vendor_id[12]="------------";
BYTE intel_id[12]="GenuineIntel";
if(bUse)
{
if ( wincpuidsupport() )
{
_asm {
xor eax, eax // Set up for CPUID instruction
CPU_ID // Get and save vendor ID
mov dword ptr vendor_id, ebx
mov dword ptr vendor_id[+4], edx
mov dword ptr vendor_id[+8], ecx
}
for (i=0;i<12;i++)
{
if (!(vendor_id[i]==intel_id[i]))
clone_flag = 1;
}
_asm {
cmp eax, 1 // Make sure 1 is valid input
// for CPUID
jl end_cpuidext // If not, jump to end
xor eax, eax
inc eax
CPU_ID // Get family/model/stepping/
// features
mov cpuidext, ax
end_cpuidext:
mov ax, cpuidext
}
}
else
{
cpu_type = wincpuid(); // If CPUID opcode is not
cpuidext = cpu_type << 8; // supported, put family
// value in extensions and
} // return
}
else
{
cpuidext = 0x0f24;
}
return cpuidext;
} // wincpuidext()
/***************************************************************
* wincpufeatures()
*
* Inputs: none
*
* Returns:
* 0 = Processor which does not execute the CPUID instruction.
* This includes 8086, 8088, 80286, 80386, and some
* older 80486 processors.
*
* Else
* Feature Flags (refer to App Note AP-485 for description).
* This DWORD was put into EDX by the CPUID instruction.
*
* Current flag assignment is as follows:
*
* bit31..10 reserved (=0)
* bit9=1 CPU contains a local APIC (iPentium-3V)
* bit8=1 CMPXCHG8B instruction supported
* bit7=1 machine check exception supported
* bit6=0 reserved (36bit-addressing & 2MB-paging)
* bit5=1 iPentium-style MSRs supported
* bit4=1 time stamp counter TSC supported
* bit3=1 page size extensions supported
* bit2=1 I/O breakpoints supported
* bit1=1 enhanced virtual 8086 mode supported
* bit0=1 CPU contains a floating-point unit (FPU)
*
* Note: New bits will be assigned on future processors... see
* processor data books for updated information
*
* Note: This function also sets the global variable clone_flag
***************************************************************/
DWORD wincpufeatures(BOOL bUse) {
int i=0;
DWORD cpuff=0x00000000;
BYTE vendor_id[12]="------------";
BYTE intel_id[12]="GenuineIntel";
if(bUse)
{
if ( wincpuidsupport() ) {
_asm {
xor eax, eax // Set up for CPUID instruction
CPU_ID // Get and save vendor ID
mov dword ptr vendor_id, ebx
mov dword ptr vendor_id[+4], edx
mov dword ptr vendor_id[+8], ecx
}
for (i=0;i<12;i++)
{
if (!(vendor_id[i]==intel_id[i]))
clone_flag = 1;
}
_asm {
cmp eax, 1 // Make sure 1 is valid input
// for CPUID
jl end_cpuff // If not, jump to end
xor eax, eax
inc eax
CPU_ID // Get family/model/stepping/
// features
mov cpuff, edx
end_cpuff:
mov eax, cpuff
}
}
}
else
{
cpuff = 0x3febfbff;
}
return cpuff;
} // wincpufeatures()
/***************************************************************
* winrdtsc()
*
* Inputs: none
*
* Returns:
* 0 = CPU does not support the time stamp register
*
* Else
* Returns a variable of type TIME_STAMP which is composed of
* two DWORD variables. The 'High' DWORD contains the upper
* 32-bits of the Time Stamp Register. The 'Low' DWORD
* contains the lower 32-bits of the Time Stamp Register.
*
* Note: This function also sets the global variable clone_flag
***************************************************************/
struct TIME_STAMP winrdtsc() {
struct TIME_STAMP timestamp; // Return variable for time
// stamp read
DWORD features = wincpufeatures(TRUE); // Processor Features
timestamp.Low = 0;
timestamp.High = 0;
if ( features & 0x00000010 ) {
RDTSC // Read Time Stamp
_asm
{
MOV timestamp.Low, EAX
MOV timestamp.High, EDX
}
}
return timestamp;
} // winrdtsc
/***************************************************************
* getdllversion()
*
* Inputs: none
*
* Returns: Major and Minor version of this DLL.
*
* i.e. getdllversion() = 0x01 00
* Major Version<--|-->Minor Version
*
***************************************************************/
unsigned short getdllversion(void) {
unsigned short Version = VERSION;
return Version;
} // getdllversion()
// Internal Private Functions //////////////////////////////////
/***************************************************************
* check_clone()
*
* Inputs: none
*
* Returns:
* 1 if processor is clone (limited detection ability)
* 0 otherwise
***************************************************************/
static WORD check_clone()
{
short cpu_type=0;
_asm
{
MOV AX,5555h // Check to make sure this
XOR DX,DX // is a 32-bit processor
MOV CX,2h
DIV CX // Perform Division
CLC
JNZ no_clone
JMP clone
no_clone: STC
clone: PUSHF
POP AX // Get the flags
AND AL,1
XOR AL,1 // AL=0 is probably Intel,
// AL=1 is a Clone
MOV cpu_type, ax
}
cpu_type = cpu_type & 0x0001;
return cpu_type;
} // check_clone()
/***************************************************************
* check_8086()
*
* Inputs: none
*
* Returns:
* 0 if processor 8086
* 0xffff otherwise
***************************************************************/
static WORD check_8086()
{
WORD cpu_type=0xffff;
_asm {
pushf // Push original FLAGS
pop ax // Get original FLAGS
mov cx, ax // Save original FLAGS
and ax, 0fffh // Clear bits 12-15 in FLAGS
push ax // Save new FLAGS value on stack
popf // Replace current FLAGS value
pushf // Get new FLAGS
pop ax // Store new FLAGS in AX
and ax, 0f000h // If bits 12-15 are set, then
cmp ax, 0f000h // processor is an 8086/8088
mov cpu_type, 0 // Turn on 8086/8088 flag
je end_8086 // Jump if processor is 8086/
// 8088
mov cpu_type, 0ffffh
end_8086:
push cx
popf
mov ax, cpu_type
}
return cpu_type;
} // check_8086()
/***************************************************************
* check_80286()
*
* Inputs: none
*
* Returns:
* 2 if processor 80286
* 0xffff otherwise
***************************************************************/
static WORD check_80286()
{
WORD cpu_type=0xffff;
_asm {
pushf
pop cx
mov bx, cx
or cx, 0f000h // Try to set bits 12-15
push cx // Save new FLAGS value on stack
popf // Replace current FLAGS value
pushf // Get new FLAGS
pop ax // Store new FLAGS in AX
and ax, 0f000h // If bits 12-15 are clear
mov cpu_type, 2 // Processor=80286, turn on
// 80286 flag
jz end_80286 // If no bits set, processor is
// 80286
mov cpu_type, 0ffffh
end_80286:
push bx
popf
mov ax, cpu_type
}
return cpu_type;
} // check_80286()
/***************************************************************
* check_80386()
*
* Inputs: none
*
* Returns:
* 3 if processor 80386
* 0xffff otherwise
***************************************************************/
static WORD check_80386()
{
WORD cpu_type=0xffff;
_asm {
mov bx, sp
and sp, not 3
pushfd // Push original EFLAGS
pop eax // Get original EFLAGS
mov ecx, eax // Save original EFLAGS
xor eax, 40000h // Flip AC bit in EFLAGS
push eax // Save new EFLAGS value on
// stack
popfd // Replace current EFLAGS value
pushfd // Get new EFLAGS
pop eax // Store new EFLAGS in EAX
xor eax, ecx // Can't toggle AC bit,
// processor=80386
mov cpu_type, 3 // Turn on 80386 processor flag
jz end_80386 // Jump if 80386 processor
mov cpu_type, 0ffffh
end_80386:
push ecx
popfd
mov sp, bx
mov ax, cpu_type
and eax, 0000ffffh
}
return cpu_type;
} // check_80386()
/***************************************************************
* check_IDProc()
*
* Inputs: none
*
* Returns:
* CPU Family (i.e. 4 if Intel 486, 5 if Pentium(R) Processor)
*
* Note: This function also sets the global variable clone_flag
***************************************************************/
static WORD check_IDProc() {
int i=0;
WORD cpu_type=0xffff;
BYTE stepping=0;
BYTE model=0;
BYTE vendor_id[12]="------------";
BYTE intel_id[12]="GenuineIntel";
_asm {
xor eax, eax // Set up for CPUID instruction
CPU_ID // Get and save vendor ID
mov dword ptr vendor_id, ebx
mov dword ptr vendor_id[+4], edx
mov dword ptr vendor_id[+8], ecx
}
for (i=0;i<12;i++)
{
if (!(vendor_id[i]==intel_id[i]))
clone_flag = 1;
}
_asm {
cmp eax, 1 // Make sure 1 is valid input
// for CPUID
jl end_IDProc // If not, jump to end
xor eax, eax
inc eax
CPU_ID // Get family/model/stepping/
// features
mov stepping, al
and stepping, 0x0f //0fh
and al, 0f0h
shr al, 4
mov model, al
and eax, 0f00h
shr eax, 8 // Isolate family
and eax, 0fh
mov cpu_type, ax // Set _cpu_type with family
end_IDProc:
mov ax, cpu_type
}
return cpu_type;
} // Check_IDProc()
///////////////////////////////////////////
//write by lr
char* wincpuVendorID(BOOL bUse) {
int i=0;
static BYTE vendor_id[12+1]="------------";
BYTE intel_id[12]="GenuineIntel";
BYTE unsupport_id[12]="unsupport_id";
if(bUse)
{
if ( wincpuidsupport() ) {
_asm {
xor eax, eax // Set up for CPUID instruction
CPU_ID // Get and save vendor ID
mov dword ptr vendor_id, ebx
mov dword ptr vendor_id[+4], edx
mov dword ptr vendor_id[+8], ecx
}
for (i=0;i<12;i++)
{
if (!(vendor_id[i]==intel_id[i]))
clone_flag = 1;
}
}
else {
// If CPUID opcode is not supported
for (i=0;i<12;i++)
{
vendor_id[i]=unsupport_id[i];
}
}
}
else
{
for (i=0;i<12;i++)
{
vendor_id[i]=intel_id[i];
}
}
return vendor_id;
} // wincpufeatures()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -