AVR code不工作我要生成随机数的帮助,请 [英] avr code not working i want to generate random numbers help please

查看:448
本文介绍了AVR code不工作我要生成随机数的帮助,请的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 > ;计划在C端口随机数
>
> ;堆栈和堆栈指针地址.EQU SPH = $ 3E
> ;高字节堆栈指针地址.EQU SPL = $ 3D
> ;低字节堆栈指针的地址
>
> .EQU RAMEND = $ 25F;堆栈地址
>
> ;端口地址
>
> .EQU PORTC = $ 15; C口输出地址
>
> .EQU DDRC = $ 14;端口C数据方向寄存器
>地址
>
> .EQU numberoneddr = DDRC
>
> .EQU numberoneport = PORTC
>
> .EQU numbertwoddr = DDRC
>
> .EQU numbertwoport = PORTC
>
> .EQU delayCount = 21
>
> .EQU random1 = $ 66
>
> ;寄存器定义
>
> .DEF了Numberone = R1;注册存储指出数据
>到由Z
>
> .DEF numbertwo = R2
>
> .DEF TEMP = R16;暂存寄存器
>
>
>
>重启:
>
> ;初始化堆栈指针。在许多AVR单片机复位自动完成
>
> LDI温度低(RAMEND)
>
>出SPL,温度
>
> LDI温度高(RAMEND)
>
>出SPH,温度
>
>
>
>
> ;端口的初始化
>
> LDI温度,$ FF
>
>出numberoneddr,温度
>
>出numberoneport,温度
>
>出numbertwoddr,温度
>
>出numbertwoport,温度
>
>
>
> ;程序初始化
>
> LDI温度,$ 66
>
> RCALL随机
>
> MOV了Numberone,温度
>
>出numberoneport,了Numberone
>
> RCALL随机
>
> MOV numbertwo,温度
>
>出numberoneport,numbertwo
>
>
>
>
>随机:MOV R19,温度
>
> LDI R17,为0x01
>
> EOR R19,R17
>
> ROR R19
>
> MOV温度,R19
>
> RET
>
>
>
>延迟:
> CLR R20
>
> CLR R21
>
> LDI R22,delayCount
>
> LOOPDELAY:
>
>十二月R20
>
> brne LOOPDELAY
>
>十二月R21
>
> brne LOOPDELAY
>
>十二月R22
>
> brne LOOPDELAY
>
> RET


解决方案

在一些通过我的古ASM源$ C ​​$ C档案搜索,我发现这对我使用在天回86 MSDOS NASM平台:

  ;. RND; AL = NUM​​ RND℃,啊取代;.rnd:PUSHA
    MOV CX,AX.rnd0:MOV BX,[CS:.rnddat]    MOV AX,[CS:.rndtim]
    异人,BH
    添加啊,BH
    RCR斧,3
    异或AL,BL
    RCL斧,2.rnd2:CMP人,CH
    JBE .rnde
    子人,CH
    或CH,CH
    JNZ .rnd2
    子人,人.rnde:MOV啊,BL
    MOV [CS:.rnddat],斧
    或人,1    XOR AX,[FS:046Ch]
    添加[CS:.rndtim],斧
    波帕
    MOV等,[CS:.rnddat]
    RET
.rnddat:DB 0,0
.rndtim:DW 0

我们的想法是有一些存储的号码做一些基本的 ALU +,*,/,&LT操作;<,>>,&安培;,^ ,但确保不发生饱和,通常掉一些价值 H,L 来保持随机性检查。所以这个端口到您的 ASM 但我强烈建议code,并尝试在电脑上先看看随机性是你的任务确定。

顺便说一句,你也可以使用程序存储器或ROM的内容为基础的随机性......这也是利用内部的 RTC 块,所以你必须省略部分或添加一个计时器或只是通过串非空数据的循环来代替。

  [0000:046C]是4字节的主时钟计数(长整型)0 =午夜递增,直到24小时当量。

我发现我的叫NOSIGNAL(从1997年TASM)的更老的演示已内RND:

  .386P
    理想
    MODEL TINY    codeSEG
    STARTUP code
主:MOV AX,19; 320 * 200 * 256
    诠释16
    推0A000h;视频片段
    流行ES;键盘测试,扬声器延迟v SI = 25610:ROR斧,CL; RND ...斧
    添加斧头,二
    STOSW;情节......
    环R1;扬声器延迟...
    MOV CX,SI
    出61H,人
R1:或二,二
    JNZ 10
    推斧
    MOV啊,1,测试键盘
    INT 16H
    流行斧
    JZ 10恩德:分斧头,斧头;关闭扬声器和退出
    出61H,人
    INT 16H
    MOV AX,3
    诠释16
    RET
    结束

它填满屏幕和扬声器,以及白噪声仿佛在模拟电视没有天线电缆。此版本是44字节长,伪随机数发生器开始于标签 10


  • 是生成的编号(也产生了prevvious像一些你TEMP)

  • 是递增的(像实际时间)...

  • CL 是递减

所以,如果我看它的权利应该是足够了:

  RND:ROR斧,CL; RND ...斧
        添加斧头,二
        INC迪
        十二月CL
        RET

和增加 PUSH / POP 如果需要存储寄存器/值。如果你需要一些更复杂然后用模主要运算。

简单的C ++伪随机数发生器

  WORD rnd_d0 = 0x66; //这些种子数。如果不选择权则随机性不好
WORD rnd_d1 = 5AH即可; //这些给予了较好的成绩
WORD rnd_d2 = 0xC3;
WORD RND()
    {
    rnd_d0 ^ = rnd_d1 | rnd_d2; // XOR
    rnd_d1 * = rnd_d2; // MUL
    rnd_d2 + = rnd_d1; //添加
    rnd_d0 =(rnd_d0&所述;&下; 8)|(rnd_d0>→8); // 8位半交换
    返回rnd_d0;
    }

以上随机生成被到地张紧的 DOS 环境时间或特殊用途。这个人是不是......随机性是这样的:

当我用它来填充NOSIGNAL图像窗口的结果是这样的:

和这里的的Gif 动画:

该NOSIGNAL填补code是因为这样:

 的for(int y = 0; Y< YS; Y ++)
  为(中间体X = 0; X&下; XS; X ++)
   PYX [Y] [X] = 0x00010101 * INT(RND()>→8);

所以才高 8位 16位伪用乘法随机数只是把它转换 8位数灰阶色。


  • XS,YS 是图像尺寸

  • PYX 是直接图像指向其行

不要在没有适当的测试与此PC上改变种子数

错误地选择种子,不会产生任何随机的。如果你想安全的种子(没有测试),然后用提供的常量种子,然后调用 RND()尽可能多的时间和你的新种子数是。现在打掉这一权利所以有可能是为了这个美好的种子,这些都只是我发现的第一批,让相当不错的成绩。

这些种子都还不错:

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

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

解决方案

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;

这篇关于AVR code不工作我要生成随机数的帮助,请的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆