Если я использую инструкцию call
, используя встроенный ассемблер GNU в коде C++, для вызова функции, которую я знаю, используется соглашение __stdcall
, нужно ли мне перечислять любые регистры, как clobbered?GNU inline asm: какие регистры получают clobbered от __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
This message thread это лучшее, что можно найти в Интернете, но я не смог найти ничего, что говорит, «это то, что __stdcall
предполагает, что он может изменить без сохранения» ...
Каждая платформа имеет различные ограничения (например, Windows и Linux не будут иметь одинаковые требования, не говоря уже о 32 и 64 бит). Лучший ресурс, который я когда-либо нашел, - это [соглашения Agner Fog's C++] (http://www.agner.org/optimize/calling_conventions.pdf), который даст вам необходимую информацию и многое другое. – syam
Википедия тоже хороша: http://en.wikipedia.org/wiki/X86_calling_conventions –
Thx both. @Mats, по какой-то причине «назначенный для использования внутри функции» в Wiki не был достаточно явным для меня, но это должно быть то, что они говорят. – 0xbe5077ed