How to seed to generate random numbers?

后端 未结 1 784
栀梦
栀梦 2020-11-28 16:44

It does not generate the intended randomness.

I thought starting with a seed like $66 and xoring the two last lower bit and ror would give me the next random number

相关标签:
1条回答
  • 2020-11-28 16:56

    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:

    randomness graph

    when I use it to fill NoSignal image window the result is this:

    NoSignal

    and here Gif animation:

    NoSignal 320x240x3

    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;
    
    0 讨论(0)
提交回复
热议问题