News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

MORE ON PROCS

Started by seymour_glass, April 06, 2006, 10:58:21 PM

Previous topic - Next topic

seymour_glass


.386
.MODEL FLAT
INCLUDE io.h

cr             EQU    0dh   ; carriage return character
Lf             EQU    0ah   ; linefeed character


.STACK  4096             ; reserve 4096-byte stack

.DATA                          ; reserve storage for data

explain               BYTE           "This program will find the Greatest Common "                                   
                           BYTE           cr,Lf, "Divisor of two numbers", cr, Lf, Lf, 0
enter1                BYTE           "Enter first number:", 0
enter2                BYTE           cr, Lf, "Enter second number:", 0
number              DWORD          ?

     
gcdDisplay         BYTE          cr, Lf, "The GCD is "
gcdVal                DWORD          ?
                            BYTE 0
 
.CODE                                                               ; start of main program code

GCD                   PROC  NEAR32
                            push ebp                                ; establish stack frame
                            mov ebp, esp
gcdLoop:               mov eax, [ebp+8]
                            mov ecx, [ebp+4]
                            cmp ecx, 0
                            je      n_equal_zero
                            cdq
                            div ecx
                            mov eax, [ebp+4]
                            mov [ebp+8], eax
                            mov [ebp+4], edx
                            jmp gcdLoop

n_equal_zero:    mov eax, [ebp+8]
                   
                            ret 8
GCD                   ENDP                 

_start:
                            output explain                        ; initial instructions\
                            output enter1                         ; ask for 1st number
                            input    number, 20                ; input number1
                            atod     number                      ; convert to integer
                            push    eax                             ; save num1
                            output  enter2                        ; ask for 2nd number
                            input    number, 20                ; input number2
                            atod     number                      ; convert to integer
                            push    eax                             ; save num2
                            call       GCD                          ; call the procedure
                 
                            mov    eax, gcdVal            ;output value returned by eax as gcd
                            output  gcdDisplay                ;                           "

                           

                           
                     
PUBLIC _start                                                    ; make entry point public
            END





ok, after inputting my 2 numbers, it freezes/pauses at run time... forever loop? help?

Appreciated,       
       seymour

seymour_glass

Ok.  I realize that   "gcdLoop" was in the wrong place....and its been moved now.  but still crashes after the input.....

Mark Jones

Hi Seymour, have you tried following along with the code in a debugger?
Perhaps try loading it into OllyDbg and keep pressing F8.  :U
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

seymour_glass

Mark,

      I did, yet i dont really understand much more than the actual code, and the registers.  However, that is how i realized that my statement label was in the wrong place and i actually was in a forever loop.  After that it seems that my problem is in the "ret 8", it stops immediately after it and i think its not returning to the caller....

     And i'm dumb...(lol)
           Seymour

Mark Jones

Hehe, no you're definately not dumb. :toothy

If you look at the bottom status-bar of the OllyDbg window when this RET 8 is encountered, does it say something like "Press F7 / F8 / F9 to pass exception to program..." If so, this means that there was a fault in that instruction. If that's the case, then try changing the RET 8 a little and see what happens.

Remember: CALL pushes the EIP (the instruction pointer) to the stack, and RET pops it back (adding one to it.) This is how RET knows where to resume program execution. If the stack pointer is not at the pushed EIP value when the RET is executed, then the program will usually crash, because RET loads an invalid value into the EIP register and tries to execute whatever is at that offset.

See the problem yet? Okay one more hint. You start a stack frame with


GCD                   PROC  NEAR32
                            push ebp                                ; establish stack frame
                            mov ebp, esp


... but where is the other half of that? :)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

MichaelW

Seymour,

A few more hints:

For 32-bit code, the PUSH instruction subtracts 4 from ESP and copies the contents of its operand to the stack at the location specified by ESP. The POP instruction copies the 32-bit value from the stack location specified by ESP to its operand and adds 4 to ESP. The key point is that ESP always points to the most recently pushed value.

When your procedure receives control, the contents of the stack relative to ESP are:

ESP+8  = input number 1
ESP+4  = input number 2
ESP+0  = return address


After pushing EBP and moving the value of ESP into EBP, the contents of the stack relative to EBP are:

EBP+12 = input number 1
EBP+8  = input number 2
EBP+4  = return address
EBP+0  = pushed EBP

eschew obfuscation

seymour_glass

thx u guys...

i now see my err.  i wasnt sure if i needed to pop the pushes off if i didnt need what was in them.  my mistaken impression was that that was what the returned parameters were for.   i managed completely to even think about the fact that i had pushed ebp, or that i forgot to change the pointer back. 

seymour

more to follow im sure....

seymour_glass

ok error gone. 

now i think that its exiting the proc, its just not outputting the gcd....but i can figure it out i think.....

thanks a million guys...(sorry about all the lowercase, im waiting on a new keyboard for my laptop lol, i only have my right side shift and its just a hassle).  this is pretty much my first procedure, and i now feel alot more comfortable doing it....glad you guys could point me in a direction without telling me what to change  :U   


seymour

seymour_glass

ok ive thought about this for so long now that ive convinced myself that my algorythm is completely wrong.....but im not sure .....


MichaelW

Seymour,

Now that I have had time to examine your code, I see that you are trying to use tail recursion. For a procedure with no declared parameters and no local variables a stack frame serves no useful purpose, and for tail recursion it is just in the way, because you must avoid re-executing the PUSH EBP. You could simplify the procedure by eliminating the stack frame and accessing the parameters (arguments) at [ESP+4] and [ESP+8]. Otherwise, your implementation as posted is almost correct, but there are still several problems that have to do with the parameters.

http://en.wikipedia.org/wiki/Euclidean_algorithm


eschew obfuscation

seymour_glass

ya i would not used the stack frame at all, only i had to, it was part of the assignment. 

also, now that ive fixed it all, i see how stupid that original code looks, while I couldn't see where i could possibly be wrong.  Thats what i like about learning it, however.   Now i see my mistakes, and hopefully i have moved past it.

seymour