首页  编辑  

CPU的一些信息

Tags: /超级猛料/Hardware.硬件相关/CPU相关/   Date Created:

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;

interface

uses

 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!}