alternative_20pseudo-random_20numbers

**This is an old revision of the document!**

*by Jon Ripley, August 2006*

*BBC BASIC for Windows* provides a pseudo-random number generator for use in BASIC programs but has no built-in support for generating pseudo-random numbers from assembly language programs. This article contains code to add support for generating pseudo-random numbers from assembly language that can be added to any program.

The following routine generates a 32-bit pseudo-random number when called, the pseudo-random number is returned in the **eax** register:

.seed dd 1 :dd 0

.Rand mov eax, &4C957F2D ; | mul dword [seed] ; | push edx ; | mov edx, [seed] ; | imul ebx, edx, &5851F42D ; |\ pop edx ; | - seed = seed * &5851F42D4C957F2D add edx, ebx ; |/ mov ebx, [seed+4] ; | imul ebx, ebx, &4C957F2D ; | add edx, ebx ; | add eax, 1 ; seed = seed + 1 adc edx, 0 mov [seed], eax ; store the new seed mov [seed+4], edx shrd eax, edx, 21 ; shift right 21 bits ret ; return

The following routine generates a pseudo-random number in the range 1 to N:

.RandRange call Rand ; get random number mov ebx, [esp+4] ; read range limit xor edx,edx ; clear edx register div ebx ; do integer division; eax / ebx mov eax,edx ; read remainder of division inc eax ; add one ret 4 ; restore stack and return

Call RandRange using code similar to the following:

push N% call RandRange

The pseudo-random number is returned in **eax**. Here **N%** can be a register **eax**, read from a pointer to a 4 byte block in memory **[addr]**, a BASIC constant **N%** defined at assemble time, a BASIC variable **[^N%]** or a numeric constant **1234**. If the assembler reports a “Size needed” error add the **dword** prefix to the pushed parameter.

To change the range of numbers returned to 0 to N remove the 'inc eax' instruction.

The following routine generates a pseudo-random number in the range 0.0 to 1.0, exclusive of 1.0:

.RandFloat call Rand ; get random number and eax, &7FFFFFFF ; clear top bit push eax ; push random number on stack call Rand ; get random number push eax ; push random number on stack push &80000000 ; \ Put &8000000000000000 push 0 ; / on the stack fild qword [esp] ; load &8000000000000000 fild qword [esp+8] ; load random number fdivrp st1,st0 ; divide random number by &8000000000000000 fabs ; convert result to absolute value mov eax,[esp+20] ; read location to store result fstp qword [eax] ; store result add esp,16 ; free local variables ret 4 ; restore stack and return

To call this routine use code similar to the following:

push ^N# call RandFloat

The result is stored in the memory pointed to by the parameter. Here **^N#** is a pointer to a 64-bit floating point BASIC variable but can be a pointer to an 8 byte block of memory **[addr]**. If the assembler reports a “Size needed” error add the **dword** prefix to the pushed parameter.

The following routine is called to seed the pseudo-random number generator with a 64-bit seed:

.RandSeed mov eax, [esp+4] ; load new seed mov edx, [esp+8] mov dword [seed], eax ; store new seed mov dword [seed+4], edx ret 8 ; restore stack and return

To seed the random number generator use the following code:

push hN push lN call RandSeed

Here we pass a 64-bit integer value to seed the pseudo-random number, **hN** is the top 32-bits of the seed and **lN** is the bottom 32-bits of the seed. By default the seed is set to the value of TIME when the code was assembled. If the assembler reports a “Size needed” error add the **dword** prefix to the pushed parameter.

These routines may be called from BASIC, instead of using the **RND** function, if you *really* want to:

result% = USR Rand :REM Return a pseudo-random number in result% SYS RandFloat, ^N# :REM Return a pseudo-random float in N# SYS RandRange, N TO result% :REM Return a range limited pseudo-random number in result% SYS RandSeed, TIME, TIME :REM Seed the pseudo-random generator using TIME

The multiplier 6364136223846793005 was obtained from Knuth, D.E., "The Art of Computer Programming," Vol 2, Seminumerical Algorithms, Third edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information

alternative_20pseudo-random_20numbers.1522502345.txt.gz · Last modified: 2018/03/31 13:19 by 127.0.0.1

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International