uses StrUtils,
Windows,
sysUtils;
type
SCPUID
SVendor = array [0..11] of char;
TCPUInfo
= class(TObject)private
FID1: string;
FID2: string;
FID3: string;
FID4: string;
FAvailable: Boolean;
FVendor: SVendor;
protected
public
constructor create;
published
property ID1: string read FID1;
property ID2: string read FID2;
property ID3: string read FID3;
property ID4: string read FID4;
property Available: Boolean read FAvailable;
end;
const
ID_BIT = $200000; // EFLAGS ID bit
implementation
function IsCPUID_Available : Boolean; register;
asm
PUSHFD {direct access to flags no possible, only via stack}
POP EAX {flags to EAX}
MOV EDX,EAX {save current flags}
XOR EAX,ID_BIT {not ID bit}
PUSH EAX {onto stack}
POPFD {from stack to flags, with not ID bit}
PUSHFD {back to stack}
POP EAX {
XOR EAX,EDX {check if ID bit affected}
JZ @exit {no, CPUID not availavle}
MOV AL,True {Result=True}
@exit:
end;
function GetCPUID : SCPUID; assembler; register;
asm
PUSH EBX {Save affected register}
PUSH EDI
MOV EDI,EAX {@Result}
MOV EAX,
DW $A20F {CPUID Command}
STOSD {CPUID[1]}
MOV EAX,EBX
STOSD {CPUID[2]}
MOV EAX,ECX
STOSD {CPUID[3]}
MOV EAX,EDX
STOSD {CPUID[4]}
POP EDI {Restore registers}
POP EBX
end;
function GetCPUVendor : SVendor; assembler; register;
asm
PUSH EBX {Save affected register}
PUSH EDI
MOV EDI,EAX {@Result (TVendor)}
MOV EAX,
DW $A20F {CPUID Command}
MOV EAX,EBX
XCHG EBX,ECX {save ECX result}
MOV ECX,4
@1:
STOSB
SHR EAX,8
LOOP @1
MOV EAX,EDX
MOV ECX,4
@2:
STOSB
SHR EAX,8
LOOP @2
MOV EAX,EBX
MOV ECX,4
@3:
STOSB
SHR EAX,8
LOOP @3
POP EDI {Restore registers}
POP EBX
end;
{ TCPUInfo }
constructor TCPUInfo.create;
var
cpuid: Scpuid;
begin
FAvailable :
FID1 := ‘00000000‘;
FID2 := ‘00000000‘;
FID3 := ‘00000000‘;
FID4 := ‘00000000‘;
if FAvailable then
begin
cpuid := getCPUID;
FID1 := inttohex(cpuid[1], 8);
FID2 := inttohex(cpuid[2], 8); //在我的机器上,屏蔽这个字段就可以获取稳定的机器码
FID3 := inttohex(cpuid[3], 8);
FID4 := inttohex(cpuid[4], 8);
FVendor := getCPUVendor;
end;
end;
end.
谢谢 学习了