📄 freq.cpp
字号:
#include "stdafx.h"
#include <Winbase.h>
#include <time.h>
#include "Freq.h"
int nCPUFreq = 0;
int CPU_Frequency(void); //MHz
class CTestFreq
{
private:
time_t tmStart;
__int64 tscStart;
public:
CTestFreq()
{
int temp_nCPUFREQ_i, MAX_nCPUFREQ=0;
for (temp_nCPUFREQ_i = 0; temp_nCPUFREQ_i <10;++temp_nCPUFREQ_i)
{
nCPUFreq = CPU_Frequency();
if (nCPUFreq > MAX_nCPUFREQ)
MAX_nCPUFREQ = nCPUFreq;
}
nCPUFreq = MAX_nCPUFREQ ;
time(&tmStart);
GetCurrentTSC(tscStart);
}
~CTestFreq()
{
_RepairTime();
}
void _RepairTime();
};
void CTestFreq::_RepairTime()
{
time_t tmNow;
__int64 tscNow;
GetCurrentTSC(tscNow);
tmNow = tmStart + ((tscNow - tscStart) / nCPUFreq) / 1000000;
struct tm tNow;
tNow = *localtime(&tmNow);
SYSTEMTIME sysTime;
sysTime.wYear = tNow.tm_year + 1900;
sysTime.wMonth = tNow.tm_mon + 1;
sysTime.wDayOfWeek = tNow.tm_wday;
sysTime.wDay = tNow.tm_mday;
sysTime.wHour = tNow.tm_hour;
sysTime.wMinute = tNow.tm_min;
sysTime.wSecond = tNow.tm_sec;
sysTime.wMilliseconds = 0;
// SetLocalTime(&sysTime);
}
static CTestFreq tmpTestFreqObj;
/*
Operating Frequency
With the introduction of the Time-Stamp Counter, it is possible for software operating in real
mode or protected mode with ring 0 privilege to calculate the actual operating frequency of the
processor. To calculate the operating frequency, the software needs a reference period. The
reference period can be a periodic interrupt, or another timer that is based on time, and not based
on a system clock. Software needs to read the Time-Stamp Counter (TSC) at the beginning and
ending of the reference period. Software can read the TSC by executing the RDTSC instruction,
or by setting the ECX register to 10h and executing the RDMSR instruction. Both instructions
copy the current 64-bit TSC into the EDX:EAX register pair.
To determine the operating frequency of the processor, software performs the following steps.
The assembly language program frequenc.asm (see Example 6) demonstrates the frequency
detection algorithm.
1. Execute the CPUID instruction with an input value of EAX=0 and ensure the vendor-ID
string returned is “GenuineIntel”.
2. Execute the CPUID instruction with EAX=1 to load the EDX register with the feature flags.
3. Ensure that the TSC feature flag (EDX bit 4) is set. This indicates the processor supports the
Time-Stamp Counter and RDTSC instruction.
4. Read the TSC at the beginning of the reference period.
5. Read the TSC at the end of the reference period.
6. Compute the TSC delta from the beginning and ending of the reference period.
7. Compute the actual frequency by dividing the TSC delta by the reference period.
Actual frequency = (Ending TSC value – Beginning TSC value) / reference period
Note: The measured accuracy is dependent on the accuracy of the reference period. A longer
reference period produces a more accurate result. In addition, repeating the calculation
multiple times may also improve accuracy.
*/
int CPU_Frequency(void) //MHz
{
LARGE_INTEGER CurrTicks, TicksCount;
__int64 iStartCounter, iStopCounter;
DWORD dwOldProcessP = GetPriorityClass(GetCurrentProcess());
DWORD dwOldThreadP = GetThreadPriority(GetCurrentThread());
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
QueryPerformanceFrequency(&TicksCount);
QueryPerformanceCounter(&CurrTicks);
TicksCount.QuadPart /= 16;
TicksCount.QuadPart += CurrTicks.QuadPart;
_asm rdtsc
_asm mov DWORD PTR iStartCounter, EAX
_asm mov DWORD PTR (iStartCounter+4), EDX
while(CurrTicks.QuadPart<TicksCount.QuadPart)
QueryPerformanceCounter(&CurrTicks);
_asm rdtsc
_asm mov DWORD PTR iStopCounter, EAX
_asm mov DWORD PTR (iStopCounter + 4), EDX
SetThreadPriority(GetCurrentThread(), dwOldThreadP);
SetPriorityClass(GetCurrentProcess(), dwOldProcessP);
return (int)((iStopCounter-iStartCounter)/62500);
}
void GetCurrentTSC(__int64& TicksCount)
{
// Inportb(0x378+1);
__int64 tmpCounter;
_asm rdtsc
_asm mov DWORD PTR tmpCounter, EAX
_asm mov DWORD PTR (tmpCounter+4), EDX
TicksCount = tmpCounter;
}
void RepairTime()
{
tmpTestFreqObj._RepairTime();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -