为什么汇编中的随机数生成器为每个函数生成固定值

问题描述

我在 TASM MS-DOS 中创建了一个游戏,为用户提供数学练习,他必须解决这些问题。练习是加法、减法、乘法和除法。每种类型都有一个单独的功能,可以在屏幕上呈现练习。

出于某种原因,每个函数总是生成相同的练习(每个函数不同),即使我使用相同的函数生成随机数。

例如,在加法练习中,您有时会看到“4 + 6”,但在乘法练习中永远不会看到“4 * 6”。另一个例子是,您有时会看到“9 / 1”而不是“9 - 1”。

代码如下:

    basicRandomNumber1 db ?
    basicRandomNumber2 db ?


proc generateBasicRandomNumber
     mov ax,40h
     mov es,ax
     mov ax,[es:6Ch]
     and al,00000111b
     mov [randomNumber],al
     mov ax,00000001b
     add [randomNumber],al
     ret
endp generateBasicRandomNumber

proc Addition
addition:
    call AddBreakLines
    call Addspaces
    call generateBasicRandomNumber
    mov dl,[randomNumber]
    mov [basicRandomNumber1],dl  
    add  dl,'0'  
    mov ah,2h  
    int 21h
    mov dx,offset plusSign
    call printStr
    push 1
    call sleep
    call generateBasicRandomNumber
    mov dl,[randomNumber]
    mov [basicRandomNumber2],dl
    add  dl,2h  
    int 21h

  

    push 1
    call sleep

...the rest of the code

endp Addition


proc Multiplication
    Multiplication:
    call AddBreakLines
    call Addspaces
    call generateBasicRandomNumber
    mov dl,offset mulSign
    call printStr
    push 1
    call sleep
    call generateBasicRandomNumber
    mov dl,2h  
    int 21h

...the rest of the code

endp Multiplication


有时,它会记录一条消息,指出对某个地址进行了非法写入或从那里非法读取。

其余的代码是指我得到用户输入的部分,检查它是否等于正确的结果并告诉他是否是

过程“sleep”是使程序从库中休眠一定时间的过程https://www.github.com/oded8bit/Assembly-Lib

我怎样才能让程序 generateBasicRandomNumber 也生成不同的数字?

解决方法

您的随机数来源是地址 046Ch 处的 BIOS.TimerTick。 这是一个每秒仅更改约 18 次的值!您需要更好的(伪)随机性来源。

这篇文章有一个例子: 8086 random number generator (not just using the system time)?


有时,它会记录一条消息,指出对某个地址进行了非法写入或从那里非法读取。

这可能来自具有错误值的段寄存器。
您的 generateBasicRandomNumber 过程破坏了 ES 段寄存器。最好像这样保存它:

proc generateBasicRandomNumber
     PUSH ES
     mov  ax,40h
     mov  es,ax

     ...

     POP  ES
     ret
endp generateBasicRandomNumber