CPUのクロック周波数の求め方
65 GetCPUClock 動作確認 Delphi2007 更新日 2008/01/31(木)

以下のようなUnitを使って
 GetCPUClock 関数を使ってみてください。

GetCPUClock 関数で
500Mhzのセレロンの場合
498.542982093664 という値が取得できました

2.4GHzのPentium4の場合
2377.059544 という値が取得できました。

────────────────────
unit CPUClock;

interface

uses
  Windows, SysUtils;

//CPUクロックを計算する
function GetCPUClock: Double;

implementation

    function EnabledCPUID: Boolean; assembler;
    //CPUID命令が使えるか調べる関数
    asm
      PUSH    EDX          //念のために退避
      PUSH    ECX          //念のために退避
      XOR     EAX, EAX     //ゼロクリア
      PUSHFD               //EFLAGSをスタックにプッシュ
      POP     EDX          //EDXにロード
      MOV     ECX, EDX     //比較のためにECXに退避
      XOR     EDX, $200000 //ビット21を設定
      PUSH    EDX          //スタックにプッシュ
      POPFD                //EFLAGSに読み込ませる
      PUSHFD               //EFLAGSをスタックにプッシュ
      POP     EDX          //EDXにロード
      XOR     EDX, ECX     //ビット21がクリアされているか調べる
      SETNZ   AL           //ZF = 0の場合CPUIDが使える
      POP     ECX          //元の内容に戻す
      POP     EDX          //元の内容に戻す
    end;

    function EnabledRDTSC: Boolean; assembler;
    //RDTSC命令が使えるか調べる関数
    asm
         CALL  EnabledCPUID //CPUIDは使える?(上の関数を呼び出す)
         CMP   EAX, $01     //戻り値を比較
         JE    @@1          //Trueの場合@@1にジャンプ
         XOR   EAX, EAX     //使えねー
         RET                //ここで関数を終了
    @@1://CPUIDが使える
         PUSH  ECX          //念のために退避
         PUSH  EDX          //念のために退避
         PUSH  EBX          //EBXは保護しないといけないので退避
         XOR   EAX, EAX     //EAXをゼロクリア
         DW    $A20F        //CPUID
         CMP   EAX, $01     //最大入力値が1以上あるか?
         JB    @@2          //ない(つまりEAX=0ちゅーこと)
         MOV   EAX, $01     //あるのでEAXを1にして...
         DW    $A20F        //CPUIDを実行
         XOR   EAX, EAX     //EAXをゼロクリア(戻り値として使う)
         TEST  EDX, $10     //ビット4が設定されてる?
         SETNZ AL           //ZFを反転して転送
         JMP   @@3          //終わり
    @@2://RDTSCは使えない
         XOR   EAX, EAX
    @@3://後始末
         POP   EBX          //スタックに退避したEBXを戻す
         POP   EDX          //元の内容に戻す
         POP   ECX          //元の内容に戻す
    end;


var
  StartTime: Cardinal = 0;
  StartTSC : Int64Rec;
  StartTSC64: Int64 absolute StartTSC;

function InitCPUClock: Boolean;
//CPUクロックの計算に必要な変数などを初期化する
begin
  Result := EnabledRDTSC;
  if Result then
  begin
    StartTime := GetTickCount;
    asm
      PUSH EDX   //念のために退避
      PUSH EAX   //念のために退避
      DW   $310F //RDTSC
      MOV  DWORD PTR [StartTSC.Hi], EDX
      MOV  DWORD PTR [StartTSC.Lo], EAX
      POP  EAX   //元の内容に戻す
      POP  EDX   //元の内容に戻す
    end;
  end;
end;

function GetCPUClock: Double;
//CPUクロックを計算する
var
  CurrTSC: Int64Rec;
  CurrTSC64: Int64 absolute CurrTSC;
begin
  if StartTime > 0 then
  begin
    asm
      PUSH  EDX   //念のために退避
      PUSH  EAX   //念のために退避
      DW    $310F //RDTSC
      MOV   DWORD PTR [CurrTSC.Hi],  EDX
      MOV   DWORD PTR [CurrTSC.Lo],  EAX
      POP   EAX   //元の内容に戻す
      POP   EDX   //元の内容に戻す
    end;
    Result := ((CurrTSC64 - StartTSC64) /
              (GetTickCount - StartTime)) / 1000; // MHz
  end else
    Result := 0;
end;


initialization

InitCPUClock;
//初期化処理

end.
────────────────────

参考────────────────────
RG VEDA DELPHI TIPS
homepage1.nifty.com\beny\tips\other09.html