The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: msqweasm on May 30, 2011, 12:14:02 PM

Title: A LEAVE Generated Before RET
Post by: msqweasm on May 30, 2011, 12:14:02 PM
From the listing file, I found that my RET is turned into LEAVE + RET.   I suspected it was related to epilogue stuff since the RET had no operand, so I used RET 0.  But, it still gives me a LEAVE.  Why is it so?  How do I turn this off?  Isn't RET with an operand suppresses epilogue generation?

BTW, I am playing around with my exotic idea of fetching the EIP into EAX.  I can put the whole fetcheip stuff into a separate proc, but i just want to do it inside my current proc

mytest proc
call fetcheip
; now eax has the eip value
...
....

fetcheip: mov eax, [esp]
ret ;<---- get turned into LEAVE+RET and killed my idea
...
mytest endp
Title: Re: A LEAVE Generated Before RET
Post by: dedndave on May 30, 2011, 12:29:10 PM
that should not happen if you have no parameters on the PROC line

at any rate, for PROC's that do have parameters, you can turn it off with OPTION
doing so leaves the responsibility of addressing parms, pushing/popping registers, and setting the RET pop size to you

;******************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

ScnMetric PROC  dwFunction:DWORD,lpValue:DWORD

        INVOKE  GetSystemMetrics,[esp+4]  ;dwFunction
        mov     edx,[esp+8]               ;lpValue
        cmp     eax,[edx]
        jae     SMexit

        mov     [edx],eax

SMexit: ret     8

ScnMetric ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;******************************************************


when you are done, return the PROLOGUE and EPILOGUE settings to their defaults   :P
Title: Re: A LEAVE Generated Before RET
Post by: drizz on May 30, 2011, 12:37:26 PM
If you want a nested function inside proc-endp use pseudo instruction "retn" as "ret" generates proc epilogue code.
You could also turn off prologue/epilogue as Dave wrote, but then you can't use some of the high level features.
Title: Re: A LEAVE Generated Before RET
Post by: hutch-- on May 30, 2011, 01:54:41 PM
The technique that Dave has shown you is a procedure with no stack frame, without the stack frame you don't need the LEAVE or the alternative and you then have to add the argument byte count to RET to balance the stack on exit if you are using STDCALL.

With a normal procedure in MASM it generates a stack frame which must be balanced on exit, LEAVE is a short and efficient way to do this, it can also be done by restoring ESP from EBP but is slightly longer.
Title: Re: A LEAVE Generated Before RET
Post by: msqweasm on May 30, 2011, 03:02:02 PM
From masm32\help\masm32.chm :

QuoteOPTION PROLOGUE


Syntax: OPTION PROLOGUE:macroname

OPTION EPILOGUE:macroname


Description

PROLOGUE registers <macroname> as the macro function to be called when a prologue needs to be generated. EPILOGUE registers <macroname> as the macro procedure to be called when a RET or IRET instruction is encountered.

You can revert to the default prologue or epilogue by specifying PrologueDef or EpilogueDef as <macroname>. EPILOGUE code is generated only if the RET or IRET instruction terminating the PROC block has no operand. The RETN, RETF, and IRETF instructions do not cause the assembler to generate epilogue code.

To suppress generation of the prologue or epilogue code, give NONE as the <macroname>.

The assembler expects a macro definition of this form:

macroname MACRO procname, flags, argbytes, localbytes, <reglist>, userparms:VARARG

So does it mean RET 0 should disable epilogue?  And apparently it doesn't :(


mytest proc .... ;may have parameters
   LOCAL ...; may have local vars....
..
call fetcheip
; now eax has the eip value
...
....
JMP continue

   fetcheip: mov eax, [esp]
   ret 0 ;<---- still get turned into LEAVE+RET

continue:
...
ret
mytest endp


My call is actually to some adhoc label inside my proc.  So would it because my RET 0  isn't the last instruction?
Title: Re: A LEAVE Generated Before RET
Post by: dedndave on May 30, 2011, 03:46:34 PM
if you have any parameters on the PROC line, you will get the prologue and epilogue
that means, at minimum, the prologue will be...
        push    ebp
        mov     ebp,esp


and, everywhere you place a RET, it will generate an epilogue...
        leave
        ret     (immed)


if you want, you can force yor own return with
        pop     ebp
        retn    (immed)


the easy way to do what you want to do is to use OPTION to disable the prologue and epilogue
Title: Re: A LEAVE Generated Before RET
Post by: jj2007 on May 30, 2011, 07:20:04 PM
Quote from: drizz on May 30, 2011, 12:37:26 PMIf you want a nested function inside proc-endp use pseudo instruction "retn" as "ret" generates proc epilogue code.

Instead of asking the same question again, why don' you just read the posts and test what drizz (correctly) writes...?
Title: Re: A LEAVE Generated Before RET
Post by: raymond on May 31, 2011, 12:57:10 AM
The simplest of ALL options is to move the called code which is not labeled as a proc (which used to be called a "sub-routine" in the old days) OUTSIDE of any proc. The LEAVE will never get generated in those circumstances.

If you don't need to pass parameters on the stack and don't need LOCAL variables, there's no need to declare such a "function" as a proc. This habit most probably comes from C where you call such code as Func(), need to write it as a proc (even if it's only a RET which I have seen :eek), and C then compiles it as a proc.
Title: Re: A LEAVE Generated Before RET
Post by: Synfire on June 05, 2011, 09:53:47 AM
I think probably the easiest way to achieve what your wanting is to just use a delta macro:

getEIP MACRO dst:REQ
   call $+5
   pop dst
ENDM

.....

getEIP eax
mov [context.eip], eax

....


Be forewarned though, if you start out using tricks like this, you'll end up making this difficult for yourself late on. A lot of anti-viruses wrongfully detect anything like this (or what you were doing) as malicious code because that's the most common place for it's use.
Title: Re: A LEAVE Generated Before RET
Post by: mineiro on June 06, 2011, 07:46:18 PM
Quote from: msqweasm on May 30, 2011, 12:14:02 PM
BTW, I am playing around with my exotic idea of fetching the EIP into EAX.  I can put the whole fetcheip stuff into a separate proc, but i just want to do it inside my current proc
Do some debug with these macros to see if can help you in your jorney.

getip macro
LOCAL arg1
push arg1
pop eax
arg1:
ENDM


getup macro dst:=<eax>
LOCAL arg1,arg2
arg2:
push arg1
pop dst
;insert some code here
; mov ecx,dword ptr [arg1]
sub dst,arg1-arg2
arg1:
endm


fetchip macro
call $+5
mov eax,[esp] ;4ever loop
jmp eax
endm


.code
   getip   ;eax = IP when this one return
   getup   ;eax = Ip of getup
   getup   ebx   ;ebx = IP of getup
fetchip   ;use only while debuggrin this, you get in a forever loop
Title: Re: A LEAVE Generated Before RET
Post by: jj2007 on June 06, 2011, 08:21:55 PM
Another variant of getting the EIP...

include \masm32\include\masm32rt.inc

.data
AppName db "The EIP of start:", 0

.code
@@:
start: push @B
pop eax
MsgBox 0, hex$(eax), addr AppName, MB_OK
exit
end start
Title: Re: A LEAVE Generated Before RET
Post by: dedndave on June 07, 2011, 01:12:42 AM
        call    @F
@@:     pop     eax
Title: Re: A LEAVE Generated Before RET
Post by: hutch-- on June 07, 2011, 07:42:15 AM
Dave,

You will find that JJs version is a better design, it does not mess up the CALL / RET pairing.
Title: Re: A LEAVE Generated Before RET
Post by: dedndave on June 07, 2011, 08:01:29 AM
of course   :P

how 'bout this code, then...
        mov     eax,@F
@@:

or
        mov     eax,$
Title: Re: A LEAVE Generated Before RET
Post by: jj2007 on June 07, 2011, 08:19:58 AM
Quote from: hutch-- on June 07, 2011, 07:42:15 AM
You will find that JJs version is a better design, it does not mess up the CALL / RET pairing.

Dave is more forward-looking, Hutch. His version produces 00401005, mine is stuck at 00401000...
Title: Re: A LEAVE Generated Before RET
Post by: dedndave on June 07, 2011, 08:20:55 AM
 :bg