hi dears.
I am using Emu8086.
I need to generating an array of random numbers.
Are there any ready procedure or intrupt?
if there are not, how can I do it?
thanks.

Edited 6 Years Ago by funfullson: n/a

If you have an Intel 82802 in your system....

http://www.intel.com/assets/pdf/manual/298029.pdf

If not, read a high precision clock register, blend the bits in a tight loop, peek at a keyboard key until a user interaction is applied such as a keystroke. You can seed the number generation from the high precision clock as well based upon computer power up time.

seed = high precision clock

Loop:
  seed = (214013 * seed + 2531011 
  if !keyhit goto Loop
 
 return (seed>>16)&0x7FFF

Edited 6 Years Ago by wildgoose: n/a

Sorry! is it pseudo code?
what are these? precision clock and !keyhit.

Review the Intel link. If accessing their chip its basically a white noise generator, which is a very good random. By constantly generating numbers until a key is pressed adds an additional variation of randomness to it.

The precision clock, access a P4 and use one of its newer instructions to get number of clock cycles since power up. Keyhit, access the BIOS, look at the keyboard flag and see if a key has been depressed or not!

rdtsc is one such instruction.

These aren't beginner things to do, so if you are a beginner, start simpler!

Edited 6 Years Ago by wildgoose: n/a

Hi,

If you are using EMU8086, I suppose you are about to learn assembly programming and generating a sequence of random numbers seems to be kind of exercise. EMU8086 does not have random number generator. Classical method for computing pseudo random numbers is the linear congruential random number generation method by Lehmer, where a new rnz is given by z(k+1) = (a*z(k) + b) mod m. For you are restricted to 16 bit registers ax, bx etc. I show you a 16 bit Lehmer generator: z = (31*z+13)%19683. Instead of 19683 you can also use 59049 (3*19683) what utilize 16bit (max. 65535) somewhat better.

Below 80x86 code is embbeded in Visual C++ program. You can simply copy this code into EMUs editor (and put some entry and exit code around it). You can then watch the dx register where 10 rnz will be computed within loop RN.

Deep down there is also my C function which I translated into 80x86 assembly. Between assembly and C functions there is a small difference: the return value of C function is furthermore mapped on interval [0..s-1]. This is somewhat more practial when using it. I omitted this not-that-important step in assembly code.

I am sure you will be able to extend the assembly code for storing the rnz appearing in register dx in an array. (If there are problems, simply ask)

int assembly86(){ 
__asm
{   ; Lehmer linear congruential random number generator
    ; z= (a*z+b) mod m = (31*z+13)%19683
    ; Rules for a, b, m by D. Knuth:
    ; 1. b and m must be relatively prime
    ; 2. a-1 must be divisible without remainder by all prime factors of m (19683 = 3^9), (31-1)%3=0
    ; 3. if m is divisible by 4, a-1 must also be divisible by 4, 19683%4 != 0, ok
    ; 4. if conditions 1 to 3 met, period of {z1, z2, z3,...} is m-1 = 19682 (Donald says)
	push ax		     ; save used registers
	push dx
	push bx
	push cx
	mov dx, 0xABBA	     ; 43962D is initial Value z for random sequence
	mov cx, 0x000A	     ; compute 0xA = 10D pseudo random numbers
RN:	mov ax, dx	     ; set new initial value z 
	mov bx, 0x001F	     ; 31D 
	mul bx		     ; 31 * z
			     ; result dx:ax, higher value in dx, lower value in ax
	add ax, 0x000D	     ; +13
	mov bx, 0x4CE3	     ; 19683D
	div bx		     ; div by 19683D
			     ; result ax:dx, quotient in ax, remainder in dx (this is the rnz)	
	;...		     ; processing random numbers here, first 10 RNZ (appearing in dx) are:
	                     ; 4708 8180 17397 7879 8066 13863 16423 17051 16836 10171
	loop RN		     ; repeat computing 10 times
	pop cx		     ; restore registers
	pop bx
	pop dx
	pop ax
}
return 0;
}
unsigned short lehmer_sh(unsigned short s)
//  linear congruential random number generator by D. Lehmer
//  x(k+1)=((a*x(k) + b) mod m) mod s
{ static unsigned short a=31, b=13, m=19683, z=43962; 
  z=(31*z+13)%19683;
  return z%s;}

I hope this code is some help for you.

-- tesu

Edited 6 Years Ago by tesuji: n/a

Thanks.I tried to get random number generating code from vs _by step debugging over "srand" function_ but it have used some registers from upper version than 8086 and it made me confused.
there is a problem at assemby86 function.it returns same sequence of random number every time.how we can improve it?

there is a problem at assemby86 function.it returns same sequence of random number every time.how we can improve it?

No thanks at all!

assemby86 or to be more specific the random generator inlined in assemby86 has been set up to produce the same sequence of pseudo random numbers every time one is calling it. Such behaviour is really necessary if one is doing serious physical experiments to be sure that the results be reproducible. Ok, that's not that a nice behaviour if using it for creating jokes and games.

If one likes to get various sequences of pseudo random numbers one must change the seed of the related generator. In my former c function changing the seed has been controlled by the range value s. If range value s is negative its absolute value is used as to be new seed. So if one wants to get new sequence of random numbers, first call generator function with negative range value to set new seed, then second, call generator function repeatedly to compute new sequence.

You seems to clever enough to extend this small assembler code getting variable seed. Meanwhile I did some statistical test on this new 16 bit generator and I am really surprised for its chi-square result is really good. The new triple (31, 13, 59049) defines a truly robust random generator, looks like to be the little daughter of Mersenne twister :)

Btw, what do you make of ABBA? I myself believe that Anni Frid has been by far the best singer ever, much more better than Agneta ;) How does it strike you?

Addendum: You are right, investigating the assembly code of progams using srand function within to-day VS can really be dizzying because of all the odd extended and odder extendedextended registers you have never seen on EMU8086 before. That was the vital reason why i did only use 8086 16 bit instructions. As for the interface of inline assembly with Visual C++ here one must make use of extended registers, e.g. ESI, EDI etc, for Visual C++ ony knows 32 bit instructions here. This is important to consider if you plan to store the inline generated pseudo random numbers into c++ array to using them within your c++ program.

-- tesu

Edited 6 Years Ago by tesuji: n/a

hi dears.
I am using Emu8086.
I need to generating an array of random numbers.
Are there any ready procedure or intrupt?
if there are not, how can I do it?
thanks.

This is simple formula for basic LCG random generator.

k = 30903 * (k & 65535)

k is seed number!
I implement basic random generator, you can see on web page
www.tahir007.com in examples section.

This article has been dead for over six months. Start a new discussion instead.