assembly - ¿Cómo sembrar para generar números aleatorios?
avr (1)
No genera la aleatoriedad prevista.
Pensé que comenzar con una semilla como $ 66 y xorrar los dos últimos bits más bajos y ror me daría el siguiente número aleatorio y así sucesivamente, pero solo muestra $ B3 y no cambia en absoluto.
¿Cómo se supone que debo alimentarme? La línea superior al azar muestra el número en el portc ya que quiero que se muestren dos números uno después del otro.
Solo estoy usando avr studio 4 para atmega 8535 a 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
Después de buscar a través de los antiguos archivos de código fuente asm míos, encontré esto para la plataforma x86 MSDOS NASM que estaba usando en aquellos días:
;.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
La idea es hacer que un número almacenado realice algunas operaciones básicas de
ALU
como
+,*,/,<<,>>,&,^
pero asegúrese de que no se produzca saturación y, por lo general, cambie
H,L
de algún valor para mantener la aleatoriedad en cheque.
Por lo tanto, transfiera esto a su
asm,
pero le recomiendo codificarlo y probar primero en la PC para ver si la aleatoriedad está bien para su tarea.
Por cierto, también puede usar la memoria del programa o cualquier contenido de ROM como base para la aleatoriedad ... esto también está explotando el bloque RTC interno, por lo que debe omitir esa parte o agregar un temporizador o simplemente recorrer un montón de datos no vacíos.
[0000:046C] are 4 Bytes master clock count (long integer) 0 = midnight and increments until a 24 hour equiv.
Encontré una demo mía aún más antigua llamada NoSignal (desde 1997 en TASM) que tiene rnd adentro:
.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
Llena la pantalla y el altavoz con ruido blanco como si no hubiera un cable de antena en la televisión analógica.
Esta versión tiene 44 bytes de longitud, el generador pseudoaleatorio comienza en la etiqueta
l0:
-
ax
es el número generado (y también el número generado anterior como tu temp) -
di
está incrementando (algo así como el tiempo real) ... -
cl
está decrementando
así que si lo miro bien debería ser suficiente:
rnd:ror ax,cl ;rnd...ax
add ax,di
inc di
dec cl
ret
y agregue
push/pop
almacenar los registros / valores si es necesario.
Si necesita algo más sofisticado, utilice la aritmética modulo prime.
[edit1] generador pseudoaleatorio simple 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;
}
Los generadores aleatorios anteriores se ajustaron al tiempo de entorno de DOS o al uso especial. Este no es ... la aleatoriedad es así:
cuando lo uso para llenar la ventana de imagen NoSignal, el resultado es este:
y aquí animación GIF :
El código de relleno de NoSignal es el siguiente:
for (int y=0;y<ys;y++)
for (int x=0;x<xs;x++)
pyx[y][x]=0x00010101*int(rnd()>>8);
Entonces, solo se usa un valor alto de 8
16bit
número pseudoaleatorio de
16bit
la multiplicación simplemente convierte este número de 8
8bit
en color de escala de grises.
-
xs,ys
es el tamaño de la imagen -
pyx
es el puntero de imagen directo a sus líneas
No cambie los números de semilla sin una prueba adecuada con esto en PC
Las semillas mal seleccionadas no conducen a ninguna aleatoriedad.
Si desea sembrar de forma segura (sin probar), siembre con las constantes proporcionadas y luego llame a
rnd()
tantas veces como sea el nuevo número de semilla suyo.
Rompió esto ahora, por lo que puede haber mejores semillas para esto, estos son solo los primeros que encontré que dan resultados bastante buenos
Estas semillas también son buenas:
WORD rnd_d0=0x37A6;
WORD rnd_d1=0x377A;
WORD rnd_d2=0x3BC3;