Hello,

I was toying around with the rand function and saw an example in C on the msdn page. The example generates a random number between a lower and a upper boundary. My problem is the conversion of this line:

rand() / RAND_MAX + 1 * (range_max - range_min) + range_min

I have big problems to convert that line of code to ASM. I've searched this msg board and saw a dozen of other rand examples. Those are not relevant for me because i want to play around with the div & mul stuff for this moment.

Can any of you translate the code to ASM for me, thx alot.

Grtz,
Slash0r
Posted on 2009-07-03 08:15:11 by Slash0r
Instead of us just doing the work for you...
How far have you gotten with converting this to ASM so far... And what exactly is the thing you got stuck on?
(If I had to guess... the line of code you posted will only work with floating point numbers, because it introduces fractions. You may want to rewrite it to avoid fractions first, something I'd recommend in C/C++ anyway).
Posted on 2009-07-03 08:21:10 by Scali
Hi Scali,

I've gotten this far:

call crt_rand ; rand() / RAND_MAX + 1 * (range_max - range_min) + range_min
xor edx, edx
mov ecx, RAND_MAX
inc ecx
div ecx ; eax = quotient, edx = remainder.

Well this was easy ofc. The problem is when the division produces remainders. What should i do with the remainder of the division (multiply it by range_max - range_min as well)? So should i multiply both quotient and remainder with range_max - range_min and add both togehter of something? It's really puzzling for me.

Grtz,
Slash0r
Posted on 2009-07-03 09:11:02 by Slash0r
mov edx,range_max
sub edx,range_min
mul edx
add eax,range_min

We are scaling the value by (max-min), thus putting it in the range (0 thru max-min)... then we are adding min, thus putting it in the range (min thru max) :)
Posted on 2009-07-03 09:13:58 by Homer
The problem here is that rand() / RAND_MAX will basically always result in something between 0 and 1.
You can't do it that way with integer math, because it will just round towards 0.

So you either have to use floating point (which I don't recommend), or you have to rework the mathematics.

For example, if I do this:
((rangemax-rangemin)*rand()) / RAND_MAX

Now it no longer uses fractions, because you scale up first, then you divide, and you end up in the 0..(rangemax-rangemin) range, which fits into an integer just fine.
Posted on 2009-07-03 09:23:39 by Scali
Yeah Scali thats more like it.

Homer is ignoring the remainder of the division, that can't be right :) (but thx anyway for your reply Homer).

I think it's wise to use imul and idiv as well btw.

What to do if we cant get around floating point arithmetic in ASM?
Posted on 2009-07-03 09:38:19 by Slash0r
Well, you can just use floats in asm... you have fadd, fsub, fmul, fdiv and all that.
It's just that it's a bit more difficult to read and write, and generally it will not perform as well for simple operations (especially converting from integer to float and back will generally cost time... and the FPU doesn't have normal registers, it uses a weird stack system to access the registers).
Posted on 2009-07-03 09:48:04 by Scali
especially converting from integer to float and back will generally cost time


That time is quite minimal, unless you have to generate a zillion random numbers without stopping.

@Slash0r
The FPU is not that difficult to use once you know how, specially if it's only for the basic arithmetic operations. If you are seriously interested, spend a bit of time looking at the following:
http://www.ray.masmcode.com/tutorial/index.html
Posted on 2009-07-03 11:55:56 by Raymond

That time is quite minimal, unless you have to generate a zillion random numbers without stopping.


Well... if I didn't care about minimal timing issues, I wouldn't bother to write it in asm in the first place ;)
Oldest discussion in the asm world.
Posted on 2009-07-03 13:33:15 by Scali