assemblyx86calling-conventionstdcallcdecl

Calling a function that can be either cdecl or stdcall


I need to write code that calls an external function that can be either stdcall call or cdecl in a 32bit windows application.
My code, the caller, can't know in advance which of these its going to be. Right now, if I try to call a cdecl function from a call site that was defined as stdcall, I get a checkEsp exception dialog, and I'm guessing that's there for a good reason.
Is there any way to do it?


Solution

  • It can be done following way:

              mov     esi, esp
    
              push    arg3
              push    arg2
              push    arg1
              call    [SomeExternalProc]
    
              mov     esp, esi   ; now the stack is always properly cleaned 
    

    The external procedure will preserve esi. Or you can use any other register preserved by the external procedure or even memory variable - local or global.

    Good, the order of the arguments is the same for CDECL and STDCALL - in reverse order. (Left-most arg at the lowest address.) So they're compatible except for where ESP points on return. Both conventions agree on which registers are call-preserved vs. call-clobbered.