Как затравить для генерации случайных чисел?

Он не генерирует предполагаемую случайность.

Я подумал, что если начать с начального числа, например, $66, и запоминание двух последних младших битов и ror даст мне следующее случайное число и так далее, но оно показывает только $B3 и не меняется вообще.

Как я должен кормить? Строка над случайным отображает число на portc, так как я хочу, чтобы два числа отображались друг за другом.

Я использую только AVR Studio 4 для Atmega 8535 на 1 МГц.

> ;Program to random numbers  on port C
> 
> ;Stack and Stack Pointer Addresses  .equ     SPH    =$3E             
> ;High Byte Stack Pointer Address   .equ     SPL    =$3D             
> ;Low Byte Stack Pointer Address 
> 
> .equ     RAMEND =$25F             ;Stack Address 
> 
> ;Port Addresses 
> 
> .equ     PORTC  =$15              ;Port C Output Address 
> 
> .equ     DDRC   =$14              ;Port C Data Direction Register
> Address 
> 
> .equ     numberoneddr=DDRC
> 
> .equ     numberoneport=portc
> 
> .equ     numbertwoddr=DDRC
> 
> .equ     numbertwoport=portc
> 
> .equ     delayCount=21
> 
> .equ    random1 =$66
> 
> ;Register Definitions 
> 
> .def    numberone   =r1               ;Register to store data pointed
> to by Z 
> 
> .def    numbertwo   =r2
> 
> .def     temp   =r16              ;Temporary storage register 
> 
> 
> 
> reset:
> 
> ; initialize stack pointer. Done automatically at reset on many AVRs
> 
>   ldi temp, low  (RAMEND)
> 
>   out spl, temp
> 
>   ldi temp, high (RAMEND)
> 
>   out sph, temp
> 
> 
> 
> 
> ;port initialisation
> 
> ldi temp,$FF
> 
> out numberoneddr,temp
> 
> out numberoneport,temp
> 
> out numbertwoddr,temp
> 
> out numbertwoport,temp
> 
> 
> 
> ;Program Initialisation 
> 
> ldi temp,$66
> 
> rcall random
> 
> mov   numberone, temp
> 
> out numberoneport,numberone
> 
> rcall random
> 
> mov   numbertwo, temp
> 
> out numberoneport,numbertwo
> 
> 
> 
> 
> random: mov r19,temp
> 
> ldi r17, 0x01
> 
> eor r19,r17
> 
> ror r19
> 
> mov temp,r19
> 
> ret
> 
> 
> 
> delay:
>         clr r20
> 
>       clr r21
> 
>       ldi r22, delayCount
> 
> loopDelay:
> 
>       dec r20
> 
>       brne loopDelay
> 
>       dec r21
> 
>       brne loopDelay
> 
>       dec r22
> 
>       brne loopDelay
> 
>         ret

1 ответ

После некоторого поиска в моих древних архивах исходного кода asm, я нашел это для платформы x86 MSDOS NASM, которую использовал в те дни:

;.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

Идея состоит в том, чтобы некоторый сохраненный номер выполнял некоторые базовые операции ALU, такие как +,*,/,<<,>>,&,^ но убедитесь, что насыщение не происходит и обычно происходит обмен H,L некоторой ценности, чтобы держать случайность в узде. Так что перенесите это на ваш ассемблер, но я настоятельно рекомендую закодировать его и сначала попробовать на ПК, чтобы убедиться, что случайность подходит для вашей задачи.

Кстати, вы также можете использовать программную память или любое содержимое ПЗУ в качестве основы для случайности... это также использует внутренний блок RTC, поэтому вы должны пропустить эту часть или добавить таймер или просто перебрать кучу непустых данных.

[0000:046C] are 4 Bytes master clock count (long integer) 0 = midnight and increments until a 24 hour equiv.

Я нашел еще более старую демоверсию под названием NoSignal (с 1997 года в TASM), в которой есть rnd:

    .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

Он наполняет экран и динамик белым шумом, как будто в аналоговом телевизоре отсутствует антенный кабель. Эта версия длиной 44 байта, псевдослучайный генератор начинается с метки l0:

  • ax является сгенерированным числом (а также предыдущим сгенерированным числом, таким как вы, темп)
  • di увеличивается (что-то вроде реального времени)...
  • cl уменьшается

так что, если я смотрю на это правильно, этого должно быть достаточно:

    rnd:ror ax,cl       ;rnd...ax
        add ax,di
        inc di
        dec cl
        ret

и добавить push/pop сохранить регистры / значения, если это необходимо. Если вам нужно что-то более сложное, используйте простую арифметику по модулю.

[edit1] простой генератор C++ псевдослучайных данных

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;
    }

Вышеуказанные случайные генераторы были настроены на время среды DOS или специальное использование. Это не... случайность такая:

график случайности

когда я использую его для заполнения окна изображения NoSignal, результат будет следующим:

Нет сигнала

а тут Gif анимация:

NoSignal 320x240x3

Код заполнения NoSignal выглядит так:

 for (int y=0;y<ys;y++)
  for (int x=0;x<xs;x++)
   pyx[y][x]=0x00010101*int(rnd()>>8);

Так просто высоко 8bit от 16bit псевдослучайное число используется умножение просто преобразует это 8bit число до серого цвета.

  • xs,ys это размер изображения
  • pyx прямой указатель изображения на его линии

Не меняйте начальные числа без надлежащего тестирования на ПК

Неправильно подобранные семена не приводят к случайности. Если вы хотите безопасно посеять (без тестирования), то посеять с предоставленными константами, а затем вызвать rnd() столько раз, сколько у вас новое число семян. Разрушил это прямо сейчас, так что могут быть лучшие семена для этого, это только первые, которые я нашел, которые дают довольно хорошие результаты

Эти семена тоже хороши:

    WORD rnd_d0=0x37A6;
    WORD rnd_d1=0x377A;
    WORD rnd_d2=0x3BC3;
Другие вопросы по тегам