【问题标题】:8086 random number generator (not just using the system time)?8086 随机数生成器(不只是使用系统时间)?
【发布时间】:2016-11-19 21:52:39
【问题描述】:

我正在使用程序集 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    

但仅在生成一个数字时才有用。重复调用得到相同的数字,因为该时钟每秒只滴答 18.2 次。

我尝试创建伪随机函数,但我对汇编还很陌生,但没有成功。 我想知道是否有办法在emu8086中做类似于java的Math.random()函数。

【问题讨论】:

  • 尝试实现一个xorshift 随机数生成器。这应该非常简单和有用。
  • 另外,Random number in assembly 有一个很长的详细答案,使用不同的 LCG,可能比这个更好的参数。

标签: assembly random x86 x86-16 emu8086


【解决方案1】:

一个简单的伪随机数生成器将当前数字乘以 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 中,而高位不在。

【讨论】:

  • 谢谢!我研究了这个主题并制作了一个线性同余生成器。
  • @MichaelPetch:是的,DX 那时已经死了。我们只需要 16x16 => 16 位乘法。 DX 中没有额外的熵,因为给定AX,您可以唯一确定DX 中的值。即向后工作以找到给出此AX 的16 位PRN 种子,您还可以计算DX。所以在DX:AX中称它为32位返回值是没有意义的。
【解决方案2】:

好主意,执行有缺陷。上面显示的代码会生成一个可预测的偶-奇-偶-奇-偶-奇等模式。这不是很“随机”。维基百科警告说,线性同余生成器的高位往往非常随机,但低位则不然。解决方法是在保存种子后立即插入 SHR AX,5。种子仍然翻转偶-奇-偶-奇,但从种子中获得的随机数忽略了五个最低有效位。 CalcNew 的结尾应该是这样的:

    mov     [PRN], ax          ; Update seed
    shr     ax,5               ; Discard 5 bits
    ret

它不必正好是 5 位。我选择了五个,因为少于五个不够随机,但超过五个会影响您选择所需随机数的能力。 AX 只有 16 位;在你丢弃其中五个之后,你会得到一个介于 0 和 2047 之间的随机数,这对于下一步除以某个数 n 并取余数非常有用。当 n 为 10 时,2047 就足够了。但是您的 n 可能会更大,具体取决于应用程序。如果你需要一个随机的 ascii 字符,你将除以 96。如果你放弃了,比如说,七位而​​不是五位,你会有一个从 0 到 511 的随机 AX,你将除以 96 到得到一个余数。这会扭曲您的结果,因为较低的余数会比较高的余数更频繁地发生。因此,当您使用 16 位 CPU 时,5 位是一个很好的折衷方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2013-02-05
    相关资源
    最近更新 更多