INVOKE dTime,CodeToMeasure1,HIGH_PRIORITY_CLASS,THREAD_PRIORITY_ABOVE_NORMAL
;***********************************************************************************************
dTime PROC USES EBX ESI EDI lpfnProc:LPVOID,dwPriClass:DWORD,dwPriLevel:DWORD
;Code Timing Function, David R. Sheldon - DednDave, Ver 1.1, May 2013
;--------------------------------------------------
;Call With: lpfnProc = address of function to be timed
; dwPriClass = process priority class
; dwPriLevel = thread priority level
;
; Returns: EAX = clock cycles (not including function CALL/RET overhead)
;
;Also Uses: ECX, EDX, all other registers are preserved
;
; Notes: 1) The function referenced by lpfnProc may not have any arguments.
; It may, however, contain local variables. The time consumed creating and
; destroying the stack frame will be included in the timing measurement.
; 2) The function referenced by lpfnProc may destroy any register contents,
; but must balance the stack (ESP) before RETurn, of course.
;--------------------------------------------------
;Process priority class Thread priority level Base priority
;
;IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE 1
; THREAD_PRIORITY_LOWEST 2
; THREAD_PRIORITY_BELOW_NORMAL 3
; THREAD_PRIORITY_NORMAL 4
; THREAD_PRIORITY_ABOVE_NORMAL 5
; THREAD_PRIORITY_HIGHEST 6
; THREAD_PRIORITY_TIME_CRITICAL 15
;
;BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE 1
; THREAD_PRIORITY_LOWEST 4
; THREAD_PRIORITY_BELOW_NORMAL 5
; THREAD_PRIORITY_NORMAL 6
; THREAD_PRIORITY_ABOVE_NORMAL 7
; THREAD_PRIORITY_HIGHEST 8
; THREAD_PRIORITY_TIME_CRITICAL 15
;
;NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE 1
; THREAD_PRIORITY_LOWEST 6
; THREAD_PRIORITY_BELOW_NORMAL 7
; THREAD_PRIORITY_NORMAL 8
; THREAD_PRIORITY_ABOVE_NORMAL 9
; THREAD_PRIORITY_HIGHEST 10
; THREAD_PRIORITY_TIME_CRITICAL 15
;
;ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE 1
; THREAD_PRIORITY_LOWEST 8
; THREAD_PRIORITY_BELOW_NORMAL 9
; THREAD_PRIORITY_NORMAL 10
; THREAD_PRIORITY_ABOVE_NORMAL 11
; THREAD_PRIORITY_HIGHEST 12
; THREAD_PRIORITY_TIME_CRITICAL 15
;
;HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE 1
; THREAD_PRIORITY_LOWEST 11
; THREAD_PRIORITY_BELOW_NORMAL 12
; THREAD_PRIORITY_NORMAL 13
; THREAD_PRIORITY_ABOVE_NORMAL 14
; THREAD_PRIORITY_HIGHEST 15
; THREAD_PRIORITY_TIME_CRITICAL 15
;
;REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE 16
; THREAD_PRIORITY_LOWEST 22
; THREAD_PRIORITY_BELOW_NORMAL 23
; THREAD_PRIORITY_NORMAL 24
; THREAD_PRIORITY_ABOVE_NORMAL 25
; THREAD_PRIORITY_HIGHEST 26
; THREAD_PRIORITY_TIME_CRITICAL 31
;**************************************************
;local variables
;--------------------------------------------------
LOCAL _hProcess :HANDLE
LOCAL _hThread :HANDLE
LOCAL _dwPriClass :DWORD
LOCAL _dwPriLevel :DWORD
LOCAL _dwAffinity :DWORD
LOCAL _dwTerminalHi :DWORD
LOCAL _dwTerminalLo :DWORD
LOCAL _dwTallyHi :DWORD
LOCAL _dwTallyLo :DWORD
LOCAL _dwPassCount :DWORD
;**************************************************
;initialization
;--------------------------------------------------
INVOKE GetCurrentProcess
mov _hProcess,eax
INVOKE GetPriorityClass,eax
mov _dwPriClass,eax
INVOKE GetCurrentThread
mov _hThread,eax
INVOKE GetThreadPriority,eax
mov _dwPriLevel,eax
INVOKE GetProcessAffinityMask,_hProcess,addr _dwAffinity,addr _dwPassCount
INVOKE SetProcessAffinityMask,_hProcess,1
rdtsc
mov esi,eax
mov edi,edx
INVOKE Sleep,125
rdtsc
xor ecx,ecx
mov _dwTerminalLo,eax
mov _dwTerminalHi,edx
mov _dwPassCount,ecx
sub eax,esi
sbb edx,edi
mov _dwTallyLo,ecx
shld edx,eax,2
shl eax,2
mov _dwTallyHi,ecx
add _dwTerminalLo,eax
adc _dwTerminalHi,edx
INVOKE Sleep,ecx
mov edi,offset DummyProc
call SinglePass
mov edi,offset DummyProc
call SinglePass
mov edi,offset DummyProc
call SinglePass
jmp short TopOfLoop
;**************************************************
;measurement single pass
;--------------------------------------------------
;EDI = proc address
ALIGN 16
SinglePass:
INVOKE SetPriorityClass,_hProcess,dwPriClass
INVOKE Sleep,0 ;bind new priority
INVOKE SetThreadPriority,_hThread,dwPriLevel
INVOKE Sleep,0 ;bind new level
INVOKE Sleep,0 ;fresh slice
rdtsc
push edx ;Ta
push eax
push ebp
call edi ;proc to be measured
rdtsc
pop ebp
push edx ;Tb
push eax
INVOKE SetPriorityClass,_hProcess,_dwPriClass
INVOKE Sleep,0 ;bind new priority
INVOKE SetThreadPriority,_hThread,_dwPriLevel
INVOKE Sleep,0 ;bind new level
pop eax
pop edx
pop esi
pop edi
mov ecx,eax
mov ebx,edx ;EBX:ECX = last tsc reading
sub eax,esi
sbb edx,edi ;EDX:EAX = measured time
retn
;**************************************************
;empty proc
;--------------------------------------------------
ALIGN 16
DummyProc:
retn
;**************************************************
;measurement loop
;--------------------------------------------------
TopOfLoop:
mov edi,offset DummyProc ;empty proc for reference
call SinglePass
push edx
push eax
mov edi,lpfnProc ;code to be measured
call SinglePass
pop esi
pop edi
sub eax,esi
sbb edx,edi
inc dword ptr _dwPassCount
add _dwTallyLo,eax
adc _dwTallyHi,edx
cmp ebx,_dwTerminalHi
jb TopOfLoop
ja dTally
cmp ecx,_dwTerminalLo
jb TopOfLoop
;**************************************************
;tally results and exit
;--------------------------------------------------
dTally: INVOKE SetProcessAffinityMask,_hProcess,_dwAffinity
mov edx,_dwTallyHi
mov eax,_dwTallyLo
or edx,edx
mov ecx,_dwPassCount
jns Tdivis
xor eax,eax
jmp short dTExit
Tdivis: cmp ecx,1
jbe dTExit
div ecx
shl edx,1
cmp edx,ecx
sbb eax,-1
dTExit: ret
dTime ENDP
;***********************************************************************************************