所以我有一个程序集需要在 Windows 上使用 fastcall 调用约定调用一个函数,但 gcc 不(afaict)支持它。GCC 确实提供了 regparm 属性,但它期望前 3 个参数在 eax、edx 和 ecx 中传递,而 fastcall 期望前两个参数在 ecx 和 edx 中传递。
我只是试图避免有效地复制一些代码路径,所以这并不是很关键,但如果它是可以避免的,那就太好了。
所以我有一个程序集需要在 Windows 上使用 fastcall 调用约定调用一个函数,但 gcc 不(afaict)支持它。GCC 确实提供了 regparm 属性,但它期望前 3 个参数在 eax、edx 和 ecx 中传递,而 fastcall 期望前两个参数在 ecx 和 edx 中传递。
我只是试图避免有效地复制一些代码路径,所以这并不是很关键,但如果它是可以避免的,那就太好了。
GCC 确实支持fastcall
, via __attribute__((fastcall))
。它似乎已在 GCC 3.4 中引入。
我知道我参加这个聚会有点晚了,但如果你们中的任何人偶然发现这一点,请记住,您可以定义一个宏来模仿它。例如:
#if defined(__GNUC__)
#define MSFASTCALL __fastcall
#define GCCFASTCALL
#elif defined(_MSC_VER)
#define MSFASTCALL
#define GCCFASTCALL __attribute__((fastcall))
#endif
int MSFASTCALL magic() GCCFASTCALL;
显然,这看起来有点难看,所以你可以定义 2 个原型(我就是这样做的)以使其更易于阅读,但有些人更喜欢需要更少打字的路线。除了特殊情况,我一般不使用调用约定。我只是让编译器优化其余部分。
现在,有一些怪癖要记住。例如,当您针对 64 位平台时,所有函数都使用 fastcall 约定以利用额外的寄存器并提高速度并降低间接成本。同样,不同平台的 fastcall 实现方式也不同,因为它不是标准化的。还有一些其他的,但这是我能想到的。
如果您从 asm 调用该函数,那么您肯定可以完全控制如何调用该函数。是什么阻止您加载寄存器并发出CALL
?