Hi,
I'm trying to write a function that will convert TimeDateStamp (dword) to its equivalent date and time string, the documented method for doing this is to add the converted to ticks TimeDateStamp (TimeDateStamp * 10000000) to 019DB1DED53E8000h (January 1, 1970), but the result is a 64-bit data in which I don't know how to handle in MASM.
Converting to string would be easy, but I'd like to know how to handle 64-bit datatypes (addition/subtraction) in MASM without using 64-bit registers and without data-loss?
Any help would be greatly appreciated.
Thanks,
-chris
When you multiply with 10000000 and add the 19DB1DEE53E8000h to the C type of DWORD time, you get the specific 64bit value, which is the same as FILETIME. You can then use for example, the Windows API FileTimeToSystemTime; to convert the 64bit value to SYSTEMTIME, which then after conversion, holds the time format in much more printable version (WORD values). :wink
See the recent thread Re: LARGE_INTEGER Divide where Raymond helped me through a similar problem a couple weeks ago.
Thanks for the great discussions about LONG_INTEGER, I learned a lot :U
Also, thanks for telling me that there's an API that do what I want to do, it saved me a lot of coding :bg
-chris
After sending more than an hour searching I was unable to determine if the correct 100-nanosecond interval adjustment value is 019DB1DED53E8000h or 19DB1DEE53E8000h, so I decided to code a program to derive the value. Unless I'm screwing up again :( , the correct value is 19DB1DED53E8000h.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
;------------------------------------------------
; For the Gregorian Calendar, leap years are all
; century years evenly divisible by 400, and all
; other years evenly divisible by 4.
;------------------------------------------------
isleapyear MACRO year
mov ecx, 100
mov eax, year
xor edx, edx
div ecx
.IF (edx) ;; if not century year
mov eax, year ;; reload year
.ENDIF
and eax, 3
mov eax, 1
jz @F ;; if evenly divisible by 4
xor eax, eax
@@:
EXITM <eax>
ENDM
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
;-------------------------------------------------------------
; The C time function returns the number of seconds elapsed
; since midnight, January 1, 1970 (as type time_t).
;
; A system file time is a 64-bit unsigned value representing
; the date and time as the number of 100-nanosecond intervals
; that have elapsed since midnight, January 1, 1601.
;-------------------------------------------------------------
xor edi, edi ; days
mov ebx, 1601
.REPEAT
.IF (isleapyear(ebx))
add edi, 366
.ELSE
add edi, 365
.ENDIF
add ebx, 1
.UNTIL (ebx == 1970)
mov eax, 24*60 ; minutes per day
mul edi ; product will fit in eax
mov edi, 60*10000000 ; 100-nanosecond intervals per minute
mul edi ; product in edx:eax
nops 4
invoke crt_printf, chr$("%I64Xh%c"), edx::eax, 10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
19DB1DED53E8000h
Press any key to exit...
Did you take into the Julian to Gregorian Calendar skip ?
Scratch that thought:
For example, even though the Gregorian Calendar was implemented on October 15, 1582 (Gregorian) we can still say that the date of the day one year before was October 15, 1581 (Gregorian), even though people alive on that day would have said that the date was October 5, 1581 (the Julian date at that time).
Regards, P1 :8)
Use the FPU with the 64bit data types. Check out Ray's tutorials:
http://website.masmforum.com/tutorials/fptute/index.html
Makes using the integers easier, with advanced math functions.
Regards, P1 :8)
I finally found a definition for the value in question in the time.c source that was included with the Windows Server 2003 PSDK:
Quote
/*
* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
*/
#define EPOCH_BIAS 116444736000000000i64
And if I change the printf statement in the source above to:
invoke crt_printf, chr$("%I64d%c"), edx::eax, 10
I get:
116444736000000000
Press any key to exit...
And the name is IMO very well chosen:
http://en.wikipedia.org/wiki/Epoch
To complete this:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
EPOCH_BIAS EQU 116444736000000000.0
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
crttime dd 0
filetime dq 0
systime1 SYSTEMTIME <>
systime2 SYSTEMTIME <>
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke GetSystemTime, ADDR systime1
invoke crt_time, NULL
mov crttime, eax
fld8 10000000.0
fimul crttime
fld10 EPOCH_BIAS ; REAL10 because EPOCH_BIAS has 57 significant bits
fadd
fistp filetime
invoke FileTimeToSystemTime, ADDR filetime, ADDR systime2
movzx eax, systime1.wYear
print ustr$(eax),9
movzx eax, systime2.wYear
print ustr$(eax),13,10
movzx eax, systime1.wMonth
print ustr$(eax),9
movzx eax, systime2.wMonth
print ustr$(eax),13,10
movzx eax, systime1.wDayOfWeek
print ustr$(eax),9
movzx eax, systime2.wDayOfWeek
print ustr$(eax),13,10
movzx eax, systime1.wDay
print ustr$(eax),9
movzx eax, systime2.wDay
print ustr$(eax),13,10
movzx eax, systime1.wHour
print ustr$(eax),9
movzx eax, systime2.wHour
print ustr$(eax),13,10
movzx eax, systime1.wMinute
print ustr$(eax),9
movzx eax, systime2.wMinute
print ustr$(eax),13,10
movzx eax, systime1.wSecond
print ustr$(eax),9
movzx eax, systime2.wSecond
print ustr$(eax),13,10
;-----------------------------------------------------
; The crt time function returns the number of seconds
; elapsed since midnight (00:00:00), January 1, 1970,
; coordinated universal time (UTC), so the elapsed
; milliseconds will always be zero.
;-----------------------------------------------------
movzx eax, systime1.wMilliseconds
print ustr$(eax),9
movzx eax, systime2.wMilliseconds
print ustr$(eax),13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Typical result:
2006 2006
2 2
6 6
4 4
23 23
36 36
31 31
795 0