汇编代码中的随机数生成器

4

有人知道如何在汇编代码中随机生成8位数字吗?

我正在使用ATmega8535和Atmel AVR汇编器,AVR模拟器进行调试。(AVR Studio 4)

抱歉,我对此还很陌生,任何帮助都将不胜感激。谢谢。

3个回答

5
这取决于你对随机的定义。如果你只是想要一串可预测但具有统计随机性的数字序列,那么在微控制器上实现最简单的方法是使用线性反馈移位寄存器linear feedback shift register。可以在此处看到在PIC设备上汇编实现的示例here
具有更好交叉相关性的变体是Gold-Codes,它们稍微复杂一些,但依赖于相同的原理。还有很多其他算法,但这取决于你需要什么样的统计特性。
如果你需要高熵(即无法预测)的东西,那么一种新颖的方法是使用设备的ADC来采样反向偏置二极管结的电压。由此产生的噪声是强大的熵源。然而,你需要小心,不要意外地引入任何顺序,因此需要在设计中谨慎处理。

2

(编辑)看起来我在这里链接的所有 AVR Freaks 上的对话都已被删除。

AVR Freaks 上有一 讨论关于使用汇编语言生成 8 位随机数的对话其中有一条评论 提供了一个内联汇编器的解决方案。

根据这个... 我想出了以下代码:

    .device ATMega324P

    .def _high = r16
    .def _low = r17
    .def _mask = r18
    .def _step = r19
    .def _delay1 = r20
    .def _delay2 = r21

    .cSeg
    .org 0x0000
    jmp resetHandler

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    .dSeg
lfsr16High:
    .byte 1
lfsr16Low:
    .byte 1

    .cSeg

    .equ lfsr16Seed = 0xACE1

.macro setup16BitLFSR
    ldi _high, high(lfsr16Seed)
    ldi _low, low(lfsr16Seed)
    sts lfsr16High, _high
    sts lfsr16Low, _low
.endMacro

.macro randomByteFrom16BitLFSR
    lds _high, lfsr16High
    lds _low, lfsr16Low

    ; Masks for 16-bit LFSR.  Uncomment only one
    ldi _mask, 0x9C
    ; ldi _mask, 0xB4
    ; ldi _mask, 0xBD
    ; ldi _mask, 0xCA
    ; ldi _mask, 0xEB
    ; ldi _mask, 0xFC

    ldi _step, 8
step:                    ; run the LFSR 8 steps
    lsr _high
    ror _low
    brcc noMask          ; output bit set?
    eor _high, _mask     ; yes, apply mask
noMask:
    dec _step            ; done?
    brne step            ; no, loop

    sts lfsr16High, _high
    sts lfsr16Low, _low ; random byte is in _low register
.endMacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    .dSeg
lfsr8:
    .byte 1

    .cSeg

.macro setup8BitLFSR
    ldi _low, 0x37       ; seed value
    sts lfsr8, _low
.endMacro

.macro randomByteFrom8BitLFSR
    lds _low, lfsr8

    ; Masks for 8-bit LFSR. Uncomment only one
    ldi _mask, 0x8E
    ; ldi _mask, 0x95
    ; ldi _mask, 0x96
    ; ldi _mask, 0xA6
    ; ldi _mask, 0xAF
    ; ldi _mask, 0xB1
    ; ldi _mask, 0xB2
    ; ldi _mask, 0xB4
    ; ldi _mask, 0xB8
    ; ldi _mask, 0xC3
    ; ldi _mask, 0xC6
    ; ldi _mask, 0xD4
    ; ldi _mask, 0xE1
    ; ldi _mask, 0xE7
    ; ldi _mask, 0xF3
    ; ldi _mask, 0xFA

    ldi _step, 8
step:                    ; run the LFSR 8 steps
    ror _low             ; shift lfsr
    brcc  noMask         ; output bit set?
    eor _low, _mask      ; apply mask
noMask:
    dec _step            ; done?
    brne step            ; no, loop

    sts lfsr8, _low      ; random byte is in _low register
.endMacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    .cSeg

resetHandler:
    cli

    ldi _high, high(RamEnd)
    ldi _low, low(RamEnd)
    out SPH, _high
    out SPL, _low

    ldi _low, 0xff
    out DDRA, _low

    ; setup8BitLFSR
    setup16BitLFSR

tryAnotherOne:
    ; randomByteFrom8BitLFSR
    randomByteFrom16BitLFSR

    out PORTA, _low

    ldi _delay1, 0xFF
outerDelay:
    ldi _delay2, 0xFF
innerDelay:
    dec _delay2
    brne innerDelay
    dec _delay1
    brne outerDelay

    rjmp tryAnotherOne

还有AVR Freaks上的另一个讨论, 提供了几个选项... 但是它们非常难以阅读,因为缺乏任何有意义的标识符,并且其作者拒绝解释。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接