Random number array sorted with Selection Sort — g

2019-08-18 22:22发布

My program takes user input (integer between 10 and 200) and prints out the entered number of random numbers and stores them in an array. Then the array is sorted and printed out (SEE IMAGE BELOW). The median is of the numbers are also printed on the screen.

I have not been able to find the error. The program works perfectly for numbers less than or equal to 130, but not over 130.

TITLE Program5    (Program5.asm)

INCLUDE Irvine32.inc

; (insert constant definitions here)
    MIN_INPUT = 10
    MAX_INPUT = 200
    LO_RANDOM = 100
    HI_RANDOM = 999

.data
request         DWORD   10
ask_user        BYTE    "How many numbers should be generated? [10 ... 200]: ", 0
error           BYTE    "Invalid input", 0

title_1         BYTE    "The unsorted random numbers: ", 0
title_2         BYTE    "The sorted list: ", 0
space           BYTE    "   ", 0
median          BYTE    "The median is: ", 0
temp            DWORD   0
list            DWORD   MAX_INPUT   DUP(?)

.code
main PROC

; (insert executable instructions here)
    call    randomize

    push    OFFSET request ;passed by reference
    call    getData

    call    CrLf

    push    request ; passed by value
    push    OFFSET list ; passed by reference
    call    fillArray

    push    OFFSET list
    push    request
    push    OFFSET title_1
    call    displaylist

    push    OFFSET list
    push    request
    call    sortList

    push    OFFSET list
    push    request
    call    displayMedian

    call    CrLf
    call    CrLf

    push    OFFSET list
    push    request
    push    OFFSET title_2
    call    displaylist

    exit    ; exit to operating system
main ENDP

; (insert additional procedures here)
getData PROC

    push    ebp ;Set up stack frame
    mov     ebp, esp

    ;get an integer from user
    mov     ebx, [ebp+8]    ;get address of request into ebx

    L1:
        mov     edx, OFFSET ask_user
        call    WriteString
        call    ReadDec

        cmp     eax, MIN_INPUT
        jl      errorMessage
        cmp     eax, MAX_INPUT
        jg      errorMessage

        cmp     eax, MIN_INPUT
        jge     endThis
        cmp     eax, MAX_INPUT
        jle     endThis

    errorMessage:
        mov     edx, OFFSET error
        call    WriteString
        call    CrLf
        jmp     L1

    endThis:
        mov     [ebx], eax
        pop     ebp
        ret     4 ; remove four more bytes from the stack (after ret @)

getData ENDP

fillArray PROC
;include parameters - request (value), array (reference)
    ; MAJORITY OF THE FOLLOWING CODE WAS EXTRACTED FROM LECTURE 20 SLIDES
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+8] ; @list in edi
    mov     ecx, [ebp+12] ; value of request in ecx

    more:
        mov     eax, HI_RANDOM
        sub     eax, LO_RANDOM
        inc     eax
        call    RandomRange
        add     eax, LO_RANDOM

        mov     [edi], eax
        add     edi, 4
        loop    more

    endmore:
        pop     ebp
        ret     8
fillArray ENDP

sortList PROC
    push    ebp
    mov     ebp, esp
    mov     edi, [ebp+12]
    mov     ecx, [ebp+8]

    dec     ecx
    mov     ebx, 0

    firstLoop:
        mov     eax, ebx
        mov     edx, ebx
        inc     edx
        push    ecx
        mov     ecx, [ebp+8]

        secondLoop:
            mov     esi, [edi + (edx * 4)]
            cmp     esi, [edi + (eax * 4)]
            jle     lesser
            mov     eax, edx    
        lesser:
            inc     edx
            loop    secondLoop

        push    edx
        push    esi
        push    [edi + (ebx * 4)] ; array[k]
        push    [edi + (eax * 4)] ; array[i]
        call    exchangeElements
        pop     [edi + (eax * 4)]
        pop     [edi + (ebx * 4)]
        pop     esi
        pop     edx
        pop     ecx ; set the 
        inc     ebx ; increment k in the first loop
        loop    firstLoop

    pop     ebp
    ret     8

sortList ENDP

exchangeElements PROC
    push    ebp
    mov     ebp, esp
    mov     esi, [ebp+12] ; array[k]
    mov     edx, [ebp+8] ; array[i]
    mov     [ebp+8], esi
    mov     [ebp+12], edx
    pop     ebp
    ret     
exchangeElements ENDP

displayMedian PROC
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    mov     eax, ecx
    mov     ebx, 2
    cdq
    div     ebx
    cmp     edx, 0
    je      isEven
    cmp     edx, 1
    je      isOdd

    ; https://github.com/TRMassey/CS271/blob/master/assignment5.asm
    isEven:
        ; find the higher number
        mov     ebx, 4
        mul     ebx
        add     edi, eax
        mov     edx, [edi]

        ; find the lower number
        mov     eax, edi
        sub     eax, 4
        mov     edi, eax
        mov     eax, [edi]

        ; add and divide them by 2
        add     eax, edx
        mov     edx, 0
        mov     ebx, 2
        cdq
        div     ebx

        ; print out the median value (rounded to the nearest int)
        call    CrLf
        call    CrLf
        mov     edx, OFFSET median
        call    WriteString
        call    WriteDec
        jmp     finish

    isOdd:
        mov     eax, [edi + (eax * 4)]
        call    CrLf
        call    CrLf
        mov     edx, OFFSET median
        call    WriteString
        call    WriteDec
        jmp     finish

    finish:
        pop ebp
        ret
displayMedian ENDP

displayList PROC
    push    ebp
    mov     ebp, esp ; [ebp+4]
    mov     ecx, [ebp+12] ; @request
    mov     edi, [ebp+16] ; @list
    mov     esi, 10

    mov     edx, [ebp+8] ; @title
    call    WriteString
    call    CrLf

    show:
        mov     eax, [edi]
        call    WriteDec
        mov     edx, OFFSET space
        call    WriteString
        add     edi, 4

        dec     esi
        cmp     esi, 0
        je      callClear

    loopAgain:
        loop    show

    jmp     endshow

    callClear:
        mov     esi, 10
        call    CrLf
        jmp     loopAgain

    endshow:
        pop     ebp
        ret     12

displayList ENDP

END main

Below is what my output currently looks like enter image description here

Below is what I want my output to look like: enter image description here

1条回答
Fickle 薄情
2楼-- · 2019-08-18 22:39

I'm going to go ahead and turn my comments into an Answer so we can close this question.

I believe the problem OP is experiencing comes from this code:

mov     ebx, 0

firstLoop:
    mov     eax, ebx
    mov     edx, ebx
    inc     edx
    push    ecx
    mov     ecx, [ebp+8]

    secondLoop:
        mov     esi, [edi + (edx * 4)]
        cmp     esi, [edi + (eax * 4)]
        jle     lesser
        mov     eax, edx    
    lesser:
        inc     edx
        loop    secondLoop

As you can see, ecx gets loaded from [ebp+8]. This is where the user input regarding the number of entries is stored. The code then walks over the array of generated random numbers located at edi.

The very first time this code is executed, ebx starts at 0. So it safely walks the (say) 200 entries in the list.

However, on subsequent passes, ebx can be larger than 0. But, ecx is still 200. So we're still going to walk 200 entries, but we are no longer starting at index zero.

Which means, we're reading/writing past the end of the allocated space. Which is why the output is junk.

The reason this seems to work for smaller numbers of entries is that the space for the list is pre-allocated (and apparently zero filled?). Since the sort is 'descending,' the zeros all look like they don't need to be moved.

While I haven't traced thru all the ins and outs of the sort, at a minimum this is going to be a problem.

A simple fix of adding sub ecx, ebx right after mov ecx, [ebp+8] seems to resolve the problem.

查看更多
登录 后发表回答