【问题标题】:C++ Assembly "RETN 10" [duplicate]C ++程序集“RETN 10”[重复]
【发布时间】:2013-07-17 06:20:15
【问题描述】:

我有以下功能:

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. RETNRETN 8RETN 10 有什么区别?
  2. 我必须将最终的RETN 更改为RETN 10,我应该对我的C++ 代码进行哪些更改?

【问题讨论】:

  • 我建议你买一本关于 x86 汇编语言的书来了解 retn 和 retn 10 之间的区别。
  • 我建议看看类似的问题stackoverflow.com/questions/1396909/…
  • 谢谢,我得到了 retn 和 retn 10 的区别,我的第二个问题呢?
  • “我的第二个问题呢”:写成stdcall? (即,如果您使用 GCC,请在函数中添加 __attribute__((stdcall))
  • @Michael "错误:标识符 "stdcall" 未定义,我可以将 __stdcall 添加到我的函数中吗?

标签: c++ assembly


【解决方案1】:

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

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

如果您使用的是 Microsoft 的 C/C++ 编译器,您可以通过添加 __stdcall modifier 来实现这一点,如下所示:

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

如果您使用的是 GCC,您可以使用stdcall attribute

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

【讨论】:

    猜你喜欢
    • 2016-08-25
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2014-11-05
    相关资源
    最近更新 更多