Search code examples
sortingassemblyx86masm

selection sort issues in masm


I have a program that I'm working on. Trying to do selection sort in assembly using MASM in Visual Studio 2010 and I have a problem. Whenever I change the condition to sort from descending to ascending order the program gives an incorrect answer. I'm trying to correct this I have the code but I also have the selection sort code in another language that I'm trying to convert from. The language is C++ off a website. I want to know how I can translate the statements with using min as an index into the array in assembly. I've waited two days. I need help guys. Im still working on the algorithm. Here's the code:

.386
.model flat,stdcall
.stack 100h

printf proto c arg1:ptr byte, printlist:vararg

.data
printmessage db "Selection Sort",0
fmtmsg1 db "%d",0
fmtmsg2 db 0dh,0ah,0

array dword 9,4,6,8,1,0
arraylength dword 5

temp dword ?
min dword ?


.code
public main
main proc
     ;invoke printf,addr fmtmsg1,addr printmessage
     ;invoke printf,addr fmtmsg2

     mov esi,offset array
     mov ecx,0   ; outerloop
     mov edx,0   ; innerloop

     mov edx,ecx ; innerloop for loop condition variables 

innerloop:
     mov ebx,5
     sub ebx,1  ; outerloop for loop condition variables

     add edx,1  ; innerloop for loop condition variables
     cmp edx,5
     jge outerloop

     mov eax,[esi]     ;9   9,4,6,8,1,0
     cmp eax,[esi + 4] ;4
     Jge noexchange
     mov min,edx

     cmp min,ecx
     je noexchange

      ;exchange values   
      xchg eax,[esi + 4]        
      mov [esi],eax     

noexchange:
      add esi,4           
      jmp innerloop

outerloop:
     mov esi,offset array
     mov edx,0  ; reset innerloop counter

     inc ecx
     cmp ecx,ebx
     jne innerloop


    mov esi,offset array

loop3:
     mov eax,[esi]
     push edx
     invoke printf,addr fmtmsg1,eax
     pop edx

     add esi,4
     inc edx
     cmp edx,5
     jne loop3

     ret
main endp
end main

C++ code I'm trying to understand how I can use the minimum value as an index into the array in MASM.

Here's the code I'm working from:

void selectionSort(int arr[], int n) {
      int i, j, minIndex, tmp;    
      for (i = 0; i < n - 1; i++) 
      {
            minIndex = i;
            for (j = i + 1; j < n; j++)
                  if (arr[j] < arr[minIndex])
                        minIndex = j;

            if (minIndex != i) 
            {
                  tmp = arr[i];
                  arr[i] = arr[minIndex];
                  arr[minIndex] = tmp;
            }
      }
}

Solution

  • I tried but I couldn't fix your assembly code, so I translated your C++ algorithm directly to assembly in a Visual Studio 2010 C++ console project. Important:

    • Instead of i, j and minIndex, I use ESI, EDI and EBX, respectively.
    • Because the array items (the numbers) are 4 bytes long, i++ is "add ESI,4", j++ is "add EDI,4".
    • The two loops (fori and forj) require "n" to know the end. Because I'm using reverse counters, it's necessary to use two "n", one for each "for" ("ni" for "fori", "nj" for "forj").

    Here's the code:

    void selection_sort () {
    int arr[5] = {1,5,2,4,3},
        n = 5,                 // ARRAY LENGTH.
        ni,nj,                 // ARRAY LENGTH FOR "FORI" AND "FORJ".
        i, j, minIndex;    
    
    __asm {      lea  esi, arr                         ;I = 0 (ESI USED AS I).
                 mov  eax, n
                 mov  ni, eax                          ;N.
             fori:
                 mov  ebx, esi                         ;MININDEX = I (EBX USED AS MININDEX).
    
                     mov  edi, esi                     ;J = I (EDI USED AS J).
                     add  edi, 4                       ;J = I+1.
                     mov  eax, n
                     mov  nj, eax                      ;N.
                 forj:
    
                 ;IF ( ARR[ J ] < ARR[ MININDEX ] ).
                     mov  eax, [ edi ]                 ;EAX = ARR[ J ].
                     mov  edx, [ ebx ]                 ;EDX = ARR[ MININDEX ].
                     cmp  eax, edx
                     jae  nextj                        ;IF ( ARR[ J ] >= ARR[ MININDEX ] ).
    
                     mov  ebx, edi                     ;ELSE: MININDEX = J.
    
                 nextj:
                 ;FOR ( J = I+1; J < N; J++ ).
                     add  edi, 4                       ;J++.
                     dec  nj                           ;REVERSE COUNTER.
                     jnz  forj                         ;IF (J < N) JUMP.
    
             ;IF ( MININDEX != I ).
                 cmp  ebx, esi  
                 je   nexti                            ;DON'T EXCHANGE.
    
                 ;EXCHANGE ARR[ I ] AND ARR[ MININDEX ].
                     mov  eax, [ esi ]                 ;EAX = ARR[ I ].
                     mov  edx, [ ebx ]                 ;EDX = ARR[ MININDEX ].
                     mov  [ esi ], edx                 ;ARR[ I ] = ARR[ MININDEX ].
                     mov  [ ebx ], eax                 ;ARR[ MININDEX ] = ARR[ I ].
    
             nexti:
             ;FOR ( I = 0; I < N-1; I++ ).
                 add  esi, 4                           ;I++.
                 dec  ni                               ;REVERSE COUNTER.
                 cmp  ni, 1                            ;MUST NOT REACH 0.
                 ja   fori                             ;IF I < (N-1) JUMP.
    }
    }