GNU 内联 asm:哪些寄存器被 __stdcall 破坏了?

问题描述 投票:0回答:1

如果我使用

call
指令,通过 C++ 代码中的 GNU 内联汇编程序调用我知道使用
__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
假设它可以在不保存的情况下修改”的东西...

c++ gcc x86 inline-assembly stdcall
1个回答
3
投票

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

所以,为了清楚起见,您需要将

ecx
标记为已损坏,因为
eax
edx
已经在内联汇编器中使用了。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.