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 没有解决方案让我很沮丧!同时我发现了一个我喜欢的所以我想贡献它。
免责声明:
- 这是一个非常简单的 16 位 RNG。如果算法和当前数字(甚至部分)已知,那么它在密码学上是极其不安全的,可以可靠地预测下一个数字。此外,它产生的数字序列将在 65535 个数字之后重复。它可以用于无风险的 "toy" 项目,例如原始问题或我的项目。
- 生成的数字顺序完全取决于第一个 "seed" 数字。相同的种子,相同的数字,永远如此。您需要找到该种子的 "really" 运行dom 源。当用户按下按钮时,我从 16 位定时器中取出一个数字。
- 如果种子数为 0,则输出将是无限的 0 序列。要获得一系列 "useful" 伪 运行dom 数字,您需要以 0 以外的数字(任何数字)开头。
- 总而言之,如果此代码损坏,您可以保留两部分。
综上所述,我发现这可以用 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" 编码,就可以轻松地将基本思想扩展到具有更多位和更长周期的生成器。
所以我有这个问题,我接到了一个任务,用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 没有解决方案让我很沮丧!同时我发现了一个我喜欢的所以我想贡献它。
免责声明:
- 这是一个非常简单的 16 位 RNG。如果算法和当前数字(甚至部分)已知,那么它在密码学上是极其不安全的,可以可靠地预测下一个数字。此外,它产生的数字序列将在 65535 个数字之后重复。它可以用于无风险的 "toy" 项目,例如原始问题或我的项目。
- 生成的数字顺序完全取决于第一个 "seed" 数字。相同的种子,相同的数字,永远如此。您需要找到该种子的 "really" 运行dom 源。当用户按下按钮时,我从 16 位定时器中取出一个数字。
- 如果种子数为 0,则输出将是无限的 0 序列。要获得一系列 "useful" 伪 运行dom 数字,您需要以 0 以外的数字(任何数字)开头。
- 总而言之,如果此代码损坏,您可以保留两部分。
综上所述,我发现这可以用 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" 编码,就可以轻松地将基本思想扩展到具有更多位和更长周期的生成器。