C有标准的ABI吗?

时间:2010-12-20 11:03:58

标签: c abi

来自讨论somewhere else

  

C ++没有标准的ABI

     

但C也没有,对吧?

     

在任何给定的平台上它几乎都可以。如果没有语言交流,那么作为语言间交流的通用语言将没有用。

你对此有何看法?

9 个答案:

答案 0 :(得分:30)

C不定义ABI。实际上,它会向后弯曲以避免定义ABI。那些喜欢我的人,他们花了大部分编程生活用C编程的16/32/64位架构,8位字节,2的补码算法和平面地址空间,通常会很惊讶于阅读复杂的语言目前的C标准。

例如,阅读有关指针的内容。标准没有说“指针是地址”这么简单,因为它会对ABI做出假设。特别是,它允许指针位于不同的地址空间并具有不同的宽度。

ABI是从语言的执行模型到特定的机器/操作系统/编译器组合的映射。在语言规范中定义一个是没有意义的,因为这会冒一些体系结构排除C实现的风险。

答案 1 :(得分:14)

C原则上没有标准的ABI,但在实践中,这很少重要:你做你的操作系统供应商所做的事。

在x86 Windows上采用调用约定,例如:Windows API使用所谓的“标准”调用约定(stdcall)。因此,任何想要与OS接口的编译器都需要实现它。但是,stdcall不支持所有C90语言功能(例如,调用没有原型的函数,可变函数)。由于Microsoft提供了C编译器,因此需要第二个调用约定,称为“C”调用约定(cdecl)。 Windows上的大多数C编译器都将此作为默认调用约定,因此可以互操作。

原则上,C ++也可能发生同样的情况,但由于C ++ ABI(包括调用约定)必然要复杂得多,编译器供应商并不同意单个ABI,但仍然可以通过回退到{ {1}}。

答案 2 :(得分:5)

ABI,即使对于C,也有与平台无关的部分,依赖于处理器的部分(应该保存哪些寄存器,用于传递参数......)和依赖于OS的部分(或多或少与处理器相同的因素,因为一些选择不是由架构强加的,而是权衡的结果,加上一些操作系统具有独立于语言的语言概念,因此任何语言的编译器都必须生成正确的要处理这些问题,处理线程也可能会对ABI施加影响 - 如果注册表指向TLS,则不能将其用于所需内容。

理论上,每个编译器都可能有自己的ABI。但通常,对于一对处理器/ OS,ABI由OS供应商修复,该供应商通常还提供C编译器和使用该ABI且竞争者更喜欢兼容的公共库。 (如果某些操作系统的例外情况不是主要的编程语言,我不会感到惊讶。)

但操作系统供应商可能出于某种原因切换ABI(新版本的处理器可能具有您想在ABI中使用的功能 - 例如有些人要求x86_64的32位ABI允许全部使用寄存器)。在迁移阶段 - 可能需要很长时间 - 您可能需要处理两个ABI。

答案 3 :(得分:4)

ABI for C是特定于平台的 - 它涵盖了寄存器分配和调用约定等问题,这些问题显然特定于特定处理器。以下是一些例子:

x86有许多调用约定,Windows下的扩展声明了哪一个被使用。嵌入式Linux的平台ABI也随着时间的推移而发生变化,导致用户空间不兼容。查看ARM Linux port here的一些历史记录,其中显示了向较新的ABI过渡的问题。

答案 4 :(得分:4)

C也没有,对吗?正确

在任何给定的平台上,几乎都可以。如果没有语言通信,它就没有用作语言间通信的通用语。
几乎可能指的是由C编译器供应商选择的其他语言的架构特定默认值。因此,如果Keil的ARM C编译器将使用从左到右的小端参数排序和堆栈来传递参数和一些预定的寄存器作为返回值,那么来自其他编译器的extern“C”将假定与此类方案兼容。

虽然这样的协议可能被认为是ABI的一部分,但与JVM浏览器沙箱等托管执行上下文不同,这远不是完全标准的ABI本身。

答案 5 :(得分:2)

  

虽然已经进行了多次尝试   为a定义单个ABI   给定跨多个架构   操作系统(特别适用于   在Unix系统上的i386),努力   没有遇到过这样的成功。   相反,操作系统倾向于   定义自己的ABI ......

引用... Linux System Programming第4页。

答案 6 :(得分:1)

C没有标准的ABI。这可以通过在那里使用的所有调用约定(cdecl,fastcall和stdcall)轻松说明。每个都是不同的ABI。

答案 7 :(得分:0)

在C89标准之前,许多平台的C编译器基本上使用相同的ABI,除了数据大小的变化。对于堆栈向下增长的机器,调用函数的代码将按顺序从右到左推送堆栈中的参数,然后调用该函数(在该过程中推送返回地址)。被调用的函数会将其参数保留在堆栈上,调用者可以随意调整堆栈指针以删除它们[或者,在某些体系结构中,可能会调整堆栈值]。尽管<stdarg.h>使得大多数程序都没有必要依赖该约定,但它仍然使用多年,因为它很简单且工作得很好。虽然没有&#34;官方&#34;文档确定这是一个跨平台的标准&#34;,大多数针对具有向下增长的堆栈的计算机的编译器都以这种方式工作,从而导致比现在更高的一致性。

答案 8 :(得分:0)

没有标准的 ABI,因为 C 一直是关于最大运行时性能的,而具有最高性能的 ABI 取决于底层硬件。因此,ABI 可能仅使用堆栈或首选寄存器来根据任何给定硬件的需要传递函数调用参数和返回值。

例如,即使是 amd64(又名 x86-64)也有两个调用约定:Microsoft x64 和 System V AMD64 ABI。前者将 4 个第一个参数放入寄存器,其余放入堆栈。后者将 6 个第一个参数放入寄存器,其余放入堆栈。我不知道为什么 Microsoft 为 amd64 硬件创建了不兼容的调用约定。据我所知,Microsoft 变体的性能稍差,并且是后来创建的。

有关详细信息,请参阅https://en.wikipedia.org/wiki/X86_calling_conventions