>How can I detect a Pentium processor from within a Delphi program?
Here is a Delphi unit to detect the CPU type, modified from Intel\'s code. Use should be fairly obvious. If not, send me email, and I can send you an example program. Because Delphi\'s assembler is 16-bit, the code looks a little wierd. Try using a 32-bit disassembler to see the 32-bit instructions (or read the comments).
-----cut here-----8<-------cut here------8<--------- unit CpuId;
{ This code comes from Intel, and has been modified for Delphi\'s inline assembler. Since Intel made the original code freely available, I am making my changes freely available.
Share and enjoy!
Ray Lischner Tempest Software 6/18/95 }
interface
type { All the types currently known. As new types are created, add suitable names, and extend the case statement in CpuTypeString. } TCpuType = (cpu8086, cpu80286, cpu386, cpu486, cpuPentium);
{ Return the type of the current CPU } function CpuType: TCpuType;
{ Return the type as a short string } function CpuTypeString: String;
implementation
uses SysUtils;
function 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, cpu8086 { 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. } or bx,0f000h { try to set bits 12-15 } push bx popf pushf pop ax and ax,0f000h { if bits 12-15 are cleared, CPU=80286 } mov ax, cpu80286 { 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, cpu386 { 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, cpu486 { 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;
function CpuTypeString: String; var kind: TCpuType; begin kind := CpuType; case kind of cpu8086: Result := \'8086\'; cpu80286: Result := \'80286\'; cpu386: Result := \'386\'; cpu486: Result := \'486\'; cpuPentium: Result := \'Pentium\'; else { Try to be flexible for future cpu types, e.g., P6. } Result := Format(\'P%d\', [Ord(kind)]); end; end;
end.
-- Ray Lischner (lisch@tempest-sw.com) Tempest Software
jeg prøver dit disk men jeg håber det virker for det skal bruges på min nye computer og nu har jeg lige givet 300 point for det!
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.