TITLE    Sorting an array by selection sort    SEL_SORT.ASM
COMMENT |
        Objective: To sort an integer array using selection sort.
            Input: Requests numbers to fill array.
|          Output: Displays sorted array.
.MODEL SMALL
.STACK 100H
.DATA
MAX_SIZE       EQU 100
array          DW  MAX_SIZE DUP (?)
input_prompt   DB  'Please enter input array: '
               DB  '(negative number terminates input)',0
out_msg        DB  'The sorted array is:',0

.CODE
.486
INCLUDE io.mac
main    PROC
        .STARTUP
        PutStr  input_prompt ; request input array
        mov     BX,OFFSET array
        mov     CX,MAX_SIZE
array_loop:
        GetInt  AX           ; read an array number
        nwln
        cmp     AX,0         ; negative number?
        jl      exit_loop    ; if so, stop reading numbers
        mov     [BX],AX      ; otherwise, copy into array
        add     BX,2         ; increment array address
        loop    array_loop   ; iterates a maximum of MAX_SIZE
exit_loop:
        mov     DX,BX        ; DX keeps the actual array size
        sub     DX,OFFSET array  ; DX := array size in bytes
        sar     DX,1         ; divide by 2 to get array size
        push    DX           ; push array size & array pointer
        push    OFFSET array
        call    selection_sort
        PutStr  out_msg      ; display sorted array
        nwln
        mov     CX,DX
        mov     BX,OFFSET array
display_loop:
        PutInt  [BX]
        nwln
        add     BX,2
        loop    display_loop
done:                        
        .EXIT
main    ENDP

;-----------------------------------------------------------
; This procedure receives a pointer to an array of integers
; and the array size via the stack. The array is sorted by
; using the selection sort. All registers are preserved.
;-----------------------------------------------------------
SORT_ARRAY  EQU  [BX]
selection_sort PROC
       pusha                 ; save registers
       mov     BP,SP
       mov     BX,[BP+18]    ; copy array pointer
       mov     CX,[BP+20]    ; copy array size
       sub     SI,SI         ; array left of SI is sorted
sort_outer_loop:
       mov     DI,SI
       ; DX is used to maintain the minimum value and AX
       ; stores the pointer to the minimum value
       mov     DX,SORT_ARRAY[SI]  ; min. value is in DX
       mov     AX,SI         ; AX := pointer to min. value
       push    CX
       dec     CX            ; size of array left of SI
sort_inner_loop:
       add     DI,2          ; move to next element
       cmp     DX,SORT_ARRAY[DI] ; less than min. value?
       jle     skip1         ; if not, no change to min. value
       mov     DX,SORT_ARRAY[DI] ; else, update min. value (DX)
       mov     AX,DI             ;       & its pointer (AX)
skip1:
       loop    sort_inner_loop
       pop     CX
       cmp     AX,SI         ; AX = SI?
       je      skip2         ; if so, element at SI is its place
       mov     DI,AX         ; otherwise, exchange
       mov     AX,SORT_ARRAY[SI]  ; exchange min. value 
       xchg    AX,SORT_ARRAY[DI]  ; & element at SI
       mov     SORT_ARRAY[SI],AX
skip2:
       add     SI,2          ; move SI to next element
       dec     CX
       cmp     CX,1          ; if CX = 1, we are done
       jne     sort_outer_loop
       popa                  ; restore registers
       ret     4
selection_sort ENDP
       END   main
