News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

re bubblesort in masm32

Started by reuby_tuesday, November 07, 2007, 05:31:47 AM

Previous topic - Next topic

reuby_tuesday

To all and sundry

I am currently a student attempting to study masm32 assembler and have to write a program to bubble sort an array of 20 integers.

I have the input and output sorted. I can read in the 20 numbers chuck em into an array and the output the array to screen. Its the sort that I have having difficulties with.

My code compiles fine, and the program runs, but dumps when it attempts to sort the array. I am faily sure that it is due to a memory access problem, in that i am acessing locations that dont exist or such.

Can someone suggest some pointers to help me out?

I can attach the entire program if required, but its only the sort that has me shagged.

Thanks

My code of what i have is below.

.data
array sdword 20 dup (0)      ;array of 20 ints, all zeros
elementSize dword type array
pArray sdword array         ; pointer to array


Sort proc uses eax ecx esi edi

      
invoke StdOut, addr LINE_FEED

mov ecx, sizeof array
  dec ecx            ; decrement counter by 1 (arraysize -1)      
   
Loop1:
          push ecx         ; save outer loop count
          mov esi, pArray      ; point to first value

      Loop2:
                          mov eax, [esi]      ; get array value
             cmp [esi+4], eax      ; compare a pair of values
             jge Loop3         ; if [ESI] <= [EDI], no exchange
             xchg eax, [esi+4]      ; exchange the pair
             mov [esi], eax         

         Loop3:
                add esi, 4      ; move both pointers forward
                jnz Loop2      ; inner loop

                pop ecx      ; retrieve outer loop count
                jnz Loop1      ; else repeat outer loop

      ret

Sort endp

MichaelW

The problem with the code is that the loops are not properly closed. The loop counter for both loops is ECX, so for each loop you need to decrement ECX and then loop if ECX is not zero. When the loop counter is ECX this can be done with a:

LOOP looplabel

Or more commonly in recent code (because it executes faster) or where you need to specify a loop counter other than ECX:

DEC  loopcounter
JNZ  looplabel
eschew obfuscation

reuby_tuesday

Thanks for that. I now have the program running correctly, but It only completes one pass of the array. as in ECX (i think) reaches zero after one pass rather than after the entire array has been parsed. I noticed that someelse seems to have a similar problem but only after 7 passes.

I inserted one decrement of ecx into the code, so my code hasent changed much, and i am reluctant to start chopping it up without direction as that just leads to misery and more problems.

I think that it has to do with the loop counter. Is it because I have used ECX for both the inner and outer loop counter, even though I push the outer loop onto the stack and retrieve it later in order to save it? Am i on the right track at least??

Below is the modified code. Thanks
   

.data
;----------------------------------------------------------

array sdword 20 dup (0) ;array of 20 ints, all zeros
elementSize dword type array
pArray psdWord array ; pointer to array
;----------------------------------------------------------
.code
;----------------------------------------------------------
Sort proc uses eax ecx esi edi

invoke StdOut, addr LINE_FEED

mov ecx, sizeof array
dec ecx                                                 ; decrement outer loop counter by 1 (arraysize -1)

Loop1:
        push ecx                 ; save outer loop count
        mov esi,, pArray                                          ; point to first value

    Loop2:
        mov eax, [esi]                             ; get array value
        cmp [esi+4], eax                         ; compare a pair of values
        jge Loop3                                 ; if [ESI] <= [EDI], no exchange
        xchg eax, [esi+4]                        ; exchange the pair
        mov [esi], eax

    Loop3:
        add esi, 4 ; move both pointers forward
        dec ecx                                     ;decrement the inner loop counter
jnz Loop2 ; inner loop

        pop ecx ; retrieve outer loop count
jnz Loop1 ; else repeat outer loop

   ret

Sort endp




After some further testing of the code, it seems that if i enter a number 5 or higher, it shifts it to a random location in the array, (usually the last 5 places or so), and I get junk numbers in a random number of other places. Very strange. It has to be because i am access numbers outside the array, or at least i think?
Am i using the right registers for the right purpose??

Tedd

Try decrementing ecx for loop1 too :wink
No snowflake in an avalanche feels responsible.

hutch--

Here is a working bubble sort with commenting on how it works. Once you understand what it does try writing your own version. Note that the correct registers are preserved in this example.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    bubble_sort PROTO :DWORD,:DWORD

    .data?
      value dd ?

    .data
      narr dd 1,9,2,8,3,7,4,6,5,0   ; 10 unsorted numbers

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    push ebx
    push esi

    print "Unsorted",13,10

    mov esi, OFFSET narr
    mov ebx, LENGTHOF narr

  @@:
    print str$([esi]),13,10
    add esi, 4
    sub ebx, 1
    jnz @B

    invoke bubble_sort,OFFSET narr,LENGTHOF narr

    print chr$(13,10)
    print "Sorted",13,10

    mov esi, OFFSET narr
    mov ebx, LENGTHOF narr

  @@:
    print str$([esi]),13,10
    add esi, 4
    sub ebx, 1
    jnz @B


    pop esi
    pop ebx

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

bubble_sort proc parr:DWORD,cnt:DWORD

    push ebx
    push esi

    sub cnt, 1                  ; set count to 1 less than member count

  lbl0:
    mov esi, parr               ; load array into ESI
    xor edx, edx                ; zero the changed flag
    mov ebx, cnt                ; set the loop counter for member count

  lbl1:
    mov eax, [esi]              ; load first pair of numbers in array
    mov ecx, [esi+4]
    cmp eax, ecx                ; compare which is higher
    jl lbl2                     

    mov [esi], ecx              ; swap if 1st number is higher
    mov [esi+4], eax
    mov edx, 1                  ; set the changed flag

  lbl2:
    add esi, 4                  ; step up one to compare next pair
    sub ebx, 1                  ; decrement the counter
    jnz lbl1

    test edx, edx               ; test if the changed flag is set.
    jnz lbl0                    ; loop back if it is

    pop esi
    pop ebx

    ret

bubble_sort endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start




[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

reuby_tuesday

Thanks heaps for the folks. Hutch, I have been though your code, and it makes sense to me, which is a good thing.

Thanks again

etow

hi Hutch,

How do you read in values to the integer array by keyboard?

Thanks

hutch--

etow,

With some difficulty. You would need to count the keyboard input, convert them to integers and then place them in an array. Then you tokenise the array and pass it to the sort.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

etow

hi Hutch,

How do you count keyboard input? How do you tokenize the array? I am curious and want to know.
Do I  just use a for loop to count every string number entered by user?

Please reply back soon.

Thanks