Assembly Language for Beginners

(Jeff_L) #1

1.23. LINEAR CONGRUENTIAL GENERATOR


void my_srand (uint32_t init)
{
rand_state=init;
}


int my_rand ()
{
rand_state=rand_state*RNG_a;
rand_state=rand_state+RNG_c;
return rand_state & 0x7fff;
}


There are two functions: the first one is used to initialize the internal state, and the second one is called
to generate pseudorandom numbers.


We see that two constants are used in the algorithm. They are taken from [William H. Press and Saul A.
Teukolsky and William T. Vetterling and Brian P. Flannery,Numerical Recipes, (2007)].


Let’s define them using a#defineC/C++ statement. It’s a macro.


The difference between a C/C++ macro and a constant is that all macros are replaced with their value by
C/C++ preprocessor, and they don’t take any memory, unlike variables.


In contrast, a constant is a read-only variable.


It’s possible to take a pointer (or address) of a constant variable, but impossible to do so with a macro.


The last AND operation is needed because by C-standardmy_rand()has to return a value in the 0..32767
range.


If you want to get 32-bit pseudorandom values, just omit the last AND operation.


1.23.1 x86


Listing 1.318: Optimizing MSVC 2013

_BSS SEGMENT
_rand_state DD 01H DUP (?)
_BSS ENDS


_init$ = 8
_srand PROC
mov eax, DWORD PTR _init$[esp-4]
mov DWORD PTR _rand_state, eax
ret 0
_srand ENDP


_TEXT SEGMENT
_rand PROC
imul eax, DWORD PTR _rand_state, 1664525
add eax, 1013904223 ; 3c6ef35fH
mov DWORD PTR _rand_state, eax
and eax, 32767 ; 00007fffH
ret 0
_rand ENDP


_TEXT ENDS


Here we see it: both constants are embedded into the code. There is no memory allocated for them.


Themy_srand()function just copies its input value into the internal
rand_statevariable.


my_rand()takes it, calculates the nextrand_state, cuts it and leaves it in the EAX register.


The non-optimized version is more verbose:


Listing 1.319: Non-optimizing MSVC 2013

_BSS SEGMENT
_rand_state DD 01H DUP (?)

Free download pdf