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

相關文章
相關標籤/搜索