1

callC++ コードで GNU のインライン アセンブラを介して命令を使用して、__stdcall規則を使用していることがわかっている関数を呼び出す場合、すべてのレジスタを clobbered としてリストする必要がありますか?

私はインターネット上で優れたガイダンスを見つけていませんが%eax、 、%edx、およびのように見えます%ecxが、前の 2 つは戻り値用に予約されています。

これが私のコードです。3 番目のコロンの後に何を入力する必要があるか知りたいです。

#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 ビット コードで保持される必要があります。

したがって、明確にするために、インライン アセンブラでおよびが既に使用されているecxため、 clobbered としてマークする必要があります。eaxedx

x86-64 の場合、ドキュメントはここにあります。

レジスタ RBX、RBP、RDI、RSI、R12、R13、R14、および R15 は不揮発性と見なされ、それらを使用する関数によって保存および復元する必要があります。

于 2013-07-29T19:40:34.593 に答える