GNU内联asm:哪些寄存器被__stdcall阻塞

GNU inline asm: which registers get clobbered by __stdcall?

本文关键字:stdcall 阻塞 寄存器 内联 asm GNU      更新时间:2023-10-16

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

我在互联网上找不到很好的指导,但看起来%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认为它可以在不保存的情况下修改的"的东西。。。

MS确实解释了EAX、EDX和ECX是";销毁";通过调用,所有其他寄存器必须由被调用者以32位代码保存,链接到MSDN文档-使用哪种调用约定并不重要。

因此,为了清楚起见,您需要将ecx标记为clobbered,因为eaxedx已经在您的内联汇编程序中使用了。

对于x86-64,文档在这里,上面写着

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