我正在使用程序集8086emu,我需要8个数字的数字生成器。 我尝试使用@johnfound的这段代码:
RANDGEN: ; generate a rand no using the system time
RANDSTART:
MOV AH, 00h ; interrupts to get system time
INT 1AH ; CX:DX now hold number of clock ticks since midnight
mov ax, dx
xor dx, dx
mov cx, 10
div cx ; here dx contains the remainder of the division - from 0 to 9
add dl, '0' ; to ascii from '0' to '9'
mov ah, 2h ; call interrupt to display a value in DL
int 21h
RET
但仅在生成1个数字时才有用。
我试图创建伪随机函数,但我对汇编很新,但我没有成功。
我想知道是否有一种方法可以在程序集8086中翻译java Math.random()
函数或类似的东西。
感谢
答案 0 :(得分:5)
一个简单的伪随机数生成器将当前数乘以25173,然后将其加13849。此值现在成为新的随机数 如果您从系统计时器开始(这称为播种随机数生成器),这一系列数字将足够随机,可用于简单的任务!
MOV AH, 00h ; interrupt to get system timer in CX:DX
INT 1AH
mov [PRN], dx
call CalcNew ; -> AX is a random number
xor dx, dx
mov cx, 10
div cx ; here dx contains the remainder - from 0 to 9
add dl, '0' ; to ascii from '0' to '9'
mov ah, 02h ; call interrupt to display a value in DL
int 21h
call CalcNew ; -> AX is another random number
...
ret
; ----------------
; inputs: none (modifies PRN seed variable)
; clobbers: DX. returns: AX = next random number
CalcNew:
mov ax, 25173 ; LCG Multiplier
mul word ptr [PRN] ; DX:AX = LCG multiplier * seed
add ax, 13849 ; Add LCG increment value
; Modulo 65536, AX = (multiplier*seed+increment) mod 65536
mov [PRN], ax ; Update seed = return value
ret
这实现了a Linear Congruential Generator (LCG) with a power-of-2 modulus。 %65536
免费发生,因为产品+增量的低16位在AX中,而较高的位不是。
答案 1 :(得分:2)
好主意,执行错误。上面显示的代码生成了偶数,奇数,奇数等的可预测模式。那不是很“随机”。维基百科警告说,线性同余生成器的较高位往往很随机,而较低位则不然。解决方法是在保存种子后立即插入SHR AX,5。种子仍然翻转奇偶奇数,但从种子获得的随机数忽略了五个最低有效位。这是CalcNew结尾的样子:
mov [PRN], ax ; Update seed
shr ax,5 ; Discard 5 bits
ret
不一定要精确到五位。我之所以选择5个,是因为少于5个随机数不够,但是超过5个却使您无法选择所需的随机数。 AX只有16位;丢弃其中的五个后,您将获得一个介于0到2047之间的随机数,这对于下一步将某个数字除以n并取余数非常有用。当n为10时,2047足够。但是您的n可能更大,取决于应用程序。如果需要一个随机的ascii字符,则将除以96。如果将7位而不是5位丢弃,则将得到一个从0到511的随机AX,将其除以96即可。得到余数。这将使您的结果出现偏差,因为余数较低的情况比高余数的发生频率更高。因此,当您使用16位CPU时,最好以5位为代价。