我的程序不会对大于 130 的数组进行排序

My program won't sort arrays that are larger than 130

所以我的程序应该接受用户输入(10 到 200 之间的整数)并打印出一个 运行dom 数字数组并打印出该数组的排序版本。但是,这仅在我输入 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

; (insert variable definitions here)
intro           BYTE    "Fun with Arrays! by ", 0
instruction     BYTE    "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order", 0

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

mult            DWORD   0.5

temp            DWORD   0

list            DWORD   MAX_INPUT   DUP(?)

.code
main PROC

; (insert executable instructions here)
    call    randomize
    call    introduction

    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

    call    CrLf

    push    OFFSET list
    push    request
    call    sortList

    call    CrLf
;
    push    OFFSET list
    push    request
    push    OFFSET title_2
    call    displaylist

    ;push   OFFSET list
    ;push   request
    ;call   displayMedian

    exit    ; exit to operating system
main ENDP

; (insert additional procedures here)
introduction PROC

    mov     edx, OFFSET intro
    call    WriteString
    call    CrLf
    mov     edx, OFFSET instruction
    call    WriteString
    call    CrLf
    ret 

introduction ENDP

getData PROC
;include parameter - request (reference)

    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
;include parameters - array (reference), request (value)
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    dec     ecx ; request - 1
    mov     ebx, 0 ; "k"

    ;for(k=0; k<request-1; k++) { 
       ;i = k; 
       ;for(j=k+1; j<request; j++) { 
          ;if(array[j] > array[i]) 
             ;i = j; 
       ;} 
       ;exchange(array[k], array[i]); 
    ;} 

    firstLoop:
        mov     eax, ebx ; "i = k"

        mov     edx, ebx ; "j = k"
        inc     edx ; "j = k + 1"
        push    ecx ; pushed the first loop's counter
        mov     ecx, [ebp+8] ; made the second loop's counter = request

        secondLoop:
            mov     esi, [edi + (edx * 4)] ; array[j] ; EXCEPTION WAS THROWN HERE
            cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
            jg      greater
            jle     lesser

            greater:
                mov     eax, edx
                inc     edx
                loop    secondLoop

            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

            ;def nlogn_median(l):
    ;l = sorted(l)
    ;if len(l) % 2 == 1:
        ;return l[len(l) / 2]
    ;else:
        ;return 0.5 * (l[len(l) / 2 - 1] + l[len(l) / 2])

    isEven:
        mov     esi, [edi + (eax - 1)]
        add     esi, [edi + (eax)]
        mov     eax, esi
        mov     ebx, 2
        cdq
        div     ebx
        call    WriteDec

    isOdd:
        mov     eax, [edi + (eax*4)]
        call    WriteDec

    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

更新

如果您查看您的寄存器,您会发现 edx0fA4h,它比崩溃所在行的应有值大。 ecx 是一个负数。这是一个线索,表明你的循环在它应该停止之后正在执行。

问题是 greater 分支会落到 lesser 分支。这将再次递减 ecx,导致它变为负数,并且您的循环将保持 运行,直到您遇到访问冲突。

快速修复是在 greater 标签下的 loop 指令之后放置一个无条件的 jmp

更好的解决方法是将循环的尾部组合成更简单的条件:

    cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
    jle     lesser
    mov     eax, edx
lesser:
    inc     edx
    loop    secondLoop