Search code examples
sortingassemblyx86masmirvine32

How do you do a selection sort in MASM Assembly?


So I'm trying to sort an array in ascending order, and it just doesn't seem to work for me. I know my swap procedure is wrong, and my minIndex procedure only works half the time, but the randomly filled array generates just fine.

Working Code Thanks to vitsoft:

include Irvine32.inc

; Constants
    NUM_INTEGERS = 20
    NUM_RANGE = 99d
    TO_ENSURE_NOT_ZERO = 1d

.data
; Declare Arrays
; Declare Array of 20 Integers
    array byte NUM_INTEGERS dup(?)

; Displayed Annotation for Unsorted Array
    unsortedArrayText byte "Randomly Generated Array, Unsorted: ", 0dh, 0ah, 0

; Displayed Annotation for Sorted Array
    sortedArrayText byte "Randomly Generated Array, Sorted from Lowest to Highest: ", 0dh, 0ah, 0

.code
main PROC
; Get Random Values for Array
    call fillArrayRandomly

; Display Array with Annotation
    mov edx, offset unsortedArrayText
    call WriteString

    mov ecx, offset array
    push ecx
    call displayArray

; Sort Array
    mov esi, offset array
    mov ecx, NUM_INTEGERS
    call findMinimum

    mov edi, offset array
    mov ecx, NUM_INTEGERS
    call selectionSort

; Display Sorted Array with Annotation
    mov edx, offset sortedArrayText
    call WriteString

    mov ecx, offset array
    push ecx
    call displayArray

; Exit Program
    exit
main endp

; Fill Array with Random Values
fillArrayRandomly PROC
; Set Counter to NUM_INTEGERS and Index to 0
    mov eax, 0
    mov ecx, NUM_INTEGERS
    mov esi, 0

getRandomNumber:
; Fill Array with Random Numbers and Increment ESI for Offset
    mov ah, NUM_RANGE
    call RandomRange
    add ah, TO_ENSURE_NOT_ZERO

testUniqueness:
    mov al, array [esi]
    cmp al, ah
    jne uniqueNumber
    loop getRandomNumber

uniqueNumber:
    mov array [esi], ah
    inc esi
    loop getRandomNumber

    ret
fillArrayRandomly ENDP

; Display Array
displayArray PROC
    pushad
    mov eax, 0
    mov ecx, NUM_INTEGERS
    mov esi, 0

display:
    mov al, array[esi]
    call WriteDec
    mov al, TAB
    call WriteChar
    inc esi
    loop display

    popad
    call Crlf
    ret
displayArray ENDP

; Selection Sort
selectionSort PROC
    dec ecx
    mov ebx, edi
    mov edx, ecx

startOuterLoop:
    mov edi, ebx
    mov esi, edi
    inc esi
    push ecx
    mov ecx, edx

startInnerLoop:
    mov al, [esi]
    cmp al, [edi]
    pushf
    inc esi
    inc edi
    popf
    jae doNotSwap
    call swap

doNotSwap:
    loop startInnerLoop
    pop ecx
    loop startOuterLoop

    ret
selectionSort ENDP

; Find Minimum Index
findMinimum PROC
    mov edi, esi

minimumIndex:
    mov al, [esi]
    cmp al, [edi]
    jae skip
    mov edi, esi

skip: 
    inc esi
    loop minimumIndex

    ret
findMinimum ENDP

; Swap
swap PROC
    mov al, [esi - 1]
    mov ah, [edi - 1]
    mov [esi - 1], ah
    mov [edi - 1], al

    ret
swap ENDP

END main

Solution

  • .data
    unsortedArrayText DB "Randomly Generated Array, Unsorted: ", 0dh, 0ah, 0
    sortedArrayText   DB "Randomly Generated Array, Sorted from Lowest to Highest: ", 0dh, 0ah, 0 
    array             DB "An array of bytes (characters) which will be sorted"
    NewLine           DB 0dh, 0ah, 0
    NUM_INTEGERS      EQU NewLine - array ; Number of integers (characters) in array  
    .code
    
    main PROC
    ; Display Array with Annotation
    ; mov edx, offset unsortedArrayText
    ; call WriteString
    ConsoleWrite unsortedArrayText
      ; push offset array
      ; call displayArray
    ConsoleWrite array
    
    ; Sort Array
      ;   push offset array
      ;   call selectionSort
    MOV EDI,array
    MOV ECX,NUM_INTEGERS
    CALL selectionSort
    
    ; Display Sorted Array with Annotation
       ; mov edx, offset sortedArrayText
       ; call WriteString
    ConsoleWrite sortedArrayText
       ; push offset array
       ; call displayArray
    ConsoleWrite array
    ; Exit Program
        ;exit
     TerminateProgram
    main endp
    
    ; Selection Sort
    selectionSort PROC ; Bubble sort ECX byte array pointed to with EDI
        DEC ECX        ; Number of compare is NUM_INTEGERS-1
        MOV EBX,EDI    ; Save array pointer to EBX
        MOV EDX,ECX    ; Save number of compare to EDX
    OuterLoop:
        MOV EDI,EBX    ; Restore array pointer     
        LEA ESI,[EDI+1] ; Neibourghing field
        PUSH ECX        ; Save OuterLoop counter on stack
         MOV ECX,EDX     ; Initialize InnerLoop counter
    InnerLoop:    
         CMPSB ; compare the first byte [EDI] with its neibourgh [ESI], advance EDI,ESI
         JAE NoSwap
         CALL swap
    NoSwap:
         LOOP InnerLoop
        POP ECX     ; Restore OuterLoop counter
        LOOP OuterLoop
        RET
    selectionSort ENDP
    
    swap PROC ; Swap bytes at [EDI-1] and [ESI-1]
         MOV AL,[ESI-1]
         MOV AH,[EDI-1]
         MOV [ESI-1],AH
         MOV [EDI-1],AL
         RET
    swap ENDP
    

    This worked well, statically defined array was sorted in few miliseconds:

    C:\ASM>bubblesortexample.exe
    Randomly Generated Array, Unsorted:
    An array of bytes (characters) which will be sorted
    Randomly Generated Array, Sorted from Lowest to Highest:
            ()Aaaaabbcccdeeeefhhhiillnoorrrrrssstttwwyy
    C:\ASM>