I been playing around with the stack a lot lately yet i'm having troubles understanding something take for example
.data?
mybuff db 256 dup(?)
.code
start:
invoke func1,33,0,0
invoke ExitProcess,0
func1 proc p1,p2,p3
push esp
call func2
ret
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff <-------------------gives some random number definitely not 33
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
'push esp' will push the value of esp, which points to the return address, not the parameter list for func1 (I assume that's what you want?).
thanks and yeah how I push the param list of the first function, without doing each 1 individually?
Just use invoke as normal
func1 proc p1,p2,p3
invoke func2,p1,p2,p3
ret
func1 endp
that's not what i'm after :\ I want to push the whole param list without doing each one individually
func1 proc p1,p2,p3
jmp func2
func1 endp
Not sure what you are after...you want to reuse the params as they are on the stack without pushing them again?
If you need to replicate the parameters on the stack I can see multiple methods, but none better than pushing them individually.
You can't depend on the stack parameters being the same on return as they were at the call. People have been known to load a parameter and save a register on top of that parameter (see the laboratory). In other cases, the parameter is used as a work value (a count), so always push them again.
what if you dont know the exact count for instance? just keep pushin? heh
I honestly don't understand your question. Could you rephrase it with an example?
Dave.
my question is very simple how can you pass on the entire stack to another function, without pushing individual parameters, or is there a way to get the count of parameters from the stack? without knowing ahead of time it takes 5 params for instance.
not without saving ESP in a variable ahead of time or something
you might try something like this
RetAddr dw ?
func1 proc p1,p2,p3
pop RetAddr
call func2
jmp dword ptr RetAddr
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff <-------------------gives some random number definitely not 33
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
another approach might be to make room on the stack before the call to func1
then, you could put the return address there and run func2 from func1
Cube,
You can pass the address of the first and calculate the rest in the called proc but a simple set of pushes is usually more efficient. coded up a test piece years ago to test this ands the MOV MEM and adjust ESP was a lot slower than the pushes. PUSH POP are generally optimised in the procressor.
You could rewrite the proc to take one pointer to a structure in EAX but its a different animal to what you are after.
RetAddr dd ?
func1 proc p1,p2,p3
pop RetAddr
call func2
ret
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff <-------------------gives some random number definitely not 33
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
this works but what's weird is parameter p1 from func1 shows up as p2 in func2, and p2 in p3
also does this do any damage, even though it's calling a function with only 3 params?
push [ebp+56]
push [ebp+52]
push [ebp+48]
push [ebp+44]
push [ebp+40]
push [ebp+36]
push [ebp+32]
push [ebp+28]
push [ebp+24]
push [ebp+20]
push [ebp+16]
push [ebp+12]
push [ebp+8]
call func2
If one function called a second function with 3 parameters, and the second called the third function with the same 3 parameters, and the parameters were not needed anymore by the second function (maybe just the return value in eax), then the second function could pop the return address from the stack into a fixed memory DWORD, then call the third function (the parameters are still on the stack), then push the fixed memory DWORD to restore the return address. The second function would have to maintain the stack frame itself and do a ret 0 and not try to adjust the stack for the 3 parameters, or the third function would have to maintain the stack frame itself and not adjust the stack for the 3 parameters, or finally, the second function could adjust adjust the stack upon return from the third function with lea esp,[esp+12] to reinstate the 3 parameters that the third function removed before the second function pushed the fixed DWORD back on the stack.
Messy, fail prone, but doable. MASM lets you get into as much trouble as you want.
Dave.
Quote from: hutch-- on July 19, 2010, 03:11:19 AM
Cube,
You can pass the address of the first and calculate the rest in the called proc
can you give simple example please
Let me correct my first reply: "lea esp,[esp-12]".
Dave.
lea esp,[esp+4] before the call fixed it, I went with daves method, thanks guys.
Quote from: KeepingRealBusy on July 19, 2010, 03:31:50 AM
Messy, fail prone, but doable. MASM lets you get into as much trouble as you want.
Yes :green
include \masm32\include\masm32rt.inc
MyTest PROTO: DWORD, :DWORD
MyFake PROTO: DWORD, :DWORD
.code
AppName db "Masm32 is great!", 0
Hello db "A message:", 0
start: mov ebx, esp
invoke MyTest, offset AppName, addr Hello
invoke MyFake, offset AppName, addr Hello
.if ebx!=esp
MsgBox 0, "The stack is not correct", "Hi", MB_OK
.endif
exit
MyFake proc arg1:DWORD, arg2:DWORD
MsgBox 0, arg1, "Now we are curious, aren't we?", MB_OK
jmp TheTrick
MyFake endp
MyTest proc arg1:DWORD, arg2:DWORD
LOCAL lv1, lv2, locbuf[260]:BYTE
TheTrick::
MsgBox 0, arg1, arg2, MB_OK
ret
MyTest endp
end start
well - it may help to simply think in terms of "what should the stack look like when we get to func2"
on the stack, you want:
1) p3
2) p2
3) p1
4) return address
if #4 is the return address inside func1, then the previous methods will work
but, if there is no code in func1 after the transfer to func2, there is an even simpler method
func1 proc p1,p2,p3
;presumably some code here
jmp func2
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
or even simpler...
func1 proc p1,p2,p3
;presumably some code here
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
which let's execution "fall through" to func2
with older assemblers, we could nest procedures
that seems to be a little trickier with newer masm versions - haven't played with it much
at any rate, it may help to turn off the default prologue and epilogue when playing with these kind of tricks
the mysterious p2 to p1 shift probably occured because the prologue pushes EBP
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;E^Cube stuff here
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
Quote from: dedndave on July 19, 2010, 12:35:19 PM
func1 proc p1,p2,p3
;presumably some code here
jmp func2
func1 endp
I didn't have the nice comment but at least my code was indented :bg
Quote from: sinsi on July 19, 2010, 01:42:36 AM
func1 proc p1,p2,p3
jmp func2
func1 endp
lol - yah - it can even be easier than that :lol
func1:
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
or ...
func1 TEXTEQU <func2>
Quote from: dedndave on July 19, 2010, 12:35:19 PM
but, if there is no code in func1 after the transfer to func2, there is an even simpler method
func1 proc p1,p2,p3
;presumably some code here
jmp func2
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
or even simpler...
func1 proc p1,p2,p3
;presumably some code here
func1 endp
func2 proc p1,p2,p3
invoke dwtoa,p1,addr mybuff
invoke MessageBox,0,addr mybuff,NULL,MB_OK
ret
func2 endp
which let's execution "fall through" to func2
Dave, you are up for surprises :green
(take my example to find out - Olly is your friend)
no surprises here Jochen - lol
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;E^Cube stuff here
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
in fact, i considered just using this at the beginning of my programs
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
because i always prefer to write that way
but, that would break compatibility with everyone in the forum :P
back, before the advent of the internet, i used to use some abbreviations, too
i couldn't use my old abbreviations for the same reason - noone else would get it - lol
BPT EQU Byte Ptr
WPT EQU Word Ptr
DPT EQU Dword Ptr
OFS EQU Offset
SHO EQU Short
mov BPT WordLabel,10h
mov ax,OFS ByteLabel
jmp SHO BranchLabel
Quote from: dedndave on July 19, 2010, 01:25:18 PM
no surprises here Jochen - lol
Dave,
fallthrough works fine if there are no local variables. Otherwise there is trouble, because part II of the framing, the sub esp, nnn is being done twice. Here is an example that works
with local variables.
include \masm32\include\masm32rt.inc
MyTest PROTO: DWORD, :DWORD
MyFake PROTO: DWORD, :DWORD
.code
AppName db "Masm32 is great!", 0
start: mov ebx, esp
; int 3
invoke MyTest, offset AppName, chr$("The real thing:")
invoke MyFake, offset AppName, chr$("The fake:")
.if ebx!=esp
MsgBox 0, "The stack is not correct", "Hi", MB_OK
.endif
exit
MyFake proc arg1:DWORD, arg2:DWORD
LOCAL lv1, LocRetVal, locbuf[260]:BYTE
MsgBox 0, arg1, "Now we are curious, aren't we?", MB_YESNOCANCEL
mov LocRetVal, eax
jmp TheTrick
MyFake endp
MyTest proc arg1:DWORD, arg2:DWORD
LOCAL lv1, WhatEver, locbuf[260]:BYTE
mov WhatEver, IDNO
TheTrick::
MsgBox 0, str$(WhatEver), arg2, MB_OK
ret
MyTest endp
end start
if i turn off prologues (and epilogues), the locals are literal and visible in the code :bg