Встроенный ассемблер GNU: какие регистры перекрываются __stdcall?

Если я использую 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 предполагает, что он может измениться без сохранения «…

1

Решение

MS объясняет, что EAX, EDX и ECX «уничтожаются» вызовами, все остальные регистры должны сохраняться вызываемым пользователем в 32-битном коде, ссылка на документы MSDN — не имеет значения, какое соглашение о вызовах используется.

Итак, чтобы быть ясно, вы должны отметить ecx как забитый, так как eax а также edx уже используются в вашем встроенном ассемблере.

А для x86-64 документация есть Вот, и говорит

Регистры RBX, RBP, RDI, RSI, R12, R13, R14 и R15 считаются энергонезависимыми и должны быть сохранены и восстановлены функцией, которая их использует.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]