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. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies

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

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