装配随机数发生器

时间:2016-11-19 21:52:40

标签: assembly x86 emu8086

我正在使用程序集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()函数或类似的东西。 感谢

2 个答案:

答案 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位为代价。