调用可以是cdecl或stdcall的函数

时间:2013-07-13 00:20:50

标签: windows assembly 32-bit stdcall cdecl

我需要编写一个调用外部函数的代码,该函数可以是32位Windows应用程序中的stdcall调用或cdecl。
我的代码,呼叫者,无法事先知道它将成为哪一个。 现在,如果我尝试从定义为stdcall的调用站点调用cdecl函数,我会得到一个checkEsp异常对话框,我猜这是有充分理由的。 有没有办法做到这一点?

3 个答案:

答案 0 :(得分:3)

可以按照以下方式完成:

          mov     esi, esp

          push    arg3
          push    arg2
          push    arg1
          call    [SomeExternalProc]

          mov     esp, esi   ; now the stack is always properly cleaned 

外部程序应该保留esi。或者,您可以使用外部过程保存的任何其他寄存器,甚至是内存变量 - 本地或全局。

好,CDECL和STDCALL的参数顺序相反 - 顺序相反。

答案 1 :(得分:1)

您还可以使用alloca(),它具有保存和恢复堆栈指针的副作用:

{
    alloca( (uintptr_t)callback & 2 );
    callback();
}

答案 2 :(得分:0)

根据定义,cdecl和stdcall不兼容。在cdecl中,调用者清理堆栈,在stdcall中,被调用者清理堆栈。如果你假设stdcall,但它实际上是cdecl,没有人清理堆栈。这意味着你的ESP(堆栈指针)将在通话后被搞砸。也许如果你提供更多的细节,可能会有一个解决方法,但是如果不知道它的调用约定而没有弄乱你的堆栈,就无法调用函数。

请参阅:http://en.wikipedia.org/wiki/X86_calling_conventions了解差异的定义。