在注册表中<br>"HKEY_LOCAL_MACHINE/hardware/DESCRIPTION/System/CentralProcessor/0"<br>对应VendorIndentifier的值 <br><br>program CpuSpeed;<br>uses SysUtils, Windows, Dialogs;<br>function GetCpuSpeed: Comp;<br>var<br> t: DWORD;<br> mhi, mlo, nhi, nlo: DWORD;<br> t0, t1, chi, clo, shr32: Comp;<br>begin<br> shr32 := 65536;<br> shr32 := shr32 * 65536;<br> t := GetTickCount;<br> while t = GetTickCount do begin end;<br> asm<br> DB 0FH<br> DB 031H<br> mov mhi,edx<br> mov mlo,eax<br> end;<br> while GetTickCount < (t + 1000) do begin end;<br> asm<br> DB 0FH<br> DB 031H<br> mov nhi,edx<br> mov nlo,eax<br> end;<br> chi := mhi; if mhi < 0 then chi := chi + shr32;<br> clo := mlo; if mlo < 0 then clo := clo + shr32;<br> t0 := chi * shr32 + clo;<br> chi := nhi; if nhi < 0 then chi := chi + shr32;<br> clo := nlo; if nlo < 0 then clo := clo + shr32;<br> t1 := chi * shr32 + clo;<br> Result := (t1 - t0) / 1E6;<br>end;<br>begin<br> MessageDlg(Format('%.1f MHz', [GetCpuSpeed]), mtConfirmation, [mbOk], 0);<br>end.<br><br><br><br><br>--------------------------------------------------------------------------------<br><br><br>function GetCPUSpeed: Double;<br>const<br> DelayTime = 500; // measure time in ms<br>var<br> TimerHi, TimerLo: DWORD;<br> PriorityClass, Priority: Integer;<br>begin<br> PriorityClass := GetPriorityClass(GetCurrentProcess);<br> Priority := GetThreadPriority(GetCurrentThread);<br> <br> SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);<br> SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);<br> <br> Sleep(10);<br> asm<br> dw 310Fh // rdtsc<br> mov TimerLo, eax<br> mov TimerHi, edx<br> end;<br> Sleep(DelayTime);<br> asm<br> dw 310Fh // rdtsc<br> sub eax, TimerLo<br> sbb edx, TimerHi<br> mov TimerLo, eax<br> mov TimerHi, edx<br> end;<br> <br> SetThreadPriority(GetCurrentThread, Priority);<br> SetPriorityClass(GetCurrentProcess, PriorityClass);<br> <br><br> Result := TimerLo / (1000.0 * DelayTime);<br>end;<br> <br><br><br><br><br>--------------------------------------------------------------------------------<br><br>function RDTSC : Int64; assembler;<br>asm<br> db $0F, $31 // opcode for RDTSC<br>end;<br><br>function RDQPC : Int64;<br>begin<br> QueryPerformanceCounter(result);<br>end;<br><br>function CPUSpeed : Integer;<br>var<br> f,tsc,pc : Int64;<br>begin<br> if QueryPerformanceFrequency(f) then<br> begin<br> Sleep(0);<br> pc := RDQPC;<br> tsc := RDTSC;<br> Sleep(100);<br> pc := RDQPC-pc;<br> tsc := RDTSC-tsc;<br> result := round(tsc*f/(pc*1000000));<br> end<br> else<br> result := -1;<br>end;<br><br><br><br><br>--------------------------------------------------------------------------------<br><br><br> <br><br> 由于使用RDTSC操作码,因此以下函数只能返回Pentium或者更高芯片的速度。另一种解决方法是使用WinAPI中的QueryPerformanceCounter或者QueryPerformanceFrequency函数。<br><br> <br><br> function GetCPUSpeed: real; <br><br> <br><br> function IsCPUID_Available: Boolean; assembler; register; <br><br> asm <br><br> PUSHFD { direct access to flags not possible, only via stack } <br><br> POP EAX { flags to EAX } <br><br> MOV EDX,EAX { save current flags } <br><br> XOR EAX,$200000 { not ID bit } <br><br> PUSH EAX { onto stack } <br><br> POPFD { from stack to flags, with not ID bit } <br><br> PUSHFD { back to stack } <br><br> POP EAX { get back to EAX } <br><br> XOR EAX,EDX { check if ID bit affected } <br><br> JZ @exit { no, CPUID not availavle } <br><br> MOV AL,True { Result=True } <br><br> @exit: <br><br> end; <br><br> <br><br> function hasTSC: Boolean; <br><br> var <br><br> Features: Longword; <br><br> begin <br><br> asm <br><br> MOV Features,0 { Features = 0 } <br><br> <br><br> PUSH EBX <br><br> XOR EAX,EAX <br><br> DW $A20F <br><br> POP EBX <br><br> <br><br> CMP EAX,$01 <br><br> JL @Fail <br><br> <br><br> XOR EAX,EAX <br><br> MOV EAX,$01 <br><br> PUSH EBX <br><br> DW $A20F <br><br> MOV Features,EDX <br><br> POP EBX <br><br> @Fail: <br><br> end; <br><br> <br><br> hasTSC := (Features and $10) <> 0; <br><br> end; <br><br> <br><br> const <br><br> DELAY = 500; <br><br> var <br><br> TimerHi, TimerLo: Integer; <br><br> PriorityClass, Priority: Integer; <br><br> begin <br><br> Result := 0; <br><br> if not (IsCPUID_Available and hasTSC) then Exit; <br><br> PriorityClass := GetPriorityClass(GetCurrentProcess); <br><br> Priority := GetThreadPriority(GetCurrentThread); <br><br> <br><br> SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS); <br><br> SetThreadPriority(GetCurrentThread, <br><br> THREAD_PRIORITY_TIME_CRITICAL); <br><br> <br><br> SleepEx(10, FALSE); <br><br> <br><br> asm <br><br> DB $0F { $0F31 操作码是Pentium指令集中的RDTSC } <br><br> DB $31 { 返回64位整数 } <br><br> MOV TimerLo,EAX <br><br> MOV TimerHi,EDX <br><br> end; <br><br> <br><br> SleepEx(DELAY, FALSE); <br><br> <br><br> asm <br><br> DB $0F { $0F31 操作码是Pentium指令集中的RDTSC } <br><br> DB $31 { 返回64位整数 } <br><br> SUB EAX,TimerLo <br><br> SBB EDX,TimerHi <br><br> MOV TimerLo,EAX <br><br> MOV TimerHi,EDX <br><br> end; <br><br> <br><br> SetThreadPriority(GetCurrentThread, Priority); <br><br> SetPriorityClass(GetCurrentProcess, PriorityClass); <br><br> Result := TimerLo / (1000 * DELAY); <br><br> end; <br><br> <br>