0

私はx86アセンブリ言語に取り組んでいます。間隔 [0,5] 内の randomrange を使用して、1 つは列で、もう 1 つは行である 2 つのパラメーターを取得したいと考えています。ここでは、乱数を 6 で割り、割り算の余りである DL に残りの数を取得することで間隔を調整しようとしました。

以前にランダム化した数値を保持し、要素が既に 1 の場合はランダム化に戻る配列も実装しました。これは、row*6+col を使用してインデックスをチェックしますが、この配列はまだ有効ではありません。

セグメンテーション違反が発生しました。何が問題なのですか?

TITLE Program Template     (template.asm)


INCLUDE Irvine32.inc
INCLUDE macros.inc

.data
onezero BYTE 36 DUP(0)

row BYTE 0
col BYTE 0
.code
main PROC

_again:

call randomrange
mov bx, 6
div bx
mov row, dl

call randomrange
div bx
mov col, dl

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

main ENDP

END main
4

2 に答える 2

1

Irvine'sRandomRangeは、数値範囲の数値を返します。したがって、EAX の引数として範囲が必要です。EAX はゼロであってはならないことを考慮してください。そうしないと、「ゼロ除算」例外が発生します。また、プログラムにはexit.

RandomRangeMicrosoft の 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
于 2015-12-21T14:53:55.253 に答える
1

irvineRandomRange関数には既に次の機能があります。

; Returns an unsigned pseudo-random 32-bit integer
; in EAX, between 0 and n-1. Input parameter:
; EAX = n.

また、 :と notdiv bxから形成された 32 ビット数を分割していることにも注意してください。dxaxeax

segfault については、デバッガーを使用してクラッシュの場所を確認してください。

于 2013-05-19T13:12:25.027 に答える