The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: pelmeen on December 27, 2011, 09:14:44 PM

Title: Calling GetLocalTime on windows
Post by: pelmeen on December 27, 2011, 09:14:44 PM
I cant understand what am i doing wrong in this piece of code. Can anyone help, please?
The goal is to get system time and if i get that working, then im going to start turning it into random. Right now, i just want the big number

getRandom proc C
   LOCAL timeWord:dword
   invoke GetLocalTime,timeWord
   mov eax, timeWord
   ret
getRandom endp

Refrence:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724338%28v=vs.85%29.aspx

Thank you.
Title: Re: Calling GetLocalTime on windows
Post by: qWord on December 27, 2011, 09:27:24 PM
Quote from: msdnA pointer to a SYSTEMTIME structure to receive the current local date and time
LOCAL systime:SYSTEMTIME
...
invoke GetLocalTime,ADDR systime
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 27, 2011, 10:34:49 PM
SYSTEMTIME requires winbase.h. It says to include windows.h
I started researching windows.h and found this site:
http://en.wikipedia.org/wiki/Windows.h
In here it says that:

winbase.h – kernel32.dll: kernel services

In my program, i already have

PUBLIC getRandom

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

getRandom proc C
   LOCAL systime:SYSTEMTIME
   invoke GetLocalTime,ADDR systime
   mov eax, systime
   ret
getRandom endp


But i still get error:
lib\random.asm(19) : error A2006: undefined symbol : SYSTEMTIME
lib\random.asm(19) : error A2195: parameter or local cannot have void type
lib\random.asm(21) : error A2006: undefined symbol : timeWord

Why cant it find SYSTEMTIME

Im really sorry, if this is stupid question, im very new to this ultimate hacking language
Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 27, 2011, 10:40:16 PM
If you have downloaded the Masm32 SDK, this will work. If not, click on my signature and download the SDK.

include \masm32\include\masm32rt.inc

.code
getRandom proc C
   LOCAL systime:SYSTEMTIME
   invoke GetLocalTime,ADDR systime
   movsx eax, systime.wMilliseconds
   ret
getRandom endp
start:
MsgBox 0, str$(rv(getRandom)), "wMilliseconds:", MB_OK
exit

end start
Title: Re: Calling GetLocalTime on windows
Post by: qWord on December 27, 2011, 10:43:03 PM
Quote from: pelmeen on December 27, 2011, 10:34:49 PM
im very new to this ultimate hacking language
:boohoo:
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 27, 2011, 11:24:36 PM
Thank you very much guys. It does return something now.

However, it only return 3 digit number, the milliseconds. I need the big number. Milliseconds from 1970. UNIX time. How change it to do that? Looking at the SYSTEMTIME info i can only see that i can get specific days, hours, minutes and such. No use to me. Too small of a number.
Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 27, 2011, 11:50:18 PM
Here is a big number. Console assemble & link.

include \masm32\include\masm32rt.inc

.code
getRandom proc uses ebx esi
   LOCAL systime:FILETIME, dosTime:WORD, dosDate:WORD
   lea ebx, systime
   invoke GetSystemTimeAsFileTime, ebx
   lea esi, dosDate
   lea ecx, dosTime
   invoke FileTimeToDosDateTime, ebx, esi, ecx
   lodsw
   shl eax, 16
   lodsw
   ret
getRandom endp

start: m2m ebx, 7
.Repeat
invoke getRandom
print str$(eax), 13, 10
invoke Sleep, 1000
dec ebx
.Until Sign?
exit
end start
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 28, 2011, 11:04:02 AM
Thank you for your reply. Im at work right now, il check it when i get home in the evening.

I did notice though that you used 2 completely different functions then i did. Il check it out later.
Title: Re: Calling GetLocalTime on windows
Post by: dedndave on December 28, 2011, 12:02:01 PM
QuoteI need the big number. Milliseconds from 1970. UNIX time.

you are looking for what MS refers to as "time_t" time
the MSVCRT library has a "time" function...
QuoteThe time function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970,
Coordinated Universal Time (UTC), according to the system clock. The return value is stored in the location
given by timer. This parameter may be NULL, in which case the return value is not stored.

http://msdn.microsoft.com/en-us/library/1f4c8f33%28VS.80%29.aspx

if you want milliseconds instead of seconds, multiply by 1000   :bg

QuoteUnix time, or POSIX time, is a system for describing instants in time, defined as the number of
seconds elapsed since midnight Coordinated Universal Time (UTC) of Thursday, January 1, 1970

i guess this system runs out of poop in 2038
i am sure there will be some 64-bit version of it, by then
i will be 83, and probably won't care   :P
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 28, 2011, 07:34:15 PM
I just went through jj2007 code and then read through dedndave description. I also ran the code i have been given.. And dedndave speaks the truth. Its seconds from 1970, not milliseconds.

I just realized that my task got a lot harder. I cant use seconds, since i need more than 1 randoms in a second.

Also, i cant use the three digit milliseconds, because i need randoms up to 5 digits long

If you have any suggestions, it would be appreciated, in the mean while, im going to search for some mathematical formula, to see if i can get 5 digit random from 3 digit number. I wont get my hopes up too much.

EDIT:
Well what can i say? I just got a whole alot smarter and it turns out i CAN use the milliseconds. And i taught i know what pseudo-random number is
Thank all of you guys SO much. Its time for me to get to work. I will let you know if i have any problems or if i was successful
Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 28, 2011, 08:26:26 PM
Quote from: pelmeen on December 28, 2011, 07:34:15 PMAlso, i cant use the three digit milliseconds, because i need randoms up to 5 digits long

If that's all what you need, here is one:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   Inkey Str$("A random number between 0 and 9999: %i", Rand(10000))
   Exit
end start

It's also the fastest one available - credits to Alex alias Antariy (http://www.masm32.com/board/index.php?topic=11679.msg123999#msg123999) :bg
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 28, 2011, 08:28:36 PM
Heh, thank you, but if i would go down on such an easy road, then i would learn nothing :)

I will try to do it myself, but i appreciate the effort.
Title: Re: Calling GetLocalTime on windows
Post by: dedndave on December 28, 2011, 09:24:03 PM
first of all, i would not depend strictly on any time function for the random values
particularly if you are grabbing values more than once a second   :P

you will be much happier with the results if you use a simple random number generator, like LCG
then, use one of the time functions to periodically seed/re-seed the generator
(QueryPerformanceCounter, GetTickCount or even the RDTSC instruction)

there are many variations on a theme
a while back i wrote a simple routine that auto-seeds itself
it's only an example to give you some ideas...

http://www.masm32.com/board/index.php?topic=11679.msg123908#msg123908
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 28, 2011, 09:57:15 PM
Well i really wanted to write a random number generator myself. Right now i made something that will be reseeded every time random is called.

I used the same thing C Rand() function does

You dont think its solid enough?


getRandom proc C
   LOCAL systime:SYSTEMTIME
   invoke GetLocalTime,ADDR systime
   movsx eax, systime.wMilliseconds
   imul eax, 1103515245
   add eax, 12345
   xor edx, edx
   mov ebx, 65536
   idiv ebx
   xor edx, edx
   mov ebx, 32768
   idiv ebx
   mov eax, edx
   ret
getRandom endp

Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 29, 2011, 12:54:36 AM
Quote from: pelmeen on December 28, 2011, 09:57:15 PM
Well i really wanted to write a random number generator myself.

QuoteI used the same thing C Rand() function does
You dont think its solid enough?

Here is ENT (http://www.fourmilab.ch/random/), A Pseudorandom Number Sequence Test Program. The MasmBasic Rand() macro shown above has been optimised for ENT, and is fast: 11-12 cycles per call. For comparison, your routine above takes about 30 cycles without the API call, and 425 cycles including the GetLocalTime call.
Title: Re: Calling GetLocalTime on windows
Post by: dedndave on December 29, 2011, 01:24:40 AM
reading any time value, whether it is from the OS or via RDTSC will be much slower than a LCG random generator
and - you won't get random stuff   :P

perhaps the best thing to do is to play with a few different methods and look at the numbers that are generated
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 29, 2011, 07:38:17 AM
Hmm, well i will probably never reach the MasmBasic optimisation and i cant get around the API call, if im using time as my seed.

But i could do something that dedndave said.

I could maybe tell the program to seed on like.. every 30th call? That way the API would be called much rarer and cycles count would be dramatically lowered.

Or maybe i could only seed the program through the time only at the start of the program. After that i could use the last random as the seed. I guess that would improve optimization dramatically. Then, every time user starts the small app, its still going to be different numbers.. only 1/999 chance that they are exactly the same :D

Regarding dedndave last post. Why wont i get random stuff?
EDIT:
Yea, i just realized that when i use milliseconds as seed on every call, i actually only have 999 states for my random. So i MUST use the last random as my seed at some point.
EDIT2:
I thought about it for a while and i believe that giving random seed only at the start is the best course of action. And i should also use the big number, which i can get from jj2007 second posts code. Im going to work on it tonight when i get home.
Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 29, 2011, 08:14:31 AM
Quote from: pelmeen on December 29, 2011, 07:38:17 AM
Hmm, well i will probably never reach the MasmBasic optimisation and i cant get around the API call, if im using time as my seed.

If you need a good "random" seed, use either rdtsc or GetTickCount - a very fast API call, it takes about 7 cycles.

I have run a few tests with ENT (http://www.fourmilab.ch/random/) concerning MasmBasic Rand() and its C equivalent, crt_rand. Both tests are limited to WORD size, because the CRT algo yields a WORD only.

MasmBasic:
Test for #0 byte
Entropy = 7.999257 bits per byte.
would exceed this value 50.00 percent of the times. <<< very good
Serial correlation coefficient is -0.002635 (totally uncorrelated = 0.0).
Test for #1 byte
Entropy = 7.999249 bits per byte.
would exceed this value 50.00 percent of the times. <<< very good
Serial correlation coefficient is -0.003110 (totally uncorrelated = 0.0).

CRT rand:
Test for #0 byte
Entropy = 7.999358 bits per byte.
would exceed this value 90.00 percent of the times. <<< bad
Serial correlation coefficient is 0.000417 (totally uncorrelated = 0.0). <<< good
Test for #1 byte
Entropy = 6.999668 bits per byte. (range is 0...32767)
would exceed this value 0.01 percent of the times. <<< very bad *)
Serial correlation coefficient is -0.002919 (totally uncorrelated = 0.0).

Overall, the MasmBasic version looks a bit better. In addition, it runs in 11 cycles instead of 30 for the CRT version.

*)
QuoteChi-square Test
    The chi-square test is the most commonly used test for the randomness of data...
Applying this test to the output of various pseudorandom sequence generators is interesting. The low-order 8 bits returned by the standard Unix rand() function, for example, yields:

    Chi square distribution for 500000 samples is 0.01, and randomly would exceed this value more than 99.99 percent of the times.

While an improved generator [Park & Miller] reports:

    Chi square distribution for 500000 samples is 212.53, and randomly would exceed this value 97.53 percent of the times.

Thus, the standard Unix generator (or at least the low-order bytes it returns) is unacceptably non-random, while the improved generator is much better but still sufficiently non-random to cause concern for demanding applications. Contrast both of these software generators with the chi-square result of a genuine random sequence created by timing radioactive decay events.

    Chi square distribution for 500000 samples is 249.51, and randomly would exceed this value 40.98 percent of the times.
Title: Re: Calling GetLocalTime on windows
Post by: dedndave on December 29, 2011, 12:43:49 PM
in one implementation, i pulled a 6-bit number from the clock and forced it to be between 64 and 128
then i used that value as the count N
count N pulls from the LCG later, i use the clock to reseed the LCG and get a new N
as you said - reasonably fast, and the numbers are quite random
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 29, 2011, 11:55:38 PM
Ahh, thank you for all of your replies. Its too late today, i must work on it tomorrow or on saturday.

Also, i gotta mention. Im really impressed on the activity rate of this community.
Title: Re: Calling GetLocalTime on windows
Post by: pelmeen on December 31, 2011, 11:41:24 AM
Using your help and links and stuff you taught me, i have put together something like this:



PUBLIC getRandom, start
include \masm32\include\masm32rt.inc

getRandom proc C
   jz getRandomCalculate
   invoke GetTickCount
   
getRandomCalculate:   
   imul eax, 1103515245
   add eax, 12345
   xor edx, edx
   mov ebx, 65536
   idiv ebx
   xor edx, edx
   mov ebx, 32768
   idiv ebx
   mov eax, edx
   ret
getRandom endp

start: m2m ebx, 10
.Repeat
invoke getRandom
print str$(eax), 13, 10
invoke Sleep, 100
dec ebx
.Until Sign?
exit
end start


What do you think?

For the real program, i wont be using the start part. Im going to call this function from a program written in C
Title: Re: Calling GetLocalTime on windows
Post by: qWord on December 31, 2011, 12:19:25 PM
Seems not  very random.
You may like the following routine, which returns a BYTE:
badRandom256 proc uses esi edi
LOCAL qw:QWORD
    rdtsc
    and eax,0ffh
    push eax
    mov esi,eax
    xor edi,edi
    .while esi
        xor edi,rv(GetTickCount)
        dec esi
    .endw
    rdtsc
    pop edx
    mul edx
    xor eax,edi
    push eax
    invoke QueryPerformanceCounter,ADDR qw
    pop eax
    xor eax,DWORD ptr qw[0]
    and eax,0ffh
    ret
   
badRandom256 endp
Title: Re: Calling GetLocalTime on windows
Post by: jj2007 on December 31, 2011, 12:57:21 PM
Quote from: pelmeen on December 31, 2011, 11:41:24 AM
What do you think?

"Thinking" is not a good approach to judging the randomness of a pseudo random generator. Fourmilab developed ENT for that purpose.
Title: Re: Calling GetLocalTime on windows
Post by: donkey on December 31, 2011, 07:16:04 PM
For myself if I need a large random array I use a Mersenne twister, if I just need a one-shot in a program (ie I only need a small array and only once) I use the Crypto functions. They're slow but I only use them in cases where speed is not an issue:

FillRandom FRAME pBuffer, nBytes
LOCAL hCryptProv :%HANDLE

// Fill pBuffer with nBytes of random data
// Returns 0 if successful, -1 otherwise

invoke CryptAcquireContext,offset hCryptProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT
test eax,eax
jz >>.ERRORCONTEXT

invoke CryptGenRandom, [hCryptProv],[nBytes],[pBuffer]
test eax,eax
jz >>.ERRORGEN

invoke CryptReleaseContext, [hCryptProv], NULL
xor eax,eax
ret

.ERRORGEN
invoke CryptReleaseContext, [hCryptProv], NULL

.ERRORCONTEXT
xor eax,eax
dec eax
RET

endf