Моя программа не будет сортировать массивы больше 130 - PullRequest
0 голосов
/ 27 мая 2019

Поэтому моя программа должна принимать пользовательский ввод (целое число от 10 до 200), распечатывать массив случайных чисел и распечатывать отсортированную версию этого массива. Однако это работает только тогда, когда я вхожу в 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

UPDATE enter image description here

enter image description here

1 Ответ

1 голос
/ 27 мая 2019

Если вы посмотрите на свои регистры, вы увидите, что edx равно 0fA4h, что больше, чем должно быть в строке, на которой он падает. ecx - отрицательное число. Это подсказка, которую выполняет ваш цикл после того, как он должен был остановиться.

Проблема в том, что ветвь greater будет проходить до ветки lesser. Это снова уменьшит значение ecx, в результате чего оно станет отрицательным, и ваш цикл будет продолжать работать до тех пор, пока вы не получите нарушение доступа.

Быстрое решение состоит в том, чтобы поместить безусловную jmp после инструкции loop под меткой greater.

Лучшее решение - объединить хвосты циклов в более простое условие:

    cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
    jle     lesser
    mov     eax, edx
lesser:
    inc     edx
    loop    secondLoop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...