I hope this is a simple question ...
If i push my arguments manually and use call for a routine, do I need to pop the arguments off
the stack after the call if I used the default proc definition ?
eg:
myproc proc arg1:DWORD, arg2:DWORD
Also, how can I push a word and balance the stack ?
rgs, striker
If you are using stdcall calling convention, you don't need to pop the arguments off the stack, the procedure does this itself. With C -calling convention you can pop the arguments off the stack after the call like this;
push 1
push 2
call myproc
add esp, 8 ; balance stack
You can "push" a word for example like this:
sub esp, 4 ; or push 'someregister', just make sure you make room for the value
mov word ptr [esp], dx ; move WORD to the stack
:dazzled:
For most functions in the windows api you don't need to since they do the cleanup themselves.
You just have to watch out for C type functions (such as wsprintf) where you have to do the cleanup - because they can have any number of arguments and the function doesn't know in advance how many that is.
Most functions you'll use will be 'stdcall' - so you don't need to cleanup, but if they're declared as "proto c" then you've got to do it :wink
Usually word arguments are padded with another null word to keep the other arguments aligned, but it depends what the function expects ::)
James,
Just to make life complicated, here is another way to perform STDCALL.
.data
TitleTxt db "MOV stack",0
MsgTxt db "Hi There",0
.code
mov DWORD PTR [esp-16], 0
mov DWORD PTR [esp-12], OFFSET MsgTxt
mov DWORD PTR [esp-8], OFFSET TitleTxt
mov DWORD PTR [esp-4], MB_OK
sub esp, 16
call MessageBox
Quote from: striker on May 12, 2005, 09:02:48 AM
I hope this is a simple question ...
If i push my arguments manually and use call for a routine, do I need to pop the arguments off
the stack after the call if I used the default proc definition ?
eg:
myproc proc arg1:DWORD, arg2:DWORD
Also, how can I push a word and balance the stack ?
rgs, striker
At the top of your source code, you should have the line .model flat,stdcall.
This means that all procs are stdcall by default.
In stdcall the procedure is responsible for stack balancing.
If you push a dword and balance the stack it is like this:
push eax
add esp,4
because a dword is 4 bytes. A word is only two bytes so:
push ax
add esp,2
Quote from: Hutch--Just to make life complicated, here is another way to perform STDCALL.
Hutch,
You're a bad, bad man <g> While it'd very likely work, it's bad practice to write below (E)SP.
I seem to recall it that writing below the stack pointer caused problems under DOS because TSRs and int. handlers use the same stack as the current program and thus you could end up with stack corruption. Just as a matter of idle curiosity, does anyone know if writing below the stack pointer does cause any problems under Windows? I'd guess not, but I'm curious if anyone's tried it.
regards,
-Brent
Quote from: doomsday on May 12, 2005, 05:47:48 PMJust as a matter of idle curiosity, does anyone know if writing below the stack pointer does cause any problems under Windows? I'd guess not, but I'm curious if anyone's tried it.
There was some discussion about this in the other forum: http://board.win32asmcommunity.net/index.php?topic=20128.0.
At least some debuggers can mess the data in the negative offsets of the esp.
Striker,
If your procedure expects a word argument, for a memory operand you could do either of these:
sub esp,2
push mem16
push word ptr 0
push mem16
And for a register operand, you could just push the dword register.
:bg
> You're a bad, bad man
You are probably right but all it does is occupy the same memory as 4 pushes so one of these days I will have a play to see if 4 MOVs are faster than 4 PUSHs.
You can certainly achieve the same goal with slight modifications and without taking any potential risk related to writing below the stack pointer.
sub esp, 16
mov DWORD PTR [esp], 0
mov DWORD PTR [esp+4], OFFSET MsgTxt
mov DWORD PTR [esp+8], OFFSET TitleTxt
mov DWORD PTR [esp+12], MB_OK
call MessageBox
Raymond
OMG - What have I started ?
:bg
James,
You are now the victim of a plethora of deviant STDCALL techniques. :boohoo:
Quote from: hutch-- on May 13, 2005, 12:42:50 AMYou are probably right but all it does is occupy the same memory as 4 pushes so one of these days I will have a play to see if 4 MOVs are faster than 4 PUSHs.
I hope i'm not going too off-topic, but i just have to say that in my Athlon, three or more mov's are faster than pushes. It also seems that Visual C++/g++ compiler goes heavily on moving the paramaters to the stack, rather than pushing them.
Hi striker,
You can code your own invoke macro, here is an example:
_invoke MACRO funcname:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
local pos,counter
counter=0
FOR arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
IFNB <arg>
counter=counter+1
pos=@InStr(1,arg,<ADDR>) OR @InStr(1,arg,<addr>) OR @InStr(1,arg,<Addr>)
IF pos
IF (OPATTR(@SubStr(arg,%pos+5))) EQ 98
lea eax,@SubStr(<arg>,%pos+5)
push eax
ELSE
push OFFSET @SubStr(<arg>,%pos+5)
ENDIF
ELSE
push arg
ENDIF
ENDIF
ENDM
call funcname
ENDM
EGAD. Why reinvent the wheel with such a complex design (probably difficult to understand even by Einstein :P) when the simple invoke instruction is already available in MASM. It may not even be usable with other assemblers.
I guess it's like climbing a mountain. People do it simply because it's there!
Raymond
Quote from: striker on May 13, 2005, 03:13:48 AM
OMG - What have I started ?
For future reference: never ask 'simple' questions on this board :lol
Quote from: raymond on May 13, 2005, 02:37:02 PM
EGAD. Why reinvent the wheel with such a complex design (probably difficult to understand even by Einstein :P) when the simple invoke instruction is already available in MASM. It may not even be usable with other assemblers.
I guess it's like climbing a mountain. People do it simply because it's there!
Raymond
Raymond,
Have a look at here to see why I reinvented the wheel :P
http://www.masmforum.com/simple/index.php?topic=99.0
:green
Nah,
We were just trying to lead James astray, walk on the wild side, do it different and still get it to work OK. :bg
QuoteHave a look at here to see why I reinvented the wheel
Thanks for the reminder. I had forgotten that I had already looked at that thread many months ago. Must be age related. :boohoo:
Raymond
No problem Raymond, just as you said the simple invoke macro is enough for general purpose codig. My simple macro example demonstrates the power of Masm macro system.