I am trying to use call to jump to a peice of code and then use ret to get back but this happens within a proc like this.



MainProc PROC
LOCAL blah:DWORD
call SubProc
invoke ExitProcess, 0
SubProc:
mov eax, blah; must be able to access locals of mainfunctions
ret ; here is the problem masm trys to adjust stack

ENDP
Posted on 2003-11-14 09:12:36 by ENF
use retn 0, it will not correct the stack.
Posted on 2003-11-14 09:27:57 by donkey
thanx
Posted on 2003-11-14 09:37:56 by ENF
retn would do. ret is a marco, I could explain it if you want.. but of course ...
Posted on 2003-11-14 09:42:32 by roticv
since I've always placed ret at the end of my functions I'd just assumed ENDP cleaned up the stack
Posted on 2003-11-14 12:06:04 by ENF
Any ret found within the frame of a procedure (i.e. between the PROC declaration and the ENDP) is considered a return from that declared procedure.

If you want to call subroutines (or other "procedures") from within a declared procedure, they must be located outside the frame of your procedure (i.e. after the ENDP). They would then return normally.

Raymond
Posted on 2003-11-14 13:17:48 by Raymond
Hi Raymond,

That is a little desceptive. If I use the following procedure, under those circumstances PrintDec eax will never be executed. However since it is executed, it is obviously allowed. It is CALL not proc/endp that sets up the stack frame.

testproc proc junk:DWORD



Call tester
PrintDec eax

ret

tester:

retn 0

testproc endp
Posted on 2003-11-14 13:28:03 by donkey
This may just be semantics but an assembler syntax is generally critical. I used the word ret because ENF had used that in his code for the embeded subroutine. And my comment, as written, is still entirely correct IMO.

I do agree that the "retn 0" would be acceptable. That is a different instruction. However, by writing subroutines outside a procedure frame should be considered a better practice to avoid potential errors due to the casual use of the simple "ret" instruction.

Raymond
Posted on 2003-11-14 21:40:26 by Raymond

This may just be semantics but an assembler syntax is generally critical. I used the word ret because ENF had used that in his code for the embeded subroutine. And my comment, as written, is still entirely correct IMO.

Hi Raymond,

I did not mean desceptive in the sense that it was incorrect or intentionally misleading, just that Proc and Endp are compiler tools for describing the stack frame and do not actually set it up or take it down, that is the job of CALL/ENTER LEAVE/RET. And for semantics sake the actual mnemonic is RET, it is not a macro of any type, the RET instruction can have an operand or not, RETN is just masm renaming those that have operands (opcodes C2 and CA). And since MASM supports nested procedures of the type the original post was refering to I simply answered the question and made no comment as to the wisdom of using the method. However I have used it in recursive algorithms, specifically a recursive directory search and it works fine. Since the first CALL pushes the return address onto the stack and the second pushes a second return address, as long as the stack is balanced there should never be a problem because the paired RET will always pop the right return address.
Posted on 2003-11-14 22:01:05 by donkey
Donkey,
It is opcode C2 and C3.

By the way, if you do not use retn and retf, how could you tell the assembler which opcode you want? Yes, Intel uses "ret" but most assembler now support retn if I am not wrong.

made a mistake with the opcodes.
Posted on 2003-11-14 23:08:37 by roticv
Opcodes (From Intel Instruction Set Reference)

C3	RET		Near Return to calling procedure

CB RET Far Return to calling procedure
C2 iw RET imm16 Near Return to calling procedure and pop imm16 bytes from stack
CA iw RET imm16 Far Return to calling procedure and pop imm16 bytes from stack


I had said "those that have operands" i.e. RETN (C2,CA), that is return from a procedure providing an operand to correct the stack. RET (C3,CB) can have no operand. An assembler can decide near or far based on the same criteria that it decides near or far jumps, I see no problem with that. If you require a stack frame then it uses C2 or CA if not then C3 or CB. GoAsm does not allow you to use a frame if there are no local vars and so it is not an issue in that assembler.

ret 0 in Goasm uses C3 or CB
ret 4 in GoAsm uses C2 or CA

retn is availble but not necessary, the same is true for masm as far as I know.
Posted on 2003-11-14 23:48:16 by donkey
In the case of MASM: putting the subroutine within the PROC/ENP is useful because then the labels used in the subroutine are local to the PROC. This can really save you a headache once your programs start getting bigger. I agree with donkey that it is very important to know what is going on with the stack. Putting RETN 0 certainly spells out what we are doing, but doesn't fit with MASM's use of RET within a PROC. For there are invisible parameters to RET (used in the OPTION EPILOGUE macro) which are defined by the PROC definition. RET is a macro within MASM, as stated already by roticv. For these reasons I simply use RETN to return from a subroutine within a PROC, but (RET 0 or RETN 0) is no less confusing.
Posted on 2003-11-15 10:42:39 by bitRAKE
"retn" too
Posted on 2003-11-15 12:28:05 by mrgone
"RET" cannot be considered a macro. A macro name gets replaced with a specified set of CPU instructions according to the parameters which may be required according to the definition of that macro. "RET" per se always gets coded as indicated previously by donkey based on the mode being used.

The PROC/ENDP pair could be considered either as a macro or an HLL directive. This gets replaced with CPU instructions to prepare a stack frame such as the "push ebp/mov ebp,esp" instructions as a minimum and an adjustement of the ESP register to reserve stack space for LOCALs when required.

The USES directive which can also be associated with the PROC directive is also replaced with the required pushes to preserve the listed registers.

The "RET" instruction between a PROC/ENDP pair simply triggers the assembler to insert the required instructions for retrieving any preserved register and destroying the stack frame before coding the "RET" instruction in a standard manner. Since a "RET" instruction in a simple subroutine does not result in the generation of all those extra instructions, how can it be considered a macro?

Raymond
Posted on 2003-11-16 21:21:59 by Raymond
MASM32.hlp:
"EPILOGUE registers <macroname> as the macro procedure to be called when a RET or IRET instruction is encountered."
"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."

So i think ret and iret can be considered as macros.
Posted on 2003-11-17 08:16:06 by Aaro

"RET" cannot be considered a macro. A macro name gets replaced with a specified set of CPU instructions according to the parameters which may be required according to the definition of that macro. "RET" per se always gets coded as indicated previously by donkey based on the mode being used.
This is not correct.

It is RET that gets replaced by the EPILOGUE macro - not ENDP.

RET is a macro within a PROC/ENDP.

See this thread and code: http://www.asmcommunity.net/board/index.php?topic=2153&highlight=EPILOGUE
Posted on 2003-11-17 08:59:24 by bitRAKE
wow another FAQ contender.
Posted on 2003-12-16 19:04:38 by evil__donkey