Delphi下获取CPUID

发布时间:2013年9月11日 作者:未知 查看次数:2251

Delphi下获取CPUID


转:Delphi下获取CPUID一法

http://my.oschina.net/uian2000/blog/115166

最近忽然有需求获取CPUID。Google后看到些东西,整理出来,防止忘记。由于我惯用Delphi,这里只列出Delphi下用法。

CPUID是一个处理器支持的操作指令,用于获取CPU特性信息。详见http://en.wikipedia.org/wiki/CPUID

既然与CPU相关,就有适用范围的问题。判断其是否可用,需要检查EFlags的第21为是否可更改,如是,则表示处理器支持。

Intel 8086/286只有Flags(不E),386的第21位为保留位,无法改写,因此这些CPU均不支持CPUID指令。

测试CPU是否支持CPUID

01 function TestCPUID: Boolean;
02 begin
03   asm
04     mov Result, 0
05     pushfd            // 将EFlags压栈
06     pop eax           // 取出EFlags
07     mov ecx, eax
08     xor eax, 200000h  // 修改第21位
09     push eax
10     popfd             // 将变更后的EFlags存入扩展标志
11     pushfd
12     pop eax           // 再次取出EFlags
13     xor eax, ecx      // 判断是否变化
14     jz @end
15     mov Result, 1
16     @end:
17   end;
18 end;

CPUID指令以EAX为参数,返回值分布于EAX,EBX,ECX,EDX四个寄存器,由此,通用的CPUID过程设计如下

01 procedure GetCPUID(var AAx, ABx, ACx, ADx: Cardinal);
02 var
03   vAx, vBx, vCx, vDx: Cardinal;
04 begin
05   // 传参与寄存器关联,此处采用内部变量缓存
06   vAx := AAx; vBx := ABx; vCx := ACx; vDx := ADx;
07   asm
08     push ebx       // 寄存器ebx需要保护
09   
10     mov eax, vAx
11     mov ebx, vBx
12     mov ecx, vCx
13     mov edx, vDx
14     cpuid
15     mov vAx, eax
16     mov vBx, ebx
17     mov vCx, ecx
18     mov vDx, edx
19   
20     pop ebx
21   end;
22   
23   AAx := vAx; ABx := vBx; ACx := vCx; ADx := vDx;
24 end;

然后,就可以根据处理器指令手册获取相关信息了。

如:获取VendorString

01 type
02   TCardinalChar = packed record
03     case Integer of
04       0: (CharA, CharB, CharC, CharD: AnsiChar;);
05       1: (Chars: Cardinal;);
06   end;
07   
08 function GetVendorString: String;
09 var
10   vAx, vBx, vCx, vDx: Cardinal;
11   vChars: TCardinalChar;
12 begin
13   Result := '';
14   
15   if not TestCPUID then Exit;
16   
17   vAx := 0;
18   GetCPUID(vAx, vBx, vCx, vDx);
19   
20   vChars.Chars := vBx;
21   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
22   vChars.Chars := vDx;
23   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
24   vChars.Chars := vCx;
25   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
26 end;

或者:获取BrandString

01 function GetBrandString: String;
02 var
03   vAx, vBx, vCx, vDx: Cardinal;
04   vChars: TCardinalChar;
05 begin
06   Result := '';
07   if not TestCPUID then Exit;
08   
09   vAx := $80000002;
10   GetCPUID(vAx, vBx, vCx, vDx);
11   vChars.Chars := vAx;
12   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
13   vChars.Chars := vBx;
14   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
15   vChars.Chars := vCx;
16   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
17   vChars.Chars := vDx;
18   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
19   vAx := $80000003;
20   GetCPUID(vAx, vBx, vCx, vDx);
21   vChars.Chars := vAx;
22   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
23   vChars.Chars := vBx;
24   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
25   vChars.Chars := vCx;
26   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
27   vChars.Chars := vDx;
28   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
29   vAx := $80000004;
30   GetCPUID(vAx, vBx, vCx, vDx);
31   vChars.Chars := vAx;
32   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
33   vChars.Chars := vBx;
34   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
35   vChars.Chars := vCx;
36   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
37   vChars.Chars := vDx;
38   Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
39 end;

以上。

另,不同CPU支持的指令不同,具体编码最好参考厂商提供的相关手册。



版权所有!www.sieye.cn
E.Mail:sieye@sohu.com QQ:66697110