Looking for a random number generator, I've found (thanks to one of my "C++ pals") a routine which could be expanded to assembly as:
iRand	PROC	USES EDX

mov EAX,00BB38435h
mul
add EAX,03619636Bh
mov ,EAX
ret

iRand ENDP


It seems to produce well-distribued random dwords and I'm used to initialize the seed with RDTSC. That's all for the integers. Now to the floating point results.

The easiest way to produce a random floating point value I've managed to write on my own is:
fRand	PROC	USES EDX

mov EAX,00BB38435h
mul
add EAX,03619636Bh
mov ,EAX
and EAX,07FFFFFFFh ; get rid of sign bit
or EAX,03F800000h ; fix the exponent
ret

fRand ENDP


This procedure provides (just as the integer one) a very good distribution of values, however:
- resulting values are in the range between 1.0 (inclusive) and 2.0 (exclusive), and I've not found any reasonable integer method for range conversion (any ideas?)
- results are returned in EAX, not on the top of FPU's stack. That seems to be against the "common" rules, but can be easily used for purposes of:
	mov ,$INVOKE(fRand)


Alternatively, I'd propose such a modification (this solves both oddities listed above):
fRand	PROC

push EAX
push EDX
fld1
mov EAX,00BB38435h
mul
fadd st(0),st(0)
add EAX,03619636Bh
mov ,EAX
and EAX,07FFFFFFFh ; get rid of sign bit
or EAX,03F800000h ; fix the exponent
xchg EAX,
pop EDX
fsub DWORD PTR
add ESP,04
ret

fRand ENDP


Cheers, Mikael
Posted on 2005-08-12 04:31:46 by MikaelC
There seems to be one more oddity with your algo for floating point values:
Based on random distribution of bits, bit30 should be set some 50% of the time. This means that the generated float value would be considered as a NAN some 50% of the time if you tried to use it as a parameter on the FPU. I do agree that the other 50% of the time, the generated number would be between 1 and 2.

A result between 0 and 1 would be more acceptable since it could easily be converted to a random value within a specified range. My suggestion to prevent NANs and provide a random fractional floating point number between 0 and 1 would be (still based on your RNG algo):

mov  eax,00BB38435h
mul 
add  eax,03619636Bh
mov  ,EAX
and  eax,3FFFFFFFh    ;instead of 7FFFFFFFh
or  eax,3F800000h    ; fix the exponent to 1
push eax
fld  dword ptr
fld1
fsubp st(1),st
pop  eax              ;clean stack


Raymond
Posted on 2005-08-12 09:26:23 by Raymond
You're absolutely right. Since we need an exponent equal to 127, bit 30 should be always cleared and thus - we need to and EAX with 3FFFFFFFh. Thanks.
Posted on 2005-08-12 11:38:15 by MikaelC