generating_20pseudo-random_20numbers

*by Richard Russell, August 2006*

BBC BASIC supplies pseudo-random numbers in three formats:

**RND**supplies a pseudo-random 32-bit integer**RND(N)**supplies a pseudo-random positive integer in the range 1 to N**RND(1)**supplies a pseudo-random floating-point number in the range 0.0 to 1.0

This article contains routines to provide similar facilities for your assembly-language programs. They are short and very fast, yet the pseudo-random numbers they supply are of an equivalent quality to those supplied by RND.

The subroutine below provides a direct equivalent to RND. Each time it is called it returns a pseudo-random 32-bit integer in the eax register:

.seed dd 0 db 1 ; ; Rnd - return a pseudo-random 32-bit integer ; Inputs - None ; Outputs - eax = result ; Destroys - eax, cl, edx, flags ; .Rnd mov eax,[seed] mov cl,[seed+4] mov edx,eax shr cl,1 rcr edx,1 rcl cl,1 shl eax,12 xor edx,eax mov eax,edx shr eax,20 xor eax,edx mov [seed+4],cl mov [seed],eax ret

This subroutine will generate the same sequence of numbers every time it is used. You are likely to want to *randomise* the sequence in order to make the results less predictable. You can simply do that using the following code, which uses the time as a seed:

.Randomise call "GetTickCount" mov [seed],eax ret

You can test the code from BASIC as follows:

CALL Randomise FOR I% = 1 TO 20 PRINT ~ USR(Rnd) NEXT

The subroutine below provides a direct equivalent to RND(N), where N is a positive integer greater than 1. Each time it is called it returns a pseudo-random integer in the range 1 to N, in the eax register:

; ; RndRange - return a pseudo-random integer in the range 1 to N ; Inputs - ebx = N ; Outputs - eax = result ; Destroys - eax, cl, edx, flags ; .RndRange call Rnd xor edx,edx div ebx mov eax,edx inc eax ret

The parameter N is passed to the subroutine in the ebx register. If you prefer to return a number in the range 0 to N-1 just delete the **inc eax** instruction.

You can test the code from BASIC as follows:

CALL Randomise FOR I% = 1 TO 20 B% = 100 PRINT USR(RndRange) NEXT

The subroutine below provides a direct equivalent to RND(1). Each time it is called it returns a pseudo-random 64-bit floating-point value (double) in the range 0.0 to 1.0:

; ; RndFloat - return a pseudo-random float in the range 0.0 to 1.0 ; Inputs - ebx = memory address of 64-bit float (double) ; Outputs - result stored at [ebx] ; Destroys - eax, ecx, edx, flags ; .RndFloat call Rnd bsr ecx,eax ror eax,cl add ecx,991 shld ecx,eax,20 shl eax,20 mov [ebx],eax mov [ebx+4],ecx ret

The value is returned in memory at the address passed in the ebx register.

You can test the code from BASIC as follows:

CALL Randomise FOR I% = 1 TO 20 B% = ^R# CALL RndFloat PRINT R# NEXT

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

generating_20pseudo-random_20numbers.txt · Last modified: 2018/04/13 10:43 by richardrussell

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