博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

Jamie.Y的个人空间

  跋锋寒吁出压在心头的一口闷气,像跌进深如渊海的回忆里般,双目神光闪闪的道:“自懂人事以来,我便感到生命是不断的重复,每天都大致上干着同一样的事,只有不断的改变环境,不断地应付新的挑战,或把自己不断陷进不同的境况内,才可感受到生命新鲜动人的一面。”接着摊开双手道:“像现在般就没有半丝重复或沉闷的感觉,摆在眼前正是个茫不可测的未来,似乎在你掌握中,又若全不受你控制……” ——《大唐双龙传》
在单片机中使用汇编语言获得伪随机数
    在单片机中使用汇编语言获得伪随机数,暨伪随机数发生器

关于单片机产生随机数,汇编

有一个产品需要用到随机数发生器
8位单片机

初步构想:
1、系统开机时取一个随机数作为种子;
2、产生伪随机数。

在网上找了一些程序
21IC的帖子也搜了一遍
周航慈那本《单片机程序设计基础》的书也在手头

开动吧!


  

1、keil中的rand函数反编译结果:

/*  TEST.c                            */
#include

void main(void)
{
    char i, j, k;
    i = 0x5f;
    j = rand();
    k = 0xf5;
}


反编译结果,随机数放在R7中
;==========================================================================
Q0003:             MOV   R4,08H                       ;0003   AC 08
                   MOV   R5,09H                       ;0005   AD 09
                   MOV   R6,0AH                       ;0007   AE 0A
                   MOV   R7,0BH                       ;0009   AF 0B
                   MOV   R0,#0FH                      ;000B   78 0F
Q000D:             MOV   A,R7                         ;000D   EF
                   MOV   C,ACC.2                      ;000E   A2 E2
                   MOV   A,R4                         ;0010   EC
                   JB    ACC.6,Q0015                  ;0011   20 E6 01
                   CPL   C                            ;0014   B3
Q0015:             ANL   A,R5                         ;0015   5D
                   ANL   A,R6                         ;0016   5E
                   ANL   A,R7                         ;0017   5F
                   CPL   A                            ;0018   F4
                   JNZ   Q001F                        ;0019   70 04
                   MOV   R4,A                         ;001B   FC
                   MOV   R5,A                         ;001C   FD
                   MOV   R6,A                         ;001D   FE
                   MOV   R7,A                         ;001E   FF
Q001F:             MOV   A,R7                         ;001F   EF
                   RRC   A                            ;0020   13
                   MOV   R7,A                         ;0021   FF
                   MOV   A,R6                         ;0022   EE
                   RRC   A                            ;0023   13
                   MOV   R6,A                         ;0024   FE
                   MOV   A,R5                         ;0025   ED
                   RRC   A                            ;0026   13
                   MOV   R5,A                         ;0027   FD
                   MOV   A,R4                         ;0028   EC
                   RRC   A                            ;0029   13
                   MOV   R4,A                         ;002A   FC
                   DJNZ  R0,Q000D                     ;002B   D8 E0
                   MOV   08H,R4                       ;002D   8C 08
                   MOV   09H,R5                       ;002F   8D 09
                   MOV   0AH,R6                       ;0031   8E 0A
                   MOV   0BH,R7                       ;0033   8F 0B
                   MOV   A,R6                         ;0035   EE
                   ANL   A,#7FH                       ;0036   54 7F
                   MOV   R6,A                         ;0038   FE
                   RET                                ;0039   22
;==========================================================================


这个没有认真看


 

2、一个简单的随机数发生函数:

rand8reg是得到的随机数,为了更随机,可以把它与定时器相加
如果可以把rand8reg保存在非易失性存储器中更好,但是什么时候保存需要认真考虑

;==============================================================
;  Name: rand8
;  Description: get a 8bit random number
;  Function: This routine sends calc a 8bit random number
;  Attention: get a random "rand8reg" before initialize the program
;  Calls: None
;  Input: rand8reg
;  Outputs: rand8reg
;  Register Usage: A, psw
;--------------------------------------------------------------
rand8:
    mov    a, rand8reg
    jnz    rand8b
    cpl    a
    mov    rand8reg, a
  rand8b:
    anl    a, #10111000b
    mov    c, p
    mov    a, rand8reg
    rlc    a
    mov    rand8reg, a
    ret

;==============================================================

3、这个可能复杂一些:

其实和周航慈《单片机程序设计基础》上的例子是一样的,使用线性移位寄存器构成随机数发生器

;**********************************************************;
;*      Random                                            *;
;*Random_Buf 6个字节看成48个位,可以表示280亿个数值,原理:用反*;
;*馈函数F()把这280亿个无顺序的放在一个可以旋转数码盘上,程序  *;
;*有定时器在跑,当随机发生时,让转盘转计数器的值圈数即可得到一个*;
;*随机数.                                                 *;
;*奇校验反馈函数d0=d48+d7+d5+d4+d2+d1+1,6Byte有280亿种状态 *;
;**********************************************************;
Random:
        PUSH    ACC
        MOV     RandomREG,Count
Data_Rotate:
        MOV     A,Random_Buf+5          ;取D41-D48的当前状态
        RLC     A                       ;将D48提取到标志中去
        MOV     A,Random_Buf            ;取D1-D8的当前状态
        ANL     A,#5BH                  ;提取D7,D5,D4,D2,D1的当前值
        MOV     ACC.7,C                 ;再加上D48的当前值
        MOV     C,PSW.0                 ;取得偶校验的结果
        CPL     C                       ;转换成奇校验,且得到反馈函数的值
        MOV     A,Random_Buf            ;开始移位操作,先处理低字节
        RLC     A                       ;将反馈函数的值移入,最高位移出
        MOV     Random_Buf,A            ;保存移位后的结果
        MOV     A,Random_Buf+1          ;再依次进行其他字节的移位操作
        RLC     A
        MOV     Random_Buf+1,A
        MOV     A,Random_Buf+2
        RLC     A
        MOV     Random_Buf+2,A
        MOV     A,Random_Buf+3
        RLC     A
        MOV     Random_Buf+3,A
        MOV     A,Random_Buf+4
        RLC     A
        MOV     Random_Buf+4,A
        MOV     A,Random_Buf+5
        RLC     A
        MOV     Random_Buf+5,A          ;完成巨型数字转盘转动一格
        DJNZ    RandomREG,Data_Rotate   ;取当前时间随机时间转动n格
Random_Exit:
        POP     ACC
        RET

4、我最终使用的程序

使用一个简单的随机数发生器产生种子
运行中用TL0作为干扰


;  test.asm
;  test
;--------------------------------------------------------------


;==============================================================
; 创建及修改记录
; -------------------------------------------------------------
; 创建人:   
; 创建时间:   
; 文件名:   
; 程序功能:   
; 初始版本:   
; -------------------------------------------------------------
; 修改日期:   
; 修改原因:   
; 修改人:   
; 版本更改:   
; -------------------------------------------------------------
; 修改日期:   
; 修改原因:   
; 修改人:   
; 版本更改:   
;==============================================================


;==============================================================
; Define
;--------------------------------------------------------------
STACK_TOP        EQU    0D0H        ; STACK : 48Bytes


Random_Buf        EQU    70H        ; VARIABLE     BUFFER (70H~75H)
RND0            EQU    70H        ; VARIABLE    第1字节
RND1            EQU    71H        ; VARIABLE    第2字节
RND2            EQU    72H        ; VARIABLE    第3字节
RND3            EQU    73H        ; VARIABLE    第4字节
RND4            EQU    74H        ; VARIABLE    第5字节
RND5            EQU    75H        ; VARIABLE    第6字节
RandCount        EQU    76H        ; VAIRABLE    跳动格数
rand8reg        EQU    77H        ; VAIRABLE    简单随机数,用来产生种子和跳动格数


;==============================================================
; MAIN PROGRAM : 程序入口
;==============================================================
ORG 0000H        ;    ; main program
    LJMP    main    ;
ORG 0003H        ;    ; Int0 Interrupt
    RETI        ;
ORG 000BH        ;    ; T0 Interrupt
    RETI        ;
ORG 0013H        ;    ; Int1 Interrupt
    RETI        ;
ORG 001BH        ;    ; T1 Interrupt
    RETI        ;
ORG 0023H        ;    ; Si1 Interrupt
    RETI        ;
ORG 002BH        ;    ; T2 Interrupt
    RETI        ;
ORG 0033H        ;    ;
    RETI        ;
ORG 003BH        ;    ; Si2 Interrupt
    RETI        ;
ORG 0043H        ;    ; Int2 Interrupt
    RETI         ;
ORG 004BH        ;    ; Int3 Interrupt
    RETI        ;
ORG 0053H        ;    ; Int4 Interrupt
    RETI         ;
ORG 005BH        ;    ; Int5 Interrupt
    RETI         ;
ORG 0063H        ;    ; WatchDog Interrupt
    RETI         ;
ORG 0100H


; 程序入口
main:
    CLR    EA

    ; Reset RAM
    MOV    R0, #0FFH
ResetRam:
    MOV    @R0, #00H
    DJNZ    R0, ResetRam

    MOV     SP, #STACK_TOP

    LCALL    Init_Random        ; 初始化随机数发生器
    MOV    R0, #20H
    MOV    R1, #40H
     RANDLOOP:
    LCALL    Random            ; 产生随机数
    MOV    A, RND0

    MOV    @R0, A            ; 把随机数暂存到RAM中
     INC    R0

    DJNZ    R1, RANDLOOP        ; 循环取40H个随机数

    NOP
    NOP
    LJMP    main

;==============================================================
;  Name: Init_Random
;  Description: initialize the random
;  Function: give the value of Random_Buf and RandCount
;  Calls: None
;  Input: Random_Buf, RandCount
;  Outputs: Random_Buf
;  Register Usage: A, psw
;--------------------------------------------------------------
Init_Random:
    ADD    A, B
    ADD    A, R0
    ADD    A, R1
    ADD    A, TH0
    ADD    A, TL0
    ADD    A, TH1
    ADD    A, TL1

    MOV    R0, #Random_Buf
    MOV    rand8reg, A        ; 给随机数发生器rand8赋初值
    LCALL    rand8
    MOV    @R0, rand8reg        ; 给随机数发生器Random赋初值
     INC    R0
    LCALL    rand8
    MOV    @R0, rand8reg
     INC    R0
    LCALL    rand8
    MOV    @R0, rand8reg
     INC    R0
    LCALL    rand8
    MOV    @R0, rand8reg
     INC    R0
    LCALL    rand8
    MOV    @R0, rand8reg
     INC    R0
    LCALL    rand8
    MOV    @R0, rand8reg

    RET

;==============================================================
;  Name: Random
;  Description: get a 6 bytes random number
;  Function: This routine sends calc a 6 bytes random number
;   Random_Buf 6个字节看成48个位,可以表示280亿个数值,原理:用反
;   馈函数F()把这280亿个无顺序的放在一个可以旋转数码盘上,程序
;   有定时器在跑,当随机发生时,让转盘转计数器的值圈数即可得到一个
;   随机数.详见周航慈《单片机程序设计基础》P242
;   奇校验反馈函数d0=d48+d7+d5+d4+d2+d1+1,6Byte有280亿种状态
;  Calls: None
;  Input: Random_Buf, RandCount
;  Outputs: Random_Buf
;  Register Usage: A, psw
;--------------------------------------------------------------
Random:
   
    LCALL    rand8
    MOV    A, rand8reg
    ADD    A, TL0
    ANL    A, #0FH
    JNZ    Get_Count
    MOV    A, #0FH
    Get_Count:
        MOV     RandCount, A        ; 获得一个1~16的跳动格数
    Data_Rotate:
        MOV     A, Random_Buf+5        ;取D41-D48的当前状态
        RLC     A                       ;将D48提取到标志中去
        MOV     A, Random_Buf           ;取D1-D8的当前状态
        ANL     A, #5BH                 ;提取D7,D5,D4,D2,D1的当前值
        MOV     ACC.7, C                ;再加上D48的当前值
        MOV     C, PSW.0                ;取得偶校验的结果
        CPL     C                       ;转换成奇校验,且得到反馈函数的值
        MOV     A, Random_Buf           ;开始移位操作,先处理低字节
        RLC     A                       ;将反馈函数的值移入,最高位移出
        MOV     Random_Buf, A           ;保存移位后的结果
        MOV     A, Random_Buf+1         ;再依次进行其他字节的移位操作
        RLC     A
        MOV     Random_Buf+1, A
        MOV     A, Random_Buf+2
        RLC     A
        MOV     Random_Buf+2, A
        MOV     A, Random_Buf+3
        RLC     A
        MOV     Random_Buf+3, A
        MOV     A, Random_Buf+4
        RLC     A
        MOV     Random_Buf+4, A
        MOV     A, Random_Buf+5
        RLC     A
        MOV     Random_Buf+5, A         ; 完成巨型数字转盘转动一格
        DJNZ    RandCount, Data_Rotate  ; 随机跳动n格
    Random_Exit:

        RET

;==============================================================
;  Name: rand8
;  Description: get a 8bit random number
;  Function: This routine sends calc a 8bit random number
;  Attention: get a random "rand8reg" before initialize the program
;  Calls: None
;  Input: rand8reg
;  Outputs: rand8reg
;  Register Usage: A, psw
;--------------------------------------------------------------
rand8:
    mov    a, rand8reg
    jnz    rand8b
    cpl    a
    mov    rand8reg, a
  rand8b:
    anl    a, #10111000b
    mov    c, p
    mov    a, rand8reg
    rlc    a
    mov    rand8reg, a
    ret

;==============================================================
; END

end

发表于: 2005-07-01,修改于: 2005-07-01 08:03,已浏览1071次,有评论0条 推荐 投诉

给我留言
版权所有 ChinaUnix.net 页面生成时间:0.75387