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

时间:2019-05-27 01:34:39

标签: assembly x86 masm irvine32

我的程序接受用户输入(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

以下是我当前的输出结果 enter image description here

以下是我希望我的输出看起来像的样子: enter image description here

1 个答案:

答案 0 :(得分:1)

我将继续将我的评论变成答案,以便我们结束这个问题。

我认为OP遇到的问题来自以下代码:

onChange

如您所见,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 加载。在此存储有关条目数量的用户输入。然后,代码遍历位于edi处的生成的随机数数组。

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

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

这意味着,我们正在读/写超出分配空间的末尾。这就是为什么输出为垃圾的原因。

这似乎适用于较少数量的条目的原因是列表的空间已预先分配(显然是零填充?)。由于排序是“降序”的,因此所有零看起来都不需要移动。

虽然我还没有从头到尾都进行过追踪,但至少这将是一个问题。

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