News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

"CALL" with Windows API

Started by lamer, January 09, 2006, 06:35:30 PM

Previous topic - Next topic

lamer

Hi all!
It seems to be a bit stupid question, but anyway...
Can I stay quiet using call instead of invoke for Windows API calls?
I mean cleaning up the stack.
Will this code be executed without any nasty outcomes:

.data?
hLib        dd        ?
.data
szUserLib  db       "user32.dll",0
szSomeFunc   db  "SomeAPI",0

.code

LOCAL hFunc    :DWORD

invoke LoadLibrary,addr szUserLib
.if eax
   mov hLib eax
   invoke GetProcAddress,addr szSomeFunc
   .if eax
      mov hFunc,eax
      push 1
      push 2
      call hFunc
   .endif
   invoke FreeLibrary,hLib
.endif


Thank you

Vortex


lamer

Who knows what they do in their functions? :bg
Generally speaking I think too - why not?
Thanks.

hutch--

lamer,

The only difference is between calling conventions, STDCALL you just use push / call notation but with C calling you must balance the stack yourself after the procedure has returned.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

lamer

hutch,
So .model flat,stdcall
allows me not to care about stack balancing?

QvasiModo

Hi :)

The .model flat,stdcall directive only sets the default calling convention as stdcall, so no, you can't stop worrying (unless you use invoke, that is).

An example of a C call is wsprintf:


invoke wsprintf, addr OutputBuffer, CTXT("%i"), SomeInteger


Becomes...


push SomeInteger
push CTXT("%i")
lea eax, OutputBuffer
push eax
call wsprintf
add esp, 12

Ian_B

Quote from: QvasiModo on January 10, 2006, 12:43:54 AM

push SomeInteger
push CTXT("%i")
lea eax, OutputBuffer        <------- NOTE THESE LINES!
push eax                     <-------
call wsprintf
add esp, 12


This can cause some issues if you aren't careful. MASM apparently always uses the EAX register as noted above to perform calculations before pushing the results. If you had stored one of the parameters in EAX and were going to push that AFTER such a calculation, the value would be trashed. I believe the compiler throws an error for this, but it does pay to take care what order you push parameters if any values are stored in EAX and there are address calculations being made in the parameter list.

Personally, I choose to explicitly set registers to values where at all possible using LEA etc. before the invoke, then use the registers as parameters, so I don't inadvertently get caught out. It also means a tiny bit more control over when the calculations are made for better optimisation.

IanB

lamer

But how can I know which convention the function uses?  :(
Is there any mention in documentation?

MichaelW

It would be mentioned somewhere in the documentation, but probably not in the function-specific documentation, unless the function deviated from the norm. To my knowledge all of the Win32 API functions other than wsprintf use the STDCALL calling convention, and all of the CRT functions (MSVCRT.DLL, CRTDLL.DLL, etc) use the C calling convention.
eschew obfuscation


hutch--

lamer,

The basics are that the stack must be corrected at the exit of the procedure that uses the stack for arguments passed to it. With STDCALL the procedure does the correction and that is why you regularly see "RET number" where number may for example be 12 bytes this "RET 12" The number must match the number of bytes that were pushed onto the stack before the procedure was called.

This technique is fine if you have a fixed number of arguments of known sizes but it does not work when you have a variable number of arguments. The alternative is the C calling convention where the calling code does the stack cleanup, usually by adding the byte count to ESP. The procedure that is called when its a C calling convention oly uses a RET without the trailing number.

A C call in code would looks something like this.


push arg2
push arg1
call proc
add esp, 8


With STDCALL where the procedure balances the stack, you have this.


push arg2
push arg1
call proc
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

lamer

hutch,
Thank you very much!
My mind is clear now :U