Title: CPU speed
Question: How to "judge" or read the CPU speed of a processor that a program is running on?
Answer:
This should the job. It will only give result with Pentium or better due to
the RDTSC opcode. An alternative is to use QueryPerformanceCounter or QueryPerformanceFrequency from the WinAPI.
function GetCPUSpeed: real;
function IsCPUID_Available: Boolean; assembler; register;
asm
PUSHFD { direct access to flags not possible, only via stack }
POP EAX { flags to EAX }
MOV EDX,EAX { save current flags }
XOR EAX,$200000 { not ID bit }
PUSH EAX { onto stack }
POPFD { from stack to flags, with not ID bit }
PUSHFD { back to stack }
POP EAX { get back to EAX }
XOR EAX,EDX { check if ID bit affected }
JZ @exit { no, CPUID not availavle }
MOV AL,True { Result=True }
@exit:
end;
function hasTSC: Boolean;
var
Features: Longword;
begin
asm
MOV Features,0 { Features = 0 }
PUSH EBX
XOR EAX,EAX
DW $A20F
POP EBX
CMP EAX,$01
JL @Fail
XOR EAX,EAX
MOV EAX,$01
PUSH EBX
DW $A20F
MOV Features,EDX
POP EBX
@Fail:
end;
hasTSC := (Features and $10) 0;
end;
const
DELAY = 500;
var
TimerHi, TimerLo: Integer;
PriorityClass, Priority: Integer;
begin
Result := 0;
if not (IsCPUID_Available and hasTSC) then Exit;
PriorityClass := GetPriorityClass(GetCurrentProcess);
Priority := GetThreadPriority(GetCurrentThread);
SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread,
THREAD_PRIORITY_TIME_CRITICAL);
SleepEx(10, FALSE);
asm
DB $0F { $0F31 op-code for RDTSC Pentium instruction }
DB $31 { returns a 64 Bit Integer }
MOV TimerLo,EAX
MOV TimerHi,EDX
end;
SleepEx(DELAY, FALSE);
asm
DB $0F { $0F31 op-code for RDTSC Pentium instruction }
DB $31 { returns a 64 Bit Integer }
SUB EAX,TimerLo
SBB EDX,TimerHi
MOV TimerLo,EAX
MOV TimerHi,EDX
end;
SetThreadPriority(GetCurrentThread, Priority);
SetPriorityClass(GetCurrentProcess, PriorityClass);
Result := TimerLo / (1000 * DELAY);
end;
Bogdan Grigorescu - BogdanG@gmail.com
BG Remote Programming Group