Irvine'sRandomRange
は、数値範囲の数値を返します。したがって、EAX の引数として範囲が必要です。EAX はゼロであってはならないことを考慮してください。そうしないと、「ゼロ除算」例外が発生します。また、プログラムにはexit
.
RandomRange
Microsoft の C ランタイム ライブラリ (MSVCRT.DLL) の関数Random32
とほぼ同じアルゴリズムであるIrvine を呼び出します。rand()
新しいシードとなる別の番号 (「シード」と呼ばれる) に基づいて番号を生成します。最初のシードを初期化しないと、常に同じ数列が得られます。Irvine の で一度初期化しRandomize
ます。
RandomRange
単純なモジュロ関数を使用して、範囲の数値を区切ります: N = rand() % EAX
. (0..0xFFFFFFFF)の範囲がRandom32
希望する範囲 (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