How to seed to generate random numbers?
Solution 1:
After some searching through ancient asm source code archives of mine I found this for x86 MSDOS NASM platform I was using back in the days:
;.rnd ;al=rnd num <0,ah>;
.rnd: pusha
mov cx,ax
.rnd0: mov bx,[cs:.rnddat]
mov ax,[cs:.rndtim]
xor al,bh
add ah,bh
rcr ax,3
xor al,bl
rcl ax,2
.rnd2: cmp al,ch
jbe .rnde
sub al,ch
or ch,ch
jnz .rnd2
sub al,al
.rnde: mov ah,bl
mov [cs:.rnddat],ax
or al,1
xor ax,[fs:046Ch]
add [cs:.rndtim],ax
popa
mov al,[cs:.rnddat]
ret
.rnddat:db 0,0
.rndtim:dw 0
The idea is to have some stored number do some basic ALU operations like +,*,/,<<,>>,&,^
but ensure that no saturation occurs and usually swap of H,L
of some value to keep the randomness in check. So port this to your asm but I strongly recommend to code it and try on PC first to see if the randomness is OK for your task.
BTW you can use also the program memory or any ROM content as base for randomness ... this is also exploiting the internal RTC block so you have to omit that part or add a timer or just loop through bunch of non empty data instead.
[0000:046C] are 4 Bytes master clock count (long integer) 0 = midnight and increments until a 24 hour equiv.
I found even older demo of mine called NoSignal (from 1997 in TASM) which have rnd inside:
.386P
IDEAL
MODEL TINY
CODESEG
STARTUPCODE
main: mov ax,19 ;320*200*256
int 16
push 0A000h ;Video segment
pop es ;keyboard test,speaker delay v si=256
l0: ror ax,cl ;rnd...ax
add ax,di
stosw ;plot...
loop r1 ;speaker delay...
mov cx,si
out 61h,al
r1: or di,di
jnz l0
push ax
mov ah,1 ;test keyboard
int 16h
pop ax
jz l0
ende: sub ax,ax ;turn off speaker and exit
out 61h,al
int 16h
mov ax,3
int 16
ret
END
It fill screen and speaker with white noise as if no antenna cable in analog TV. This version is 44 Bytes long, pseudo random generator starts at label l0:
-
ax
is the generated number (and also the prevvious generated number like you temp) -
di
is incrementing (something like actual time)... -
cl
is decrementing
so if I look at it right it should be enough:
rnd:ror ax,cl ;rnd...ax
add ax,di
inc di
dec cl
ret
and add push/pop
store the registers/values if needed. If you need something more sophisticated then use modulo prime arithmetics.
[edit1] simple C++ pseudo random generator
WORD rnd_d0=0x66; // these are seed numbers if not selected right then the randomness is not good
WORD rnd_d1=0x5A; // these give fairly good results
WORD rnd_d2=0xC3;
WORD rnd()
{
rnd_d0^=rnd_d1|rnd_d2; // xor
rnd_d1*=rnd_d2; // mul
rnd_d2+=rnd_d1; // add
rnd_d0=(rnd_d0<<8)|(rnd_d0>>8); // 8bit halves swap
return rnd_d0;
}
The above random generators was tighted to DOS environment time or special usage. This one is not ... the randomness is like this:
when I use it to fill NoSignal image window the result is this:
and here Gif animation:
The NoSignal fill code is as this:
for (int y=0;y<ys;y++)
for (int x=0;x<xs;x++)
pyx[y][x]=0x00010101*int(rnd()>>8);
So just high 8bit
from the 16bit
pseudo random number is used the multiplication just converts this 8bit
number to gray-scale color.
-
xs,ys
is image size -
pyx
is the direct image pointer to its lines
Do not change the seed numbers without proper testing with this on PC
Wrongly selected seeds leads to no randomness at all. If you want to safely seed (without testing) then seed with provided constants and then call rnd()
as much times as the new seed number of yours is. Busted this right now so there may be better seeds for this, these are just the first ones I found that gives fairly good results
These seeds are also good:
WORD rnd_d0=0x37A6;
WORD rnd_d1=0x377A;
WORD rnd_d2=0x3BC3;