Hi.
I found this random generator in a magazine, but couldn't get it to work. I'm also not very good at C language :( so I would appreciate any comments that might help. I really don't know how is it supposed to work... (if at least I fully understood it I could port it to MASM).
Thanks.
``````#include <stdio.h>
#include <stdlib.h>
#define TRUE -1
#define FALSE 0
#define boolean int
static void rmarin(int ij, int kl);
void ranmar(float rvec[], int len);
void main ()
{
float temp;
int ij, kl, len, i;
/* test seeds */
ij = 1802;
kl = 9373;
/* initialize */
rmarin(ij,kl);
/* generate 20,000 random numbers */
len = 100;
for (i=1; 0<=200; i++)
ranmar(temp, len);
}
static float u, c, cd, cm;
static int i97, j97;
static boolean test = FALSE;
static void rmarin( int ij, int kl )
{
/* This is the initialization routine.
It must be called before invoking RANMAR().
The "seeds" can take this values:
0 <= IJ <= 31328
0 <= KL <= 30081
*/
int i, j, k, l, ii, jj, m;
float s, t;
if (ij<0 || ij>31328 || kl<0 || kl>30081) {
puts("The first seed must be a number between 0 and 31328.");
puts("The first seed must be a number between 0 and 30081.");
exit(1);
}
i = (ij/177)%177 + 2;
j = ij%177 + 2;
l = kl%169;
for (ii=1; ii<=97; ii++) {
s = 0.0;
t = 0.5;
for (jj=1; jj<=24; jj++) {
m = (((i*j)%179)*k) % 179;
i = j;
j = k;
k = m;
l = (53*1 + 1) % 169;
if ((1*m)%64 >= 32) s += t;
t *= 0.5;
}
u[ii] = s;
}
c = 362326.0 / 16777216.0;
cd = 7654321.0 / 16777216.0;
cm = 16777213.0 / 16777216.0;
i97 = 97;
j97 = 33;
test = TRUE;
}
void ranmar( rvec, len )
float rvec[];
int len;
/* This is the random number generator */
{
int ivec;
float uni;
if (test==FALSE) {
puts("Call RMARIN() before invoking RANMAR().");
exit(2);
}
for (ivec=1; ivec<=len; ivec++) {
uni = u[i97] - u[j97];
if (uni < 0.0) uni += 1.0;
u[i97] = uni;
i97-;
if (i97==0) j97 = 97;
j97-;
if (j97==0) j97 = 97;
c -= cd;
if (c<0.0) c += cm;
uni -= c;
if (uni<0.0) uni += 1.0;
rvec[ivec] = uni;
}
}``````
Posted on 2003-10-28 18:16:57 by QvasiModo
Why don't you use something better and simpler:
``````
.data
rando dd 0
.code

rand proc uses ebx ecx edx maxi_value
RDTSC
xor rando,edx
mov eax,rando
xor edx,edx
mov ecx,maxi_value
div ecx
mov eax,edx
ret
rand endp
``````

:grin:

the code you posted just makes hell of a lot calculations, which leads to a higher number of pseudo-random numbers in the cycle of "randomness".
Posted on 2003-10-29 01:29:33 by Ultrano

Why don't you use something better and simpler:
``````
.data
rando dd 0
.code

rand proc uses ebx ecx edx maxi_value
RDTSC
xor rando,edx
mov eax,rando
xor edx,edx
mov ecx,maxi_value
div ecx
mov eax,edx
ret
rand endp
``````

:grin:

the code you posted just makes hell of a lot calculations, which leads to a higher number of pseudo-random numbers in the cycle of "randomness".

Just to let you know I'm copying your code ;)
Posted on 2003-10-29 15:33:18 by x86asm
okay, but I noticed my code will work better like this:
``````
.data
rando dd 0
.code

rand proc uses ebx ecx edx maxi_value
RDTSC
xor rando,edx
mov eax,rando
xor edx,edx
mov ecx,maxi_value
div ecx
mov eax,edx
ret
rand endp
``````

This will make sure that you get more distant results if you call "rand" many times one after another. Because in this case RDTSC will sometimes return almost similar values, and you'll get only a few bits changed on each new immediately consecutive call. :)
Posted on 2003-10-29 15:44:11 by Ultrano
If you want, you can remove that xor edx,edx.
Posted on 2003-10-30 02:39:49 by roticv
uhm, won't that lead to an exception (overflow)?! If edx is not 0, and maxi_value isn't big enough for a 32-bit result , then an exception happens. In other words, (1002 * 2^32 + 554) % 15 will crash the app.
The only thing you can safely remove there is the "uses ebx"
Posted on 2003-10-30 06:30:51 by Ultrano
the overflow will depend on the value of maxi_value and how many times you call it. Actually I think if it is removed, the value in edx would be harder to predict and thus more "random". But like you mention of course there would be a possibility of the overflow exception. of course one can wrap it with seh and then change the null the value in edx to 0 if the exception occurs.
Posted on 2003-10-30 07:44:45 by roticv
hrm, a PRNG based just on RDTSC? I hope you're not going to use this for anything "secure"...
Posted on 2003-10-30 07:47:39 by f0dder
Thanks guys for all the replies. I wasn't expecting much from a C post in an ASM board! :grin:
Thanks Ultrano for your algo. Anyway, I am aware that there are better ways to make a PRGN in assembly (in fact the masm32 lib comes with NaN's excellent implementation of Parker Miller). I was just curious about this particular code... I thought it would be interesting to see how it works. (After all, so many calculations MUST do something in the end ;) ).
Can anyone figure out what it is supposed to do? All it seems to do is cause a GPF. :(
Posted on 2003-10-30 16:16:20 by QvasiModo
No wonder it causes a GPF. See around the 15th line:
``````
/* generate 20,000 random numbers */
len = 100;
[color=red]for (i=1;[/color][color=green] 0<=200[/color][color=red]; i++)[/color]
ranmar(temp, len);
}
``````

The snippet I posted is really not good for security or best results. Its only + is for speed :) (and it could be made faster, though) . I created it on the fly ;)
Posted on 2003-10-30 23:03:23 by Ultrano
lol That C code is never meant to be used. Or if you ever want to compile it, you should follow the author's mind- he has all compiler optimizations off, and uses old-style C compiler. Strange, but this gen returns "random" floats into an array, instead of in eax. Looking at this code, I recall some C coding competitions, where you should write the most strange code, and bring the compiler to its knees :grin:
Posted on 2003-10-31 13:33:43 by Ultrano
Yeah, the code is bizarre. I found it as a sample in a C programming course, as part of a magazine. The code is somewhat old (that's why it's C and not C++). And of course the typo is mine :grin:
Thanks. I'll fix it and see what I get...
Posted on 2003-11-02 15:27:41 by QvasiModo