sorting - assembly 中的选择排序过程

标签 sorting assembly x86 masm irvine32

我认为我的交换以及如何访问数组中的元素遇到了问题。现在,所有代码都会运行,但排序后列表不会改变。他是我想要实现的高级类型

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]);
}

这是汇编代码。注意:作业是关于将元素压入/弹出堆栈的,因此我无法更改参数。

;this is a library with macros for things like printing numbers and strings    
INCLUDE Irvine32.inc

    MIN = 10            ;lower range limit
    MAX = 200           ;upper range limit
    LRANGE = 100        
    HRANGE = 999        

.data

;title, intro, and prompts
    title_1     BYTE    "PROGRAMMING ASSIGNMENT 5: RANDOM GEN/SORT", 0dh, 0ah, 0

    intro_1     BYTE    "This program generates random numbers in the range (100 - 999),", 0dh, 0ah
        BYTE    "displays the original list, sorts the list, and calculates the median value.", 0dh, 0ah
        BYTE    "Finally, it displays the sorted list in descending order.", 0dh, 0ah, 0

    prompt_1    BYTE    "How many numbers should be generated? (10 - 200): ", 0 

    error_1     BYTE    "Out of range.", 0dh, 0ah, 0

    display_1   BYTE    "List of random numbers: ", 0dh, 0ah, 0
    display_2   BYTE    "The median is: ", 0
    display_3   BYTE    "The sorted list: ", 0dh, 0ah, 0

;placeholders for user entries and calculated data
    randArray   DWORD   MAX DUP(?)
    userNum     DWORD   ?           ;integer to be entered by user

;strings for posting results
    goodBye_1   BYTE    "Thank you for using the Gen/sort-ulator! Good-bye!", 0


.code
main PROC
    call    Randomize

;Title Screen
    push    OFFSET  title_1
    push    OFFSET  intro_1
    call    Intro

;Get and validate user numbers
    push    OFFSET  error_1
    push    OFFSET  prompt_1
    push    OFFSET  userNum
    call    GetData

;Fill Array with random numbers
    push    OFFSET  randArray
    push    userNum
    call    FillArray

;display unsorted results
    push    OFFSET  randArray
    push    userNum
    push    OFFSET  display_1
    call    DisplayList

;sort the results
    push    OFFSET  randArray
    push    userNum
    call    SortList

;display the median
    push    OFFSET  randArray
    push    userNum
    push    OFFSET  display_2
    call    median

;display sorted results
    push    OFFSET  randArray
    push    userNum
    push    OFFSET  display_3
    call    DisplayList

;Say "goodbye"
    push    OFFSET  goodBye_1
    call    Goodbye

    exit        ; exit to operating system
main ENDP

;-------------------------------------------------------
;Gives an Intro to the program
; Receives parameters on the system stack (in the order pushed):
;       Address of the title
;       Address of the intro
;post: intro displayed
;registers: none
;-------------------------------------------------------
Intro PROC
    pushad
    mov     ebp, esp
    mov     edx, [ebp+40]
    call    writeString
    call    CrLf
    mov     edx, [ebp+36]
    call    writeString
    call    CrLf
    popad
    ret     8
Intro   ENDP

;-------------------------------------------------------
;Prompts user for an integer, int stores in userNum
; Receives parameters on the system stack (in the order pushed):
;       Address of the error message
;       Address of the prompt
;       Address of return value
;Post: userNum
;registers: none
;-------------------------------------------------------
GetData PROC
    pushad

;setup stack and prompt for entry   
    mov     ebp, esp
reenter:
    mov     edx, [ebp+40]
    mov     ebx, [ebp+36]
    call    WriteString
    call    ReadInt

;validate entry
    cmp     eax, MIN            ;if eax < LOWER
    jl      badEntry            ;jump to summary 
    cmp     eax, MAX            ;if eax > UPPER
    jg      badEntry            ;reprompt 
    jmp     goodEntry           ;else jump to end, we have a good value

;bad entry reprompt
badEntry:
    mov     edx, [ebp+44]
    call    WriteString
    jmp     reenter

goodEntry:
    call    CrLf
    mov     [ebx], eax
    popad
    ret     12
GetData ENDP

;-------------------------------------------------------
;Fills array with a number of random integers within RANGE
;Recieves parameters on the system stack (in order pushed)
;       array
;       userNum
;Post: array is filled with userNum number of randoms
;Registers used: none
;-------------------------------------------------------
FillArray   PROC
    pushad
    mov     ebp, esp    
    mov     ecx, [ebp+36]           ;initialize loop counter with user entry
    mov     edi, [ebp+40]           ;setup array offset
    fillLoop:
    call    nextRand
    add     edi, 4  
    loop    fillLoop
    popad
    ret     8
FillArray   ENDP

;-------------------------------------------------------
; Procedure nextRand
; adapted from check lecture 20 solutions
; Procedure to get the next random number in the range specified by the user.
; Preconditions:  LRANGE < HRANGE
; Registers used:  eax, edi
;-------------------------------------------------------
nextRand    PROC            
    mov     eax, HRANGE
    sub     eax, LRANGE
    inc     eax                 ;add 1 to get the number of integers in range
    call    RandomRange 
    add     eax, LRANGE         ;eax has value in [LOW - HIGH]
    mov     [edi],eax       
    ret                     
nextRand    ENDP

;-------------------------------------------------------
;Sorts the contents of an integer array
; Receives parameters on the system stack (in order pushed)
;           Array
;           Array Size
;registers: none
;-------------------------------------------------------
sortList    PROC
    pushad
    mov     ebp, esp
    mov     ecx, [ebp+36]
    mov     edi, [ebp+40]
    dec     ecx                 ;ecx < request-1
    mov     ebx, 0              ;ebx=k

;for(k=0; k<request-1; k++)
outerLoop:
    mov     eax, ebx            ;eax=i=k
    mov     edx, eax
    inc     edx                 ;edx=j=k+1
    push    ecx
    mov     ecx, [ebp+36]       ;ecx < request

;for(j=k+1; j<request; j++)
innerLoop:
    mov     esi, [edi+edx*4]
    cmp     esi, [edi+eax*4]
    jle     skip
    mov     eax, edx
skip:
    inc     edx
    loop    innerLoop

;swap elements
    lea     esi, [edi+ebx*4]
    push    esi
    lea     esi, [edi+eax*4]
    push    esi
    call    exchange
    pop     ecx
    inc     ebx
    loop    outerLoop

    popad
    ret     8
sortList    ENDP

;-------------------------------------------------------
; Exchange k and i
; Receives parameters on the system stack (in order pushed)
;           array[k]
;           array[i]
;registers: none
;-------------------------------------------------------
Exchange    PROC
    pushad
    mov     ebp,esp
    mov     eax, [ebp+40]       ;array[k] low number
    mov     ecx, [eax]
    mov     ebx, [ebp+36]       ;array[i] high number
    mov     edx, [ebx]
    mov     [eax], edx
    mov     [ebx], ecx
    popad       
    ret 8
Exchange    ENDP


;-------------------------------------------------------
;Displays the median of an integer array
; Receives parameters on the system stack (in order pushed)
;           Array
;           Array Size
;           display string
;registers: none
;-------------------------------------------------------
Median PROC
    pushad
    mov     ebp, esp
    mov     edi, [ebp+44]
;display string
    mov     edx, [ebp+36]
    call    writeString

;calculate median element
    mov     eax, [ebp+40]
    cdq
    mov     ebx, 2
    div     ebx
    shl     eax, 2
    add     edi, eax
    cmp     edx, 0
    je      isEven
;Array size is odd, so display the middle value         
    mov     eax, [edi]
    call    writeDec
    call    CrLf
    call    CrLf
    jmp     endMedian
isEven:
;Array size is even so average the two middle values
    mov     eax, [edi]
    add     eax, [edi-4]
    cdq     
    mov     ebx, 2
    div     ebx
    call    WriteDec
    call    CrLf
    call    CrLf
endMedian:
    popad
    ret 12
Median ENDP

;-------------------------------------------------------
;Displays the contents of an integer array, 10 per row
; Receives parameters on the system stack (in order pushed)
;           Array
;           Array Size
;           display string
;registers: none
;-------------------------------------------------------
DisplayList PROC
    pushad
    mov     ebp, esp

;display string
    mov     edx, [ebp+36]
    call    writeString
    call    CrLf
    mov     ecx, [ebp+40]
    mov     edi, [ebp+44]
    mov     ebx, 0

;display array contents
listloop:
    inc     ebx             ;counter for 10 items per row
    mov     eax, [edi]      
    call    writeDec
    add     edi, 4
    cmp     ebx, 10
    jne     noReturn        ;jump if 10 items are not yet printed
    call    CrLf
    mov     ebx, 0
    jmp     noTab           ;this skips adding a tab on a new row
noReturn:
    mov     al, TAB
    call    writeChar
noTab:
    loop listloop
    call    CrLf
    popad
    ret 12
DisplayList ENDP

;-------------------------------------------------------
;Says good-bye to the user
; Receives parameters on the system stack:
;       Address of string
;registers: none
;-------------------------------------------------------
Goodbye PROC
    pushad
    mov     ebp, esp
    mov     edx, [ebp+36]
    call    writeString
    call    CrLf
    popad
    ret     4
Goodbye ENDP

END main

最佳答案

为了交换元素,您应该传递它们的地址(换句话说,指向每个元素的指针)。您所做的只是交换作为参数传递的值,这些值也立即被释放。您的代码相当于此 C 函数:

void Exchange(int x, int y)
{
    int eax = x;
    int ebx = y;
    x = ebx;
    y = eax;
}

你需要这样的东西:

void Exchange(int* x, int* y)
{
    int eax = *x;
    int ebx = *y;
    *x = ebx;
    *y = eax;
}

在 asm 中,这可能看起来像:

Exchange    PROC
    pushad
    mov     eax, [esp+40]
    mov     ecx, [eax]
    mov     ebx, [esp+36]       
    mov     edx, [ebx]
    mov     [eax], edx
    mov     [ebx], ecx
    popad       
    ret 8
Exchange    ENDP

要调用此函数,您将使用以下命令:

    lea     esi, [edi+ebx*4]
    push    esi
    lea     esi, [edi+eax*4]
    push    esi
    call    Exchange

请注意,您的 Exchange 函数有一条指令 mov eax, [edi],我无法理解它。

更新:是的,您可以通过手动计算来模拟LEA的功能。例如,lea esi, [edi+ebx*4] 变为:

    mov esi, ebx
    shl esi, 2    ; esi=ebx*4
    add esi, edi  ; esi=edi+ebx*4

关于sorting - assembly 中的选择排序过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13407151/

相关文章:

algorithm - 查找链表中的乱序元素

.s文件可以直接执行吗?

c++ - 汇编的 c++ 似乎包含多余的指令

python - 桶排序比快速排序更快

python - 将排列应用于列表的就地方法? (与按键排序相反)

php - 自然排序关联数组?

assembly - 为什么 ARM7 上 MUL 表达式的前两个参数不能相同?

linux - 为什么 gcc 为 x64 共享库强制 PIC?

c - gcc 删除内联汇编代码

assembly - MMX 和 XMM 寄存器之间的区别?