I think you would only get a stack blowout, if the proc was not called often, it may keep going but with the unmatched "push ebp" at the begining of the proc, it would cause a stack fault once the stack was loaded enough times.

EDIT : Funny enough, after having looked at the timing for LEAVE, it seems to be a tidy stall free procedure exit.


Posted on 2002-02-17 06:51:38 by hutch--
perhaps you have forgotten that ret takes the return-eip from the
stack? Without leave or manual stack-fixing, ret would take the old
ebp value as eip... which is VERY likely to crash your app ;).
Posted on 2002-02-17 06:55:00 by f0dder
Always helps to take the guesswork out if it. The process is of little use except in narrow format procedures that are manually coded.

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


push ebp

mov eax, [esp + 8]
mov ecx, [esp + 12]
mov ebp, [esp + 16]
; -------------------------------------
; code something in the registers here
; -------------------------------------
add eax, ecx
add eax, ebp
; -------------------------------------

pop ebp

db 0C3h

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Subtract 4 from the stack addresses if you don't want to use EBP. IE No push/pop ebp and substitute EDX for the instance of EBP.

I seriously doubt that the internals of ML.EXE would handle a single switch between NEAR and FAR by passing it to the MACRO engine in ML.EXE in much the same way that it would not pass the difference between a segmented executable that uses a FAR call and RET and a FLAT model NEAR call to the MACRO engine. Its probably just a bit more complex than that.


Posted on 2002-02-17 17:31:22 by hutch--
Yadda yadda. Take a look at this. Perhaps you want to trace it
with a debugger if you haven't forgotten how such a thing works.

procnear proc arg1:dword
mov eax, [arg1]
procnear endp

procfar proc far, arg1:dword
mov eax, [arg1]
procfar endp

invoke procnear, 42424242h
invoke procfar, 42424242h

invoke MessageBox, NULL, offset szText, offset szText, MB_OK
invoke ExitProcess, 0
Posted on 2002-02-18 02:44:54 by f0dder
I am not shure I understand what the fuzz is all about.

MyProc proc arg:DWORD


call MySub



MyProc endp

Does nothing weird and is fully recursive and is sometimes very useful.

Posted on 2002-02-18 03:31:19 by KetilO

I am not either but it does not really matter, I am a pragmatist, not a purist.

Yadda yadda.

Sounds like it. :tongue:

The proc I posted can be made go faster by a very simple means, as pushing the data onto the stack is slow, just directly pass in registers and you lose the stack overhead. The technique is restricted to not using true locals and can only load registers so you may as well pass in registers and pick up the extra speed.

When I can see an advantage in specifying RETN or RETF, I may stop yawning about it but if it ain't smaller or faster, who cares. The technique may be useful for doing binary patches but then you code them in HEX, not mnemonics so its hard to stop yawning about all of this profundity. :grin:



PS: WHy bother to trace it in SOFTICE when a dead listing will do it better, clearer and faster ?
Posted on 2002-02-18 06:00:42 by hutch--
Who said softice? I just said trace... and that was mainly to show
a little interesting fact you probably don't know: when pusing a
segment register on a 32bit stack, stack changes by 4 bytes... even
though segment register is only two bytes.

But oh well.
Posted on 2002-02-18 06:13:57 by f0dder
Sorry f0dder but segment registers interest me about as much a tuning a T model ford for formula one. It probably can be done but why bother. :)


Posted on 2002-02-18 06:28:42 by hutch--
I'm pretty sure that MASM 1 through MASM 4 allowed nested procedures. The nested procedures were actually pulled out and I believe the inner procedures were positioned after the enclosing procedure. I'd have to find the copy of MASM 4 that I had to verify this.
Posted on 2002-02-18 20:12:15 by tank