Hi guys, I'm new around here but I feel like this could be a sweet place to expand my knowledge about assembly.

I've been googling for a while now, but havn't found an answer to this question:

What is the main difference between call and invoke? What is the advantages of manually pushing data on to the stack?

invoke GetModuleFileName, 0, addr szfile, 255

push 255
push addr szfile
push 0
call GetModuleFileName

Thank you in advance for your answers and suggestions!
Posted on 2008-09-04 11:25:02 by n1mda
Technically there is no difference between "CALL" and "INVOKE".
INVOKE has been introduced by Microstuff according to they preference to obfuscate anything (look at your operating system and try to change some system settings in a simple way).
TurboAssembler from Borland doesn't need this distinction.
CALL should be used if a real single processor instruction shall be used to invoke a subroutine.
INVOKE should be used if the assembler shall calculate the stack PUSH/POP instructions automatically depending on the calling conventions like __cdecl, __fastcall, __stdcall and so on. You should prefer this calling method if you call Windows-API and C-API functions mixed up.
If you decide to use CALL only you have to bother about the parameters pushed on/popped from the stack which makes the code more unreliable.

Here is an example which simplifies the calling of two different calling conventions (STDCALL for Windows-API and C for the MSVCRT-API):

szCmdLineString db "This is the commandline: %s",0

invoke GetCommandlineA ;EAX receives the pointer to the EXE-command line using STDCALL
;call GetCommandlineA ;CALL is possible too in this special case because this function doesn't need any stack parameters
invoke printf, ADDR szCmdLineString, EAX ;MSVCRT-__cdecl-like calling convention, no need to bother about stack cleaning.

Posted on 2008-09-04 16:52:51 by TasmDev
invoke has been created to make calling subroutines be extremely readable, with automatic parameter-checking and conversion, and automatic stack adjustment if necessary: "add esp,..."

i.e "addr localVar" will be transformed into "lea eax,localVar  | push eax" when localVar's address is EBP-dependent.
Also, you can push QWORD parameters, and invoke will automatically split that in two correct PUSH instructions.

A precaution note: there's something like a bug in MASM, thanks to which you must not specify a PROC with BYTE and WORD arguments:

SomeProc proc wrong1:BYTE,wrong2:WORD,correct1:DWORD,correct2:QWORD,wrong3:TWORD
Use only DWORD and QWORD as size of arguments!

TasmDev: obfuscation != ultimate convenience with absolutely predictable results and mechanism of work.
Posted on 2008-09-05 02:35:21 by Ultrano
Hi Ultrano,

If you are referring to half stack operations, this is not a bug in MASM but a limitation of the x86 stack, ESP must always be on a 32 bit boundary so pushing any size less than 32 bit would unalign the stack pointer. If you attempt to push a WORD, you must either push another WORD immediately or the assembler must push a NULL WORD in order to maintain alignment. BYTEs are completely forbidden though MASM may make allowances for them.
Posted on 2008-09-05 08:17:31 by donkey
A precaution note: there's something like a bug in MASM, thanks to which you must not specify a PROC with BYTE and WORD arguments:
This bug has been fixed in version ML v9.00.30729.01 FINALLY  :)
Posted on 2008-09-05 15:46:24 by drizz
code is shorter

Try CreateWindowEx, it uses One or two lines and if you push the paremeters one by one onto the stack it needs fifteen lines...
Posted on 2008-09-27 09:21:12 by Grincheux
Thank you all for your replies!

I've been playing around with both alternatives and i havn't found any major differences. It's just a matter of taste.
Posted on 2008-09-27 18:47:20 by n1mda