【问题标题】:Generating random numbers in assembly在汇编中生成随机数
【发布时间】:2016-02-23 16:48:44
【问题描述】:

我是汇编新手,在生成随机数时遇到问题。

我的代码很简单:它在0-25 范围内生成 100 个数字并将它们存储在一个数组中。

我遇到的问题是,当我在 emu8086 汇编程序上运行 con 时,它成功运行并生成 100 个随机数,这些随机数存储在数组中。但是当我在masm611 上运行它时,它每 4 个周期生成一个新的随机数。这意味着数组中的值对于 4 个值是连续相同的数字,然后存储下一个随机值。

这是我的代码:

.model small
.stack 100h
.data

range db 25
i db 0                  ;iterator

arr db 15 dup(0)        ; an array

.code
   mov ax,@data
   mov ds,ax

   mov bx,offset arr    ;getting the adress of the arr in bx
    L1:

    mov ah,2ch      
    int 21h

    mov ah,0  
    mov al,dl            ;using dl by seeing  2ch details
    div range            ; so the number is in range


    mov [bx],ah          ;ah has remainder as using 8 bits div and  
    inc bx               ;moving to the next index

    inc i
    cmp i,100
    jbe L1


mov ah,4ch               ;returning control
int 21h 
end

我的代码有问题吗?我需要添加一些东西吗?谢谢。

【问题讨论】:

  • AFAIK 系统计时器仅每 1/18.2 秒更改一次。将返回值直接基于此似乎不是一个好主意。
  • 使用RDRAND 指令! ;-)
  • @Michael 我该怎么办?
  • 不要依赖外部的东西(在你的情况下是计时器)。实现一些众所周知的 RNG,例如LFSR。另请注意,通过使用模运算符来拟合范围内的数字,数字会变得不均匀分布(例如,0..255 mod 240 会使数字 0..15 出现的频率增加一倍)。
  • 那边的“相关”面板中有几个有用的链接--->>

标签: assembly random x86 masm emu8086


【解决方案1】:

您的代码的主要问题是它根本不生成随机数。因为系统时钟不是随机数发生器。我想说,它是非常非随机数生成器。

程序启动后的第一次读取仍然可以认为是“随机的”,但前提是您在随机时刻手动运行程序。

所有接下来的数字都不是随机的。

这样,从系统时钟读取的值适合用作其他算法的种子(起始值),用于生成(伪)随机数。

随机(和伪随机)数生成器是一个复杂的主题,需要一些研究。至少以wikipedia 开头。

顺便说一句,尽管整个主题很复杂,但一些随机数生成器足够简单,可以由初学者程序员实现。例如middle-square-method。尝试用汇编语言实现它,方法是将当前种子 AX 自身乘以结果的中间 4 个十六进制数字形成下一个数字:

; here ax contains the previous number

    mul ax
    mov al, ah
    mov ah, dl 

; here ax contains the next pseudo random number.

【讨论】:

  • 感谢它提供了丰富的信息,但我通过设置 dummy loop 解决了我的问题,这会导致迭代延迟。问题是 masm611 太快了,在此之前毫秒在 dl 寄存器中改变了 2ch ,它在改变之前存储了值。
  • @HamzaAnis 好吧,实际上你没有。你只是掩盖了问题。
【解决方案2】:

要以 johnfound 的答案为基础,您可以通过运行他用 Weyl 序列描述的中间平方方法来制作更强大的随机数生成器。这是基于 Bernard Widynski 于 2017 年 4 月 4 日发表的 Middle Square Weyl Sequence RNG 的想法。

可以按照以下方式构建程序集实现:

    mul ax      ; square random number
    add cx, bx  ; calculate next iteration of Weyl sequence
    add ax, cx  ; add Weyl sequence
    mov al, ah  ; get lower byte of random number from higher byte of ax
    mov ah, dl  ; get higher byte of random number from lower byte of dx
    ...         ; use new random number stored in ax

关于上述代码的几点说明:

  • 随机数存储在ax
  • 初始种子存储在bx 中(例如,您可以使用从系统时钟派生的东西)。种子的高 8 位必须为奇数且非零。
  • Weyl序列存储在cx中,每次迭代时加上bx得到。

与标准的中间平方方法不同,将其与 Weyl 序列相结合可防止随机数序列向 0 收敛。我建议阅读上述出版物以获取更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 2011-10-12
    • 2012-07-14
    • 1970-01-01
    相关资源
    最近更新 更多