Assembly 使用Easy 68K(68000)在范围内装配随机数
我正在使用Easy 68K模拟器创建一个简单的黑杰克游戏,需要使用一个随机数来分配卡。我的卡必须在2到11之间。我似乎每次都得到相同的数字,但它不在我预期的范围内。我的卡值需要在D3中结束,因此我有以下随机数字代码:Assembly 使用Easy 68K(68000)在范围内装配随机数,assembly,random,68000,Assembly,Random,68000,我正在使用Easy 68K模拟器创建一个简单的黑杰克游戏,需要使用一个随机数来分配卡。我的卡必须在2到11之间。我似乎每次都得到相同的数字,但它不在我预期的范围内。我的卡值需要在D3中结束,因此我有以下随机数字代码: CLR.L D0 CLR.L D3 MOVE.B #8, D0 ;Access time TRAP #15 AND.L #$5FFFFF,D1 ;prevent overflow in di
CLR.L D0
CLR.L D3
MOVE.B #8, D0 ;Access time
TRAP #15
AND.L #$5FFFFF,D1 ;prevent overflow in divu
DIVU #10, D1
SWAP D1
ADDQ.W #1, D1
MOVE D1, D3
我是通过修改此站点上的代码来实现的:
我希望能找到生成数字2到11的帮助。我在网上搜索了好几个小时。我知道我需要使用Move.B#8,D0来访问时间,但除此之外,我还没有取得多大进展。任何帮助都将不胜感激 在
和.L
(“在divu中防止溢出”)中使用的掩码仅适用于除以100的情况——对于除以10的情况,需要使用0x7FFFF
进行掩码
原因:
此外,您拥有的代码将为您提供一个从1到10(0-9+1)的数字。如果你想要2到11,你必须加2,而不是1
这里有一个更高级的随机数生成器,它是从Mac OS QuickDraw源代码中借来的。请注意,您可能需要稍微翻译语法(它是25年前编写的!)和/或修改它加载和存储种子的方式
;--------------------------------------------------------------
;
; FUNCTION Random: INTEGER;
;
; returns a signed 16 bit number, and updates unsigned 32 bit randSeed.
;
; recursion is randSeed := (randSeed * 16807) MOD 2147483647.
;
; See paper by Linus Schrage, A More Portable Fortran Random Number Generator
; ACM Trans Math Software Vol 5, No. 2, June 1979, Pages 132-138.
;
; Clobbers D0-D2, A0
;
;
; GET LO 16 BITS OF SEED AND FORM LO PRODUCT
; xalo := A * LoWord(seed)
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE #16807,D0 ;GET A = 7^5
MOVE D0,D2 ;GET A = 7^5
MULU RANDSEED+2(A0),D0 ;CALC LO PRODUCT = XALO
;
; FORM 31 HIGHEST BITS OF LO PRODUCT
; fhi:=HiWord(seed) * ORD4(a) + HiWord(xalo);
;
MOVE.L D0,D1 ;COPY xalo
CLR.W D1
SWAP D1 ;GET HiWord(xalo) as a long
MULU RANDSEED(A0),D2 ;MULT BY HiWord(seed)
ADD.L D1,D2 ;ADD LEFTLO = FHI
;
; GET OVERFLOW PAST 31ST BIT OF FULL PRODUCT
; k:=fhi DIV 32768;
;
MOVE.L D2,D1 ;COPY FHI
ADD.L D1,D1 ;CALC 2 TIMES FHI
CLR.W D1
SWAP D1 ;CALC FHI SHIFTED RIGHT 15 FOR K
;
; ASSEMBLE ALL THE PARTS AND PRE-SUBTRACT P
; seed:=((BitAnd(XALO,$0000FFFF) - P) + BitAnd(fhi,$00007FFF) * b16) + K;
;
AND.L #$0000FFFF,D0 ;GET LO WORD XALO
SUB.L #$7FFFFFFF,D0 ;SUBTRACT P = 2^31-1
AND.L #$00007FFF,D2 ;BitAnd(fhi,$00007FFF)
SWAP D2 ;TIMES 64K
ADD.L D1,D2 ;PLUS K
ADD.L D2,D0 ;CALC TOTAL
;
; IF seed < 0 THEN seed:=seed+p;
;
BPL.S UPDATE
ADD.L #$7FFFFFFF,D0
UPDATE MOVE.L D0,RANDSEED(A0) ;UPDATE SEED
CMP.W #$8000,D0 ;IS NUMBER -32768 ?
BNE.S NUMOK ;NO, CONTINUE
CLR D0 ;YES, RETURN ZERO INSTEAD
NUMOK MOVE.W D0,4(SP) ;RETURN LO WORD AS RESULT
RTS
--------------------------------------------------------------
;
; 随机函数:整数;
;
; 返回有符号的16位数字,并更新无符号的32位随机种子。
;
; 递归是随机种子:=(随机种子*16807)MOD 2147483647。
;
; 参见Linus Schrage的论文,这是一种更便携的Fortran随机数生成器
; ACM Trans Math软件第5卷,第2期,1979年6月,第132-138页。
;
; 重锤D0-D2,A0
;
;
; 获取LO 16位种子并形成LO产品
; xalo:=A*LoWord(种子)
;
MOVE.L GRAFGLOBALS(A5),A0;指向“快速绘制全局”
移动#16807,D0;得到A=7^5
移动D0,D2;得到A=7^5
MULU RANDSEED+2(A0),D0;计算低积=XALO
;
; 表31本振乘积的最高位
; fhi:=HiWord(seed)*ORD4(a)+HiWord(xalo);
;
移动1 D0,D1;复制xalo
文娱艺术中心D1
掉期D1;将HiWord(xalo)作为长
MULU RANDSEED(A0),D2;多字(种子)
增补1 D1、D2;添加LEFTLO=FHI
;
; 溢出超过完整产品的第31位
; k:=fhi分区32768;
;
动议1.D2,D1;复制FHI
增补1 D1、D1;计算2倍FHI
文娱艺术中心D1
掉期D1;计算FHI右移15,以获得K
;
; 组装所有零件并预减去P
; 种子:=((比特和(XALO,$0000FFFF)-P)+比特和(fhi,$00007FFF)*b16)+K;
;
和.L#$0000FFFF,D0;得到一个单词XALO
分包L#$7FFFFFFF,D0;减去P=2^31-1
及.L#$00007FFF,D2;比特兰德(fhi,$00007FFF)
掉期D2;时代64K
增补1 D1、D2;加K
增补1 D2,D0;计算总数
;
; 如果种子<0,则种子:=种子+p;
;
BPL.S更新
添加.L#$7FFFFFFF,D0
更新MOVE.ld0,RANDSEED(A0);更新种子
CMP.W#8000美元,D0;电话号码是32768吗?
法国新墨西哥州;不,继续
CLR-D0;是的,返回零
新港西D0,4(SP);返回LO字作为结果
实时战略
您需要根据您的时间间隔(最小值和最大值)使用正确的掩码,此代码将解决所有问题,它包含两个参数:D5中的最小值和D6中的最大值,它还使用D0、D7和A1
RAND_GEN
SUB D5,D6 ;You should give Min in D5 and Max in D6
MOVE D6,D7
ADDI #1,D6
MULU #$FFFF,D7
LEA SEED,A1
MOVE.B #8,d0
TRAP #15
ADD (A1),D1
MULU #$FFFF,D1
EOR.L #$F321F23A,D1
MOVE D1,(A1)
AND.L D7,D1 ;PREVENT OVERFLOW FOR (Max-Min)
DIVU D6,D1 ;time count / (Max-Min)
SWAP D1 ;swap upper and lower words of D1 to put remainder in low word
ADD D5,d1 ;D1.W contains number in the range of (Min,Max)
RTS
* Put variables and constants here
SEED
DC.W 1
在程序开始时,种子默认为1,并在每次RAND_GEN调用后自动更新,您也可以随时更改它
在EASY68K上测试。这似乎是可行的,尽管在整个程序中我似乎只得到一个随机数。我所有的牌都一样。当我重新运行程序时,我会得到一个不同的数字,但每张卡都等于这个数字(尽管我每次发卡时都会清除寄存器并调用Move.B#8,D0),这是因为这些“随机”数字的基础在调用之间不会改变--
Move.B#8,D0
只需百分之一秒就可以得到午夜后的时间。由于运行代码可能不到1/100秒,因此结果不会改变。我将在我的答案中添加另一个随机数函数。
RAND_GEN
SUB D5,D6 ;You should give Min in D5 and Max in D6
MOVE D6,D7
ADDI #1,D6
MULU #$FFFF,D7
LEA SEED,A1
MOVE.B #8,d0
TRAP #15
ADD (A1),D1
MULU #$FFFF,D1
EOR.L #$F321F23A,D1
MOVE D1,(A1)
AND.L D7,D1 ;PREVENT OVERFLOW FOR (Max-Min)
DIVU D6,D1 ;time count / (Max-Min)
SWAP D1 ;swap upper and lower words of D1 to put remainder in low word
ADD D5,d1 ;D1.W contains number in the range of (Min,Max)
RTS
* Put variables and constants here
SEED
DC.W 1