超级猛料上的资料Test8086:测试CPU型号{ Will always be 2 (386 or later) } Test8087:测试协处理器{ Will always be 3 (387 or later) } TestFDIV: 测试奔腾芯片是否有缺陷{ -1: 有缺陷, 0: 不能决定, 1: OK }Q: How do I detect for a co-processor? Q: How can I tell which CPU is being used?A: Here is the short version. The problem here is that it doesn't detect the pentium.var winFlags: LongInt; begin winFlags := GetWinFlags; { Get math coprocessor status } If winFlags And WF_80x87 > 0 Then Caption := 'Present' Else Caption := 'Not Present'; { Get CPU type } If winFlags And WF_CPU486 > 0 Then edit1.text := '486' {also pentium} else If winFlags And WF_CPU386 > 0 Then edit1.text := '386' else If winFlags And WF_CPU286 > 0 Then edit1.text := '286'; end; Here is a version that will work with the pentium:{ This code comes from Intel, and has been modified for Delphi's inline assembler. }unit Cpu;interfaceuses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;type { All the types currently known. As new types are created, add suitable names, and extend the case statement in the GetCpuType function. } TCPUType = (i8086CPU, i286CPU, i386CPU, i486CPU, iPentiumCPU); TForm1 = class(TForm) Edit1: TEdit; Label1: TLabel; BitBtn1: TBitBtn; procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); private { Return the type of the current CPU } function CpuType: TCPUType; { Return the type as a string } function GetCPUType: String; public end;var Form1: TForm1; { Define the winFlags variable for 286 check } winFlags: Longint;implementation{$R *.DFM} { Get CPU type } function TForm1.GetCPUType: String; var kind: TCPUType; begin if winFlags and WF_CPU286 > 0 then Result := '80286' else begin kind := CpuType; case kind of i8086CPU: Result := '8086'; i386CPU: Result := '80386'; i486CPU: Result := '80486'; iPentiumCPU: Result := 'Pentium'; else { Try to be flexible for future cpu types, e.g., P6. } Result := Format('P%d', [Ord(kind)]); end; end; end;{ Assembly function to get CPU type including Pentium and later } function TForm1.CpuType: TCPUType; assembler; asm push DS { First check for an 8086 CPU } { Bits 12-15 of the FLAGS register are always set on the } { 8086 processor. } pushf { save EFLAGS } pop bx { store EFLAGS in BX } mov ax,0fffh { clear bits 12-15 } and ax,bx { in EFLAGS } push ax { store new EFLAGS value on stack } popf { replace current EFLAGS value } pushf { set new EFLAGS } pop ax { store new EFLAGS in AX } and ax,0f000h { if bits 12-15 are set, then CPU } cmp ax,0f000h { is an 8086/8088 } mov ax, i8086CPU { turn on 8086/8088 flag } je @@End_CpuType { 80286 CPU check } { Bits 12-15 of the FLAGS register are always clear on the } { 80286 processor. } { Commented out because 'pop ax' crashes it to the DOS prompt when running } { with a Delphi form on some Machines.} { or bx,0f000h } { try to set bits 12-15 } { push bx } { popf } { pushf } { pop ax } { This crashes Delphi programs on some machines } { and ax,0f000h } { if bits 12-15 are cleared, CPU=80286 } { mov ax, i286CPU } { turn on 80286 flag } { jz @@End_CpuType } { To test for 386 or better, we need to use 32 bit instructions, but the 16-bit Delphi assembler does not recognize the 32 bit opcodes or operands. Instead, use the 66H operand size prefix to change each instruction to its 32-bit equivalent. For 32-bit immediate operands, we also need to store the high word of the operand immediately following the instruction. The 32-bit instruction is shown in a comment after the 66H instruction. } { i386 CPU check } { The AC bit, bit #18, is a new bit introduced in the EFLAGS } { register on the i486 DX CPU to generate alignment faults. } { This bit can not be set on the i386 CPU. } db 66h { pushfd } pushf db 66h { pop eax } pop ax { get original EFLAGS } db 66h { mov ecx, eax } mov cx,ax { save original EFLAGS } db 66h { xor eax,40000h } xor ax,0h { flip AC bit in EFLAGS } dw 0004h db 66h { push eax } push ax { save for EFLAGS } db 66h { popfd } popf { copy to EFLAGS } db 66h { pushfd } pushf { push EFLAGS } db 66h { pop eax } pop ax { get new EFLAGS value } db 66h { xor eax,ecx } xor ax,cx { can't toggle AC bit, CPU=Intel386 } mov ax, i386CPU { turn on 386 flag } je @@End_CpuType { i486 DX CPU / i487 SX MCP and i486 SX CPU checking } { Checking for ability to set/clear ID flag (Bit 21) in EFLAGS } { which indicates the presence of a processor } { with the ability to use the CPUID instruction. } db 66h { pushfd } pushf { push original EFLAGS } db 66h { pop eax } pop ax { get original EFLAGS in eax } db 66h { mov ecx, eax } mov cx,ax { save original EFLAGS in ecx } db 66h { xor eax,200000h } xor ax,0h { flip ID bit in EFLAGS } dw 0020h db 66h { push eax } push ax { save for EFLAGS } db 66h { popfd } popf { copy to EFLAGS } db 66h { pushfd } pushf { push EFLAGS } db 66h { pop eax } pop ax { get new EFLAGS value } db 66h { xor eax, ecx } xor ax, cx mov ax, i486CPU { turn on i486 flag } je @@End_CpuType { if ID bit cannot be changed, CPU=486 } { without CPUID instruction functionality } { Execute CPUID instruction to determine vendor, family, } { model and stepping. The use of the CPUID instruction used } { in this program can be used for B0 and later steppings } { of the P5 processor. } db 66h { mov eax, 1 } mov ax, 1 { set up for CPUID instruction } dw 0 db 66h { cpuid } db 0Fh { Hardcoded opcode for CPUID instruction } db 0a2h db 66h { and eax, 0F00H } and ax, 0F00H { mask everything but family } dw 0 db 66h { shr eax, 8 } shr ax, 8 { shift the cpu type down to the low byte } sub ax, 1 { subtract 1 to map to TCpuType }@@End_CpuType: pop ds end; { Get the Windows Flags to check for 286. The 286 assembly code crashes due to a problem when using with Delphi Forms on some machines. This method is safer. } procedure TForm1.FormCreate(Sender: TObject); begin winFlags := GetWinFlags; end;{ Call the CPU function and assign it to the Edit box } procedure TForm1.BitBtn1Click(Sender: TObject); begin Edit1.Text := GetCPUType;end;end.{This code came from Lloyd's help file!}
The problem here is that it doesn't detect the pentium.FT!
function GetCPUSpeed : Double;
const
DelayTime = 500; // measure time in ms
var
TimerHi, TimerLo : DWORD;
PriorityClass, Priority : Integer;
begin
PriorityClass := GetPriorityClass(GetCurrentProcess);
Priority := GetThreadPriority(GetCurrentThread); SetPriorityClass(GetCurrentProcess,
REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread,
THREAD_PRIORITY_TIME_CRITICAL); Sleep(10);
asm
dw 310Fh // rdtsc
mov TimerLo, eax
mov TimerHi, edx
end;
Sleep(DelayTime);
asm
dw 310Fh // rdtsc
sub eax, TimerLo
sbb edx, TimerHi
mov TimerLo, eax
mov TimerHi, edx
end; SetThreadPriority(GetCurrentThread, Priority);
SetPriorityClass(GetCurrentProcess, PriorityClass); Result := TimerLo / (1000.0 * DelayTime);
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
Stop := False;
while not Stop do
begin
label1.Caption := Format('CPU speed: %f MHz',
[GetCPUSpeed]);
Application.ProcessMessages;
end;
end;
procedure TForm1.Label1DblClick(Sender: TObject);
begin
Stop := True;
end;
上面的程序我在赛扬和AMD的cpu试过都可以.
偶P2.4的CPU竟然得到1703。如果用过忧化大师或CPU测试软件就知道,他们的CPU主频信息非常非常准,是取的而不是算出来的。
CSDN上难道没人研究过吗?
Test8087:测试协处理器{ Will always be 3 (387 or later) }
TestFDIV: 测试奔腾芯片是否有缺陷{ -1: 有缺陷, 0: 不能决定, 1: OK }Q: How do I detect for a co-processor?
Q: How can I tell which CPU is being used?A: Here is the short version. The problem here is that it doesn't detect the pentium.var winFlags: LongInt;
begin
winFlags := GetWinFlags;
{ Get math coprocessor status }
If winFlags And WF_80x87 > 0 Then Caption := 'Present'
Else Caption := 'Not Present'; { Get CPU type }
If winFlags And WF_CPU486 > 0 Then edit1.text := '486' {also pentium}
else If winFlags And WF_CPU386 > 0 Then edit1.text := '386' else If winFlags And WF_CPU286 > 0 Then edit1.text := '286';
end;
Here is a version that will work with the pentium:{ This code comes from Intel, and has been modified for Delphi's
inline assembler.
}unit Cpu;interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Buttons;type
{ All the types currently known. As new types are created,
add suitable names, and extend the case statement in the GetCpuType function.
}
TCPUType = (i8086CPU, i286CPU, i386CPU, i486CPU, iPentiumCPU); TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
BitBtn1: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Return the type of the current CPU }
function CpuType: TCPUType;
{ Return the type as a string }
function GetCPUType: String;
public
end;var
Form1: TForm1; { Define the winFlags variable for 286 check }
winFlags: Longint;implementation{$R *.DFM}
{ Get CPU type }
function TForm1.GetCPUType: String;
var
kind: TCPUType;
begin
if winFlags and WF_CPU286 > 0 then
Result := '80286'
else
begin
kind := CpuType;
case kind of
i8086CPU:
Result := '8086';
i386CPU:
Result := '80386';
i486CPU:
Result := '80486';
iPentiumCPU:
Result := 'Pentium'; else
{ Try to be flexible for future cpu types, e.g., P6. }
Result := Format('P%d', [Ord(kind)]);
end;
end;
end;{ Assembly function to get CPU type including Pentium and later }
function TForm1.CpuType: TCPUType; assembler;
asm
push DS
{ First check for an 8086 CPU }
{ Bits 12-15 of the FLAGS register are always set on the }
{ 8086 processor. }
pushf { save EFLAGS }
pop bx { store EFLAGS in BX } mov ax,0fffh { clear bits 12-15 }
and ax,bx { in EFLAGS }
push ax { store new EFLAGS value on stack }
popf { replace current EFLAGS value }
pushf { set new EFLAGS }
pop ax { store new EFLAGS in AX }
and ax,0f000h { if bits 12-15 are set, then CPU }
cmp ax,0f000h { is an 8086/8088 }
mov ax, i8086CPU { turn on 8086/8088 flag } je @@End_CpuType { 80286 CPU check }
{ Bits 12-15 of the FLAGS register are always clear on the }
{ 80286 processor. }
{ Commented out because 'pop ax' crashes it to the DOS prompt when running }
{ with a Delphi form on some Machines.}
{ or bx,0f000h } { try to set bits 12-15 }
{ push bx }
{ popf }
{ pushf }
{ pop ax } { This crashes Delphi programs on some machines } { and ax,0f000h } { if bits 12-15 are cleared, CPU=80286 }
{ mov ax, i286CPU } { turn on 80286 flag }
{ jz @@End_CpuType } { To test for 386 or better, we need to use 32 bit instructions,
but the 16-bit Delphi assembler does not recognize the 32 bit opcodes
or operands. Instead, use the 66H operand size prefix to change
each instruction to its 32-bit equivalent. For 32-bit immediate
operands, we also need to store the high word of the operand immediately following the instruction. The 32-bit instruction is shown in a comment
after the 66H instruction.
} { i386 CPU check }
{ The AC bit, bit #18, is a new bit introduced in the EFLAGS }
{ register on the i486 DX CPU to generate alignment faults. }
{ This bit can not be set on the i386 CPU. } db 66h { pushfd }
pushf
db 66h { pop eax }
pop ax { get original EFLAGS }
db 66h { mov ecx, eax } mov cx,ax { save original EFLAGS }
db 66h { xor eax,40000h }
xor ax,0h { flip AC bit in EFLAGS }
dw 0004h
db 66h { push eax }
push ax { save for EFLAGS }
db 66h { popfd }
popf { copy to EFLAGS }
db 66h { pushfd }
pushf { push EFLAGS }
db 66h { pop eax }
pop ax { get new EFLAGS value }
db 66h { xor eax,ecx } xor ax,cx { can't toggle AC bit, CPU=Intel386 }
mov ax, i386CPU { turn on 386 flag }
je @@End_CpuType { i486 DX CPU / i487 SX MCP and i486 SX CPU checking }
{ Checking for ability to set/clear ID flag (Bit 21) in EFLAGS }
{ which indicates the presence of a processor }
{ with the ability to use the CPUID instruction. }
db 66h { pushfd }
pushf { push original EFLAGS }
db 66h { pop eax } pop ax { get original EFLAGS in eax }
db 66h { mov ecx, eax }
mov cx,ax { save original EFLAGS in ecx }
db 66h { xor eax,200000h }
xor ax,0h { flip ID bit in EFLAGS }
dw 0020h
db 66h { push eax }
push ax { save for EFLAGS }
db 66h { popfd }
popf { copy to EFLAGS }
db 66h { pushfd }
pushf { push EFLAGS } db 66h { pop eax }
pop ax { get new EFLAGS value }
db 66h { xor eax, ecx }
xor ax, cx
mov ax, i486CPU { turn on i486 flag }
je @@End_CpuType { if ID bit cannot be changed, CPU=486 }
{ without CPUID instruction functionality } { Execute CPUID instruction to determine vendor, family, }
{ model and stepping. The use of the CPUID instruction used }
{ in this program can be used for B0 and later steppings } { of the P5 processor. }
db 66h { mov eax, 1 }
mov ax, 1 { set up for CPUID instruction }
dw 0
db 66h { cpuid }
db 0Fh { Hardcoded opcode for CPUID instruction }
db 0a2h
db 66h { and eax, 0F00H }
and ax, 0F00H { mask everything but family }
dw 0
db 66h { shr eax, 8 }
shr ax, 8 { shift the cpu type down to the low byte } sub ax, 1 { subtract 1 to map to TCpuType }@@End_CpuType:
pop ds
end;
{ Get the Windows Flags to check for 286. The 286 assembly code
crashes due to a problem when using with Delphi Forms on some machines. This
method is safer.
}
procedure TForm1.FormCreate(Sender: TObject);
begin
winFlags := GetWinFlags;
end;{ Call the CPU function and assign it to the Edit box }
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Edit1.Text := GetCPUType;end;end.{This code came from Lloyd's help file!}