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.
Quote from: msdnA pointer to a SYSTEMTIME structure to receive the current local date and time
LOCAL systime:SYSTEMTIME
...
invoke GetLocalTime,ADDR systime
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
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
Quote from: pelmeen on December 27, 2011, 10:34:49 PM
im very new to this ultimate hacking language
:boohoo:
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.
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
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.
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
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
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
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.
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
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
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.
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
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.
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 goodSerial 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 goodSerial 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. <<<
badSerial correlation coefficient is 0.000417 (totally uncorrelated = 0.0). <<<
goodTest 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.
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
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.
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
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
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.
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