News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Sort Array!!

Started by arsenalftw067, October 27, 2015, 12:22:25 PM

Previous topic - Next topic

arsenalftw067

I have an assignment where I'm given an array of BYTE size, with 7 elements. They are all in random order and I have to sort them so the values progress from left to right.

I have 2 big problems:

1) It compiles, but nothing is showing on the console! I have a ShowArray proc which shows the memory and it doesn't display at all, HOWEVER:
When I call this proc for troubleshooting purposes, it will show the contents of the array, BUT it won't show anything if I run the program normally

2) When I troubleshoot my program, and I call my ShowArray proc here and there to see if my values are getting sorted, the sorting is in the wrong order!

BTW:

I am not asking for formatting help, so please refrain yourself from saying things like "oh why don't you use 64 bit" "oh why isn't your proc in your main" "oh you should do this.. do that"

These types of suggestions do not help me and they deviate from the actual problem I am presenting, anyways thanks!

CODE:


TITLE Sort array (Array.asm)

; This program sorts an array with random integers
; and outputs them in order

INCLUDE Irvine32.inc ; new
includelib C:\Irvine\Kernel32
includelib C:\Irvine\User32
includelib C:\Irvine\Irvine32

.data
array BYTE 20, 10, 60, 5, 120, 90, 100 ; array with 7 values
arraysize = ($ - array) -1 ; size of array
count DWORD ? ; mem to hold ecx


.code
main PROC
call SortArray ; call function to sort
call ShowArray ; call function to show
call DumpRegs ; display the registers
call WaitMsg        ; Pause until a key is pressed
exit
main ENDP


SortArray PROC
mov esi, OFFSET array
mov ecx, arraysize ; inner loop
L1:
mov eax, [esi]
push esi ; save esi counter
mov count, ecx ; save the outer loop count
mov ecx, arraysize ; outer loop
L2:
CMP eax, [esi]; compare second value with previous
JGE exchg ; perform exchange
JLE dntxchg ; dont perform exchange

dntxchg:
inc esi
loop L2 ; start loop again

exchg:
mov ebx, [esi] ; store next value in temp
xchg [esi], eax ; exchange value
pop esi ; restore esi
xchg [esi], ebx ; exchange value
mov eax, [esi] ; reset eax to point to least
push esi ; save esi
inc esi ; point to next
loop L2 ;

pop esi ; pop saved esi back
inc esi ; point to next element
mov ecx, count ; restore the loop
loop L1 ; start all over

ret
SortArray ENDP


ShowArray PROC

;show contents of array
mov edi, OFFSET array
mov ecx, arraysize
inc ecx
L3:
mov ebx, TYPE array
call DumpMem
loop L3

ret
ShowArray EndP
END main

hutch--

 :biggrin:

There is always a solution to the type of problems you are addressing here.

Quote
I am not asking for formatting help, so please refrain yourself from saying things like "oh why don't you use 64 bit" "oh why isn't your proc in your main" "oh you should do this.. do that"

These types of suggestions do not help me and they deviate from the actual problem I am presenting, anyways thanks!

Feel free to write your own.

rrr314159

arsenalftw067,

As I mentioned before you should read bytes not words, since it's a byte array.

;instead of

mov eax, [esi]

;use

mov al, BYTE PTR [esi]


- or else use the movsx instruction that I mentioned b4. Either way you have to change a few more statements in similar way. Couple other problems also
I am NaN ;)

arsenalftw067

So one of the issues is that because the array is in BYTE and the registers are 32 bit, it is adding extra hex values onto the registry to fill it up?

jj2007

Quote from: arsenalftw067 on October 27, 2015, 12:22:25 PM1) It compiles, but nothing is showing on the console!

That is because your editor doesn't auto-detect that it's a console application, so you need to specify it somewhere, e.g. in qEditor under Project/Console Build All

You get wrong results when using dword instructions on a byte array:

array BYTE 20, 10, 60, 5, 120, 90, 100 ; array with 7 values
...
   mov esi, OFFSET array
   mov eax, [esi]   << eax is now filled with 4 bytes:
al=20
ah=10
ax=20+10*256
eax=20+10*256+60*65536+5*256*65536

So that won't work. Same for
   CMP eax, [esi]; compare second value with previous
etc.

There are fascinating little gadgets called "books" which could explain to you how such stuff works 8)

arsenalftw067

Thanks but that is not an issue, my compiler is set up to properly run assembly through masm

Anyways, I have changed all the registers and memories to be 8 bit

But the problem is still there, I've ran the logic of my code several times and it makes sense to me, the most important part of the code is the nested loops which do the sorting and I can't find out what's wrong

gelatine1

I see an error in your showarray proc. The dumpmem requires your address to be in esi and not in Edi! :icon_exclaim: check the documentation http://programming.msjc.edu/asm/help/source/irvinelib/dumpmem.htm

At the moment you call the showarray proc your esi points to the end of the array. Also I wouldn't use the loop there l, simply use it like in the example on the documentation page I showed.

dedndave

let's get one routine working, first - SortArray
then, worry about displaying it (maybe the problem will be fixed - lol)

here, I have added a few comments to your code
hopefully, you will find them helpful

SortArray PROC
mov esi, OFFSET array
mov ecx, arraysize ; inner loop
L1:
mov al, [esi]

;ok, here is a PUSH that is probably not necessary
;in this routine, i see 2 PUSH's and only 1 POP

push esi ; save esi counter

;now, you save the inner loop count, which need not be loaded yet
;if i were going to use PUSH, though, this is a good place - rather than using the global variable "count"

mov count, ecx ; save the outer loop count
mov ecx, arraysize ; outer loop
L2:

;the problem here is, you have not adjusted ESI to point to a different byte on the first pass
;so, you compare the first byte with the first byte

CMP al, [esi]; compare second value with previous

;for signed bytes ( -128 to +127 ), we use JG, JL, JGE, JLE
;for unsigned bytes ( 0 to 255 ), we use JA, JB, JAE, JBE
;and - there only needs to be one branch instruction
;if it does not branch on JGE, it "falls through" to JL case code

JGE exchg ; perform exchange
JLE dntxchg ; dont perform exchange

;here, the dntxchg and exchg code should be very similar, except for the byte swap
;on one, you LOOP - on the other, you POP and LOOP and do a bunch of other stuff :)
;as an added problem, when ECX is 1, and you dntxchg, the LOOP instruction falls through to the exchg code :(

dntxchg:
inc esi
loop L2 ; start loop again

exchg:
mov ebx, [esi] ; store next value in temp
xchg [esi], eax ; exchange value
pop esi ; restore esi
xchg [esi], ebx ; exchange value
mov eax, [esi] ; reset eax to point to least
push esi ; save esi
inc esi ; point to next
loop L2 ;

;here, you POP again - i think the stack will be misaligned - oops

pop esi ; pop saved esi back
inc esi ; point to next element
mov ecx, count ; restore the loop
loop L1 ; start all over

ret
SortArray ENDP

dedndave

another thought....
see if the ShowArray routine works first, by displaying the unsorted array
you can temporarily comment out the call to SortArray to get that part working

; call SortArray ; call function to sort
call ShowArray ; call function to show
call DumpRegs ; display the registers
call WaitMsg        ; Pause until a key is pressed
exit


you might even make it part of the finished program - to show the unsorted array before sorting

call ShowArray ; call function to show
call SortArray ; call function to sort
call ShowArray ; call function to show
call DumpRegs ; display the registers
call WaitMsg        ; Pause until a key is pressed
exit