sbi - sreg assembly



Como semear para gerar números aleatórios? (1)

Não gera a aleatoriedade pretendida.

Eu pensei que começar com uma semente como $ 66 e xoring os dois últimos bits inferiores e ror me daria o próximo número aleatório e assim por diante, mas ele mostra apenas $ B3 e não muda.

Como devo me alimentar? A linha acima aleatória exibe o número no portc, pois quero que dois números sejam exibidos um após o outro.

Estou usando apenas o avr studio 4 para o atmega 8535 em 1Mhz.

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

Depois de alguma pesquisa nos meus antigos arquivos de código-fonte asm, encontrei isso para a plataforma x86 MSDOS NASM que eu estava usando nos dias de hoje:

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

A idéia é que algum número armazenado faça algumas operações básicas da ALU como +,*,/,<<,>>,&,^ mas garanta que não ocorra saturação e, normalmente, troque H,L de algum valor para manter a aleatoriedade em Verifica. Portanto, transfira isso para o seu asm, mas eu recomendo fortemente codificá-lo e experimentar o PC primeiro para verificar se a aleatoriedade está correta para sua tarefa.

BTW, você também pode usar a memória do programa ou qualquer conteúdo da ROM como base para a aleatoriedade ... isso também está explorando o bloco RTC interno, então você deve omitir essa parte ou adicionar um temporizador ou apenas percorrer um monte de dados não vazios.

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

Encontrei uma demo minha ainda mais antiga, chamada NoSignal (de 1997 no TASM), que tem rnd por dentro:

    .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

Ele preenche a tela e o alto-falante com ruído branco, como se não houvesse cabo de antena na TV analógica. Esta versão tem 44 bytes de comprimento, o gerador pseudo-aleatório inicia no rótulo l0:

  • ax é o número gerado (e também o número gerado anterior como você temp)
  • di está aumentando (algo como o tempo real) ...
  • cl está diminuindo

então, se eu olhar direito, deve ser o suficiente:

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

e adicione push/pop armazenar os registros / valores, se necessário. Se você precisar de algo mais sofisticado, use a aritmética modulo prime.

[edit1] gerador pseudo-aleatório simples de 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;
    }

Os geradores aleatórios acima foram restringidos ao horário do ambiente DOS ou uso especial. Este não é ... a aleatoriedade é assim:

quando eu o uso para preencher a janela da imagem NoSignal, o resultado é o seguinte:

e aqui animação GIF :

O código de preenchimento NoSignal é o seguinte:

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

Portanto, apenas 8bit 16bit altos do número pseudo-aleatório de 16bit são usados, a multiplicação apenas converte esse número de 8bit em cores em escala de cinza.

  • xs,ys é o tamanho da imagem
  • pyx é o ponteiro direto da imagem para suas linhas

Não altere os números de sementes sem testar adequadamente com isso no PC

Sementes selecionadas incorretamente não levam a nenhuma aleatoriedade. Se você deseja propagar com segurança (sem teste), propague as constantes fornecidas e chame rnd() quantas vezes for o seu novo número de propagação. Rebentou isso agora, então pode haver sementes melhores para isso, estas são apenas as primeiras que achei que dão resultados razoavelmente bons

Essas sementes também são boas:

    WORD rnd_d0=0x37A6;
    WORD rnd_d1=0x377A;
    WORD rnd_d2=0x3BC3;




avr