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
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
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??
Try decrementing ecx for loop1 too :wink
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]
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
hi Hutch,
How do you read in values to the integer array by keyboard?
Thanks
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.
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