尝试使用JSR $ E09A在我的C64上生成一系列随机数,并从$ 63和$ 64中检索数字。 (根据我所看到的所有文档,当你使用BASIC的RND(0)时,它是相同的例程。但是不能让它迭代。下面的代码将工作并在63美元中放置一个不同的数字单独执行时$ 64。
. C000 A5 00 LDA $00
. C002 20 9A E0 JSR $E09A
. C005 00 BRK
现在当我尝试使用以下代码迭代10次时,它永远不会返回。
. C000 A0 0A LDY #$0A
. C002 A9 00 LDA #$00
. C004 20 9A E0 JSR $E09A
. C007 88 DEY
. C008 D0 F8 BNE $C002
. C00A 00 BRK
我错过了一些如此明显的东西,我无法看到它。我并不担心"随机"它是。此时我只想要一系列随机数字。
答案 0 :(得分:8)
SID芯片实际上可以生成比BASIC的伪随机数更随机的数字。使用以下命令启动发电机:
LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
RTS
然后您可以随时获得随机数:
LDA $D41B ; get random value from 0-255
答案 1 :(得分:6)
感谢Ross Ridge建议被调用的函数正在改变Y寄存器中的值。我知道它必须是明显的东西!
通过在JSR
之前存储Y并在之后恢复,它现在将正确迭代。这是快速修复:
修改:已于7/10/17更新 - 显示完整代码并纳入JeremyP建议。这实际上是一个硬币翻转迭代器(50000次重复),用于试验随机
.C 033c A9 00 LDA #$00
.C 033e 85 FB STA $FB ; set up register for counter
.C 0340 85 FC STA $FC
.C 0342 A2 C8 LDX #$C8 ; outer loop= 200
.C 0344 86 FD STX $FD
.C 0346 A0 FA LDY #$FA ; inner loop=250
.C 0348 84 FE STY $FE
.C 034a 20 94 E0 JSR $E094 ; Get random# Vic20 Address (E09B for C64)
.C 034d A5 63 LDA $64
.C 034f C9 80 CMP #$80 ; >128 = HEADS
.C 0351 90 0D BCC $0360 ; else continue loop
.C 0353 18 CLC ; increment 2 byte number
.C 0354 A5 FB LDA $FB
.C 0356 69 01 ADC #$01 ; LSB
.C 0358 85 FB STA $FB
.C 035a A5 FC LDA $FC
.C 035c 69 00 ADC #$00 ; MSB
.C 035e 85 FC STA $FC
.C 0360 C6 FE DEC $FE
.C 0362 D0 E6 BNE $034A ; end inner loop
.C 0364 C6 FD DEC $FD
.C 0366 D0 DE BNE $0346 ; end outer loop
.C 0368 60 RTS ; return to basic
我可以在循环中按LDA $63
或LDA $64
获取随机数,并将其用于我的目的。
事实证明这比预期慢很多,只花了一半时间用于BASIC。 RND函数需要很多周期,但是,我发现这个Compute! article使用SID芯片作为随机数生成器。
LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
启用后,它会独立生成数字,不必再次执行。重复调用LDA $D41B
的循环将在每次迭代时获得一个新的随机数。在我的测试中,50,000次迭代耗时1.25秒,百万次耗时超过24秒。 1MHz计算机令人印象深刻!
答案 2 :(得分:1)
您实际上是在调用使用计时器生成种子的RND(0)
。但是,这在组装中不是直接可用的。首先尝试切换到正数(任意数字)并查看它是否开始产生值。
答案 3 :(得分:0)
如果你没有带有定时栅格-IRQ或类似功能的程序,你可以随机获得一个"随机" lda $d012
的号码。
答案 4 :(得分:0)
现在已经很晚了,但根据要求,你也可以推出自己的PRNG。一些算法很容易实现,例如,我将使用参数[3,25,24]
在这里显示一个32位xorshift实现(因为这使得两个移位使用非常少的代码)。返回的随机数有16位:
rnd_seed:
sta $22 ; store pointer to PRNG state
stx $23
lda #$00 ; initialize with 0
ldy #$03
rs_clrloop: sta ($22),y
dey
bne rs_clrloop
lda $d012 ; except for LSB, use current raster
bne seed_ok
lda #$7f ; or a fixed value if 0
seed_ok: sta ($22),y
rts
rnd:
sta $22 ; store pointer to PRNG state
stx $23
ldy #$03
r_cpyloop: lda ($22),y ; copy to ZP $fb - $fe
sta $fb,y
dey
bpl r_cpyloop
ldy #$03 ; and shift left 3 bits
r_shiftloop: asl $fb
rol $fc
rol $fd
rol $fe
dey
bpl r_shiftloop
ldy #$03
r_xorloop: lda ($22),y ; xor with original state
eor $fb,y
sta ($22),y
dey
bpl r_xorloop
ldy #$03
lda ($22),y
lsr a ; MSB >> 1 gives ">> 25"
ldy #$00
eor ($22),y ; xor with original state
sta ($22),y
ldy #$03 ; this is also value for "<< 24"
eor ($22),y ; so xor with MSB
sta ($22),y
tax ; use the two "higher" bytes as result ...
dey
lda ($22),y ; ... in A/X
rts
用法示例:
main:
lda init
bne noinit
lda #<prng
ldx #>prng
inc init
jsr rnd_seed
noinit: lda #<prng
ldx #>prng
jsr rnd
jmp $bdcd ; C64 BASIC routine output 16bit int in A/X
init: .byte $00
prng: .res 4 ; 32bit PRNG state
答案 5 :(得分:0)
我发现此线程在C64汇编中搜索更通用的RND(开始,结束)例程。此BASIC示例已实现的东西:
INT(RND(1) * (end- start + 1)) + start
尽管这里有很多有用的答案,但我却缺少这种解决方案,因此我必须找到自己的解决方案。这可能会对另一个人使用此线程有所帮助,所以就这样:
lda #<end
sta $FD
lda #>end
sta $FE
lda #<start
sta $FB
lda #>start
sta $FC
rnd:
//reseed, to avoid repeated sequence; RND(0)
lda #00
jsr $E09A
//++end
inc $FD
bne skip1
inc $FE
skip1:
//- start
lda $FD
sec
sbc $FB
sta $FD
lda $FE
sbc $FC
sta $FE
//++end-start to FAC
ldy $FD
lda $FE
jsr $B391 //A(h),Y(L) - FAC
ldx #<flt
ldy #>flt
jsr $BBD4 //store FAC to flt
//get actual RND(1)
lda #$7f
jsr $E09A
//multiply by ++end - start
lda #<flt
ldy #>flt
jsr $BA28
//to integer
jsr $BCCC
//FAC to int;
jsr $B1BF
lda $65
clc
adc $FB
sta $14
lda $64
adc $FC
sta $15
rts
flt: .byte 0,0,0,0,0
该例程使用16位数字(范围为0-32767)工作。参数以251,252开始;以253、254结尾。 在$ 14中找到16位结果。
答案 6 :(得分:0)
C64上真正的问题是:
SID生成的数字也是伪随机的,并且它们按顺序重复(我找不到讨论它的链接)
栅格位置不是随机的。
c64中真正随机性的唯一来源是用户输入。
所以我要做的是:
然后,您将获得自己喜欢的伪随机例程的随机种子。或只是一杆16/24/32位随机数。
例如,在游戏中,当用户移动操纵杆并获得随机字节时,您可以获取cia计时器。
注意:在仿真器中放置prg或d64与编写“ load ...”有很大不同,因为在这种情况下,每个用户每次编写的内容都不相同,而计时器LSB是“随机的”。
在某些仿真器中,由于这个原因,随机延迟被添加到计算机启动中。