NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: edge363 on November 04, 2014, 05:23:26 AM

Title: Sorting numbers in an array in ascending order
Post by: edge363 on November 04, 2014, 05:23:26 AM
Hello! this is my first post and I was wondering if I could receive some help on an assembly project for one of my college courses. The goal of the assignment is to  take in N double word integers and then print them out in ascending order. It should also do some other stuff, but I am confident I can do that myself.  When I run this code I get a segmentation fault, and after tracing through the program twice, I do not see why! After each method I explain what they do, so I would really appreciate it if someone could tell me what is wrong! I don't see why it does it incorrectly.

%include "Along32.inc"
section .data ;data section
;               Start Main Method

section .bss             
array resd 100;

section .code                   ;code section
global _start

  _start:   ; main program
mov ecx,0;
call readInts ;
; methods

//this one works, it reads in the ints and places them into a array.

readInts:
call ReadInt ; puts an int into eax along libraries
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
pop ecx ;
mov [array+ecx*4],eax ;
inc ecx ;
call readInts ;

//this saves values, subtracts one from ecx( ecx ends up being one over because arrays start at the index of 0) it then grabs the last value, and places it in ebx

sortSetUp:
pop ecx ;
dec ecx ;
mov eax,ecx ;
mov edx,ecx ;
mov ebx,[array+ecx*4];
call sort ;

//this is the method that will sort the array. It does so by comparing ebx(containing last value) to every other value. If the value ebx is being compared to is //larger it exchanges places with the two different numbers.

sort:
cmp [array+ecx*4],ebx ;
jg greaterThan ;
jecxz sortNext ;
loop sort ;

//This number will first exchange the larger number with ebx(ebx now holds the larger number) It then copies the larger value to the last slot in the array as to put them in descending order. This will find the largest number and place it in the last slot after comparing all values. Subsequent loops will then not compare values to the last value. Which will allow the program to run slightly faster, but more importantly it will not copy the largest value over and over again.

greaterThan:
xchg [array+ecx*4],ebx ;
mov  [array+edx*4],ebx ;
ret ;

//as stated int the previous explenation, this method decrements edx so we wont grab the last value on the next go through, and it will continue until we reach the last value, and since it is the only value left we know it is in the right place so it then jumps to the end of the program(the method that prints out all of the values)

sortNext:
dec edx ;
mov ecx,edx ;
jecxz printAllSetUp ;
mov ebx,[array+edx*4];
call sort ;

//we have this method so we can restore ecx to its original glory.

printAllSetUp:
mov ecx, eax ;
call printAll ;

//this method basically just uses edx(which equals 0) and moves it up by one each go around to simply write out the ints

printAll:
mov eax,[array+edx*4] ;
inc edx ;
call WriteInt ; along method, prints out a vaue from eax.
jecxz exit ; leaves the program once all the values have been printed
loop printAll ;

exit:                                   ;exit function
       mov     eax,1                    ;mov 1 eax
       int     0x80                     ; ask kernal to exit
Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 04, 2014, 07:36:23 AM
Hello edge363,

I haven't analyzed your code at all, but it seems to me that you have too many recursive function calls.

good luck
gammac
Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 04, 2014, 06:21:26 PM
Is that bad? Does it cause errors? Like stack overflow or something to do with the stack pointer?
Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 04, 2014, 06:26:46 PM
I will redesign it with less recursive calls. Give me 1 or 2 hours, also! If anybody can correct my original code I would be more than happy.
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 04, 2014, 10:34:15 PM
Hi edge363,

Sorry, I'm having a little trouble getting "focused" on this... but I'm on it. I think gammac's right - too many "call"s, but I don't think they're really intended to be "recursive". The segfault appears to be in:
Code: [Select]
    mov ebx, [array + ecx * 4]
I think (not certain) that this is in your "sortSetUp" routine. Having ecx be negative at this point would segfault, and having ecx be a return address inadvertantly popped off the stack might, too. I haven't had any luck fixing the problem yet. I have only just begun to fight! :)

The research continues...

Best,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 05, 2014, 02:00:06 AM
Thank you so much frank! I'm working on it to, and will have a few less calls shortly.
Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 05, 2014, 02:45:24 AM
I changed the loop completely so its more understandable, and more easily debugged.

So this version works....some of the time. I do not get why it only works some of the time. But when it works it does it perfectly! example
give it -1,-34,45,67 then 0

will give you
-34,-1,45,67

give it -1,-23,-34,-45,-56,-67,-87,56,67,789,34545,0
it gives me a segmentation fault. Damnit. Its acceptable, but I really want it to work all the time.

Code: [Select]
%include "Along32.inc"
section .data ;data section
;               Start Main Method

section .bss
array resd 100;

section .code          ;code section
global _start

  _start:   ; main program
mov ecx,0;
call readInts ;
; methods

;this one works, it reads in the ints and places them into a array.

greaterThan:
xchg [esi+ecx*4],ebx ;
mov  [esi+edx*4],ebx ;
ret ;

readInts:
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
pop ecx ;
call WriteInt ;
call Crlf ;
mov [array+ecx*4],eax ;
inc ecx ;
call readInts ;

;this saves values, subtracts one from ecx( ecx ends up being one over because arrays start at the index of 0) it then grabs the last value, and
;places it in ebx

sortSetUp:
mov esi, array ;
pop ecx ;
mov eax,ecx ;
mov edx,ecx ;
dec ecx ;
call sortNext ;

;this is the method that will sort the array. It does so by comparing ebx(containing last value) to every other value. If the value ebx is being
;compared to is //larger it exchanges places with the two different numbers.

sortNext:
push ecx ;
dec edx ;
jecxz printAllSetUp ;
mov ebx,[esi+edx*4] ;
mov ecx,edx ;
call sort ;
pop ecx ;
loop sortNext;
sort:
cmp [esi+ecx*4],ebx ;
JG greaterThan ;
loop sort ;
ret ;

;This number will first exchange the larger number with ebx(ebx now holds the larger number) It then copies the larger value to the last slot in the
;array as to put them in descending order. This will find the largest number and place it in the last slot after comparing all values.
;Subsequent loops will then not compare values to the last value. Which will allow the program to run slightly faster, but more importantly
;it will not copy the largest value over and over again.
;as stated int the previous explanation, this method decrements edx so we wont grab the last value on the next go through, and it will continue
;until we reach the last value, and since it is the only value left we know it is in the right place so it then jumps to the end of the
;program(the method that prints out all of the values)

;we have this method so we can restore ecx to its original glory.

printAllSetUp:
mov edx,0 ;
mov ecx,eax ;
call printAll ;

;this method basically just uses edx(which equals 0) and moves it up by one each go around to simply write out the ints

printAll:
mov eax,[esi+edx*4] ;
inc edx ;
call WriteInt ;
jecxz exit ;
loop printAll ;

exit:                                   ;exit function
call Crlf ;
       mov     eax,1                    ;mov 1 eax
       int     0x80                     ; ask kernal to exit
Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 05, 2014, 01:25:39 PM
Are you sure that you have a balanced stack? I mean, has esp at _start: and exit: the same value? I doubt it.

Why don't you use a clean structure (input -> sort -> output -> exit) without so many unnecessary and confusing calls?

I bet, in a few months without working on this code, you wont understand your own code. I wouldn't understand it.

Your code does not work for input: 0

Is it intended to run sortNext: twice? Why?
Title: Re: Sorting numbers in an array in ascending order
Post by: Rob Neff on November 05, 2014, 03:21:20 PM
readInts:
   call ReadInt ;
   push ecx ;
   mov ecx, eax ;
   jecxz sortSetUp ;
   pop ecx ;
   call WriteInt ;
   call Crlf ;
   mov [array+ecx*4],eax ;
   inc ecx ;
   call readInts ;

Are you 100% certain that your call to ReadInt, WriteInt, and Crlf doesn't destroy ECX and EAX?

;this method basically just uses edx(which equals 0) and moves it up by one each go around to simply write out the ints

printAll:
   mov eax,[esi+edx*4] ;
   inc edx ;
   call WriteInt ;
   jecxz exit ;
   loop printAll ;

Are you 100% certain that your call to WriteInt doesn't destroy ECX and EDX?
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 05, 2014, 04:40:29 PM
For some reason, I continue to have trouble getting "in the mood" to test this. Being 32-bit Linux, I "can" test it which usually pleases me (not true of 64-bit nor Windows). I even have the Along32 macros/libraries in place (although I usually don't use 'em). Pretty sure they do preserve ecx/edx - which is not true of "normal" libraries! Good point, Rob! It's a Linux/Nasm port of Kip Irvine's "irvine32.lib" (for Windows/Masm). It would probably make a good "general rule" to tell us where to find any include files your code uses... http://along32.sourceforge.net/ in this case.

Another good "general rule" would be to use "code tags" - just the word "code" in square brackets (like a Nasm memory reference) at the top of your code, and "/code" at the end. I edited your code to use 'em. It may or may not make the code easier to read - definitely makes it easier to cut-and-paste. We should probably say that someplace prominent. Maybe it would make a good alternative to the "guess the puzzle" we put ya through (that'll go away after a few posts). I dunno...

Anyway... we definitely don't have a balanced stack.
Code: [Select]
%include "Along32.inc"
section .data ;data section
;               Start Main Method

section .bss
array resd 100;

section .code          ;code section
global _start

  _start:   ; main program
mov ecx,0;
call readInts ;
; methods
If, in fact, we ever returned from this call, we would "fall through" and do it all again. Not what we want! A general form like...
Code: [Select]
main_or_start:
call fill_array
; return to here
call sort_array
; return to here
call print_array
; return to here
exit:
; sys_exit or other clean exit

fill_array:
; do it
ret

sort_array:
;do it
ret

print array:
; do it
ret
might be better.

I deduce that when the prompts are added it will say "enter zero when finished". It is clearly intentional that an input of 0 "doesn't work".

I'll try to get into this and have more specific suggestions soon (I hope)...

Later,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 05, 2014, 04:58:03 PM
Frank, 0 is a possible input and should be handled! Or not? If I say "it doesn't work" I didn't mean "it's not supported" I mean it's not handled and it's a fault.



Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 05, 2014, 06:24:47 PM
Well, I dunno...
Code: [Select]
; ...
readInts:
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;

That looks to me like an input of 0 is "supposed" to indicate "end of input". I'm not sure how else we let the user indicate they're done. Maybe make 'em say "how many items in array?" first? The "customer specification" (assignment) may say how this is supposed to be handled? Always understand the "specification" first! :)

I've only just assembled edge363's latest version - haven't really started to debug. I can confirm that sometimes it segfaults and sometimes exits cleanly. Sometimes the "sort" seems to work, and sometimes not. I wouldn't consider this "acceptable", but definitely "improved". Still "too many calls and not enough rets", IMO...

Sorry to be so slow-moving on this - even worse than usual. The research continues...

Best,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 05, 2014, 06:39:12 PM
Code: [Select]
sortSetUp:
pop ecx ;
dec ecx ;


 ecx will be -1 if the input is only zero and imho this results in an unpredictable program state.
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 05, 2014, 07:02:54 PM
Right! Entering 0 as the first and only item results in a segfault.

Best,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 06, 2014, 01:13:55 AM
0 is the call that is supposed to tell the program to stop taking in input and instead end. I am sorry for my messy, sloppy, code. I would loveeeeee to have a  better way, but with our teacher I am basically teaching myself completely. This is the way that makes the most sense to me right now.
Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 06, 2014, 01:23:45 AM
0 is not added to the array. It is not viable input.
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 06, 2014, 02:50:57 AM
Okay. Sorry you feel that all you're getting is criticism. It's intended to be "constructive criticism". We don't want to "do your homework for you". By all means try to work it out yourself! The fact that it "works sometimes" suggests that it's not a simple error that we can find and tell you. I'll keep looking and let you know if I spot anything. "too many calls and not enough rets" looks like a problem to me, and maybe "trying to use ecx for too many things". I'd introduce a variable for "item_count" once the user has entered 0, rather than saving it in eax and restoring it from there - might not help. Sorry I haven't gotten farther with it. Come back if you need "more" help - not that you've gotten much. You might catch me on a better day. :)

Best,
Frank

Edit: Hmmm... the post that this was in reply to has vanished. Never mind...
Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 06, 2014, 04:31:01 PM
Hello edge363,

Frank's right, all criticism it's intended to be constructive and we don't want to do your homework it's right too. You got a lot of hints and keywords (e.g. stack balancing) to feed your search engine with it. You should try to rewrite your code, look at reply #9, Frank gave you a good skeleton for your program structure, try to use it. Post your new program here and maybe there is nothing to criticise any more. :) And do not use 'call' like a branch.

And 0 it's a possible input and no possible input should cause a segfault. Every possible input should be handled.

Good luck
gammac

PS: excuse my bad english, I hope you get me right.
Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 06, 2014, 10:10:41 PM
Working version. For anybody who needs it.
Thank you Frank.(note, I over reacted and took part of the post down.) Thank you Gammac.
I did not want you to do my homework. I just wanted help when thinking about the logic of the program. The reason it wasn't working is because it was essentially quick sort without a pivot element. So it just clustered lower elements at the lower end and clustered higher elements at the top. Misleading with low numbers of input or high numbers of input.

Code: [Select]
%include "Along32.inc"
section .data
max dd 0
maxIndex dd 0
prompt1    : db "Overflow error, must use less than 100 numbers.",0ah, 0   
prompt2    : db "You must submit at least 1 number.",0ah, 0   
size dd 0
section .bss
array resd 100;
section .code
global _start
  _start:   ; main program
push esp ;
mov ecx,0;
call readInts ;

;explenation-reads in an array of ints, sorts them by finding largest and puting it in last place over and over, and then printing out the array.

overFlow:
mov edx, prompt1 ;
call WriteString ;
jmp exit ;
zeroError:
mov edx, prompt2 ;
call WriteString ;
jmp exit ;
readInts:
cmp ecx, 100 ;
je overFlow ;
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
pop ecx ;
mov [array+ecx*4],eax ;
inc ecx ;
call readInts ;
sortSetUp:
pop ecx ;
cmp ecx, 0 ;
je zeroError ;
dec ecx ;
mov esi, array ;
mov [size], ecx ;
mov edx, ecx ;
sortNext:
cmp edx,0 ;
je printAllSetUp;
mov ebx,[esi+edx*4] ;
mov [max],ebx ;
mov [maxIndex],edx ;
mov ecx,edx ;
sort:
cmp ebx,[esi+ecx*4] ;
Jge skip ;
mov ebx,[array+ecx*4];
mov [max], ebx ;
mov [maxIndex], ecx ;
mov eax,[max] ;
skip:
cmp ecx, 0;
je zeroLoopEnd ;
dec ecx ;
jmp sort ;
zeroLoopEnd:
mov eax, [max] ;
xchg [esi+edx*4], eax ;
mov ebx,[maxIndex] ;
mov [esi+ebx*4],eax ;
dec edx ;
call sortNext;
printAllSetUp:
mov edx,0 ;
mov ecx, [size] ;
inc ecx ;
call printAll ;
printAll:
mov eax,[esi+edx*4] ;
inc edx ;
call WriteInt ;
jecxz exit ;
loop printAll ;
exit:                                   ;exit function
       pop esp ;
       call Crlf ;
       mov     eax,1                    ;mov 1 eax
       int     0x80                     ; ask kernal to exit
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 06, 2014, 11:09:54 PM
Good! I'm still not making much progress with this. I think my brain's on vacation this week... or this month... maybe forever...

Maybe I shouldn't mention this, but the same (apparently) question has appeared on Stack Overflow. http://stackoverflow.com/questions/26771581/how-do-i-sort-an-array-in-nasm
Answered by the same poster (a pretty young woman, if the picture is to be believed - who knows?) Supposed to work - I haven't tried it. Look at it only if you're desperate for help...

Anyway, I'll look at the new version... with the usual disclaimer "if I can get my asm in gear"... Still looks like "too many calls" to me...

Best,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 07, 2014, 12:17:10 AM
Working version. For anybody who needs it.

Congratulation, but sorry, do you really think your code is bug free and reusable? :(

Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 07, 2014, 07:03:04 AM
Well... I've only just assembled this and tried it with a couple of input sequences - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 and 9, 8, 7, 6, 5, 4, 3, 2, 1, 0. The good news is that the sort worked perfectly both times. The bad news is that it segfaulted both times. (apparently on "call Crlf", which seems strange!)

So... "the research continues", but let me point out a couple of things that "don't look right to me" before I get back (I hope) to trying to find the actual problem...

Code: [Select]
%include "Along32.inc"
section .data
max dd 0
maxIndex dd 0
prompt1    : db "Overflow error, must use less than 100 numbers.",0ah, 0   
prompt2    : db "You must submit at least 1 number.",0ah, 0   
size dd 0
section .bss
array resd 100;
section .code
global _start
  _start:   ; main program
push esp ;

This is apparently an attempt to assure that esp is going to be the same at the end of the program as at the beginning - but it isn't going to work. If the stack gets messed up, the value you pop into esp at the end isn't going to be the same value you pushed here! (that's probably why "call Crlf" appears to fail for me - but perhaps not for you)

Code: [Select]
mov ecx,0;
call readInts ;
This call never returns. Already the stack is messed up! It may not be obvious to a beginner that "call" (and "ret") use the stack at all, but they sure do!

"call" does something like this:
Code: [Select]
; call somefunc
; next_instruction:
push next_instruction
jmp somefunc
and when the CPU gets to "ret" in "somefunc" (we hope it does) it does:
Code: [Select]
; ret
pop return_address
jmp return_address
If all goes well, "return_address" is "next_instruction" and we continue right after the "call" ("somefunc" can be called from different places, and should return to where it was called from). But the CPU doesn't know if the stack is "balanced" and will "pop" and "jmp" whatever it finds next on the stack. If it's total garbage, the crash is immediate. If it is some valid address, but not the right one, execution may continue for quite a while before the problem becomes obvious - if it does. This can make for a very hard to find bug!

Anyway, back to your code:
Code: [Select]
;explenation-reads in an array of ints, sorts them by finding largest and puting it in last place over and over, and then printing out the array.

overFlow:
mov edx, prompt1 ;
call WriteString ;
jmp exit ;
zeroError:
mov edx, prompt2 ;
call WriteString ;
jmp exit ;
readInts:
cmp ecx, 100 ;
je overFlow ;
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
pop ecx ;
mov [array+ecx*4],eax ;
inc ecx ;
call readInts ;
Another "call" with no "ret". Return-addresses pile up on the stack. One for every input (which may explain the different behavior on different runs). Just "jmp readInts" should work here, and would be "better", I think.

While we're here...
Code: [Select]
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
This is a legitimate "call" - Curtis Wong's code has a "ret" in it and the stack should have the proper return address on it, so we return here with the users input clutched firmly in eax. Gammac's right that 0 is a valid input, but we need to use it to pretend they said "quit". I don't understand why you did it the way you did ("because it came to me to do it that way" is a good reason). Why not:
Code: [Select]
        call ReadInt
        cmp eax, 0
        jz sortSetUp
        ...
This would save pushing and popping ecx - it could remain the "item count". I think the way you do it should work, but I get nervous when I see anything like:
Code: [Select]
push something
set some condition code ("flags")
any conditional jump
pop something
As long as the pushes and pops match on both branches of the conditional jump, it's no problem, but it's a place where bugs can sneak in. Since "pop" doesn't alter the flags, we can often do:
Code: [Select]
push something
set some condition codes
pop something
some conditional jump
but when we're popping ecx and the condition is "jecxz", this isn't going to work!

Code: [Select]
sortSetUp:
pop ecx ;
cmp ecx, 0 ;
je zeroError ;
dec ecx ;
mov esi, array ;
mov [size], ecx ;
mov edx, ecx ;
sortNext:
cmp edx,0 ;
je printAllSetUp;
mov ebx,[esi+edx*4] ;
mov [max],ebx ;
mov [maxIndex],edx ;
mov ecx,edx ;
sort:
cmp ebx,[esi+ecx*4] ;
Jge skip ;
mov ebx,[array+ecx*4];
mov [max], ebx ;
mov [maxIndex], ecx ;
mov eax,[max] ;
skip:
cmp ecx, 0;
je zeroLoopEnd ;
dec ecx ;
jmp sort ;
zeroLoopEnd:
mov eax, [max] ;
xchg [esi+edx*4], eax ;
mov ebx,[maxIndex] ;
mov [esi+ebx*4],eax ;
dec edx ;
call sortNext;
Yet another "call" with no "ret". Well, your sort routine seems to be working. Could probably do "jmp sortNext" with no ill effects. The way I learned to do a bubble sort, as I remember it, went something like:
Code: [Select]
top:
set some "swap flag" to zero (some register)
iterate through the array doing comparisons
jge noswap ; or some condition
do the swap
set the "swap flag" to non-zero
noswap:
continue through the array, until done
check the "swap flag"
if it's still zero, we're done
if not, go back to top and make another pass
If you call a "print_array" after each pass, you can watch the larger numbers "bubble" up to the top of the array. Since your method seems to work, better leave it alone - maybe get rid of that excess "call".

Code: [Select]
printAllSetUp:
mov edx,0 ;
mov ecx, [size] ;
inc ecx ;
call printAll ;
printAll:
mov eax,[esi+edx*4] ;
inc edx ;
call WriteInt ;
jecxz exit ;
loop printAll ;
This looks good and seems to work right.
Code: [Select]
exit:                                   ;exit function
       pop esp ;
       call Crlf ;
This is where it crashes for me. I said it was unusual for a "call" to crash (usually it's the "ret"s that get ya). If the value we popped into esp were any legitimate memory, it would have worked. It might not have been the "right" place on the stack, but "call" would have had someplace to put its return address, and the "ret" in Crlf would have found it. But if we'd popped something else - an array index or a value for number of items or anything - when "call" tried to save its return address, it would have been trying to write to invalid memory, and would segfault. I haven't tracked down why, but I think that must be what's happening. If you'd put the "pop esp" after the "call", we might never have noticed that the stack was messed up - but it still would have been.
Code: [Select]
       mov     eax,1                    ;mov 1 eax
Useless comment. One ring to rule them all? Oh, I see, it's sys_exit! :) sys_exit doesn't care what shape the stack is in. All of the memory for our process - including the stack - just vanishes and we return to the shell (bash, which is buggy as it turns out) not to here.

Code: [Select]
       int     0x80                     ; ask kernal to exit
Old-fashioned way to spell "kernel". Not wrong, just "old school". Okay, I'm just being picky now. I hear a bell ringing. I think it's recess! TTYL

Best,
Frank

Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 07, 2014, 11:37:25 AM

Code: [Select]
printAllSetUp:
...
call printAll ;
printAll:
...
jecxz exit ;
loop printAll ;
This looks good and seems to work right.

Sorry Frank, but this messed up the stack too.
Title: Re: Sorting numbers in an array in ascending order
Post by: gammac on November 07, 2014, 12:02:11 PM
Hello edge363,

I've found something for you!

http://williams.comp.ncat.edu/COMP375/AsmCall.pdf (http://williams.comp.ncat.edu/COMP375/AsmCall.pdf)
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 07, 2014, 10:58:21 PM
That's a gem, gammac! A much better find than that wayward "call" I missed. :)

Best,
Frank


Title: Re: Sorting numbers in an array in ascending order
Post by: edge363 on November 11, 2014, 11:38:11 PM
I am pretty sure the way I am doing this with the exiting the state of the stack will not matter. I do not plan to make this work in any c library or as a macro. I have not had any problems running it, but I will test it again tonight. I will change some of the calls to jumps. I really like using call because sometimes whenever I change it to jump it breaks the program with segfaults. I do not know why at all.
Title: Re: Sorting numbers in an array in ascending order
Post by: Frank Kotler on November 12, 2014, 09:35:54 AM
Hi edge363,

I don't know why either. Your latest code, posted Nov 6 at 10:10, definitely segfaults for me. Even if I enter just 0 to test your error message (which works fine - that's a plus). I confess I did not enter 100 numbers to test that one (but it looks like it should work). If it works for you.... well, if it works it works... You are correct that it shouldn't bother sys_exit.

I have modified your code, removing the "push esp" at the start and the "pop esp" at the end. That "sounds like a good idea if you say it quick" but actually makes things worse (causes the following "call Crlf" to segfault - leaves esp pointed into read-only memory). I have replaced all the non-returning "call"s with "jmp"s. I don't know why that's giving you trouble. I have added code to print esp at the beginning and end (just for debugging purposes - you probably want to remove it). Proves that you've got the "push"s and "pop"s balanced - another plus. Other than that, it's all your code:

Code: [Select]
%include "Along32.inc"
section .data
max dd 0
maxIndex dd 0
prompt1    : db "Overflow error, must use less than 100 numbers.",0ah, 0   
prompt2    : db "You must submit at least 1 number.",0ah, 0   
size dd 0
section .bss
array resd 100;
section .code
global _start
  _start:   ; main program
; push esp ; bad idea

; display current esp
mov eax, esp
call WriteHex
call Crlf

mov ecx,0;
jmp readInts ;

;explenation-reads in an array of ints, sorts them by finding largest and puting it in last place over and over, and then printing out the array.

overFlow:
mov edx, prompt1 ;
call WriteString ;
jmp exit ;

zeroError:
mov edx, prompt2 ;
call WriteString ;
jmp exit ;

readInts:
cmp ecx, 100 ;
je overFlow ;
call ReadInt ;
push ecx ;
mov ecx, eax ;
jecxz sortSetUp ;
pop ecx ;
mov [array+ecx*4],eax ;
inc ecx ;
jmp readInts ;

sortSetUp:
pop ecx ;
cmp ecx, 0 ;
je zeroError ;
dec ecx ;
mov esi, array ;
mov [size], ecx ;
mov edx, ecx ;

sortNext:
cmp edx,0 ;
je printAllSetUp;
mov ebx,[esi+edx*4] ;
mov [max],ebx ;
mov [maxIndex],edx ;
mov ecx,edx ;

sort:
cmp ebx,[esi+ecx*4] ;
Jge skip ;
mov ebx,[array+ecx*4];
mov [max], ebx ;
mov [maxIndex], ecx ;
mov eax,[max] ;
skip:
cmp ecx, 0;
je zeroLoopEnd ;
dec ecx ;
jmp sort ;
zeroLoopEnd:
mov eax, [max] ;
xchg [esi+edx*4], eax ;
mov ebx,[maxIndex] ;
mov [esi+ebx*4],eax ;
dec edx ;
jmp sortNext;

printAllSetUp:
mov edx,0 ;
mov ecx, [size] ;
inc ecx ;
jmp printAll ;
printAll:
mov eax,[esi+edx*4] ;
inc edx ;
call WriteInt ;
jecxz exit ;
loop printAll ;

exit:                                   ;exit function
;       pop esp ; really bad idea
       call Crlf ;

; display ending esp
mov eax, esp
call WriteHex
call Crlf

       mov     eax,1                    ;mov 1 eax
       int     0x80                     ; ask kernal to exit

Try it - you don't have to use it. Good luck!

Best,
Frank