Delphi下获取CPUID一法

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

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

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

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

测试CPU是否支持CPUID 设计

function TestCPUID: Boolean;
begin
  asm
    mov Result, 0
    pushfd            // 将EFlags压栈
    pop eax           // 取出EFlags
    mov ecx, eax
    xor eax, 200000h  // 修改第21位
    push eax
    popfd             // 将变动后的EFlags存入扩展标志
    pushfd
    pop eax           // 再次取出EFlags
    xor eax, ecx      // 判断是否变化
    jz @end
    mov Result, 1
    @end:
  end;
end;
CPUID指令以EAX为参数,返回值分布于EAX,EBX,ECX,EDX四个寄存器,由此,通用的CPUID过程设计以下

procedure GetCPUID(var AAx, ABx, ACx, ADx: Cardinal);
var
  vAx, vBx, vCx, vDx: Cardinal;
begin
  // 传参与寄存器关联,此处采用内部变量缓存
  vAx := AAx; vBx := ABx; vCx := ACx; vDx := ADx;
  asm
    push ebx       // 寄存器ebx须要保护

    mov eax, vAx
    mov ebx, vBx
    mov ecx, vCx
    mov edx, vDx
    cpuid
    mov vAx, eax
    mov vBx, ebx
    mov vCx, ecx
    mov vDx, edx

    pop ebx
  end;

  AAx := vAx; ABx := vBx; ACx := vCx; ADx := vDx;
end;
而后,就能够根据处理器指令手册获取相关信息了。

如:获取VendorString code

type
  TCardinalChar = packed record
    case Integer of
      0: (CharA, CharB, CharC, CharD: AnsiChar;);
      1: (Chars: Cardinal;);
  end;

function GetVendorString: String;
var
  vAx, vBx, vCx, vDx: Cardinal;
  vChars: TCardinalChar;
begin
  Result := '';

  if not TestCPUID then Exit;

  vAx := 0;
  GetCPUID(vAx, vBx, vCx, vDx);

  vChars.Chars := vBx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vDx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vCx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
end;

或者:获取BrandString ip

function GetBrandString: String;
var
  vAx, vBx, vCx, vDx: Cardinal;
  vChars: TCardinalChar;
begin
  Result := '';
  if not TestCPUID then Exit;

  vAx := $80000002;
  GetCPUID(vAx, vBx, vCx, vDx);
  vChars.Chars := vAx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vBx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vCx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vDx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vAx := $80000003;
  GetCPUID(vAx, vBx, vCx, vDx);
  vChars.Chars := vAx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vBx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vCx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vDx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vAx := $80000004;
  GetCPUID(vAx, vBx, vCx, vDx);
  vChars.Chars := vAx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vBx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vCx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
  vChars.Chars := vDx;
  Result := Result + vChars.CharA + vChars.CharB + vChars.CharC + vChars.CharD;
end;
以上。

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

相关文章
相关标签/搜索