#ifndef __TIMING__INCLUDED__IOSA_4__
#define __TIMING__INCLUDED__IOSA_4__
#include <crtdefs.h>
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>
#ifdef __cplusplus
extern "C" {
#endif
_CRTIMP void __cdecl _wassert(_In_z_ const wchar_t* _Message, _In_z_ const wchar_t* _File, _In_ unsigned _Line);
#ifdef __cplusplus
}
#endif
#define ENFORCE(_Expression) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression),_CRT_WIDE(__FILE__),__LINE__),0))
static unsigned __int64 UisHnack, CpuFreq, MilliCpuFreq;
__declspec(naked) static unsigned __int64 LoadTSC ( void ) {
__asm rdtsc
__asm ret
}
__declspec(naked) static void TSleep ( unsigned int dwMilliseconds ) {
static unsigned __int64 tStart;
__asm {
rdtsc
mov dword ptr [tStart], eax
mov dword ptr [tStart+4], edx
mov eax, 4[esp]
mov dword ptr [UisHnack+4], 0
mov dword ptr [UisHnack], eax
}
UisHnack *= MilliCpuFreq;
while ( LoadTSC () - tStart <= UisHnack );
__asm ret
}
static unsigned __int64 LoadSpecifyCpuFreq ( unsigned int CpuCoreIndex ) {
unsigned __int64 timeStart64, cpu_fm64, timeToRDTSC, timeToQPF, Q_Error, QsecTCnt, pfq, lpQFCount;
unsigned __int32 OldPriClassFlags, OldPriThreadFlags;
HANDLE CurProcessHandle = GetCurrentProcess();
HANDLE CurThreadHandle = GetCurrentThread ();
OldPriClassFlags = GetPriorityClass ( CurProcessHandle );
OldPriThreadFlags = GetThreadPriority( CurThreadHandle );
ENFORCE ( CpuCoreIndex < 4 );
ENFORCE ( SetThreadAffinityMask ( CurThreadHandle, ( (unsigned int) 1 << CpuCoreIndex ) ) );
ENFORCE ( SetProcessAffinityMask ( CurProcessHandle, ( (unsigned int) 1 << CpuCoreIndex ) ) );
ENFORCE ( QueryPerformanceFrequency ( ( (LARGE_INTEGER*) &pfq) ) );
ENFORCE ( SetPriorityClass ( CurProcessHandle, REALTIME_PRIORITY_CLASS ) );
ENFORCE ( SetThreadPriority( CurThreadHandle, THREAD_PRIORITY_HIGHEST ) );
__asm {
rdtsc
mov ebx, eax /* call rdtsc * 1 */
mov ecx, edx
rdtsc
sbb edx, ecx
sub eax, ebx
mov dword ptr [timeToRDTSC], eax
mov dword ptr [timeToRDTSC+4], edx
rdtsc
mov dword ptr [timeToQPF], eax
mov dword ptr [timeToQPF+4], edx
push offset UisHnack
call dword ptr [QueryPerformanceCounter]
rdtsc
sub eax, dword ptr [timeToQPF]
sbb edx, dword ptr [timeToQPF+4]
mov dword ptr [timeToQPF], eax
mov dword ptr [timeToQPF+4], edx
push offset UisHnack
call dword ptr [QueryPerformanceCounter]
lea eax, QsecTCnt
push eax
call dword ptr [QueryPerformanceCounter]
mov eax, dword ptr [UisHnack] ; low
mov ebx, dword ptr [UisHnack+4] ; high
sub dword ptr [QsecTCnt], eax
sbb dword ptr [QsecTCnt+4], ebx
}
QueryPerformanceCounter((LARGE_INTEGER*)&lpQFCount);
timeStart64 = lpQFCount;
__asm {
rdtsc
mov dword ptr [cpu_fm64], eax
mov dword ptr [cpu_fm64+4], edx
}
while ((Q_Error = (lpQFCount - timeStart64)) <= pfq )
{
QueryPerformanceCounter((LARGE_INTEGER*)&lpQFCount);
}
__asm {
rdtsc
sub eax, dword ptr [cpu_fm64]
sbb edx, dword ptr [cpu_fm64+4]
mov dword ptr [cpu_fm64], eax
mov dword ptr [cpu_fm64+4], edx
}
MilliCpuFreq = ( CpuFreq = cpu_fm64 = cpu_fm64 - timeToQPF - timeToRDTSC - (unsigned __int64)( (double) ( Q_Error - pfq ) / (double) QsecTCnt * ( double ) timeToQPF ) ) / 1000;
ENFORCE ( timeToRDTSC < 800 );
ENFORCE ( SetPriorityClass ( CurProcessHandle, OldPriClassFlags ) );
ENFORCE ( SetThreadPriority( CurThreadHandle, OldPriThreadFlags ) );
return cpu_fm64;
}
static unsigned __int64 SetFrame ( unsigned int FrameTicks, unsigned int CpuCoreIndex ) {
return ( LoadSpecifyCpuFreq ( CpuCoreIndex ) / ( unsigned __int64 ) FrameTicks );
}
#endif
.686 ; create 32 bit code
.mmx
.xmm
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
; marco
byt equ byte ptr
wot equ word ptr
dwot equ dword ptr
; extrn Windows API ...
extrn exit:proc ; no WindowsAPI
extrn MessageBoxA@16:proc
extrn GetPriorityClass@4:proc
extrn SetPriorityClass@8:proc
extrn GetThreadPriority@4:proc
extrn SetThreadPriority@8:proc
extrn SetThreadAffinityMask@8:proc
extrn SetProcessAffinityMask@8:proc
extrn QueryPerformanceCounter@4:proc
extrn QueryPerformanceFrequency@4:proc
.data?
__rdtsc_t dd 2 dup(?)
__per_freq dd 2 dup(?)
__time_temp1 dd 2 dup(?)
__time_temp2 dd 2 dup(?)
__time_temp3 dd 2 dup(?)
__time_temp4 dd 2 dup(?)
__rdtsc_clock dd 2 dup(?)
__per_counter_clock dd 2 dup(?)
__per_counter_clock_plck dd 2 dup(?)
.code
__load_main_cpu_ticks proc C
option prologue:none, epilogue:none
push 1
push -2
call SetThreadAffinityMask@8
cmp eax, 0
je __exit
push 1
push -1
call SetProcessAffinityMask@8
cmp eax, 0
je __exit
push 256
push -1
call SetPriorityClass@8
cmp eax, 0
je __exit
push 2
push -2
call SetThreadPriority@8
cmp eax, -1
je __exit
push offset __per_freq
call QueryPerformanceFrequency@4
; main
mov eax, 35600
wait_some:
dec eax
jne wait_some
rdtsc
mov ecx, eax ; low 8 bit
rdtsc
sub eax, ecx ; low 8 bit sub ...
mov dwot[__rdtsc_clock], eax
rdtsc
mov dwot[__rdtsc_t], eax
push offset __time_temp1
call QueryPerformanceCounter@4
rdtsc
sub eax, dwot[__rdtsc_t]
sub eax, dwot[__rdtsc_clock]
mov dwot[__per_counter_clock], eax
push offset __time_temp1
call QueryPerformanceCounter@4
push offset __time_temp2
call QueryPerformanceCounter@4
mov eax, dwot[__time_temp2]
sub eax, dwot[__time_temp1]
mov dwot[__per_counter_clock_plck], eax
rdtsc
mov dwot[__time_temp3], eax
mov dwot[__time_temp3+4], edx
push offset __time_temp1
call QueryPerformanceCounter@4
mov eax, dwot[__time_temp1]
mov edx, dwot[__time_temp1+4]
mov dwot[__time_temp2], eax
mov dwot[__time_temp2+4], edx
align 16
main_loop:
mov eax, dwot[__time_temp2]
mov edx, dwot[__time_temp2+4]
sub eax, dwot[__time_temp1]
sbb edx, dwot[__time_temp1+4]
cmp edx, dwot[__per_freq+4]
ja __out_step
jb __in_step
sub eax, dwot[__per_freq]
jae __out_step
__in_step:
push offset __time_temp2
call QueryPerformanceCounter@4
jmp main_loop
align 16
__out_step:
cvtsi2sd xmm0, eax
rdtsc
sub eax, dwot[__time_temp3]
sbb edx, dwot[__time_temp3+4]
sub eax, dwot[__rdtsc_clock]
sbb edx, dwot[__rdtsc_clock+4]
mov ecx, dwot[__per_counter_clock]
shl ecx, 1
sub eax, ecx
sbb edx, 0
cvtsi2sd xmm2, dwot[__per_counter_clock]
cvtsi2sd xmm1, dwot[__per_counter_clock_plck]
divsd xmm2, xmm1
mulsd xmm2, xmm0
cvtsd2si ecx, xmm2
sub eax, ecx
sbb edx, 0
ret
__exit:
push 0
push 0
push 0
push 0
call MessageBoxA@16
push -1
call exit
add esp, 4
ret
__load_main_cpu_ticks endp
end

- 大小: 21 KB
分享到:
相关推荐
这个操作可以是任何无副作用的计算,只要能确保在不同的CPU频率下,循环次数相同。 3. **再次获取时间戳**:在循环结束后,再执行一次RDTSC,获取结束时间戳,记为T2。 4. **计算时间差**:计算T2与T1的时间差ΔT...
- **RDTSC指令**:与上述两个方法相比,RDTSC指令能够直接访问CPU的时间戳寄存器,提供更直接且高精度的时间测量方式。这种方法适用于需要极高精度的计时场景,特别是在循环体内的计时需求。 ##### 3. 高精度计时的...
总之,无论是使用汇编语言还是C语言,通过RDTSC指令都能有效地获取CPU当前的速度。这种方法对于性能测试、基准测试以及优化代码性能等方面具有重要意义。不过,要注意RDTSC的使用场景和潜在限制,以确保结果的准确性...
RDTSC指令是Intel 80386微处理器提供的一种特殊指令,它用于读取CPU的时间戳计数器,该计数器在每个时钟周期都会递增。RDTSC指令返回的结果分为两个部分,高32位存储在EDX寄存器,低32位存储在EAX寄存器。然而,为了...
利用 rdtsc 汇编指令可以得到 CPU 内部定时器的值, 每经过一个 CPU 周期, 这个定时器就加一。 如果在一段时间内数得 CPU 的周期数, CPU工作频率 = 周期数 / 时间 为了不让其他进程和线程打扰, 必需要设置最高的...
总结来说,通过VC++编程实现CPU主频检测,主要依赖于Intel 80386的RDTSC指令,结合Windows API函数和适当的界面设计,提供了一种简单易用的CPU主频检测方法,对于用户来说更加便捷。同时,使用汇编语言增强了程序的...
RDTSC指令用于无延迟地读取TSC,而RDTSCP指令则增加了保证在读取TSC之前所有之前指令完成执行的保证,这对于精确测量性能尤其有用。 手册还将涵盖TSC的可预测性问题。在某些处理器中,TSC可能会受到电源管理技术的...
`rdtsc`指令从CPU的Time-Stamp Counter寄存器中读取值,这个寄存器以处理器时钟周期为单位递增,通常与处理器的时钟频率同步。由于它是硬件级别的,因此不受操作系统调度、中断或其他软件层面的影响,能够提供微秒...
1. RDTSC(Read Time-Stamp Counter):这是Intel CPU中的一种指令,可以直接读取CPU内部的计数器,提供自CPU启动以来的总时钟周期数。RDTSC是无中断的,因此对于高精度计时非常有用。 2. QueryPerformanceCounter...
- TSC(Time Stamp Counter):CPU内部的计数器,根据外部振荡器频率递增,可通过rdtsc指令读取。 - CPU Local Timer:类似于PIT,但仅对其处理器发送中断,频率取决于CPU FSB。 - HPET(High Precision Event ...
随着现代CPU频率的提高,TSC能够提供非常高的时间分辨率,通常达到纳秒级别,这使得它成为实现高精度计时的理想选择。 #### RDTSC 指令 为了读取TSC中的值,Intel提供了RDTSC指令(Read Time Stamp Counter)。这...
来检测 rdtscp 指令是否可用。 如果没有,它会绕过该代码(否则会抛出 SIGILL)。 您还可以传入 CPU 频率,单位为 GHz。 如果不这样做,则使用频率 1,这会为那些使用滴答计数的时钟源返回未修改的滴答计数(即,与 ...
《深入x86的内存寻址》I/O 外设硬件开发举例一.本包是原文《深入x86的内存寻址》I/O 寻址的充部分,提供PC...另外对芯片工作频率的探测也作了一定的深入,使用了CPUID、RDTSC 等指令来获取CPU硬件信息以适合程序需求。
需要注意的是,`RDTSC`指令的结果可能会受到CPU的超线程、频率变化等因素的影响,因此在多核或动态频率调整的环境中,可能需要额外的处理来确保时间测量的准确性。例如,可以使用`CPUID`指令来同步时钟周期计数器,...
这里需要注意的是,`rdtsc()` 的结果需要乘以每个时钟周期的实际时间(通常由处理器频率决定)才能转换为实际时间。 ### 四、总结 综上所述,通过上述两种方法可以有效地测量上下文切换的时间消耗。`gettimeofday...
RDTSC指令则用于获取处理器的时钟周期,对于性能测试和基准测试尤为关键。 libcpuid库通过封装这些底层硬件指令,让开发者无需深入底层硬件细节就能获取到如处理器供应商、核心代号、支持的功能和指令集以及缓存...
rdtsc指令可以提供更高的精度,即单个时钟周期,但需要注意其在多核CPU中的局限性,因为不同核心的周期可能不同。通过 sched_setaffinity 函数可以将进程绑定到特定的 CPU 核心上以提高计时的准确性。 1.2 分析性能...
- **RDTSC指令**:在x86/x64架构上,可以通过汇编语言直接调用处理器的Time Stamp Counter(TSC),获取CPU自启动以来的周期数。不过,由于不同CPU速度可能不同,跨CPU的比较需要谨慎处理。 2. **高频事件的产生**...
RDTSC(Read Time Stamp Counter)是一个汇编指令,可以直接读取 CPU 的时间戳寄存器,其精度可以达到纳秒级别。 **示例代码**: ```c long hStart, lStart, hEnd, lEnd; long hCnt, lCnt; __asm { RDTSC mov ...
2. **硬件定时器**:直接操作硬件定时器,如Intel的RDTSC(Read Time-Stamp Counter)指令,可以获取CPU时钟周期数。这种方法可以达到非常高的精度,但需要注意线程迁移和超线程的影响,因为这些情况可能导致RDTSC...