The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: shawn on April 09, 2010, 06:53:11 PM

Title: I needs your help
Post by: shawn on April 09, 2010, 06:53:11 PM
now I am coding a bubble sort with MASM
the goal is simpel
read numbers and store it in array and sort it.

I tried it several times but it's not working


.586
.MODEL FLAT

INCLUDE io.h            ; header file for input/output

.STACK 4096

.DATA

number   DWORD   ?
count    DWORD   ?

prompt   BYTE    "Enter the number", 0

string   BYTE     20 DUP (?)

sortLbl   BYTE  "The sorted array is", 0


sortAnswer    BYTE     11 DUP (?), 0
nbrArray      DWORD    100 DUP (?)


.CODE
_MainProc PROC

            lea    ebx,nbrArray     ; get address of nbrArray
            mov    ecx,0

            input  prompt, string, 20
            atod   string
            cmp    eax,0
            je     exitGo
            add    [ebx],eax
            add    ebx,4
            inc    ecx           

   goinput: input prompt, string, 20
            atod string
            add    [ebx],eax
            add    ebx,4
            inc    ecx           
            cmp    eax,0
            jz     goNext             
            jmp    goinput             

                   
   goNext: dec ecx
           call goSort
         
           
                lea    ebp,nbrArray     ; get address of nbrArray
  printArray  : mov    eax,[ebp]
                add    ebp,4
                dtoa   sortAnswer,eax        ;convert to ASCII character   
                output sortLbl,sortAnswer
                mov    eax,[ebp]
                cmp eax,0
                jz exitGo
                loop PrintArray




exitGo: 
            mov   eax, 0      ; exit with return code 0
            ret

_MainProc ENDP
                           

goSort      PROC NEAR32
            dec ecx           ; do not count last 0 input
            dec ecx ; decrement outer loop counter by 1 (arraysize -1)
           
       lp1: add edx, ecx                 ; save outer loop count
            mov ebx, nbrArray                      ; point to first value

      [color=Red] lp2: mov eax, [ebx]  [/color]                           
          cmp [ebx+4], eax                       
          jge lp3                              
          xchg eax, [ebx+4]                       
          mov [ebx], eax

       lp3:    add ebx, 4 ; move both pointers forward
        loop lp2      ; inner loop

        dec  edx ; retraeve outer loop count
     loop  lp1 ; else repeat outer loop
         
       lp4: ret
goSort  ENDP

END 

When I run it,

Unhandled exception at 0x00411aae in windows32.exe: 0xC0000005: Access violation reading location 0x00000002.

this message occured at lp2(red color)

I needs your help. I just want to figure out it's problem of syntax or algorithm

Thank you

Added code tags
Title: Re: I needs your help
Post by: Slugsnack on April 09, 2010, 06:58:34 PM
mov ebx, offset nbrArray
Title: Re: I needs your help
Post by: shawn on April 09, 2010, 07:03:08 PM
Quote from: Slugsnack on April 09, 2010, 06:58:34 PM
mov ebx, offset nbrArray

thank for your interest but when I changed it.

Microsoft Visual Studio C Runtime Library has detected a fatal error in windows32.exe.

Press Break to debug the program or Continue to terminate the program.

this messgae occur and  dbghook.c file poped up
Title: Re: I needs your help
Post by: Slugsnack on April 09, 2010, 07:04:07 PM
can you upload a compilable version of your code and i'll test it and find where the bug is. or the io.h file
Title: Re: I needs your help
Post by: redskull on April 09, 2010, 07:23:56 PM
You probably shouldn't be changing EBP, or at least preserving it for the function calls (before the 'output')

-r
Title: Re: I needs your help
Post by: shawn on April 09, 2010, 07:24:29 PM
I would like to upload the file but I don't know how to upload it  :eek

this is url to download the necessary file

http://www.jblearning.com/catalog/samplefile.aspx?isbn13=9780763772239&isbn=0763772232&filename=windows32.zip&isOlder=0

I really appreciate your help
Title: Re: I needs your help
Post by: Slugsnack on April 09, 2010, 08:00:34 PM
that compiles and runs fine for me. but it's not a bubble sort, just adds two numbers..
Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 09:07:39 PM
Shawn
in here, we all use the masm32 package
at the upper right corner of the forum is a link to download it
when you install it, close all programs until it is done building the libraries

your code makes no sense to us because it is written to be used with the C compiler   :bg

bsort.asm(29) : error A2008: syntax error : input
bsort.asm(30) : error A2008: syntax error : atod
bsort.asm(73) : error A2008: syntax error : sortAnswer
bsort.asm(74) : error A2008: syntax error : output
bsort.asm(79) : error A2006: undefined symbol : PrintArray


i am going to have a look at the windows32.zip file....
Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 09:18:37 PM
ok - i have io.h in there, now   :P

bsort.obj : error LNK2001: unresolved external symbol __getInput
bsort.obj : error LNK2001: unresolved external symbol __showOutput
bsort.obj : error LNK2001: unresolved external symbol _atodproc
bsort.obj : error LNK2001: unresolved external symbol _dtoaproc
bsort.obj : error LNK2001: unresolved external symbol _wtoaproc
bsort.obj : error LNK2001: unresolved external symbol _atowproc

i think if i change some names with "crt__" prefixes, i can make it work
Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 09:24:56 PM
QuoteI would like to upload the file but I don't know how to upload it

below the reply window is a link that says > Additional Options
click on that, then attach your file
it must be a ZIP file, less than 256 Kb
Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 10:24:14 PM
ok - i have taken the io.asm file and created an obj - i chose to rename it DetmerIO.asm/DetmerIO.obj
also, i have renamed io.h to DetmerIO.inc

now my only problem   :P
how do you link multiple obj files with this new-fangled linker ? - lol
in the old days, you could use LINK file1.obj+file2.obj
that doesn't seem to work
any help ?
Title: Re: I needs your help
Post by: clive on April 09, 2010, 10:31:22 PM
You just enumerate them LINK moe.obj larry.obj curly.obj
-Clive
Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 10:39:05 PM
thanks Clive
i still have unresolved externals
i don't know enough about C libraries to make it work, i guess
Title: Re: I needs your help
Post by: GregL on April 09, 2010, 10:54:46 PM
Yeah, I got it to compile and run with VS 2010 too, like Slugsnack says it's not a bubble sort, it asks for two numbers and then adds them and displays the result.

It uses Richard Detmer's IO library from his book. They are not C libraries they are MASM format despite the .h file extensions.


Title: Re: I needs your help
Post by: dedndave on April 09, 2010, 11:08:49 PM
i am sure i am missing something, then
if it builds for you guys, you don't need me   :P
Title: Re: I needs your help
Post by: Slugsnack on April 10, 2010, 01:25:46 AM
well i was not building with masm32, but vc++
Title: Re: I needs your help
Post by: clive on April 10, 2010, 03:28:48 AM
Fixing the sort, there are a couple of things that could work more efficiently. The xchg is VERY expensive, and the loop could exit quicker if it determined the list was in order.
-Clive

goSort          PROC NEAR32

                push    esi
                push    edi

                dec     ecx             ; do not count last 0 input
                jz      lp4             ; Empty list
                dec     ecx             ; decrement outer loop counter by 1 (arraysize -1)
                jz      lp4             ; List of 1 already sorted

lp1:            mov     edx, ecx        ; save outer loop count
                lea     esi, nbrArray   ; point to first value

lp2:            mov     eax, [esi]
                cmp     [esi+4], eax
                jge     lp3

                xchg    eax, [esi+4]
                mov     [esi], eax

lp3:            add     esi, 4          ; move both pointers forward
                loop    lp2             ; inner loop

                mov     ecx, edx        ; retrieve outer loop count
                loop    lp1             ; else repeat outer loop

lp4:            pop     edi
                pop     esi
                ret

goSort          ENDP

Title: Re: I needs your help
Post by: clive on April 10, 2010, 03:51:52 AM
Here with some optimization. Still a bubblesort, but easy enough to understand.
-Clive

goSort          PROC NEAR32

                push    ebx
                push    esi
                push    edi

                dec     ecx             ; do not count last 0 input
                jz      lp4             ; Empty list
                dec     ecx             ; decrement outer loop counter by 1 (arraysize -1)
                jz      lp4             ; List of 1 already sorted

lp1:            mov     edx, ecx        ; save outer loop count
                lea     esi, nbrArray   ; point to first value
                xor     edi, edi        ; clear exchange flag

                mov     eax, [esi+0]    ; Hold current element in eax

lp2:            mov     ebx, [esi+4]    ; Hold next element in ebx
                cmp     ebx, eax
                jge     lp3

                xchg    eax, ebx        ; register to register cheap
                mov     [esi+0], eax    ; echo change back to memory
                mov     [esi+4], ebx    ;  will use write buffers

                add     edi, 1          ; flag an exchange

lp3:            add     esi, 4          ; move both pointers forward

                mov     eax, ebx        ; move element next element to current

                sub     ecx, 1
                jnz     lp2             ; inner loop

                or      edi, edi        ; list sorted if no exchanges
                jz      lp4

                mov     ecx, edx        ; retrieve outer loop count
                sub     ecx, 1
                jnz     lp1             ; else repeat outer loop

lp4:            pop     edi
                pop     esi
                pop     ebx

                ret

goSort          ENDP
Title: Re: I needs your help
Post by: lingo on April 10, 2010, 06:59:36 PM
shawn,
just take a look :wink
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 16
BblSrt proc  lenArea:dword, lpArea:dword
pop eax   ; return addres
pop edx   ; edx->lenArea in DWords
mov [esp-1*4], ebx           ; saving register ebx
pop ebx   ; ebx->lpArea
mov [esp-1*4], esi          ; saving register esi
sub edx, 1
mov esi, esp   ; saving register esp
jle lExit
jne NoExchangesArea
align 16
ExchangesArea:
pop [esp-2*4]
sub ecx, 1
mov     [esp-1*4], eax
je NoExchangesArea
@@:
cmp eax, [esp]
jae ExchangesArea
sub ecx, 1
pop eax
jne @b

NoExchangesArea:
mov esp, ebx             ; ebx->lpArea
mov ecx, edx         ; edx->length of area /4 ->in Dwords
pop eax
@@:
cmp [esp], eax
jb ExchangesArea
sub ecx, 1
pop eax
jne @b
lExit:
mov ebx, [esi-2*4]   ; restoring ebx register
mov esp, esi ; restoring esp register
mov esi,  [esi-1*4] ; restoring esi register 
        jmp dword ptr [esp-3*4]     ; jmp to return address
BblSrt endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

Title: Re: I needs your help
Post by: clive on April 10, 2010, 07:17:52 PM
Quote from: lingo
   xchg   eax, [esp]

This instruction will absolutely murder performance, it is locked and atomic. You can measure the RAM access speed with this construct.

-Clive
Title: Re: I needs your help
Post by: jj2007 on April 10, 2010, 08:27:33 PM
Quote from: clive on April 10, 2010, 07:17:52 PM
Quote from: lingo
   xchg   eax, [esp]

This instruction will absolutely murder performance, it is locked and atomic. You can measure the RAM access speed with this construct.

-Clive

Clive is right...

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
555     cycles for mov
2010    cycles for xchg

Title: Re: I needs your help
Post by: lingo on April 10, 2010, 08:56:08 PM
"This instruction will absolutely murder performance..."

Ok, corrected... :wink
Title: Re: I needs your help
Post by: clive on April 10, 2010, 09:49:34 PM
That has to win a prize for the nastiest, stack unsafe code I've seen in a while. :cheekygreen:
-Clive
Title: Re: I needs your help
Post by: lingo on April 10, 2010, 10:12:34 PM
"..for the nastiest, stack unsafe code.."

Don't talk about things you don't understand, and don't tell God how to run the world and how to write safety code in assembly... :naughty:
Title: Re: I needs your help
Post by: jj2007 on April 10, 2010, 10:30:55 PM
Quote from: clive on April 10, 2010, 09:49:34 PM
That has to win a prize for the nastiest, stack unsafe code I've seen in a while. :cheekygreen:
-Clive

Can you explain why you consider it unsafe? The stack is your property, isn't it?
(I hate to defend lingo, I am just curious :bg)
Title: Re: I needs your help
Post by: clive on April 10, 2010, 10:44:54 PM
Anything below the stack pointer is fair game for the processor to use as it pleases. The operating system, or parts thereof, might also reasonably expect the user space stack to be usable.

-Clive
Title: Re: I needs your help
Post by: jj2007 on April 10, 2010, 10:53:43 PM
Rumours (in this forum) say that was correct for old versions of Windows but nowadays the OS won't touch [esp-4] any more.
Title: Re: I needs your help
Post by: dedndave on April 10, 2010, 11:19:11 PM
i prefer not to use area under [esp] - i think it's a matter of time before something bad happens
this is a discussion we have had a few times before, but we shouldn't confuse poor Shawn any more than he already is   :bg
Title: Re: I needs your help
Post by: qWord on April 10, 2010, 11:47:29 PM
Quote from: dedndave on April 10, 2010, 11:19:11 PM
i prefer not to use area under [esp] - i think it's a matter of time before something bad happens
I've never problems when using this "dubious" technique . Also I don't think, that the OS (or whatever) will extract ESP from threads context to use memory below esp...
Title: Re: I needs your help
Post by: GregL on April 11, 2010, 12:41:56 AM
In case we get more questions about this book "Introduction to 80x86 Assembly Language and Computer Architecture" Second Edition, the libraries and source code for it are here (http://www.jblearning.com/catalog/9780763772239/) under Samples. The book is intended to be used with Visual Studio 2008 as the development environment. Also, even though the include files are .h files they are in MASM format.
Title: Re: I needs your help
Post by: dedndave on April 11, 2010, 04:04:53 AM
i realize that i am posting 16-bit code in a 32-bit forum   :bg
but, this routine is simple and seemed to work fairly well - it wouldn't take much effort to make a 32-bit routine out of it

;--------------------------------------------------------------------------------------------

BSort   PROC   NEAR
;
;Byte Array Bubble Sort
;
;Call With: SI = address of array
;           CX = size of array in bytes
;
;  Returns: the array is sorted, lower values at lower addresses
;
;           all general registers are used and not saved
;
;-------------------------------------------

        jcxz    BSort4            ;if array size = 0, sort is done

        dec     cx                ;count to last byte
        jz      BSort4            ;if array size = 1, sort is done

        mov     bp,1              ;bp = 1 - used to set the swap flag
        xor     dx,dx             ;dx = 0 - initial swap flag
        cmp     cx,bp             ;if cx = 1, there are only 2 bytes
        ja      BSort0            ;more than 2 - skip the adjustment

        mov     bp,dx             ;if only 2 bytes, we want one pass, so flag = 0

BSort0: add     cx,si             ;cx = top address
        dec     si                ;adjust for the skip (DI gets ADD'ed before 1st pass)
        mov     di,-1             ;di = 1 for up, -1 for down (gets NEG'ed before 1st pass)
        mov     bx,si             ;bx = bottom address (gets XCHG'ed with CX before 1st pass)
        dec     bx                ;adjust for "one less" (DI gets SUB'ed before 1st pass)

BSort1: sub     bx,di             ;one less next time
        xchg    bx,cx             ;swap ends
        neg     di                ;switch direction
        add     si,di             ;skip one - already did that pair
        add     si,di             ;skip another one - one less next time

BSort2: mov     ax,[si]           ;get 2 bytes
        cmp     al,ah             ;do they need to be swapped ?
        jbe     BSort3            ;no - next address

        xchg    al,ah             ;yes - swap them
        mov     dx,bp             ;set the swap flag
        mov     [si],ax           ;store the swapped byte pair

BSort3: add     si,di             ;step in the current direction
        cmp     si,bx             ;are we at the end ?
        jnz     BSort2            ;no - next pair

        dec     dx                ;yes - clear the sort flag if it is 1
        jz      BSort1            ;if the sort flag was 1 before DEC, we are not done

BSort4: ret                       ;exit the routine

BSort   ENDP

;--------------------------------------------------------------------------------------------
Title: Re: I needs your help
Post by: hutch-- on April 11, 2010, 01:08:47 PM
Like most lessons I have learnt them all the hard way and the stack is no different. Work on the right side of the stack and you can make as much mess as you like up to the limit of stackl memory, work on the wrong side of the stack and it often jumps up and bites you. RE exchanges of data ALA sort algos there is a stat on taken or not taken exchanges that is theoretically 50/50 depending on the data and vagualy I remember that pre-loading the data was faster than testing first. XCHG is an old timer that lives in microcode and is best left there.
Title: Re: I needs your help
Post by: dedndave on April 11, 2010, 01:16:54 PM
xchg reg,reg seems to work ok   :bg
i don't use xchg reg,mem very often - and when i do, it is not a speed-critical application

i was thinking about the stack issue
if for no other reason than this, the area below [esp] should be regarded as "unsafe"
we all know about commited stack pages - and probing the stack down prior to allocating larger stack spaces
what would happen if, by chance, the location [esp-4*n] falls on a page that has not been commited, yet
well - i can guess what will happen - lol
error c0000005 will happen

i don't see anything wrong with reserving the space you want to use on the stack with SUB ESP,nnnnnnnn
a few bytes and clock cylces buys you peace of mind   :bg
Title: Re: I needs your help
Post by: hutch-- on April 11, 2010, 01:45:00 PM
Dave,

There is nothing wrong with XCHG except that its really slow, it works fine just like LOOP but apart from legacy code that has not be re-written yet, it is an old instruction that is way off the pace to manually coded alternatives. x86 is RISC under the hood and have a preferred instruction set, vary from that and you get really slow code in algos that matter. There will never be a fast bubble sort unless you are sorting nearly sorted data and a double ender (cocktail shaker sort) is nearly as simple and does not suffer the same limitations but you can make a bubble sort even slower by using antique instructions.
Title: Re: I needs your help
Post by: dedndave on April 11, 2010, 02:31:55 PM
i wonder if that applies to the special case single-byte XCHG  EAX,reg form
that includes the NOP instruction (which is essentially XCHG EAX,EAX)
i use this form quite often - any time i have tried to replace it, the code seemed to get slower
Title: Re: I needs your help
Post by: lingo on April 11, 2010, 02:58:31 PM
"i prefer not to use area under [esp] - i think it's a matter of time before something bad happens"
"routine is simple and seemed to work fairly well"

"i don't use xchg reg,mem very often - and when i do, it is not a speed-critical application"

"i was thinking about the stack issue
if for no other reason than this, the area below [esp] should be regarded as "unsafe"

"any time i have tried to replace it, the code seemed to get slower"

"i wonder if that applies to the special case single-byte XCHG  EAX,reg"


Why do you poison every thread with garbage and code like this? Who needs all that nonsense?

No offense, but don't talk about things you don't understand, just get your pills and try to control yourself... :wink
Title: Re: I needs your help
Post by: dedndave on April 11, 2010, 03:35:50 PM
lol Lingo
you are a fairly decent coder, but you have the manners of bogdan - lol
no wonder neither of you have any friends
well - at least you can code a little

as for not understanding things - you may be right
that is why i asked the question
this is the campus and i am trying to learn from the discussion
Title: Re: I needs your help
Post by: jj2007 on April 11, 2010, 04:18:30 PM
Quote from: dedndave on April 11, 2010, 01:16:54 PM
if for no other reason than this, the area below [esp] should be regarded as "unsafe"
we all know about commited stack pages - and probing the stack down prior to allocating larger stack spaces
what would happen if, by chance, the location [esp-4*n] falls on a page that has not been commited, yet

Dave,
That problem would also apply if you previously put a sub esp, nnn, so it should not be an argument.
I wonder if we could design a testbed...
Title: Re: I needs your help
Post by: dedndave on April 11, 2010, 04:38:05 PM
QuoteThat problem would also apply if you previously put a sub esp, nnn, so it should not be an argument.

you got me, there, Jochen   :P

designing a test bed sounds like as much fun as watching paint dry
i don't think there is any way to test for "what could happen"
i was having more fun talking about lingo's lack of personality   :bg

i guess, when it comes down to it, accessing memory below [esp] is a matter of personal preference
Title: Re: I needs your help
Post by: jj2007 on April 11, 2010, 05:09:23 PM
Quote from: dedndave on April 11, 2010, 04:38:05 PM
designing a test bed sounds like as much fun as watching paint dry

Let's try:

Button1 proc
StackRange = 8000
mov ecx, StackRange-4
.Repeat
mov dword ptr [esp+ecx-StackRange], ecx
sub ecx, 4
.Until Sign?
.Repeat
mov eax, [esp-4] ; 15 seconds to switch tasks, work with MS Word, ....
sub eax, 4
mov edx, [esp-8]
.if eax!=edx
MsgBox 0, "FOUL A!!", "Hi", MB_OK
exit
.endif
dec ecx
.Until Zero?
mov ecx, StackRange-4
.Repeat
mov eax, [esp+ecx-StackRange]
.if eax!=ecx
MsgBox 0, "Foul B!!", "Hi", MB_OK
exit
.endif
sub ecx, 4
.Until Sign?
MsgBox 0, chr$("Thank you so much for pushing me!"), addr txApp, MB_OK
ret
Button1 endp


EDIT: Extended the test. After the long loop, the whole StackRange is being checked for modifications. Under Windows XP SP2, there are none, but a check under Win9x might be interesting.