为啥我的选择排序代码不起作用?

Posted

技术标签:

【中文标题】为啥我的选择排序代码不起作用?【英文标题】:Why isn't my selection sort code working?为什么我的选择排序代码不起作用? 【发布时间】:2013-05-16 17:58:47 【问题描述】:

我正在学习汇编。我需要使用选择排序来对整数列表进行排序。我在交换函数上花了几个小时,但我无法弄清楚为什么我的程序在以下步骤停止编译:mov [eax]、edx & mov [ebx]、ecx。问题在于排序功能和交换功能。有人可以看看并给我一些指导。非常感谢!

(更新:我的代码现在可以编译 - 问题已解决)

    INCLUDE Irvine32.inc

MIN_NUM = 10
MAX_NUM = 200
LOW_VAL = 100
HIGH_VAL = 999

.data

intro_1         BYTE    "Sorting Random Integers", 0
intro_2         BYTE    "This program generates random numbers in the range [100...999], ", 0
intro_3         BYTE    "displays the original list, sorts the list, and calculate the ", 0
intro_4         BYTE    "median value. Finally, it displays the list sorted in descending order.", 0
prompt_1        BYTE    "How many numbers should be generated? [10 ... 200]: ", 0   
error_msg       BYTE    "Invalid input", 0
request         DWORD   ?
sortArr         DWORD   MAX_NUM DUP(?)
cnt             DWORD   0       ;count of elements in array

displayRes_1    BYTE    "The unsorted random numbers:", 0
displayRes_2a   BYTE    "The median is ", 0
displayRes_2b   BYTE    ".", 0
displayRes_3    BYTE    "The sorted list:",0


.code
main PROC

;introduce the program
call    intro       

;get data
push    MIN_NUM
push    MAX_NUM
push    OFFSET error_msg
push    OFFSET request
call    getRequest  

;generate random integers and put them into the array
push    LOW_VAL
push    HIGH_VAL
push    OFFSET sortArr
push    request
call    fillArray

;display list
push    cnt
push    OFFSET sortArr
push    request
push    OFFSET displayRes_1
call    displayList

;sort list - selection sort
push    OFFSET sortArr
push    request
call    sortList_desc


;display median

;display list
push    cnt
push    OFFSET sortArr
push    request
push    OFFSET displayRes_3
call    displayList

    exit    ; exit to operating system
main ENDP

; ***************************************************************
;Procedure to introduce the program.
;receives: none
;returns: none
;preconditions:  none
;registers changed: edx
; ***************************************************************

intro PROC
    ;display introductions line 1
    mov     edx, OFFSET intro_1
    call    WriteString
    call    CrLf
    ;display introductions line 2
    mov     edx, OFFSET intro_2
    call    WriteString
    call    CrLf
    ;display introductions line 3
    mov     edx, OFFSET intro_3
    call    WriteString
    call    CrLf
    ;display introductions line 4
    mov     edx, OFFSET intro_4
    call    WriteString
    call    CrLf
    call    CrLf

    ret
intro ENDP

; ***************************************************************
;Procedure to get a request from the user.
;Implementation note: This procedure accesses its parameters by setting up a
;   "stack frame" and referencing parameters relative to the top of the 
;   system stack.  
;receives: addresses of parameters on the system stack
;returns: user input values for the reference
;preconditions:  none
;registers changed: eax, ebx, edx
; ***************************************************************

getRequest PROC
    push    ebp
    mov     ebp, esp
    mov     edx, OFFSET prompt_1    
    call    WriteString             ;prompt user
    call    ReadInt                 ;get user's request
    call    CrLf
    call    CrLf
    cmp     eax, [ebp+20]           ;valid user input           
    jl      input_notOK
    cmp     eax, [ebp+16]           ;valid user input
    jg      input_notOK
    mov     ebx, [ebp+8]            ;address of request in ebx
    mov     [ebx], eax              ;store user input to the variable, request
    jmp     theEnd
    input_notOK:                    
        mov     edx, [ebp+12]       ;address of error_msg in edx
        call    WriteString
        call    CrLf
        pop     ebp
        jmp     getRequest
    theEnd:
        pop ebp
        ret 16          
getRequest ENDP

; ***************************************************************
; Procedure to put random integers into the array.
; receives: addresses of parameters on the system stack
; returns: an array of random integers
; preconditions: request is the user input we received earlier
; registers changed: eax, ecx, edi
; ***************************************************************

fillArray PROC
    push    ebp
    mov     ebp, esp
    mov     ecx, [ebp+8]
    mov     edi, [ebp+12]
    call    Randomize
    ;generate random integer for each element in the array
    ;adapted from Lecture 20 slides
    randGen:
        mov     eax, [ebp+16]   ;get HIGH_VAL
        sub     eax, [ebp+20]   ;HIGH_VAL - LOW_VAL
        inc     eax             
        call    RandomRange 
        add     eax, [ebp+20]   
        mov     [edi], eax
        add     edi, 4
        loop    randGen
    endRandGen:
        pop ebp
        ret 16

fillArray ENDP

; ***************************************************************
; Procedure to sort the array
; receives: addresses of parameters on the system stack
; returns: an array of sorted integers
; preconditions: an array filled with random integers
; registers changed: eax, ecx, edi
; ***************************************************************

sortList_desc PROC
    push    ebp
    mov     ebp, esp
    mov     edi, [ebp+12]   ;address of array in edi
    mov     ecx, [ebp+8]    ;loop control in loop_1 ecx = request-1
    dec     ecx             ;ecx-1 because single element is also maximum element
    mov     ebx, 0          ;"index" in ebx (index=k)

    ;for (int i=k, i<request-1;i++)
    loop_1:
        ;find the index of the biggest element
        ;assume the first element is the biggest (i=k)
        mov     eax, ebx        ;store biggest index in eax (eax=i=k)

        ;test against elements after finding the biggest
        ;for (j = k + 1; j < request; j++)
        mov     edx, eax
        inc     edx                     ;edx=j=k+1
        push    ecx                     ;save ecx register 
        mov     ecx, [ebp+8]            ;loop control in loop_2 ecx = request

        loop_2:
        mov     esi, [edi+edx*4]        ;store sortArr[j] in esi
        cmp     esi, [edi+eax*4]        ;compare sortArr[j] and sortArr[k] 
        jle     not_bigger
                                        ;if edx is bigger, it is the new max value 
        mov     eax, edx                ;found new biggest index, replace the old biggest index
    not_bigger:
        inc     edx             ;next element
        loop    loop_2

        ;eax is the maximum index(i), swap it with the current position (k)
        ;exchange (array[k], array[i])
        push    [edi+ebx*4]                  
        push    [edi+eax*4]             
        pop     [edi+ebx*4]
        pop     [edi+eax*4]
        pop     ecx         ;restore ecx register
        inc     ebx         ;next iteration of loop_1
        loop    loop_1      

    pop ebp
    ret 8
sortList_desc ENDP

【问题讨论】:

它是停止编译,还是在该行运行时崩溃? @MichaelDorgan 它给了我一条错误消息:Project.exe 已停止工作。一个问题导致程序停止正常工作。 【参考方案1】:

为什么需要交换功能?

IMO 这也应该进行交换:

    push [edi+ebx*4]
    push [edi+eax*4]
    pop [edi+ebx*4]
    pop [edi+eax*4]

这不会解决您的段错误,但会降低复杂性。

你是从 C 函数中调用它吗?如果是,那么这就是错误。我删除了它,它对我有用。

ret 8

应该是:

ret

编译器在 C 调用中清理堆栈,所以你也不应该这样做。 :)

【讨论】:

欢迎您。是一个很好的练习,因为我多年来没有做太多的组装。 :) 我还有一个问题。不知道能不能解释清楚。当我打印排序列表时,一切看起来都很好,直到我要求我的程序打印 110 个排序整数。我开始收到一些看起来像地址的奇怪数字(例如,543516754 等)。当我打印 200 个排序列表时,我得到的只是一堆“笑脸”符号。无论如何,你能想到会导致这种情况的任何事情吗?我正在使用 Microsoft Visual Studio。 将其作为第二个问题发布,您将获得更多关注。

以上是关于为啥我的选择排序代码不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为核密度估计选择带宽和空间。 (为啥我的带宽不起作用?)

为啥我的直系后代选择器不起作用?

为啥我的 XPath 选择文本不起作用?

本地主机上的谷歌分析:为啥我的测试代码不起作用?

为啥我的 jQuery :not() 选择器在 CSS 中不起作用?

为啥我的 jQuery :not() 选择器在 CSS 中不起作用?