5 Replies - 758 Views - Last Post: 23 March 2013 - 09:05 AM

#1 Shozin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 04-May 12

Procedure debug help

Posted 22 March 2013 - 09:43 PM

Hi, I had an assignment where I was supposed to implement two procedures to find the max and the average the concatenate the values into an output box. I am fairly new to procedures and am having trouble getting my program to run and keep getting the error, Unhandled exception at 0x0018fed8 in windows32.exe: 0xC0000005: Access violation. I'm thinking that the problem is in one of my functions(most likely calc_average) however can't figure out what it is.



 
.586
.MODEL FLAT
INCLUDE io.h
.STACK 4096

.DATA
prompt1 BYTE "Enter ten scores (separated by a space each): ",0
prompt2 BYTE "output is: ",0
outprompt BYTE " ",0
scoreArray DWORD 10 dup (?)
temp byte 11 dup(?),0
tempx byte 11 dup(" "),0;     //or,..dup(20H); 20H=space
temp2 byte 11 dup(?),0
score_number DWORD ?
average DWORD ?
maximum DWORD ?
count1 dword 0
scoreString byte 80 dup(?),0
scores byte "scores: ",81 dup(?)
aveString byte 0dh,"Average: ",20 dup(?),0
maxString byte 0dh,"MaxScore: ",20 dup(?),0
outputString byte 150 dup(?)
counter DWORD 0

.CODE
_MainProc PROC
        input	prompt1, scoreString, 80; //gets five scores
        lea ebx, scoreString
        
 outerLoop: inc count1; //outer loop counter++
        lea esi, tempx; //flush temp string before using
        lea edi, temp
        cld
        mov ecx, 11
        rep movsb
        
        lea edx, temp;
 innerLoop: cmp byte ptr[ebx], 20h; //if ending mark(space), done
        je done1; 
        cmp byte ptr[ebx], 00h;     //elsif null char, also done
        je done1;
        mov AL, byte ptr[ebx]; //otherwise, get 1 byte from input string
        mov [edx], AL;         //and move it to temp

        inc ebx;       //to next byte in input string
        inc edx;       //to next byte in temp string
        jmp innerLoop; //inner loop (temp <- one score)
        
 done1:
        atod temp; //eax <- temp

        mov ecx, count1;
        dec ecx;       //counter:1 -> array index:0
        imul ecx, 4;   //array ele size = 4 bytes
        mov scoreArray[ecx], eax; //store one score in array
         
        inc ebx;       //skip the end mark(space) in the input string
        cmp count1, 10; //loop 10 times
        jnge outerLoop


		
		pushd 10             ;parameter 2
		lea eax, scoreArray  ;parameter 1
		push eax
		call calc_maximum
		add esp,8
		mov maximum,eax     ;store eax in the maximum dword




		lea eax,counter    ;parameter 3
		push eax
		pushd 10			;paramater 2
		lea eax, scoreArray ;parameter 1
		push eax
		call calc_average     
		add esp,12
		mov average,eax  ;store eax in the average dword


	
		dtoa aveString+10,average
		dtoa maxString+10,maximum

		lea esi,aveString
		lea edi,outputString
		cld
		mov ecx,20
		rep movsb

		lea esi,maxString
		lea edi,outputString
		cld
		mov ecx,20
		rep movsb
		


		output outprompt,outputString
		




		
        
        

        mov     eax, 0
        ret
_MainProc ENDP

calc_average PROC

push ebp
mov ebp,esp
push eax
push ebx
push ecx
push edx




mov ebx,[ebp+8]  ;get adress of first element in the array
mov ecx,[ebp+12] ;get the number of elements in the array
mov edx,[ebp+16];get the counter to be used in the function
mov eax,0




firstloop:

cmp edx,[ecx]   ;cmp edx to number of elements
jge doneAverage
inc edx         ;inc edx
add eax,[ebx]   ;add array elements and store in eax
add ebx,4
jmp firstloop



doneAverage:  
mov ebx,10
cdq
idiv ebx   ;divide the average by the 10 elements

pop edx
pop ecx
pop ebx
pop ebp
ret

calc_average ENDP

calc_maximum PROC

push ebp
mov ebp,esp
push eax
push ebx
push ecx

mov ebx,[ebp+8]
mov ecx,[ebp+12]
mov eax,0


maxloop:
       cmp eax,[ebx]
	   jge doneMaxLoop
	   mov eax,[ebx]
doneMaxLoop: add ebx,4
		  loop maxloop


		  pop ecx
		  pop ebx
		  pop ebp
		  ret



calc_maximum ENDP








END
















Is This A Good Question/Topic? 0
  • +

Replies To: Procedure debug help

#2 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,279
  • Joined: 28-March 11

Re: Procedure debug help

Posted 22 March 2013 - 11:09 PM

First, why are you using the CDECL calling convention? Normally we use STDCALL.

Just looking at your code, I spotted the problem, didn't even have to run it. As a developer, you should have a "Just In Time" debugger set up, so when you get a segfault, you can open your debugger to the offending code and see the problem.

First and the biggie, you are not restoring esp!!!!! You do this:
    push    ebp
    mov     ebp, esp


and at the end of your procs you do:
	pop     ebp
	ret

Where are you restoring esp????
Should be:
	mov     esp, ebp
	pop     ebp
	ret

or better yet, for your epilogue, just do:
	leave
	ret


There is no need to manually create stack frames the way you are doing it. By using the proc macro the Assembler already creates a prologue and epilogue, and then you are creating one on top of that.
Was This Post Helpful? 0
  • +
  • -

#3 Shozin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 04-May 12

Re: Procedure debug help

Posted 22 March 2013 - 11:46 PM

Ok now I see where its crashing exactly, at
cmp edx,[ecx]
.Are you not allowed to compare two registers,or not allowed to increment edx?Not sure what the problem is.
Was This Post Helpful? 0
  • +
  • -

#4 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,279
  • Joined: 28-March 11

Re: Procedure debug help

Posted 23 March 2013 - 12:06 AM

Why are you using MASM if you are not going to take advantage of its features??? Why are you pushing and poping registers in the procedures? I ask, because you are doing it wrong!

In calc_maximum, you do:
push eax
push ebx
push ecx

and at the end you do:
    pop ecx
    pop ebx

Your missing a pop, no?

calc_average:
push eax
push ebx
push ecx
push edx

pop edx
pop ecx
pop ebx

Another missing pop, no? All these messed up pushes/pops will mess up other functions.

Create your functions like this:
calc_average proc uses edx ecx edx pArray:DWORD, Elements:DWORD, Counter:DWORD
mov ebx,pArray  ;get adress of first element in the array
mov ecx,Elements ;get the number of elements in the array
mov edx,Counter;get the counter to be used in the function
mov eax,0

...
...
    ret
calc_average ENDP

Less errors, and more readable. You gain nothing by using manual stack frames as a newbie, but headaches.
Was This Post Helpful? 0
  • +
  • -

#5 Shozin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 04-May 12

Re: Procedure debug help

Posted 23 March 2013 - 12:35 AM

The reason I'm not popping eax is because I want the functions to return that. Also, I'm kind of limited in the methods that I can use because I am taking a course, and only know what I have learned in there.Also, we don't us MASM only visual studio with particular include files. I'll look into the other way just didn't know you could do it that way. Not really in the book either.
Was This Post Helpful? 0
  • +
  • -

#6 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,279
  • Joined: 28-March 11

Re: Procedure debug help

Posted 23 March 2013 - 09:05 AM

Quote

Also, we don't us MASM only visual studio with particular include files

Er, what Assembler do you think VS uses? MASM is an Assembler from Microsoft, and that is what VS uses. So, whether or not you know it, you are using MASM. Problem is, these "professors" use libraries that are built on top of MASM so most of the sample code you will find might not work.

Quote

The reason I'm not popping eax is because I want the functions to return that

So, why are you pushing eax onto the stack??? You push a register onto the stack to save its values, and pop it to restore the values.

The standard way of returning a value is in eax, but not the way you are doing it. All you have to do is mov eax, SomeReturnValue
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1