News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

What time is it?

Started by frktons, August 30, 2010, 08:15:20 PM

Previous topic - Next topic

frktons

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 
Mind is like a parachute. You know what to do in order to use it :-)

GregL

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.




cobold

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

cobold

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?


Antariy

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

cobold

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

Antariy

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.

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)

GregL

#8
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.

frktons

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



Mind is like a parachute. You know what to do in order to use it :-)

GregL

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.



evlncrn8

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

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)

zemtex

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.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)