1

如果我call通过 GNU 的 C++ 代码中的内联汇编程序使用该指令来调用我知道使用__stdcall约定的函数,我是否必须将任何寄存器列为被破坏的?

我在互联网上找不到很好的指导,但它看起来像%eax,%edx%ecx是调用者保存的,前两个保留用于返回值。

这是我的代码。我想知道我需要在第三个冒号后面放什么。

#include <cstdint>

namespace {

inline uint64_t invoke_stdcall(uint64_t (* stdcall_func)())
{
    unsigned long hi32, lo32;
    asm(
        "call %2"
        : "=d" (hi32), "=a" (lo32)
        : "m" (stdcall_func)
        : /* HELP! What goes here? */
    );
    return static_cast<uint64_t>(hi32) << 32 | static_cast<uint32_t>(lo32);
}

} // anonymous namespace

这个消息线程是我在互联网上能找到的最好的,但我找不到任何说“这是__stdcall假设它可以在不保存的情况下修改”...

4

1 回答 1

2

MS确实解释了EAX,EDX和ECX被调用“破坏”,所有其他寄存器必须由被调用者以32位代码保存,链接到MSDN文档- 使用哪种调用约定都没有关系。

因此,需要明确的是,您需要标记ecx为 clobbered,因为eax并且edx已经在您的内联汇编器中使用。

对于 x86-64,文档在这里,并说

寄存器 RBX、RBP、RDI、RSI、R12、R13、R14 和 R15 被认为是非易失性的,必须由使用它们的函数保存和恢复。

于 2013-07-29T19:40:34.593 回答