let's see how this runs on different machines :P
EDIT: final version attached
:t
Quote
0 KHz
Press any key to continue ...
deleted
On my old i7,
0 KHz
Press any key to continue ...
0 kHz on i5, Win7-64
Intel(R) Core(TM) i7-4930K CPU @ 3.40GHz Windows 8.1
53157 KHz
win 10
black screen ...black screen,is it slow ??
i5 / Win8.1 x64
0 KHz
Press any key to continue ...
Hi,
P-III 800 MHz.
12528 KHz
Pentium M 1.76 G
9727 KHz
Press any key to continue ...
Regards,
Steve
i can see i have some work to do on that one :lol:
thanks guys :t
ok - i found the math error - (subtracted from EDI when it should have been from ECX - lol)
now, i will have to isolate the reason for the 0 results
there are a few possible causes, so i will add some sort of report code to isolate the problem
ok - new post at top of thread
i appreciate your help, guys :t
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3000218 KHz
Press any key to continue ...
Processor: AMD Athlon(tm) II X2 220 Processor (2 CPUs), ~2.8GHz
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2800001 KHz
deleted
deleted
Hi,
P-III
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
801818 KHz
Press any key to continue ...
Pentium M
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
632730 KHz
Press any key to continue ...
HTH,
Steve N.
Intel(R) Core(TM) i7-4930K CPU @ 3.40GHz Windows 8.1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3402080 KHz
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
And no errors reported by GetLastError ::)
Numbers 0-13 show straight away, then a wait for 14,15, speed=0
AMD A10-7850 3.70 GHz, Windows 7 Ultimate x64
edit: Same thing for i7-4790 3.60 GHz, Windows 10 Pro
deleted
No luck on my old i7.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
Press any key to continue ...
dang - back to the drawing board
the one that makes me scratch my head is 22 KHz - lol
the 0's are a bit of a mystery, too - but one that probably has a simple fix that i am overlooking
thanks again, guys :t
i5 / Win8.1 x64
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
Press any key to continue ...
yah - i have some work to do - lol
thought i had the bases covered
makes me feel like a novice :(
Intel Core i5 HP Prodesk
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
Press any key to continue ...
@Dave - thanks for personal mail btw
Intel(R) Core(TM) i3-4150 CPU @ 3.50GHz
Microsoft Windows 10 Famille Version: 10.0.10240
-----------------------------------------------------------------------------------------------------------------
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
-------------------------------------------------------------------------------------------------------------------
Press any key to continue ...
Perhaps a stupid question,why not used cpuid instruction to get the frequency
that is the "design" frequency - the frequency that the manufacturer intended the processor to be used
i want to measure the actual clock frequency
honestly, i thought this would be easy - lol
in the old forum, Edgar came up with some code (and i wrote a program using it)
it seemed to work fairly well
however, that was before windows 8 and 10 (and newer processors, i guess)
also, i am doing some things differently
at the moment, i am time limited
my mom is in the hospital, and i have been spending every night with her
so - i get some time during the day, but i am somewhat exhausted - probably the reason for the errors :P
Hi Dave,
Quote from: dedndave on October 15, 2015, 02:04:56 PM
that is the "design" frequency - the frequency that the manufacturer intended the processor to be used
i want to measure the actual clock frequency
Makes sense. I guess it is accuracy that would make things
tricky. A rough estimate with an ugly spread should be easy?
Quoteat the moment, i am time limited
my mom is in the hospital, and i have been spending every night with her
so - i get some time during the day, but i am somewhat exhausted - probably the reason for the errors
Sorry to hear that. I hope things are getting better.
Best of luck,
Steve N.
Running on my POS Windows 8.1-64 laptop, with a 2.16GHz Celeron, I get:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
For a laptop I was expecting the clock speed to vary a lot, so in my code I did everything I could think of to maximize the resolution and accuracy, and surprisingly the variation is limited to the 6th decimal place.
;===============================================================================
include \masm32\include\masm32rt.inc
.686
;===============================================================================
.data
pf LARGE_INTEGER <>
pc1 LARGE_INTEGER <>
pc2 LARGE_INTEGER <>
cc1 LARGE_INTEGER <>
cc2 LARGE_INTEGER <>
giga REAL8 1000000000.0
freq REAL8 ?
.code
;===============================================================================
start:
;===============================================================================
invoke GetCurrentProcess
mov ebx, eax
invoke SetProcessAffinityMask, ebx, 1
invoke SetPriorityClass, ebx, REALTIME_PRIORITY_CLASS
invoke GetCurrentThread
invoke SetThreadPriority, eax, THREAD_PRIORITY_TIME_CRITICAL
invoke Sleep, 2000
invoke QueryPerformanceFrequency, ADDR pf
;printf("%I64d\n\n",pf.QuadPart)
xor eax, eax
cpuid
rdtsc
mov cc1.HighPart, edx
mov cc1.LowPart, eax
invoke QueryPerformanceCounter, ADDR pc1
invoke Sleep, 2000
xor eax, eax
cpuid
rdtsc
mov cc2.HighPart, edx
mov cc2.LowPart, eax
invoke QueryPerformanceCounter, ADDR pc2
; elapsed counter cycles = pc2.QuadPart - pc1.QuadPart
; elapsed seconds = elapsed counter cycles / pf.QuadPart
; elapsed clock cycles = cc2.QuadPart - cc1.QuadPart
; clock speed = elapsed cycles / elapsed seconds
fild pc2.QuadPart
fild pc1.QuadPart
fsub
fild pf.QuadPart
fdiv
fild cc2.QuadPart
fild cc1.QuadPart
fsub
fdivr
fld giga
fdiv
fstp freq
printf("%fGHz\n\n", freq)
inkey
exit
end start
;===============================================================================
Since I've not yet fully understood the meaning of the results, I rolled my own:
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
Heating up...
RDTSC in ... out, 2.552 GHz
RDTSC in ... out, 2.517 GHz
RDTSC in ... out, 2.518 GHz
RDTSC in ... out, 2.536 GHz
RDTSC in ... out, 2.542 GHz
Intel(R) Celeron(R) CPU N2840 @ 2.16GHz
Heating up...
RDTSC in ... out, 2.201 GHz
RDTSC in ... out, 2.202 GHz
RDTSC in ... out, 2.201 GHz
RDTSC in ... out, 2.204 GHz
RDTSC in ... out, 2.203 GHz
Why not meassure it in direct memory transfer within looping in 1 gigs loop. It will force the vendor design better.
mov ecx,some_pointer
mov ecx,1000000000
break_vendor_credibilitty:
mov eax,[some_pointer]
jecxz break_vendor_credibility
:greenclp:
AMD 2.8 GHz
AMD Athlon(tm) II X2 220 Processor
Heating up...
RDTSC in ... out, 2.807 GHz
RDTSC in ... out, 2.901 GHz
RDTSC in ... out, 2.851 GHz
RDTSC in ... out, 2.817 GHz
RDTSC in ... out, 2.894 GHz
with simple versionRDTSC in ... out, 2.903 GHz
RDTSC in ... out, 2.868 GHz
RDTSC in ... out, 2.831 GHz
RDTSC in ... out, 2.823 GHz
RDTSC in ... out, 2.858 GHz
.686
.model flat,stdcall
ExitProcess PROTO :DWORD
GetTickCount PROTO
INCLUDELIB kernel32.lib
printf PROTO CDECL :VARARG
INCLUDELIB msvcrt.lib
.data
msg1 DB "RDTSC in ... ",0
msg2 DB "out",0
msg3 DB ", %4.3f GHz",13,10,0
m1 QWORD 0.000000001
pf QWORD ?
.code
main PROC
xor ecx, ecx
.Repeat
inc ecx
.Until Sign?
REPEAT 5
invoke printf, addr msg1
cpuid
rdtsc
push edx
push eax
invoke GetTickCount
add eax, 1000 ; one second
push eax
xor esi, esi
.Repeat
inc esi
test esi, 0ffffffh
.if Zero?
invoke GetTickCount ; ca. 93 calls per run
.endif
.Until eax>[esp]
pop edx
invoke printf, offset msg2
rdtsc
push edx
push eax
fild qword ptr [esp]
add esp, qword
fild qword ptr [esp]
add esp, qword
fsub
fmul qword ptr m1
fst pf
invoke printf, offset msg3, pf
ENDM
INVOKE ExitProcess,0
main ENDP
END main
Hi,
Doesn't work on the P-III as expected. Here are the Pentium M
results. First to screen, second redirected to a file.
Intel(R) Pentium(R) M processor 1.70GHz
Heating up...
RDTSC in ... out, 1.705 GHz
RDTSC in ... out, 1.704 GHz
RDTSC in ... out, 1.736 GHz
RDTSC in ... out, 1.732 GHz
RDTSC in ... out, 1.721 GHz
Intel(R) Pentium(R) M processor 1.70GHz
Heating up...
RDTSC in ... out, 1.702 GHz
RDTSC in ... out, 1.708 GHz
RDTSC in ... out, 1.705 GHz
RDTSC in ... out, 1.706 GHz
RDTSC in ... out, 1.706 GHz
Regards,
Steve N.
Intel(R) Core(TM) i7-4930K CPU @ 3.40GHz
Heating up...
RDTSC in ... out, 3.439 GHz
RDTSC in ... out, 3.440 GHz
RDTSC in ... out, 3.473 GHz
RDTSC in ... out, 3.440 GHz
RDTSC in ... out, 3.474 GHz
Hi Dave!
Doszip Macro Assembler Version 2.14, BETA 09/11/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Assembling: Getcpufrequency.asm
***********
ASCII build
***********
Getcpufrequency.asm(138) : error A2084: constant value too large
_
Assembly Error
Presione una tecla para continuar . . .
JWasm v2.13, Aug 8 2015, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
***********
ASCII build
***********
GetCpuFrequency.asm(138) : Error A2239: Constant value too large: 1F4000000h
GetCpuFrequency.asm: 466 lines, 1 passes, 136 ms, 0 warnings, 1 errors
Modification:
__CountExponent = 22
Results:
AMD A6-3500 APU with Radeon(tm) HD Graphics
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 KHz
Press any key to continue ...
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 KHz
Press any key to continue ...
Modification:
__CountExponent = 12
Result:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2101141 KHz
__CountExponent = 8
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2859 KHz
AMD A6-3500 APU with Radeon(tm) HD Graphics
Heating up...
RDTSC in ... out, 2.124 GHz
RDTSC in ... out, 2.120 GHz
RDTSC in ... out, 2.202 GHz
RDTSC in ... out, 2.157 GHz
RDTSC in ... out, 2.142 GHz
1 SHL 23 is 1000 0000 0000 0000 0000 0000 binary, or 800000h - that should fit in 32 bits :redface:
Ok. Ml compile with 1 SHL 23, but result 0 Khz. Work well with 1 SHL 12 (and others like 18).
deleted
thanks HSE and nidud - that is definately a bug that i missed :t
it probably happened, as i increased the __CountExponent, without checking the range of 1000X - oops
that does solve a few problems - like the case where the routine takes too long
it doesn't make sense to me that it causes a 0 result, though - have to look into that :redface:
that one was easy to fix
mov edx,_dwQPFreqHi
mov eax,__CountLength
mov ebx,_dwQPFreqLo
bsr ecx,edx
.if !ZERO?
inc ecx
shrd ebx,edx,cl
adc ebx,0
xor edx,edx
shr eax,cl
adc eax,edx
.endif
.if ebx
mov edx,1000
mul edx
div ebx
load the unmultiplied value - then MUL by 1000 just before DIV
Ok with __CountExponent = 20
ok - ready to try again.....
QueryPerformanceFrequency: 00000000_B2D0FA40h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 1
dwMultiplier: 1536020480
Measured: 8389545, 8389215, 8388772, 8389125, 8389433
Sorted: 8388772, 8389125, 8389215, 8389433, 8389545
GetCpuFrequency: 3000241 KHz
Press any key to continue ...
test program and source attached...
QueryPerformanceFrequency: 00000000_00342787h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 2451
dwMultiplier: 1750011
Measured: 890, 1006, 166412, 879, 1019
Sorted: 879, 890, 1006, 1019, 166412
GetCpuFrequency: 0 KHz
thanks John :t
guess i have to re-think that calculation, altogether :lol:
QueryPerformanceFrequency: 00000000_00DA7A64h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 583
dwMultiplier: 7330908
Measured: 1993179744, 1993179680, 1993180756, 1993181674, 1993181084
Sorted: 1993179680, 1993179744, 1993180756, 1993181084, 1993181674
GetCpuFrequency: 3402081 KHz
Press any key to continue ...
AMD 2.8 GHz
AMD Athlon(tm) II X2 220 Processor
QueryPerformanceFrequency: 00000000_00DA7A64h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 583
dwMultiplier: 7330908
Measured: 1640441959, 1640437624, 1640440917, 1640440083, 16404
39766
Sorted: 1640437624, 1640439766, 1640440083, 1640440917, 16404
41959
GetCpuFrequency: 2800001 KHz
AMD E450 1.65 GHzQueryPerformanceFrequency: 00000000_00188916h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 5214
dwMultiplier: 823274
Measured: 817, 1045, 459, 846, 903
Sorted: 459, 817, 846, 903, 1045
GetCpuFrequency: 0 KHz
AMD 1,35 GHzQueryPerformanceFrequency: 00000000_00141434h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00240010h
dwSleepTime: 6372
dwMultiplier: 673737
Measured: 560, 808, 924, 371, 944
Sorted: 371, 560, 808, 924, 944
GetCpuFrequency: 0 KHz
thanks again, guys :t
that gives me enough data to fix the problems - lol
ok - i changed the way it works
before, i tried to use a fixed elapse count for QueryPerformanceCounter
i was not prepared to see such low performance counter frequencies
with this one, i use a fixed amount of time, instead
QueryPerformanceFrequency: 00000000_B2D08510h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00340805h
dwPerfPeriod: 11718789
dwMultiplier: 256
Measured: 11719050, 11719673, 11719275, 11718990, 11718780
Sorted: 11718780, 11718990, 11719050, 11719275, 11719673
GetCpuFrequency: 3000069 KHz
Press any key to continue ...
AMD E1-6010 1,35 GHz
QueryPerformanceFrequency: 00000000_00141435h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00341E0Dh
dwPerfPeriod: 5140
dwMultiplier: 256
Measured: 5264337, 5264364, 5264158, 5264324, 5264316
Sorted: 5264158, 5264316, 5264324, 5264337, 5264364
GetCpuFrequency: 1347666 KHz
QueryPerformanceFrequency: 00000000_003408A8h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Dh
dwPerfPeriod: 13321
dwMultiplier: 256
Measured: 13641720, 13641590, 13641614, 13641747, 13641348
Sorted: 13641348, 13641590, 13641614, 13641720, 13641747
GetCpuFrequency: 3492250 KHz
Press any key to continue ...
It is the same frequence given by CPUID
:t
QueryPerformanceFrequency: 00000000_003708E5h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00341E0Dh
dwPerfPeriod: 14089
dwMultiplier: 256
Measured: 14428148, 14428110, 14427783, 14427204, 14428086
Sorted: 14427204, 14427783, 14428086, 14428110, 14428148
GetCpuFrequency: 3693593 KHz
Running on my 2.16GHz laptop:
QueryPerformanceFrequency: 00000000_0020492Bh
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Bh
dwPerfPeriod: 8265
dwMultiplier: 256
Measured: 8464378, 8464118, 8464456, 8464326, 8464014
Sorted: 8464014, 8464118, 8464326, 8464378, 8464456
GetCpuFrequency: 2166874 KHz
Press any key to continue ...
This one works fine on my old i7.
QueryPerformanceFrequency: 00000000_0029B1CAh
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Bh
dwPerfPeriod: 10674
dwMultiplier: 256
Measured: 10931202, 10931220, 10931190, 10931190, 10931187
Sorted: 10931187, 10931190, 10931190, 10931202, 10931220
GetCpuFrequency: 2798385 KHz
Press any key to continue ...
QueryPerformanceFrequency: 00000000_00DA7A64h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Dh
dwPerfPeriod: 55930
dwMultiplier: 256
Measured: 13290343, 13289866, 13291558, 13290018, 13289183
Sorted: 13289183, 13289866, 13290018, 13290343, 13291558
GetCpuFrequency: 3402225 KHz
Press any key to continue ...
thanks guys - would like to see Tim's machine(s) to make sure :P
i see a couple places for improvement in accuracy, but the concept seems to be ok
QueryPerformanceFrequency: 00000000_002F9361h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Dh
dwPerfPeriod: 12179
dwMultiplier: 256
Measured: 12472264, 12472320, 12472304, 12472120, 12472160
Sorted: 12472120, 12472160, 12472264, 12472304, 12472320
GetCpuFrequency: 3192905 KHz
Press any key to continue ...
Intel Core i5 @ 3.2Ghz
AMD E450 1.65 GHz :t
QueryPerformanceFrequency: 00000000_0018890Dh
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00341B06h
dwPerfPeriod: 6281
dwMultiplier: 256
Measured: 6432714, 6432795, 6432741, 6432423, 6432765
Sorted: 6432423, 6432714, 6432741, 6432765, 6432795
GetCpuFrequency: 1646785 KHz
i updated the attachment at the top of the thread with the final version
it's pretty much like the one you guys just ran, with some accuracy improvements
no need to post results, unless there is some kind of problem :biggrin:
thanks for all the help :t
QueryPerformanceFrequency: 00000000_00DA7A64h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 00341B05h
dwPerfPeriod: 55930
dwMultiplier: 256
Measured: 13391013, 13392498, 13392825, 13392039, 13392771
Sorted: 13391013, 13392039, 13392498, 13392771, 13392825
GetCpuFrequency: 3428515 KHz
Press any key to continue ...
3.4 GHZ, i guess ?
Excellent work, dave.
Was it suppose to show only the CPU frequency without other infos ? On your GetCpuFreqStatus3 i have different results then the last one you update. Here are some results on my I7
On the updated app it shows only this:
2933435 KHz
Press any key to continue ...
And on version 3 it shows a more complete info. :
QueryPerformanceFrequency: 00000000_AED78580h
EFlags Toggle: 00240000h
CPUID TSC: Supported
RDTSC Test: Pass
GetCpuidSupport: 0034080Bh
dwPerfPeriod: 11458438
dwMultiplier: 256
Measured: 11458353, 11458341, 11458092, 11458612, 11458678
Sorted: 11458092, 11458341, 11458353, 11458612, 11458678
GetCpuFrequency: 2933337 KHz
Press any key to continue ...
i was having trouble getting it to work correctly on some machines
so, i had it display additional information :biggrin:
No only 3.0 Ghz
http://www.phrio.biz/download/MyPc.jpg
Hi Dave
Can you give me a hand, pls ;)
I´m testing a app i´m using to analyse the different algorithms for timming. In order to the app work, it grabs the Frequency of the CPU. I was using QueryperformanceFrequency to find the proper value, but, in some machines (Intel I5 420 U) the frequency found by your function is different.
For example, using CPUID alone, it displays 1,70 GHZ, but, after computing with GetCpuFrequency the frequency shows 2,39 ?!
That´s from a thread i´m talking here:
http://masm32.com/board/index.php?topic=4925.15
Which values are the correct ones ?
it may be overclocked - i don't know
here is my final version
there are 2 PROC's: GetCpuFrequency, which requires GetCpuidSupport
.XCREF
.NoList
INCLUDE \Masm32\Include\Masm32rt.inc
.686p
.List
;###############################################################################################
.DATA
szKernel32 db 'Kernel32.dll',0
szAffinMask db 'SetProcessAffinityMask',0
;###############################################################################################
.CODE
;***********************************************************************************************
main PROC
call GetCpuFrequency
print ustr$(eax),' KHz',13,10,13,10
inkey
exit
main ENDP
;***********************************************************************************************
GetCpuFrequency PROC
;David R. Sheldon (C)opyright 2015
;version 3.01
;EAX = Returns the CPU clock frequency in KHz
; Returns 0 if any required function is not supported on the current system
;ECX = 1000
;EDX = 0 (ECX and EDX are prepared for DIV ECX, if frequency in MHz is desired)
;---------------------------------
_dwQPFreqHi TEXTEQU <Dword Ptr [EBP+20]>
_dwQPFreqLo TEXTEQU <Dword Ptr [EBP+16]>
;saved EBX contents [EBP+12]
;saved ESI contents [EBP+8]
;saved EDI contents [EBP+4]
;saved EBP contents [EBP]
_hProcess TEXTEQU <Dword Ptr [EBP-4]>
_dwPrcsClass TEXTEQU <Dword Ptr [EBP-8]>
_hThread TEXTEQU <Dword Ptr [EBP-12]>
_dwThrdLevel TEXTEQU <Dword Ptr [EBP-16]>
_dwSystemAffinityMask TEXTEQU <Dword Ptr [EBP-20]>
_dwProcessAffinityMask TEXTEQU <Dword Ptr [EBP-24]>
_lpfnSetProcessAffinityMask TEXTEQU <Dword Ptr [EBP-28]>
_dwPerfPeriod TEXTEQU <Dword Ptr [EBP-32]>
_dwQPCountHi TEXTEQU <Dword Ptr [EBP-36]>
_dwQPCountLo TEXTEQU <Dword Ptr [EBP-40]>
;---------------------------------
push eax ;[EBP+20] = _dwQPFreqHi
push eax ;[EBP+16] = _dwQPFreqLo
INVOKE QueryPerformanceFrequency,esp
.if eax
push ebx
push esi
push edi
push ebp
mov ebp,esp
INVOKE GetCurrentProcess
push eax ;[EBP-4] = _hProcess
INVOKE GetPriorityClass,eax
push eax ;[EBP-8] = _dwPrcsClass
INVOKE GetCurrentThread
push eax ;[EBP-12] = _hThread
INVOKE GetThreadPriority,eax
push eax ;[EBP-16] = _dwThrdLevel
INVOKE GetModuleHandleA,offset szKernel32
mov esi,offset szAffinMask
xchg eax,ebx ;EBX = hmoduleKernel32
INVOKE GetProcAddress,ebx,esi
mov byte ptr [esi],'G'
xchg eax,edi ;EDI = lpfnSetProcessAffinityMask
INVOKE GetProcAddress,ebx,esi
mov byte ptr [esi],'S'
xor ecx,ecx
push ecx ;[EBP-20] = _dwSystemAffinityMask placeholder
mov edx,esp
push ecx ;[EBP-24] = _dwProcessAffinityMask placeholder
.if (eax) && (edi)
mov ebx,esp
push edi ;[EBP-28] = _lpfnSetProcessAffinityMask
push edx ;GetProcessAffinityMask:lpSystemAffinityMask
push ebx ;GetProcessAffinityMask:lpProcessAffinityMask
push _hProcess ;GetProcessAffinityMask:hProcess
call eax ;GetProcessAffinityMask
xor eax,eax
mov edx,_dwProcessAffinityMask
stc
.repeat
rcl eax,1
.break .if CARRY?
test eax,edx ;first available core
.until !ZERO?
.if !CARRY?
push eax ;SetProcessAffinityMask:lpProcessAffinityMask
push _hProcess ;SetProcessAffinityMask:hProcess
call edi ;SetProcessAffinityMask
INVOKE Sleep,1
.endif
.else
push ecx ;[EBP-28] = _lpfnSetProcessAffinityMask = NULL
.endif
call GetCpuidSupport
.if eax&100000h
;calculate performance counter period
mov ecx,_dwQPFreqLo
mov edx,_dwQPFreqHi
.if (edx) || (ecx>255)
shrd ecx,edx,8
adc ecx,0
.endif
push ecx ;[EBP-32] = _dwPerfPeriod
;make 5 measurement passes
push eax ;[EBP-36] = _dwQPCountHi placeholder
push eax ;[EBP-40] = _dwQPCountLo placeholder
mov ebx,5
mov edi,esp ;EDI = lpqwQPCount
.repeat
INVOKE SetPriorityClass,_hProcess,REALTIME_PRIORITY_CLASS
INVOKE Sleep,1
INVOKE SetThreadPriority,_hThread,THREAD_PRIORITY_TIME_CRITICAL
INVOKE Sleep,1
INVOKE QueryPerformanceCounter,edi
mov esi,[edi]
.repeat
INVOKE QueryPerformanceCounter,edi
.until esi!=[edi]
rdtsc
mov esi,[edi]
push eax
.repeat
INVOKE QueryPerformanceCounter,edi
mov eax,[edi]
sub eax,esi
.until eax>=_dwPerfPeriod
pop ecx
rdtsc
sub eax,ecx
push eax ;store measurement on stack
INVOKE SetPriorityClass,_hProcess,_dwPrcsClass
INVOKE Sleep,1
INVOKE SetThreadPriority,_hThread,_dwThrdLevel
INVOKE Sleep,1
dec ebx
.until ZERO?
;recall the 5 measurements from the stack and in-register sort
pop esi
pop edx
pop eax
pop ecx
pop ebx
.if ebx>ecx
xchg ebx,ecx
.endif
.if ecx>eax
xchg eax,ecx
.endif
.if eax>edx
xchg eax,edx
.endif
.if edx>esi
xchg edx,esi
.endif
.if edx<eax
xchg eax,edx
.endif
.if eax<ecx
xchg eax,ecx
.endif
.if ecx<ebx
xchg ebx,ecx
.endif
.if ecx>eax
xchg eax,ecx
.endif
.if eax>edx
xchg eax,edx
.endif
.if eax<ecx
xchg eax,ecx
.endif
;ESI = A(4) highest
;EDX = A(3)
;EAX = A(2)
;ECX = A(1)
;EBX = A(0) lowest
;throw away the lowest and highest, A(0) and A(4)
;find the closest pair of A(1),A(2) or A(2),A(3)
; if A(3)-A(2) > A(2)-A(1), use (A(2)+A(1))/2 as the result
; if A(3)-A(2) < A(2)-A(1), use (A(3)+A(2))/2 as the result
; if A(3)-A(2) = A(2)-A(1), use A(2) as the result
mov esi,edx ;ESI = A(3)
mov ebx,eax ;EBX = A(2)
sub esi,eax ;ESI = A(3)-A(2)
sub ebx,ecx ;EBX = A(2)-A(1)
cmp ebx,esi
.if CARRY?
add eax,ecx
.elseif !ZERO?
add eax,edx
.else
shl eax,1
.endif
shr eax,1
adc eax,0
;scale the result, Freq(KHz) = Measurement*qwQPCount/1000*dwPerfPeriod
mov esi,eax
xor edi,edi
mul _dwQPFreqLo
xchg eax,esi
xchg edx,edi
mul _dwQPFreqHi
mov ecx,_dwPerfPeriod
add eax,edi ;product in EAX:ESI
div ecx
xchg eax,esi
div ecx ;quotient in ESI:EAX, modulo in EDX
mov edx,esi
mov ecx,1000
div ecx
shr ecx,1
cmp edx,ecx
sbb eax,-1
.else
xor eax,eax
.endif
;restore affinity and exit
mov ecx,_lpfnSetProcessAffinityMask
.if ecx
push eax
push _dwProcessAffinityMask ;SetProcessAffinityMask:dwProcessAffinityMask
push _hProcess ;SetProcessAffinityMask:hProcess
call ecx ;SetProcessAffinityMask
INVOKE Sleep,0
pop eax
.endif
mov ecx,1000
xor edx,edx
leave
pop edi
pop esi
pop ebx
.endif
add esp,8
ret
GetCpuFrequency ENDP
;***********************************************************************************************
GetCpuidSupport PROC
;David R. Sheldon (C)opyright 2015
;version 3.01
;Returns a value in EAX with the following flag bits:
;
; Bit Description
;
;0-7 Highest CPUID standard leaf supported
;8-15 Highest CPUID extended leaf supported
; 18 Processor is 80486 or later
; 20 Processor has TimeStampCounter (RDTSC supported)
; 21 Processor supports CPUID instruction
;
;All other bits are reserved.
;It is possible, however unlikely, that different values may be returned from individual cores.
;It is advisable to select a single specific core prior to calling this routine.
;---------------------------------
push ebx
pushfd
mov ecx,240000h ;bit 21 = CPUID, bit 18 = 486+
pop ebx
mov edx,ebx ;EDX = original EFlags
xor ebx,ecx ;EBX = toggled EFlags
push ebx
popfd ;EFlags = toggled flags
pushfd
pop ebx ;EBX = test flags
push edx ;original EFlags on stack
xor ebx,edx ;EBX = toggle result
and ebx,ecx
mov ecx,200000h ;ECX = bit 21 only
xor eax,eax ;EAX = CPUID leaf 0
test ebx,ecx
.if !ZERO?
or edx,ecx
push ebx
push edx
popfd
cpuid
pop ebx
.if ah==5
or ebx,100000h ;TSC supported for pre-b0 stepping
.elseif eax
.if eax>0FFh
mov bl,0FFh
.else
mov bl,al
.endif
mov eax,1
push ebx
cpuid
pop ebx
and edx,10h ;TSC support flag
shl edx,16
or ebx,edx
mov eax,80000000h
push ebx
cpuid
pop ebx
.if eax>800000FFh
mov bh,0FFh
.else
mov bh,al
.endif
.endif
.if ebx&100000h
rdtsc
push eax
INVOKE Sleep,1
rdtsc
pop edx
.if eax==edx
and ebx,0FFEFFFFFh ;TSC not running
.endif
.endif
.endif
xchg eax,ebx
popfd ;EFlags = original
pop ebx
ret
GetCpuidSupport ENDP
;###############################################################################################
END main
2.39 GHz ~ 2.4 GHz, which is a common clock freq
http://www.notebookcheck.net/Intel-Core-i5-4210U-Notebook-Processor.115081.0.html (http://www.notebookcheck.net/Intel-Core-i5-4210U-Notebook-Processor.115081.0.html)
QuoteEach core offers a base speed of 1.7 GHz, but can dynamically increase clock rates
with Turbo Boost up to 2.7 GHz for 1 active core or 2.4 GHz for 2 active cores.
http://masm32.com/board/index.php?topic=4925.msg53020#msg53020
Thanks Dave. A LOT ! Your function is amazing. I´m using it on the app i was talking about I hope that once i succeed to finish the fine tunnings, i can make a dll so you guys can use it on your apps too. Biased on the results the guys are reporting, the values seems accurated :)
I found 2 problems only. The huge variance found in mabdelouahab (which maybe explained by the increasing of speed as you told) and the problems when analyzing short codes (as "xor eax eax" alone) . On both, although the values of the mean are acceptable, the variance is too high to be correct, meaning that something has passed through a function i built to block such rare situations.
Hi Dave,
does your function works inside a dll? I mean, since it is using SetProcessAffinityMask Api, can the function be used inside a dll (As an export function or not) ?
https://msdn.microsoft.com/pt-br/library/windows/desktop/ms686223%28v=vs.85%29.aspx
what they mean is....
don't use it in a DLL that may be used by more than one process at a time
...my intention is to use it in a static library (LIB)
the code is then imported to the EXE when you build it
Phew ! (http://i65.tinypic.com/10rl407.png)
I thought for a moment i´ll have to rewrite the Benchmark app to it allow the dll form :greensml:
I was confused by the msdn doc.
If you use GetCurrentProcess(), it is calling process handle?
Hi dave, take a look at this source
http://fluid-particles.googlecode.com/svn/trunk/CoreDetection/CpuTopology.cpp
You may find interesting the cpu classes :)
Btw....Also the project per se is quite amazing (Fluid particles system)
Dave, do not use SetProcessAffinityMask !!!
I found a bug (at least on WinP) inside that API. The stack is being returned incorrectly. There is a major stack problem there. There is a lack of "leave" or "mov esp ebp". This is causing the function to needs an adjustment on the stack after it is used. I made some tests on your function and saved the registers while using it. All i left was eax to it returns the proper Flags retrieved by GetCpuidSupport. The problem was after using the GetCpuFrequency it was saving at ebx the same value as in eax (ebx was being "poped" by eax), regardless i saved all registers with the chain of push/pop, during the entrance and exiting of the function. Take a look at the disassembled code from kernel32.dll as below:
; BOOL __stdcall SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask)
public _SetProcessAffinityMask@8
_SetProcessAffinityMask@8 proc near ; DATA XREF: .text:off_7C802654o
hProcess = dword ptr 8
dwProcessAffinityMask= dword ptr 0Ch
mov edi, edi
push ebp
mov ebp, esp
push 4
lea eax, [ebp+dwProcessAffinityMask]
push eax
push 21
push [ebp+hProcess]
call ds:__imp__NtSetInformationProcess@16 ; NtSetInformationProcess(x,x,x,x)
test eax, eax
jge short loc_7C862E48
push eax
call _BaseSetLastNTError@4 ; BaseSetLastNTError(x)
xor eax, eax
jmp short loc_7C862E4B
; ---------------------------------------------------------------------------
loc_7C862E48:
xor eax, eax
inc eax
loc_7C862E4B: ; MISSING A "LEAVE" OR "MOV ESP EBB" HERE !!!!
pop ebp
retn 8
_SetProcessAffinityMask@8 endp
I succeeded to fix that and rebuilt both APis used:GetProcessAffinityMask and SetProcessAffinityMask. I´ll post the corrected functions on another thread. I managed to fix retrieving the values from the TEB/PEB structures as the same way the original APis did, but, i fixed them, while on XP it is still broken ! (I believe that probably, it is also broken in others windows versions as well, but i didn´t analyzed them yet)
deleted
Quote from: guga on December 26, 2015, 03:05:58 AMI found a bug (at least on WinP) inside that API. The stack is being returned incorrectly. There is a major stack problem there. There is a lack of "leave" or "mov esp ebp". This is causing the function to needs an adjustment on the stack after it is used.
Can you post an executable that shows this behaviour, with an int 3 inserted shortly before?
My tests on Win XP and Win7-64 do not show any abnormal behaviour:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
Init
mov esi, 111111111
mov edi, 222222222
mov ebx, 333333333
mov ecx, 444444444
deb 4, "In", esi, edi, ebx, ebp, ecx, esp
ClearLastError
push ecx
invoke SetProcessAffinityMask, rv(GetCurrentProcess), 1
pop ecx
deb 4, "SPAM", eax, $Err$()
deb 4, "Out", esi, edi, ebx, ebp, ecx, esp
EndOfCodeIn
esi 111111111
edi 222222222
ebx 333333333
ebp 1638292
ecx 444444444
esp 1638284
SPAM
eax 1
$Err$() Operazione completata.
Out
esi 111111111
edi 222222222
ebx 333333333
ebp 1638292
ecx 444444444
esp 1638284
Hi Guys...Many tks for the feedback.
Indeed that was not a fault of GetProcessAffinityMask/SetProcessAffinityMask.
The problem was in one of my macros. The counting of the stack was incorrect, leading the values to return 4 bytes ahead
many tks, and Merry Xmas, to you all :)
In any case, if someone wants a new version of those Apis (GetProcessAffinityMask and SetProcessAffinityMask) here they are:
GetProcessAffinityMask
[BASE_STATIC_SERVER_DATA.WindowsDirectory.LengthDis 0
BASE_STATIC_SERVER_DATA.WindowsDirectory.MaximumLengthDis 2
BASE_STATIC_SERVER_DATA.WindowsDirectory.BufferDis 4
BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.LengthDis 8
BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.MaximumLengthDis 10
BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.BufferDis 12
BASE_STATIC_SERVER_DATA.NamedObjectDirectory.LengthDis 16
BASE_STATIC_SERVER_DATA.NamedObjectDirectory.MaximumLengthDis 18
BASE_STATIC_SERVER_DATA.NamedObjectDirectory.BufferDis 20
BASE_STATIC_SERVER_DATA.WindowsMajorVersionDis 24
BASE_STATIC_SERVER_DATA.WindowsMinorVersionDis 26
BASE_STATIC_SERVER_DATA.BuildNumberDis 28
BASE_STATIC_SERVER_DATA.CSD.wServicePackMajorDis 30
BASE_STATIC_SERVER_DATA.CSD.wServicePackMinorDis 32
BASE_STATIC_SERVER_DATA.CSD.szCSDVersionDis 34
BASE_STATIC_SERVER_DATA.Padding1Dis 286
BASE_STATIC_SERVER_DATA.SysInfo.ReservedDis 288
BASE_STATIC_SERVER_DATA.SysInfo.TimerResolutionDis 292
BASE_STATIC_SERVER_DATA.SysInfo.PageSizeDis 296
BASE_STATIC_SERVER_DATA.SysInfo.NumberOfPhysicalPagesDis 300
BASE_STATIC_SERVER_DATA.SysInfo.LowestPhysicalPageNumberDis 304
BASE_STATIC_SERVER_DATA.SysInfo.HighestPhysicalPageNumberDis 308
BASE_STATIC_SERVER_DATA.SysInfo.AllocationGranularityDis 312
BASE_STATIC_SERVER_DATA.SysInfo.MinimumUserModeAddressDis 316
BASE_STATIC_SERVER_DATA.SysInfo.MaximumUserModeAddressDis 320
BASE_STATIC_SERVER_DATA.SysInfo.ActiveProcessorsAffinityMaskDis 324
BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis 328
BASE_STATIC_SERVER_DATA.SysInfo.Padding1Dis 329
BASE_STATIC_SERVER_DATA.Padding2Dis 332
BASE_STATIC_SERVER_DATA.TimeOfDay.BootTimeDis 336
BASE_STATIC_SERVER_DATA.TimeOfDay.CurrentTimeDis 344
BASE_STATIC_SERVER_DATA.TimeOfDay.TimeZoneBiasDis 352
BASE_STATIC_SERVER_DATA.TimeOfDay.TimeZoneIdDis 360
BASE_STATIC_SERVER_DATA.TimeOfDay.ReservedDis 364
BASE_STATIC_SERVER_DATA.IniFileMappingDis 368
BASE_STATIC_SERVER_DATA.NlsUserInfo.sAbbrevLangNameDis 372
BASE_STATIC_SERVER_DATA.NlsUserInfo.iCountryDis 532
BASE_STATIC_SERVER_DATA.NlsUserInfo.sCountryDis 692
BASE_STATIC_SERVER_DATA.NlsUserInfo.sListDis 852
BASE_STATIC_SERVER_DATA.NlsUserInfo.iMeasureDis 1012
BASE_STATIC_SERVER_DATA.NlsUserInfo.sDecimalDis 1172
BASE_STATIC_SERVER_DATA.NlsUserInfo.sThousandDis 1332
BASE_STATIC_SERVER_DATA.NlsUserInfo.sGroupingDis 1492
BASE_STATIC_SERVER_DATA.NlsUserInfo.iDigitsDis 1652
BASE_STATIC_SERVER_DATA.NlsUserInfo.iLZeroDis 1812
BASE_STATIC_SERVER_DATA.NlsUserInfo.iNegNumberDis 1972
BASE_STATIC_SERVER_DATA.NlsUserInfo.sCurrencyDis 2132
BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonDecSepDis 2292
BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonThouSepDis 2452
BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonGroupingDis 2612
BASE_STATIC_SERVER_DATA.NlsUserInfo.iCurrDigitsDis 2772
BASE_STATIC_SERVER_DATA.NlsUserInfo.iCurrencyDis 2932
BASE_STATIC_SERVER_DATA.NlsUserInfo.iNegCurrDis 3092
BASE_STATIC_SERVER_DATA.NlsUserInfo.sPosSignDis 3252
BASE_STATIC_SERVER_DATA.NlsUserInfo.sNegSignDis 3412
BASE_STATIC_SERVER_DATA.NlsUserInfo.sTimeFormatDis 3572
BASE_STATIC_SERVER_DATA.NlsUserInfo.sTimeDis 3732
BASE_STATIC_SERVER_DATA.NlsUserInfo.iTimeDis 3892
BASE_STATIC_SERVER_DATA.NlsUserInfo.iTLZeroDis 4052
BASE_STATIC_SERVER_DATA.NlsUserInfo.iTimeMarkPosnDis 4212
BASE_STATIC_SERVER_DATA.NlsUserInfo.s1159Dis 4372
BASE_STATIC_SERVER_DATA.NlsUserInfo.s2359Dis 4532
BASE_STATIC_SERVER_DATA.NlsUserInfo.sShortDateDis 4692
BASE_STATIC_SERVER_DATA.NlsUserInfo.sDateDis 4852
BASE_STATIC_SERVER_DATA.NlsUserInfo.iDateDis 5012
BASE_STATIC_SERVER_DATA.NlsUserInfo.sLongDateDis 5172
BASE_STATIC_SERVER_DATA.NlsUserInfo.iCalTypeDis 5332
BASE_STATIC_SERVER_DATA.NlsUserInfo.iFirstDayDis 5492
BASE_STATIC_SERVER_DATA.NlsUserInfo.iFirstWeekDis 5652
BASE_STATIC_SERVER_DATA.NlsUserInfo.sLocaleDis 5812
BASE_STATIC_SERVER_DATA.NlsUserInfo.UserLocaleIdDis 5972
BASE_STATIC_SERVER_DATA.NlsUserInfo.fCacheValidDis 5976
BASE_STATIC_SERVER_DATA.DefaultSeparateVDMDis 5980
BASE_STATIC_SERVER_DATA.Wx86EnabledDis 5981
BASE_STATIC_SERVER_DATA.Padding3Dis 5982]
[Size_Of_BASE_STATIC_SERVER_DATA 5984]
[PROCESS_BASIC_INFORMATION.ExitStatusDis 0
PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4
PROCESS_BASIC_INFORMATION.AffinityMaskDis 8
PROCESS_BASIC_INFORMATION.BasePriorityDis 12
PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16
PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20]
[Size_of_PROCESS_BASIC_INFORMATION 24]
[BaseStaticServerData: D$ 0]
Proc GetProcessAffinityMask:
Arguments @hProcess, @lpProcessAffinityMask, @lpSystemAffinityMask
Structure @PROCESS_BASIC_INFORMATION 24, @PROCESS_BASIC_INFORMATION.ExitStatusDis 0,
@PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4, @PROCESS_BASIC_INFORMATION.AffinityMaskDis 8,
@PROCESS_BASIC_INFORMATION.BasePriorityDis 12, @PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16,
@PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20
Uses ecx, edx
call 'Ntdll.NtQueryInformationProcess' D@hProcess, &PROCESS_BASICINFORMATION,
D@PROCESS_BASIC_INFORMATION, Size_of_PROCESS_BASIC_INFORMATION, 0
If eax <> &STATUS_SUCCESS
call BaseSetLastNTError eax
xor eax eax
Else
; Copy the affinity mask, and get the system one from our shared data
mov ecx D@lpProcessAffinityMask
mov eax D@PROCESS_BASIC_INFORMATION.AffinityMaskDis | mov D$ecx eax
call 'ntdll.RtlAcquirePebLock' ; <------- Always lock the PEb before using it.
call GetBaseStaticServerFromTEB BaseStaticServerData
mov eax D$BaseStaticServerData
mov eax D$eax+BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis
mov ecx D@lpSystemAffinityMask | mov D$ecx eax
call 'ntdll.RtlReleasePebLock'; <---- And, of course, don´t forget to unlock it.
mov eax &TRUE
End_If
EndP
SetProcessAffinityMask
Proc SetProcessAffinityMask:
Arguments @hProcess, @dwProcessAffinityMask
Uses ecx, edx
; Directly set the affinity mask
lea eax D@dwProcessAffinityMask
call 'Ntdll.NtSetInformationProcess' D@hProcess, &PROCESS_AFFINITYMASK, eax, 4
If eax <> &STATUS_SUCCESS
call BaseSetLastNTError eax
xor eax eax
Else
mov eax &TRUE
End_If
EndP
And the additional functions
BaseSetLastNTError
Proc BaseSetLastNTError:
Arguments @ErrorCode
Uses esi, ecx, edx, ebx
call 'ntdll.RtlNtStatusToDosError' D@ErrorCode | mov esi eax
call 'kernel32.SetLastError' eax
mov eax esi
EndP
GetBaseStaticServerFromTEB
;;
GetBaseStaticServerFromTEB
This function retrieves the pointer to a BASE_STATIC_SERVER_DATA structure that contains information about your system.
Arguments:
pOutput (out): Pointer to a Variable that will holds the data to the structure BASE_STATIC_SERVER_DATA
Returned Values:
This function will return a pointer to BASE_STATIC_SERVER_DATA structure. Also, it will store it on the proper variable at pOutput
Example of usage:
[BaseStaticServerData: D$ 0]
call 'ntdll.RtlAcquirePebLock' ; <------- Always lock the PEb before using it.
call GetBaseStaticServerFromTEB BaseStaticServerData
add eax BASE_STATIC_SERVER_DATA.NamedObjectDirectory.LengthDis
(...)
call 'ntdll.RtlReleasePebLock' <---- And, of course, don´t forget to unlock it.
See Also: BASE_STATIC_SERVER_DATA structure
Remarks: Always lock and unlock the PEb when retrieving the information from TEB/PEB data.
To lock you must use a call to 'ntdll.RtlAcquirePebLock' and to unlock you must use the function ntdll.RtlReleasePebLock
See the example above.
Author:
Gustavo Trigueiros (aka: Beyond2000! or Guga)
jul/2014
;;
[TEB.Tib.ExceptionListDis 0
TEB.Tib.StackBaseDis 4
TEB.Tib.StackLimitDis 8
TEB.Tib.SubSystemTibDis 12
TEB.Tib.FiberDataDis 16
TEB.VersionDis 16
TEB.Tib.ArbitraryUserPointerDis 20
TEB.Tib.SelfDis 24
TEB.EnvironmentPointerDis 28
TEB.ClientId.UniqueProcessDis 32
TEB.ClientId.UniqueThreadDis 36
TEB.ActiveRpcDDis 40
TEB.ThreadLocalStoragePointerDis 44
TEB.PebDis 48
TEB.LastErrorValueDis 52
TEB.CountOfOwnedCriticalSectionsDis 56
TEB.CsrClientThreadDis 60
TEB.Win32ThreadInfoDis 64
TEB.Win32ClientInfoDis 68
TEB.WOW32ReservedDis 192
TEB.CurrentLocaleDis 196
TEB.FpSoftwareStatusRegisterDis 200
TEB.SystemReserved1Dis 204
TEB.Spare1Dis 420
TEB.ExceptionCodeDis 424
TEB.SpareBs1Dis 428
TEB.SystemReserved2Dis 468
TEB.GdiTebBatch.OffsetDis 508
TEB.GdiTebBatch.HDCDis 512
TEB.GdiTebBatch.BufferDis 516
TEB.gdiRgnDis 1756
TEB.gdiPenDis 1760
TEB.gdiBrushDis 1764
TEB.RealClientId.UniqueProcessDis 1768
TEB.RealClientId.UniqueThreadDis 1772
TEB.GdiCachedProcessDDis 1776
TEB.GdiClientPIDDis 1780
TEB.GdiClientTIDDis 1784
TEB.GdiThreadLocaleInfoDis 1788
TEB.UserReservedDis 1792
TEB.glDispachTableDis 1812
TEB.glReserved1Dis 2932
TEB.glReserved2Dis 3036
TEB.glSectionInfoDis 3040
TEB.glSectionDis 3044
TEB.glTableDis 3048
TEB.glCurrentRCDis 3052
TEB.glContextDis 3056
TEB.LastStatusValueDis 3060
TEB.StaticUnicodeString.LengthDis 3064
TEB.StaticUnicodeString.MaximumLengthDis 3066
TEB.StaticUnicodeString.BufferDis 3068
TEB.StaticUnicodeBufferDis 3072
TEB.PADDINGDis 3594
TEB.DeallocationStackDis 3596
TEB.TlsSlotsDis 3600
TEB.TlsLinks.FlinkDis 3856
TEB.TlsLinks.BlinkDis 3860
TEB.VdmDis 3864
TEB.ReservedForNtRpcDis 3868
TEB.DbgSsReservedDis 3872
TEB.HardErrorDisabledDis 3880
TEB.InstrumentationDis 3884
TEB.WinSockDataDis 3948
TEB.GdiBatchCountDis 3952
TEB.Spare2Dis 3956
TEB.Spare3Dis 3960
TEB.Spare4Dis 3964
TEB.ReservedForOleDis 3968
TEB.WaitingOnLoaderLockDis 3972
TEB.Reserved5Dis 3976
TEB.TlsExpansionSlotsDis 3988]
[PEB.InheritedAddressSpaceDis 0
PEB.ReadImageFileExecOptionsDis 1
PEB.BeingDebuggedDis 2
PEB.SpareBoolDis 3
PEB.MutantDis 4
PEB.ImageBaseAddressDis 8
PEB.LdrDataDis 12
PEB.ProcessParametersDis 16
PEB.SubSystemDataDis 20
PEB.ProcessHeapDis 24
PEB.FastPebLockDis 28
PEB.FastPebLockRoutineDis 32
PEB.FastPebUnlockRoutineDis 36
PEB.EnvironmentUpdateCountDis 40
PEB.KernelCallbackTableDis 44
PEB.EventLogSectionDis 48
PEB.EventLogDis 52
PEB.FreeListDis 56
PEB.TlsExpansionCounterDis 60
PEB.TlsBitmapDis 64
PEB.TlsBitmapBitsDis 68
PEB.ReadOnlySharedMemoryBaseDis 76
PEB.ReadOnlySharedMemoryHeapDis 80
PEB.ReadOnlyStaticServerDataDis 84
PEB.AnsiCodePageDataDis 88
PEB.OemCodePageDataDis 92
PEB.UnicodeCaseTableDataDis 96
PEB.NumberOfProcessorsDis 100
PEB.NtGlobalFlagDis 104
PEB.Spare2Dis 108
PEB.CriticalSectionTimeoutDis 112
PEB.HeapSegmentReserveDis 120
PEB.HeapSegmentCommitDis 124
PEB.HeapDeCommitTotalFreeThresholdDis 128
PEB.HeapDeCommitFreeBlockThresholdDis 132
PEB.NumberOfHeapsDis 136
PEB.MaximumNumberOfHeapsDis 140
PEB.ProcessHeapsDis 144
PEB.GdiSharedHandleTableDis 148
PEB.ProcessStarterHelperDis 152
PEB.GdiDCAttributeListDis 156
PEB.LoaderLockDis 160
PEB.OSMajorVersionDis 164
PEB.OSMinorVersionDis 168
PEB.OSBuildNumberDis 172
PEB.OSPlatformIdDis 176
PEB.ImageSubSystemDis 180
PEB.ImageSubSystemMajorVersionDis 184
PEB.ImageSubSystemMinorVersionDis 188
PEB.ImageProcessAffinityMaskDis 192
PEB.GdiDBufferDis 196
PEB.PostProcessInitRoutineDis 332
PEB.TlsExpansionBitmapDis 336
PEB.TlsExpansionBitmapBitsDis 340
PEB.SessionIdDis 468]
[TEXT_INFO.ReservedDis 0
TEXT_INFO.SystemStringsDis 4]
[Size_Of_TEXT_INFO 8]
Proc GetBaseStaticServerFromTEB:
Arguments @pOutput
Uses edi
mov edi D@pOutput
mov eax D$fs:TEB.Tib.SelfDis ; retrieve TEB structure for the current process
mov eax D$eax+TEB.PebDis ; pointer to a PEB structure
mov eax D$eax+PEB.ReadOnlyStaticServerDataDis ; retrieve the ReadOnlyStaticServerData (a TEXT_INFO structure)
mov eax D$eax+TEXT_INFO.SystemStringsDis ; pointer to a BASE_STATIC_SERVER_DATA structure and not a SYSTEM_STRINGS structure (eah member points to a UNICODE_STRING String)
mov D$edi eax
EndP
Equates :
PROCESS_BASICINFORMATION = 0
PROCESS_AFFINITYMASK = 21
STATUS_SUCCESS = 0
or, another version of GetProcessAffinityMask
Alternative version
Proc GetProcessAffinityMask:
Arguments @hProcess, @lpProcessAffinityMask, @lpSystemAffinityMask
Structure @PROCESS_BASIC_INFORMATION 24, @PROCESS_BASIC_INFORMATION.ExitStatusDis 0,
@PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4, @PROCESS_BASIC_INFORMATION.AffinityMaskDis 8,
@PROCESS_BASIC_INFORMATION.BasePriorityDis 12, @PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16,
@PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20
Uses ecx, edx
call 'Ntdll.NtQueryInformationProcess' D@hProcess, &PROCESS_BASICINFORMATION,
D@PROCESS_BASIC_INFORMATION, Size_of_PROCESS_BASIC_INFORMATION, 0
If eax <> &STATUS_SUCCESS
call BaseSetLastNTError eax
xor eax eax
Else
; Copy the affinity mask, and get the system one from our shared data
mov ecx D@lpProcessAffinityMask
mov eax D@PROCESS_BASIC_INFORMATION.AffinityMaskDis | mov D$ecx eax
mov ecx D@lpSystemAffinityMask
mov eax D@PROCESS_BASIC_INFORMATION.PebBaseAddressDis | mov eax D$eax+PEB.ReadOnlyStaticServerDataDis
mov eax D$eax+TEXT_INFO.SystemStringsDis | mov eax D$eax+BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis
mov D$ecx eax
mov eax &TRUE
End_If
EndP