0

我有以下功能:

int __declspec() MyFunc(SOCKET sSocket, const char* sData, int sSize, int sFlag)
{
    pSocket = sSocket;
    return send(sSocket,sData, sSize, sFlag);
}

这是编译后的汇编代码:

PUSH EBP
MOV EBP,ESP
PUSH DWORD PTR SS:[EBP+14]               // Flags
MOV EAX,DWORD PTR SS:[EBP+8]
PUSH DWORD PTR SS:[EBP+10]               // DataSize
MOV DWORD PTR DS:[pSocket],EAX
PUSH DWORD PTR SS:[EBP+C]                // Data
PUSH EAX                                 // Socket
CALL DWORD PTR DS:[<&WS2_32.#19_send>]   // send
POP EBP
RETN

我的问题是:

  1. RETN和有什么区别RETN 8RETN 10
  2. 我必须将 final 更改RETNRETN 10,我应该对我的 C++ 代码进行哪些更改?
4

1 回答 1

1

我必须将最终的 RETN 更改为 RETN 10,我应该对我的 c++ 代码进行哪些更改?

要让被调用函数在返回之前清理堆栈(使用RET(N) imm或通过其他方式),请使其使用stdcall调用约定

如果您使用的是 Microsoft 的 C/C++ 编译器,则可以通过添加__stdcall 修饰符来实现此目的,如下所示:

void __stdcall foo(int arg1, int arg2) {
  // ...
}

如果您使用的是 GCC,则可以使用stdcall 属性实现此目的:

void __attribute__ ((stdcall)) foo(int arg1, int arg2) {
  // ...
}

您当然可以#define __stdcall__attribute__ ((stdcall))自己节省一些输入,并使代码更具可移植性。

在 Cygwin 中使用 GCC 编译上述函数会产生以下程序集:

_foo@8:
push    ebp
mov ebp, esp
... (omitted for brevity)
leave
ret 8
于 2013-07-17T07:07:04.817 回答