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
|