Irvine'sRandomRange
返回一个数字范围内的数字。因此,它需要范围作为 EAX 中的参数。考虑一下,EAX 不能为零,否则你会得到一个“被零除”的异常。此外,该程序缺少exit
.
RandomRange
调用 Irvine 的哪个算法与微软的 C 运行时库(MSVCRT.DLL)Random32
中的函数几乎相同。rand()
它基于另一个数字(称为“种子”)生成一个数字,该数字将成为新的种子。如果您不初始化第一个种子,您将始终获得相同的数字序列。用 Irvine 初始化一次Randomize
。
RandomRange
使用简单的模函数来分隔多个范围:N = rand() % EAX
. 如果Random32
(0..0xFFFFFFFF) 的范围不能均匀地分成所需范围 (0..EAX-1) 的部分,那么您会比其他数字更频繁地获得一些数字。更好地分布数字的公式:
(rand() / (RAND_MAX+1) * EAX
=> (rand() * EAX) / (RAND_MAX+1) ; RAND_MAX is 0xFFFFFFFF (according to Irvine)
这可以在汇编中轻松编程:
myRandomRange PROC USES EBX EDX
mov ebx,eax ; maximum value
call Random32 ; eax = random number
mul ebx ; rand() * EAX => EDX:EAX
mov eax, edx ; SHL EDX:EAX,32 = Divide EDX:EAX by 0x100000000 (RAND_MAX+1)
ret
myRandomRange ENDP
全体:
TITLE Program Template (template.asm)
INCLUDE Irvine32.inc
.DATA
onezero BYTE 36 DUP(0)
row BYTE 0
col BYTE 0
.CODE
myRandomRange PROC USES EBX EDX
mov ebx,eax ; maximum value
call Random32 ; eax = random number
mul ebx ; rand() * EAX => EDX:EAX
mov eax, edx ; SHL EDX:EAX,32 = Divide EDX:EAX by 0x100000000 (RAND_MAX+1)
ret
myRandomRange ENDP
main PROC
call Randomize
_again:
mov eax, 6
call myRandomRange
; mov bx, 6
; div bx
; mov row, dl
mov row, al
mov eax, 6
call myRandomRange
; div bx
mov col, al
movzx eax, row
mov ebx, 6
mul ebx
movzx ecx, col
add eax, ecx
mov edi, eax
mov al, 1
cmp al, onezero[edi]
je _again
movzx eax, row
call writeint
movzx eax, col
call writeint
exit
main ENDP
END main