AVR Studio 中的随机数生成器(没有 C 或任何其他编程语言!)

Random number generator in AVR Studio (no C or any other programming language!)

所以我有这个问题,我接到了一个任务,用AVR Studio做一个轰炸游戏。说实话,我对如何使用 AVR 毫无头绪,而且我的编程也不太好。我以某种方式完成了我的飞船,但现在我需要一个随机数生成器。现在已经在互联网上搜索了大约 2 天,只在 Java 中找到了 C 语言的源代码,绝对是所有其他语言,但不是我需要的语言。谁能建议我为兰德写什么?现在,我的源代码如下所示:

;ports

.equ PORTC =     ;port C address

.equ DDRC  = 

.equ PORTA =     ;port A address

.equ DDRA  = 

;registers

.def leds = r16     ;storing data for leds

.def temp = r18     ;Temporary storage register

.def save = r19     ;Temporary storage register for status registers

.def YL   = r20     ;Defining low bite of Y

.def YH   = r21     ;Defining high bite of Y

;

.equ SREG = F     ;Status Register Address

.equ SPH  = E     ;High bite Stack Pointer address

.equ SPL  = D     ;Low bite Stack Pointer address

.equ RAMEND = F  ;Stack Address

;Random number generator

        ldi r16, 

        ldi r17, $C0


;Set stack pointer to registers

        ldi temp,high(RAMEND)

        out SPH,temp

        ldi temp,low(RAMEND)

        out SPL,temp

;Initialise output ports

        ldi temp, $ff

        out DDRC, temp

clear:  clc

;       clr leds

        out PORTC, leds

        rjmp SHIP2_prep

SHIP1_prep: ldi leds, 

        rjmp SHIPS



SHIP2_prep: ldi leds, 

        out PORTC, leds

        ldi leds, $C0

        rjmp SHIPS



SHIP3_prep: ldi leds, 

        out PORTC, leds

        ldi leds, $C0

        out PORTC, leds

        ldi leds, $E0

        rjmp SHIPS

;Rotate ships right

SHIPS:  out PORTC, leds

;       rcall delay

        ror leds

        brcs clear

        rjmp SHIPS


;delay: in  save,SREG

;       ldi YH,high($FF9C)

;       ldi YL,low($FF9C)

loop:   sbiw Y,1

        brne loop

        out SREG, save

        ret

这个问题已经存在一年多了,但我也是在为 AVR 汇编程序项目寻找简单的 RNG 时发现的。 Whosebug 没有解决方案让我很沮丧!同时我发现了一个我喜欢的所以我想贡献它。

免责声明:

  1. 这是一个非常简单的 16 位 RNG。如果算法和当前数字(甚至部分)已知,那么它在密码学上是极其不安全的,可以可靠地预测下一个数字。此外,它产生的数字序列将在 65535 个数字之后重复。它可以用于无风险的 "toy" 项目,例如原始问题或我的项目。
  2. 生成的数字顺序完全取决于第一个 "seed" 数字。相同的种子,相同的数字,永远如此。您需要找到该种子的 "really" 运行dom 源。当用户按下按钮时,我从 16 位定时器中取出一个数字。
  3. 如果种子数为 0,则输出将是无限的 0 序列。要获得一系列 "useful" 伪 运行dom 数字,您需要以 0 以外的数字(任何数字)开头。
  4. 总而言之,如果此代码损坏,您可以保留两部分。

综上所述,我发现这可以用 6 行汇编代码完成,这真是太神奇了。

我的算法是基于the Galois LFSR section of the Wikipedia article on linear feedback shift registers中所示的C代码。

经过轻微质量测试。

为了确保我没有实现垃圾,我复制了 C 代码,在其周围包裹了一些测试代码,并向自己保证它确实为至少少数 (5) 个测试生成了长度为 65535 的序列种子。

我在 AtmelStudio 的模拟器中 运行 我的 AVR 汇编程序实现(对于 AtTiny2313,但它应该 运行 在大多数 AVR 型号上)具有相同的测试种子,并验证了前 20 个数字每个序列都与 C 程序中的相同。

够废话了!这是我的代码:

.INCLUDE    "tn2313def.inc"

start:
            ldi     xl, low(1234)
            ldi     xh, high(1234)
again:      rcall   galois
            nop     ; do something with rn here...
            rjmp    again

galois:     ; subroutine for computing the next prime in X
            lsr     xh
            ror     xl
            brsh    noxor
            ldi     r17, $B4
            eor     xh, r17
noxor:
            ret

只需增加寄存器的数量并使用与 $B400 不同的合适 "tap polynomial" 编码,就可以轻松地将基本思想扩展到具有更多位和更长周期的生成器。