问题
I am new to assembly, and I am having problems generating random numbers.
My code is simple: it generates 100 numbers in the 0-25
range and stores them in an array.
The problem I am experiencing is that when I run the con on the emu8086
assembler it runs successfully and generates 100 random numbers, that are stored in the array. But when I run it on the masm611
, it generates a new random number every 4 cycles. Which means the values in the array are consecutive same number for 4 values and then next random value is stored.
Here is my code:
.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
Is there is a problem in my code? Do I need to add something? Thanks.
回答1:
The main problem of your code is that it does not generate random numbers at all. Because the system clock is not random number generator. I would say, it is very non-random number generator.
The first time read after the start of the program still can be considered "random", but only if you run the program manually in random moment in time.
All next numbers will be not random at all.
This way, the value read from the system clock is suitable for use as a seed (starting value) of some other algorithm for generation of (pseudo)random numbers.
The random (and pseudo random) number generators are complex topic, that need some study. Start at least with wikipedia.
BTW, despite of the complexity of the topic as a whole, some random number generators are simple enough to be implemented by beginner programmers. For example middle-square-method. Try to implement it in assembly language by multiplying the current seed AX by itself and form the next number by the middle 4 hexadecimal digits of the result:
; here ax contains the previous number
mul ax
mov al, ah
mov ah, dl
; here ax contains the next pseudo random number.
回答2:
To build upon johnfound's answer, you could make a more robust random number generator by running the middle-square method he described with a Weyl sequence. This is based on ideas from Middle Square Weyl Sequence RNG, published by Bernard Widynski on 4th April 2017.
An assembly implementation could be built along the following lines:
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
A few notes about the above code:
- The random number is stored in
ax
. - The initial seed is stored in
bx
(you could for instance use something derived from the system's clock). The seed must be odd and non-zero in the 8 upper bits. - The Weyl sequence is stored in
cx
, and obtained by addingbx
at each iteration.
Unlike the standard middle-square method, combining it with a Weyl sequence prevents convergence towards 0 of the random number sequence. I recommend reading the publication mentioned above for additional information.
来源:https://stackoverflow.com/questions/35583343/generating-random-numbers-in-assembly