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
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
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.
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.
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?
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
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...?
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.
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.
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
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
call @F
@@: pop eax
Dave,
You will find that JJs version is a better design, it does not mess up the CALL / RET pairing.
of course :P
how 'bout this code, then...
mov eax,@F
@@:
or
mov eax,$
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...
:bg