📄 cpuid.pas
字号:
unit cpuid;
interface
uses
Windows;
const
CPU_TYPE_INTEL = 1;
CPU_TYPE_AMD = 2;
type
TCpuInfo = Record
//HasInstruction: Boolean;
CPUType: Byte;
DTS: Boolean; //支持温度检测
FID: Boolean; //支持频率检测 AMD intel不知道去哪找
VID: Boolean; //支持电压检测 AMD
Frequency: Double;
multiplier: Double;
Maxmultiplier: Double;
FSB: Double;
VendorIDString: array [0..11] of Char; //厂家字串
CpuName: array [0..47] of Char; //CPU名称
PhysicalCore: Byte; //物理核心数
end;
var
CpuInfo: TCpuInfo;
Function GetCpuInfo: TCpuInfo;
function GetCPUSpeed(var CpuSpeed: Double): Boolean;
implementation
const
VendorIDIntel: array [0..11] of Char = 'GenuineIntel';
VendorIDAMD: array [0..11] of Char = 'AuthenticAMD';
function HasCPUIDInstruction: Boolean;
const
ID_FLAG = $200000;
asm
PUSHFD
POP EAX
MOV ECX, EAX
XOR EAX, ID_FLAG
AND ECX, ID_FLAG
PUSH EAX
POPFD
PUSHFD
POP EAX
AND EAX, ID_FLAG
XOR EAX, ECX
SETNZ Result
end;
procedure CallCPUID(ValueEAX, ValueECX: Cardinal; var ReturnedEAX, ReturnedEBX, ReturnedECX, ReturnedEDX);
begin
asm
PUSH EDI
PUSH EBX
MOV EAX, ValueEAX
MOV ECX, ValueECX
// CPUID
DB 0FH
DB 0A2H
MOV EDI, ReturnedEAX
MOV Cardinal PTR [EDI], EAX
MOV EAX, ReturnedEBX
MOV EDI, ReturnedECX
MOV Cardinal PTR [EAX], EBX
MOV Cardinal PTR [EDI], ECX
MOV EAX, ReturnedEDX
MOV Cardinal PTR [EAX], EDX
POP EBX
POP EDI
end;
end;
procedure ProcessIntel(var CPUInfo: TCpuInfo; HiVal: Cardinal);
var
ExHiVal, EAX, EBX, ECX, EDX: Cardinal;
begin
CPUInfo.CpuType := CPU_TYPE_INTEL;
//CPUInfo.Manufacturer := 'Intel';
//Todo : FID, VID;
if HiVal >= 4 then
begin
CallCPUID(4, 0, EAX, EBX, ECX, EDX);
CPUInfo.PhysicalCore := ((EAX and $FC000000) shr 26) + 1; //核心数
end;
if Hival >=6 then
begin
CallCPUID(6, 0, EAX, EBX, ECX, EDX);
CPUInfo.DTS := (EAX and 1) = 1; //温度
//CPUInfo.FID := (ECX and 1) = 1; //IA32_MPERF MSR and IA32_APERF MSR
end;
//取CPU名称
CallCPUID($80000000, 0, ExHiVal, EBX, ECX, EDX);
if ExHiVal >= $80000002 then
CallCPUID($80000002, 0, CPUInfo.CpuName[0], CPUInfo.CpuName[4], CPUInfo.CpuName[8], CPUInfo.CpuName[12]);
if ExHiVal >= $80000003 then
CallCPUID($80000003, 0, CPUInfo.CpuName[16], CPUInfo.CpuName[20], CPUInfo.CpuName[24], CPUInfo.CpuName[28]);
if ExHiVal >= $80000004 then
CallCPUID($80000004, 0, CPUInfo.CpuName[32], CPUInfo.CpuName[36], CPUInfo.CpuName[40], CPUInfo.CpuName[44]);
end;
procedure ProcessAMD(var CPUInfo: TCpuInfo; HiVal: Cardinal);
var
ExHiVal, EAX, EBX, ECX, EDX: Cardinal;
begin
CPUInfo.CpuType := CPU_TYPE_AMD;
//CPUInfo.Manufacturer := 'AMD';
//取CPU名称
CallCPUID($80000000, 0, ExHiVal, EBX, ECX, EDX);
if ExHiVal >= $80000002 then
CallCPUID($80000002, 0, CPUInfo.CpuName[0], CPUInfo.CpuName[4], CPUInfo.CpuName[8], CPUInfo.CpuName[12]);
if ExHiVal >= $80000003 then
CallCPUID($80000003, 0, CPUInfo.CpuName[16], CPUInfo.CpuName[20], CPUInfo.CpuName[24], CPUInfo.CpuName[28]);
if ExHiVal >= $80000004 then
CallCPUID($80000004, 0, CPUInfo.CpuName[32], CPUInfo.CpuName[36], CPUInfo.CpuName[40], CPUInfo.CpuName[44]);
if ExHival >= $80000008 then //get PhysicalCore;
begin
CallCPUID($80000008,0, EAX, EBX, ECX, EDX);
CpuInfo.PhysicalCore := ECX and $F + 1; //核心数
end;
if ExHiVal >= $80000007 then
begin
CallCPUID($80000007,0, EAX, EBX, ECX, EDX);
CpuInfo.DTS := (EDX and 1) = 1; //温度
CpuInfo.FID := (EDX and 2) = 2; //频率
CpuInfo.VID := (EDX and 4) = 4; //电压
end;
end;
Function GetCpuInfo: TCpuInfo;
var
Hival: Cardinal;
begin
FillChar(Result, sizeof(Result), 0);
Result.PhysicalCore := 1;
CallCPUID(0, 0, HiVal, Result.VendorIDString[0], Result.VendorIDString[8], Result.VendorIDString[4]);
if Result.VendorIDString = VendorIDIntel then
ProcessIntel(Result, HiVal)
else if Result.VendorIDString = VendorIDAMD then
ProcessAMD(Result, HiVal);
end;
function ReadTimeStampCounter: Int64; assembler;
asm
DW $310F
end;
function GetCPUSpeed(var CpuSpeed: Double): Boolean;
var
T0, T1: Int64;
CountFreq: Int64;
Cycles: Int64;
Stamp0, Stamp1: Int64;
Ticks: Double;
Priority: Integer;
Thread: THandle;
begin
CpuSpeed := 0.0;
Stamp0 := 0;
stamp1 := 0;
Thread := GetCurrentThread();
Result := QueryPerformanceFrequency(CountFreq);
if not Result then Exit;
QueryPerformanceCounter(T0);
T1 := T0;
Priority := GetThreadPriority(Thread);
if Priority <> THREAD_PRIORITY_ERROR_RETURN then SetThreadPriority(Thread, THREAD_PRIORITY_TIME_CRITICAL);
try
while T1 - T0 < 50 do
begin
QueryPerformanceCounter(T1);
Stamp0 := ReadTimeStampCounter;
end;
T0 := T1;
while T1 - T0 < 1000 do
begin
QueryPerformanceCounter(T1);
Stamp1 := ReadTimeStampCounter;
end;
finally
if Priority <> THREAD_PRIORITY_ERROR_RETURN then SetThreadPriority(Thread, Priority);
end;
Cycles := Stamp1 - Stamp0;
Ticks := (T1 - T0) / CountFreq * 100000;
CpuSpeed := Cycles / Ticks;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -