Search code examples
arrayssortingassemblyx86bubble-sort

x86 Assembly - need assistance with program that sorts two given arrays with bubble-sort


I'm making a x86 Assembly program that utilizes the bubble-sort algorithm detailed in the Irvine Assembly textbook (for x86 systems) to sort two given arrays in ascending order. The second of my procedures searches each of the arrays and outputs the greatest value in each. I know that I have forgotten a jump command (sortAscending procedure), though I am unsure as to where to place it to accomplish what I need to do. When I go to build my ASM file in VS2022, I receive the following error:

1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations\masm.targets(50,5): error MSB3721: The command "ml.exe /c /nologo /Sg /Zi /Fo"Debug\Template.obj" /Fl"Project.lst" /I "C:\irvine" /W3 /errorReport:prompt /TaTemplate.asm" exited with code 1.

I'm not sure if there are any other errors, but if someone notices them, please point them out. My code is shown below.

TITLE Sort Arrays, Version 1  (SortArrays.asm)

; This program sifts through and 
; sorts arrays (in place) in ascending
; order and outputs the greatest value 
; in each array.
; Name: Kasizah
; Date: 10-19-2022

INCLUDE Irvine32.inc

.data
Array1  DWORD 0C0D12AFh, 00030256h, 0FFAABBCCh, 0F700F70h, 00000000h, 0E222111Fh, 0ABCDEF01h, 01234567h
Array2  DWORD 61A80000h, 024F4A37h, 0EC010203h, 0FAEEDDCCh, 2C030175h, 84728371h, 63AA5678h, 0CD454443h, 22222222h, 61B1C2D3h, 7A4E96C2h, 81002346h, 0FDB2726Eh, 65432100h, 0FFFFFFFFh

; message strings
largestUnsignedS BYTE "The largest unsigned value in the array is: ",0
largestUnsignedF BYTE ".",0

.code
main PROC
    mov  esi,OFFSET Array1   ; point to start of Array1
    mov  ecx,LENGTHOF Array1 ; get length of Array1
    call sortAscending       ; sort Array1
    ; display sorted array using DumpMem
    mov  esi,OFFSET Array1   ; starting OFFSET
    mov  ecx,LENGTHOF Array1 ; number of units
    mov  ebx,TYPE Array1     ; doubleword format
    call DumpMem
    ; get greatest value in Array1
    mov  esi,OFFSET Array1   ; point to start of Array1
    mov  ecx,LENGTHOF Array1 ; get length of Array1
    call Crlf                ; skip line
    call getLargest          ; display largest value in Array1
    call Crlf                ; skip line
    
    mov  esi,OFFSET Array2   ; point to start of Array2
    mov  ecx,LENGTHOF Array2 ; get length of Array2
    call sortAscending       ; sort Array2
    ; display sorted array using DumpMem
    mov  esi,OFFSET Array2   ; starting OFFSET
    mov  ecx,LENGTHOF Array2 ; number of units
    mov  ebx,TYPE Array2     ; doubleword format
    call DumpMem
    ; get greatest value in Array2
    mov  esi,OFFSET Array2   ; point to start of Array2
    mov  ecx,LENGTHOF Array2 ; get length of Array2
    call Crlf                ; skip line
    call getLargest          ; display largest value in Array2
    call Crlf                ; skip line
    
    exit                     ; exit the program
main ENDP
;-------------------------------------------------------
sortAscending PROC
;
; Sorts an array of 32-bit signed integers in ascending
;   order using the bubble sort algorithm.
; Receives: pointer to array, array size
; Returns: nothing
;-------------------------------------------------------
    mov  edi,esi            ; duplicate "point to first value" 
                            ; (used to reset ESI)
    dec  ecx                ; decrement ECX (count) by 1
    outer_loop:
        push ecx                ; save outer loop count
        mov  esi,edi            ; point to first value
        sort:
            mov  eax,esi            ; get current array value
            cmp  [esi+4],eax        ; compare [ESI] and [ESI+4]
            jg   next               ; if [ESI] <= [ESI+4], no swap
            xchg eax,[esi+4]        ; else swap pair
            mov  [esi],eax
        next:
            add  esi,4              ; move both pointers forward
            loop sort               ; inner loop
            
            pop  ecx                ; retrieve outer loop count
            loop outer_loop         ; else repeat outer loop
    quit:
        ret
sortAscending ENDP
;-------------------------------------------------------
getLargest PROC
;
; Searches an array for its largest 
;   value.
; Receives: ESI - pointer
; Returns: statement of largest value in array
;-------------------------------------------------------
    sift:
        mov  eax,[esi]              ; move [ESI] into EAX 
        cmp  [esi+4],eax            ; compare EAX with [ESI+4]
        jg   next                   ; if EAX >= [ESI+4] don't replace
        mov  eax,[esi+4]            ; mov [ESI+4] into EAX
    next:
        add  esi,4                  ; move pointer forward
        cmp  ecx,esi                ; make sure that esi isn't at the end of array
        je   quit                   ; jump to quit if at the end of array
        loop sift                   ; else return to sift loop
    quit:
        mov  ebx,eax                ; move EAX into EBX temporarily
        mov  eax,largestUnsignedF   ; move largestUnsignedF string into EAX
        call WriteString            ; display largestUnsignedF string
        mov  eax,ebx                ; move EBX into EAX
        call WriteInt               ; display EAX
        mov  eax,largestUnsignedS   ; move largestUnsignedS string into EAX
        call WriteString            ; display largestUnsignedS string
        ret
getLargest ENDP
END main

Solution

  • mov  eax,esi            ; get current array value
    

    You forgot the square brackets to load the value stored at address ESI:

    mov  eax, [esi]
    

    The getLargest code can simple fetch the last array element given that the array got sorted ascendingly.

    mov  eax, [esi + ecx * 4 - 4]
    

    Also your messages talk about unsigned results, but the sorting algorithm treats the elements as signed dwords! For unsigned, use ja (JumpIfAbove).

    Your sift code has errors:

        cmp  ecx,esi                ; make sure that esi isn't at the end of array
        je   quit                   ; jump to quit if at the end of array
        loop sift                   ; else return to sift loop
    quit:
    

    The cmp ecx, esi compares a count with an address! Can't work! Just drop these 2 lines.
    The loop instruction would be enough provided you pre-decrement ECX before starting the loop and that you fetch the result via mov ebx, [esi].


    A code that finds the largest element could look like this:

     mov  eax, 80000000h ; Smallest signed dword
    More:
     cmp  [esi], eax
     jng  Skip
     mov  eax, [esi]
    Skip:
     add  esi, 4
     dec  ecx
     jnz  More
     mov  ebx, eax        ; The signed maximum