使用选择排序排序的随机数数组 - 大小 > 130 的垃圾字符输出

Random number array sorted with Selection Sort -- garbage characters output for size > 130

我的程序接受用户输入(10 到 200 之间的整数)并打印出输入的随机数并将它们存储在一个数组中。然后数组被排序并打印出来(见下图)。数字的中位数也打印在屏幕上。

我没能找到错误。该程序完美适用于小于或等于 130 但不超过 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

下面是我的输出目前的样子

下面是我希望输出的样子:

我将继续把我的评论变成一个答案,这样我们就可以结束这个问题了。

我相信 OP 遇到的问题来自这段代码:

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

如您所见,ecx 从 [ebp+8] 加载。这是存储有关条目数的用户输入的位置。然后代码遍历位于 edi 的生成的随机数数组。

第一次执行此代码时,ebx 从 0 开始。因此它安全地遍历列表中的(比方说)200 个条目。

然而,在随后的遍历中,ebx 可以大于 0。但是,ecx 仍然是 200。所以我们仍然要遍历 200 个条目,但我们不再从索引零开始。

这意味着,我们 reading/writing 已超过分配的 space。这就是为什么输出是垃圾的原因。

这似乎适用于较少条目的原因是列表的 space 是 pre-allocated(显然是零填充?)。由于排序是 'descending,',所有零看起来都不需要移动。

虽然我还没有追查到所有的来龙去脉,但至少这将是一个问题。

mov ecx, [ebp+8] 之后添加 sub ecx, ebx 的简单修复似乎可以解决问题。