Если я использую 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
предполагает, что он может измениться без сохранения «…
MS объясняет, что EAX, EDX и ECX «уничтожаются» вызовами, все остальные регистры должны сохраняться вызываемым пользователем в 32-битном коде, ссылка на документы MSDN — не имеет значения, какое соглашение о вызовах используется.
Итак, чтобы быть ясно, вы должны отметить ecx
как забитый, так как eax
а также edx
уже используются в вашем встроенном ассемблере.
А для x86-64 документация есть Вот, и говорит
Регистры RBX, RBP, RDI, RSI, R12, R13, R14 и R15 считаются энергонезависимыми и должны быть сохранены и восстановлены функцией, которая их использует.
Других решений пока нет …