0

我正在研究 x86 汇编语言。我想得到两个参数,一个是列,另一个是行,使用区间 [0,5] 内的随机范围。在这里,我尝试通过将随机数除以 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

irvineRandomRange函数已经有这个功能:

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

另请注意,除以:和 notdiv bx形成的 32 位数字。dxaxeax

至于段错误,使用调试器,看看崩溃在哪里。

于 2013-05-19T13:12:25.027 回答
1

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
于 2015-12-21T14:53:55.253 回答