.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
Procedure debug help
Page 1 of 15 Replies - 469 Views - Last Post: 23 March 2013 - 09:05 AM
#1
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.
Replies To: Procedure debug help
#2
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:
and at the end of your procs you do:
Where are you restoring esp????
Should be:
or better yet, for your epilogue, just do:
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.
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.
#3
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.
#4
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:
and at the end you do:
Your missing a pop, no?
calc_average:
Another missing pop, no? All these messed up pushes/pops will mess up other functions.
Create your functions like this:
Less errors, and more readable. You gain nothing by using manual stack frames as a newbie, but headaches.
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.
#5
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.
#6
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
Page 1 of 1
|
|

New Topic/Question
Reply


MultiQuote







|