Question

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
Was it helpful?

Solution 2

.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>    

OTHER TIPS

LOAD EFFECTIVE ADDRESS computes address of 2nd operand and moves it to the first operand.

lea esi,[edi+1] can be replaced with

mov esi,edi
inc esi 

if you don't mind that INC will also change ZERO flag.

You should learn cmpsb and other string instructions ASAP, they are very useful.

cmpsb can be replaced with

MOV AL,[ESI]
CMP AL,[EDI]
PUSHF
 INC ESI
 INC EDI 
POPF

After selectionSort has been called, the minimal value will be in the first field of your array. Nevertheless, if your assignment was to find a pointer to the minimal value of array, here you are:

findMinimum PROC ; Return EDI=offset of leftmost byte in array with minimal value
; Input: ESI is offset of an byte array,  ECX is the size of array
      MOV EDI,ESI  ; Initialize pointer with so far minimal value
 next:MOV AL,[ESI] ; Load next value
      CMP AL,[EDI] ; Compare with minimal value so far 
      JAE skip
      MOV EDI,ESI  ; Value loaded from [ESI] was below, so ESI is better candidate
 skip:INC ESI      ; Advance offset in array
      LOOP next
      RET
findMinimum ENDP
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top