I'm looking for mnemonics that give me the system time, or even better a representation
of the actual time in milliseconds elapsed compared to a starting point that the computer knows.
Is there any MASM instruction doing this sort of things? Or any API DLL function to call to
have back these infos.
A small working example would be much appreciated. :-)
Thanks
frktons,
The Windows APIs are GetSystemTime or GetFileTime. GetSystemTime returns a SYSTEMTIME structure and GetFileTime returns a FILETIME structure. It is preferred to use a FILETIME if you want to perform date and time calculations. The SYSTEMTIME structure is used if you want to display the date and time. Take a look in \masm32\datetime, it is a library called DateTime that I wrote.
There is also the RDTSC instruction and QueryPerformanceCounter Windows API for timing purposes.
Hi,
there is no mnemonic for Systemtime or time elapsed since system was started, but API:
include \masm32\include\masm32rt.inc
.data
szfmt1 db "SystemTime is %02d:%02d",13,10,0
szfmt2 db " LocalTime is %02d:%02d",13,10,0
.code
start:
call main
exit
; -------------------------------------------------------------------------
main proc
local stime :SYSTEMTIME
local ltime :SYSTEMTIME
local millisecs :DWORD
; is defined in windows.inc as follows:
; SYSTEMTIME STRUCT
; wYear WORD ?
; wMonth WORD ? ; 1 = January, 2 = February, and so on
; wDayOfWeek WORD ? ; 0 = Sunday, 1 = Monday, and so on
; wDay WORD ?
; wHour WORD ?
; wMinute WORD ?
; wSecond WORD ?
; wMilliseconds WORD ?
; SYSTEMTIME ENDS
; load SystemTime to STRUC stime
invoke GetSystemTime,ADDR stime
; and print it
invoke crt_printf,ADDR szfmt1,stime.wHour,stime.wMinute
invoke GetLocalTime,ADDR ltime
invoke crt_printf,ADDR szfmt2,ltime.wHour,ltime.wMinute
; get milliseconds since system start (return in EAX)
invoke GetTickCount
mov millisecs,eax
print "Milliseconds since system boot: "
print str$(millisecs),13,10
ret
main endp
end start
Something is wrong with my example:
invoke crt_printf,ADDR szfmt1,stime.wHour,stime.wMinute ; shows SystemTime is 21:3801088
but
movzx eax,ltime.wHour
print str$(eax),":"
movzx eax,ltime.wMinute
print str$(eax),13,10 ;shows 23:58 as is expected
why does crt_printf print the correct WORD value of wHour but shows invalid value of wMinute?
Bug in crt_printf OR MORE LIKEY I made some error in formatstring?
Quote from: cobold on August 30, 2010, 10:06:07 PM
Something is wrong with my example:
invoke crt_printf,ADDR szfmt1,stime.wHour,stime.wMinute ; shows SystemTime is 21:3801088
but
movzx eax,ltime.wHour
print str$(eax),":"
movzx eax,ltime.wMinute
print str$(eax),13,10 ;shows 23:58 as is expected
why does crt_printf print the correct WORD value of wHour but shows invalid value of wMinute?
Bug in crt_printf OR MORE LIKEY I made some error in formatstring?
You must use second version, with "movzx". Because entryes in this structure are WORD-sized. But parameters must have sizes divisable to DWORD size (4bytes). So, you must extend WORD to DWORD with MOVZX, and push reg after this:
movzx eax,stime.wMinute
movzx edx,stime.wHour
invoke crt_printf,ADDR szfmt1,edx,eax ; this is correct form
When you use simple passing as parameters to invoke, this parameters is pushed as words, not dwords.
If you are pass the REAL8 (C(++) double FPU type), it be passed by value to crt_printf, but this is right - double have size 8 bytes - this is divisable by 4.
Alex
Thanks,
you are rigth alex, I suspected it had to do with WORD-size of parameters!
But "funny" thing was, that wHour was displayed correctly. Suppose because its on DWORD-boundary within the STRUCTURE.
Thanks anyway!
cobold - aka Klaus
Quote from: cobold on August 30, 2010, 10:26:41 PM
Thanks,
you are rigth alex, I suspected it had to do with WORD-size of parameters!
But "funny" thing was, that wHour was displayed correctly. Suppose because its on DWORD-boundary within the STRUCTURE.
Thanks anyway!
cobold - aka Klaus
This is funny: ml.exe vesion 8 makes this piece for pushing of WORDs:
0040104C |. 6A 00 PUSH 0
0040104E |. 66:FF75 FA PUSH WORD PTR SS:[EBP-6]
00401052 |. 6A 00 PUSH 0 ; /<%02d> = 0
00401054 |. 66:FF75 F8 PUSH WORD PTR SS:[EBP-8] ; |<%02d>
00401058 |. 68 00204000 PUSH OFFSET 00402000 ; |format = "SystemTime is %02d:%02d",CR,LF,""
0040105D |. FF15 1C104000 CALL DWORD PTR DS:[<&msvcrt.printf>] ; \MSVCRT.printf
So, compiler try to regulate the stack, but developers are forgot, what need emit WORD-sized PUSH 0, with opcode 666A00.
This is really bug of ML.Because this hours is shown right - after hours pushed zero DWORD, so, hours have size 6 bytes :) And have right format for looking to it as DWORD.
EDITED: For clearness: under "after hours pushed zero DWORD" I meant, what zero DWORD is after hours WORD in memory space - i.e. zero DWORD have bigger address than hours WORD. Code pushes zero DWORD before hours WORD, but for stack this is have reversed meaning.
Alex
P.S. But, if need pushing something, what not have size divisable to 4, need to make it to size, which divisable to 4.
Quote from: Greg Lyon on August 30, 2010, 09:22:03 PM
frktons,
The Windows APIs are GetSystemTime or GetFileTime. GetSystemTime returns a SYSTEMTIME structure and GetFileTime returns a FILETIME structure. It is preferred to use a FILETIME if you want to perform date and time calculations. The SYSTEMTIME structure is used if you want to display the date and time. Take a look in \masm32\datetime, it is a library called DateTime that I wrote.
There is also the RDTSC instruction and QueryPerformanceCounter Windows API for timing purposes.
Thanks Greg. :U
Well, Alex and Cobold have given a good example/explanation of the APIs involved.
They can be useful for displaying Date and Time, and also for general timing purposes.
What the instruction RDTSC is used for? Timing purposes? So it counts something?
CPU cycles? Could anybody post an example of RDTSC use? And of QueryPerformanceCounter?
Maybe the routine for testing the performance of routines we use on the forum use RDTSC?
Thanks everybody for your help.
According to INTEL manual:
Quote
RDTSC—Read Time-Stamp Counter
Description:
Loads the current value of the processor's time-stamp counter (a 64-bit MSR) into
the EDX:EAX registers. The EDX register is loaded with the high-order 32 bits of the
MSR and the EAX register is loaded with the low-order 32 bits. (On processors that
support the Intel 64 architecture, the high-order 32 bits of each of RAX and RDX are
cleared.)
The processor monotonically increments the time-stamp counter MSR every clock
cycle and resets it to 0 whenever the processor is reset.
My processor is 64 bit, does that means that high-order of RAX and RDX are cleared?
Strange enough. It has to be for compatibility reason with 32 bit machines.
Why not use a qword RXX register or an MMX register?
Frank
Frank,
Yes, it's used for timing purposes. If you are running 64-bit Windows and the executable is 64-bit then "the high-order 32 bits of each of RAX and RDX are cleared" applies, otherwise it does not. At the time RDTSC was created there was no 64-bit Windows and probably no MMX either.
[Edit] I was curious, so I looked it up. RDTSC was introduced with the Pentium, MMX was introduced with the Pentium MMX.
Quote from: Greg Lyon on August 31, 2010, 01:35:26 AM
frktons,
Yes, it's used for timing purposes. If you are running 64-bit Windows and the executable is 64-bit then "the high-order 32 bits of each of RAX and RDX are cleared" applies, otherwise it does not. At the time RDTSC was created there was no 64-bit Windows and probably no MMX either.
Thanks Greg.
Well, I run windows/7 64 bit, but I usually use MASM32, so in this case I just have to use EAX and EDX.
"the high-order 32 bits of each of RAX and RDX are cleared" anyway, I suppose, when the programs run
on the 64 bit OS, if I don't remember wrong, they are converted "on the fly" EAX -> RAX, EDX -> RDX.
For the time being I have to take care of EAX and EDX if I use RDTSC, unless I use a 64 bit capable assembler. :U
Quote from: frktonsFor the time being I have to take care of EAX and EDX if I use RDTSC, unless I use a 64 bit capable assembler. ThumbsUp
Ya, that's right.
to retrieve the boot time you could use NtQuerySystemInformation, using SystemTimeOfDayInformation (3) as the class type you want
it returns a struct of SYSTEM_TIMEOFDAY_INFORMATION
SYSTEM_TIMEOFDAY_INFORMATION STRUCT
BootTime LARGE_INTEGER <?>
CurrentTime LARGE_INTEGER <?>
TimeZoneBias LARGE_INTEGER <?>
CurrentTimeZoneId ULONG ?
Reserved ULONG ?
Reserved2 DWORD 4 DUP (?)
SYSTEM_TIMEOFDAY_INFORMATION ENDS
Quote from: evlncrn8 on September 06, 2010, 12:39:07 PM
to retrieve the boot time you could use NtQuerySystemInformation, using SystemTimeOfDayInformation (3) as the class type you want
it returns a struct of SYSTEM_TIMEOFDAY_INFORMATION
SYSTEM_TIMEOFDAY_INFORMATION STRUCT
BootTime LARGE_INTEGER <?>
CurrentTime LARGE_INTEGER <?>
TimeZoneBias LARGE_INTEGER <?>
CurrentTimeZoneId ULONG ?
Reserved ULONG ?
Reserved2 DWORD 4 DUP (?)
SYSTEM_TIMEOFDAY_INFORMATION ENDS
Thanks, it can be useful. :U
Frank
Quote from: cobold on August 30, 2010, 09:30:16 PM
Hi,
there is no mnemonic for Systemtime or time elapsed since system was started, but API:
There is no mnemonic, but there is an apicall you can use. GetTickCount will give you the amount of miliseconds passed since the system was started.
Keep in mind it resets every 49.7 days.
If you want to time your code it might be better to use performance counters. Use QueryPerformanceCounter and QueryPerformanceFrequency.
QueryPerformanceFrequency will give you the amount of ticks the performance counter performs per second and QueryPerformanceCounter will give
you the amount of ticks since system startup.
Quote from: zemtex on September 06, 2010, 12:57:11 PM
There is no mnemonic, but there is an apicall you can use. GetTickCount will give you the amount of miliseconds passed since the system was started.
Keep in mind it resets every 49.7 days.
If you want to time your code it might be better to use performance counters. Use QueryPerformanceCounter and QueryPerformanceFrequency.
QueryPerformanceFrequency will give you the amount of ticks the performance counter performs per second and QueryPerformanceCounter will give
you the amount of ticks since system startup.
Thanks zemtex,
All these are good solutions :U
Frank
Quote from: cobold on August 30, 2010, 09:30:16 PM
Hi,
there is no mnemonic for Systemtime or time elapsed since system was started, but API:
include \masm32\include\masm32rt.inc
.data
szfmt1 db "SystemTime is %02d:%02d",13,10,0
szfmt2 db " LocalTime is %02d:%02d",13,10,0
.code
start:
call main
exit
; -------------------------------------------------------------------------
main proc
local stime :SYSTEMTIME
local ltime :SYSTEMTIME
local millisecs :DWORD
; is defined in windows.inc as follows:
; SYSTEMTIME STRUCT
; wYear WORD ?
; wMonth WORD ? ; 1 = January, 2 = February, and so on
; wDayOfWeek WORD ? ; 0 = Sunday, 1 = Monday, and so on
; wDay WORD ?
; wHour WORD ?
; wMinute WORD ?
; wSecond WORD ?
; wMilliseconds WORD ?
; SYSTEMTIME ENDS
; load SystemTime to STRUC stime
invoke GetSystemTime,ADDR stime
; and print it
invoke crt_printf,ADDR szfmt1,stime.wHour,stime.wMinute
invoke GetLocalTime,ADDR ltime
invoke crt_printf,ADDR szfmt2,ltime.wHour,ltime.wMinute
; get milliseconds since system start (return in EAX)
invoke GetTickCount
mov millisecs,eax
print "Milliseconds since system boot: "
print str$(millisecs),13,10
ret
main endp
end start
I tried it again. This version shows the correct time on my machine, maybe because I'm using
ML V. 10 that do the needed conversion.