Question

I am working on x86 assembly language. I want to get two parameters that one is column and other one is row, using randomrange within the interval [0,5]. Here I tried to adjust the interval by dividing the random number by 6, and getting the number remains in DL which is remainder of the division.

I also implemented an array that holds the numbers that randomized before and jumps back to randomization if the element is already 1, which uses row*6+col to check the index, but this array is not effective yet.

I get a segmentation fault, what could be the problem?

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
Was it helpful?

Solution

The irvine RandomRange function already has this functionality:

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

Also note that div bx is dividing the 32 bit number formed from dx:ax and not eax.

As for the segfault, use a debugger and see where the crash is.

OTHER TIPS

Irvine's RandomRange returns a number of a range of numbers. Therefore, it needs the range as argument in EAX. Consider, that EAX must not be zero, otherwise you'll get a "division by zero" exception. Also, the program lacks of an exit.

RandomRange calls Irvine's Random32 which algorithm is almost the same as that of the rand() function in Microsoft's C runtime library (MSVCRT.DLL). It produces a number based on another number (called "seed") which will become the new seed. If you don't initialize the first seed, you will always get the same sequence of numbers. Initialize it once with Irvine's Randomize.

RandomRange uses a simple modulo function to separate a number of the range: N = rand() % EAX. If the range of Random32 (0..0xFFFFFFFF) cannot evenly splitted into parts of the wished range (0..EAX-1), you get some numbers more frequently than others. A formula for a better distribution of the numbers:

(rand() / (RAND_MAX+1) * EAX
=> (rand() * EAX) / (RAND_MAX+1)    ; RAND_MAX is 0xFFFFFFFF (according to Irvine)

This can be easily programmed in assembly:

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

The whole bunch:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top