1

I have created a game in TASM MS-DOS that gives the user math exercises and he has to solve them. The exercises are in addition, subtraction, multiplication and division. Each type has a separate function that renders the exercises on the screen.

For some reason, each function always generates the same exercises (different in each function), even though I use the same function for generating the random number.

For example, in the addition exercises, you'll sometimes see "4 + 6" but you'll never see "4 * 6" in the multiplication exercises. Another example is that you'll sometimes see "9 / 1" but not "9 - 1".

Here is the code:

    basicRandomNumber1 db ?
    basicRandomNumber2 db ?


proc generateBasicRandomNumber
     mov ax, 40h
     mov es, ax
     mov ax, [es:6Ch]
     and al, 00000111b
     mov [randomNumber], al
     mov ax, 40h
     mov es, ax
     mov ax, [es:6Ch]
     and al, 00000001b
     add [randomNumber], al
     mov ax, 40h
     mov es, ax
     mov ax, [es:6Ch]
     and al, 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, '0'  
    mov ah, 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, [randomNumber]
    mov [basicRandomNumber1], dl
    add  dl, '0'  
    mov ah, 2h  
    int 21h
    mov dx, offset mulSign
    call printStr
    push 1
    call sleep
    call generateBasicRandomNumber
    mov dl, [randomNumber]
    mov [basicRandomNumber2], dl
    add  dl, '0'  
    mov ah, 2h  
    int 21h

...the rest of the code

endp Multiplication


Sometimes, it logs a message that says there has been an illegal write to some address or an illegal read from there.

The rest of the code means the part where I get the user's input, check if it's equal to the correct result and tell him if it is

the procedure "sleep" is a procedure for making the program sleep for a certain amount of time from the library https://www.github.com/oded8bit/Assembly-Lib

How can I make it so the procedure generateBasicRandomNumber generates different numbers too?

Tal
  • 21
  • 2
  • 1
    That's not a random number generator, that's just reading a timestamp(?) repeatedly, at `0040h:006Ch`, really inefficiently resetting ES every time. Use that once to seed an actual PRNG, like xorshift, LFSR, or an LCG (linear congruential generator) – Peter Cordes Jun 21 '21 at 16:24

1 Answers1

2

Your source of random numbers is the BIOS.TimerTick at address 046Ch. that's a value that only ever changes some 18 times per second! You need a better source of (pseudo) randomness.

This post has an example: 8086 random number generator (not just using the system time)?


Sometimes, it logs a message that says there has been an illegal write to some address or an illegal read from there.

That could come from a segment register that has the wrong value.
Your generateBasicRandomNumber procedure clobbers the ES segment register. Best preserve it like so:

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

     ...

     POP  ES
     ret
endp generateBasicRandomNumber
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • the problem is that the code in the link generates a 16-bit random number. I need a random number between 0-9. – Tal Jun 21 '21 at 16:51
  • 2
    @Tal Well that's precisely what the code in the link does. Look carefully and you'll find that there is a division that produces a remainder between 0 and 9. – Sep Roland Jun 21 '21 at 16:53