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

时间:2013-07-29 19:19:50

标签: c++ gcc x86 inline-assembly stdcall

如果我使用call指令,通过GNU的C ++代码内联汇编程序,调用我知道的函数使用__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

This message thread是我在互联网上找到的最好的,但我找不到任何说“这是__stdcall假设它可以修改而不保存”...... < / p>

1 个答案:

答案 0 :(得分:2)

MS确实解释了EAX,EDX和ECX被调用“破坏”,所有其他寄存器必须由被调用者以32位代码保存link to MSDN docs - 使用哪种调用约定无关紧要。

因此,需要明确的是,您需要将ecx标记为已破坏,因为eaxedx已在您的内联汇编程序中使用。

对于x86-64,文档为here,并说

  

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