2013-07-29 3 views
1

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

+1

Каждая платформа имеет различные ограничения (например, Windows и Linux не будут иметь одинаковые требования, не говоря уже о 32 и 64 бит). Лучший ресурс, который я когда-либо нашел, - это [соглашения Agner Fog's C++] (http://www.agner.org/optimize/calling_conventions.pdf), который даст вам необходимую информацию и многое другое. – syam

+1

Википедия тоже хороша: http://en.wikipedia.org/wiki/X86_calling_conventions –

+0

Thx both. @Mats, по какой-то причине «назначенный для использования внутри функции» в Wiki не был достаточно явным для меня, но это должно быть то, что они говорят. – 0xbe5077ed

ответ

2

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

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

И для x86-64, документация here, и говорит

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