繁体   English   中英

我应该使用什么调用约定来实现可移植性?

[英]What calling convention should I use to make things portable?

我正在为 CPU 的cpuid指令编写一个 C 接口。 我这样做只是作为一种练习:我不想使用依赖于编译器的标头,例如cpuid.h的 cpuid.h 或 MSVC 的intrin.h 此外,我知道使用 C 内联汇编将是更好的选择,因为它避免了考虑调用约定(请参阅此实现):我只需要考虑不同的编译器语法。 不过,我想开始练习一下集成汇编和 C。

鉴于我现在必须为每个主要汇编器(我在考虑 GAS、MASM 和 NASM)编写不同的汇编实现,并且为 x86-64 和 x86 编写不同的汇编实现,我应该如何处理不同的机器和 C编译器可能使用不同的调用约定?

如果你真的想写一个程序集 function,作为一个练习,它“符合”x86_64 的所有常见调用约定(我只知道 Windows 一个和 System V 一个),而不依赖于属性或编译器标志来强制调用约定,让我们看看有什么共同之处。

Windows GPR 传递顺序是rcx , rdx , r8 , r9 System V 的传递顺序是rdirsirdxrcxr8r9 在这两种情况下,如果 rax 适合并且是 POD 的一部分,则rax持有返回值。 从技术上讲,如果它 (0) 保存了每个 ABI 认为非易失性的内容的并集,并且 (1) 返回可以放入单个寄存器的内容,并且 (2) 需要不超过 2 GPR arguments,因为重叠会发生在过去。 为了绝对通用,您可以使它采用指向某个结构的单个指针,该结构将保存您想要的任意返回数据。

所以现在我们的 arguments 将通过rcxrdxrdirsi来。 你如何判断哪个包含 arguments? 我实际上不确定一个好方法。 也许你可以做的是有一个包装器,将 arguments 放在正确的位置,并让你的实际 function 采取“填充”arguments,这样你的 arguments 总是落在rcxrdx中。 您可以通过这种方式在技术上扩展到r8r9

#ifdef _WIN32
#define CPUID(information) cpuid(information, NULL, NULL, NULL)
#else
#define CPUID(information) cpuid(NULL, NULL, NULL, information)
#endif

// d duplicates a
// c duplicates b
no_more_than_64_bits_t cpuid(void * a, void * b, void * c, void * d);

然后,在你的程序集中,保存每个 ABI 认为非易失性的联合,做你的事,把你想要的任何信息放在rcx指向的结构中,然后恢复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM