简体   繁体   English

C 有标准的 ABI 吗?

[英]Does C have a standard ABI?

From a discussion somewhere else :来自其他地方的讨论:

C++ has no standard ABI (Application Binary Interface) C++ 没有标准的 ABI(应用程序二进制接口)

But neither does C, right?但 C 也不行,对吧?

On any given platform it pretty much does.在任何给定的平台上,它几乎都可以。 It wouldn't be useful as the lingua franca for inter-language communication if it lacked one.如果缺少一种语言,它就无法用作跨语言交流的通用语言。

What's your take on this?你怎么看?

C defines no ABI. C 没有定义 ABI。 In fact, it bends over backwards to avoid defining an ABI.事实上,它向后弯曲以避免定义 ABI。 Those people, who like me, who have spent most of their programming lives programming in C on 16/32/64 bit architectures with 8 bit bytes, 2's complement arithmetic and flat address spaces, will usually be quite surprised on reading the convoluted language of the current C standard.那些像我一样在 8 位字节、2 的补码算术和平面地址空间的 16/32/64 位体系结构上用 C 语言编程的人,通常会在阅读复杂的语言时感到非常惊讶当前的 C 标准。

For example, read the stuff about pointers.例如,阅读有关指针的内容。 The standard doesn't say anything so simple as "a pointer is an address" for that would be making an assumption about the ABI.该标准并没有像“指针是地址”那样简单地说明任何事情,因为那将是对 ABI 的假设。 In particular, it allows for pointers being in different address spaces and having varying width.特别是,它允许指针位于不同的地址空间并具有不同的宽度。

An ABI is a mapping from the execution model of the language to a particular machine/operating system/compiler combination. ABI 是从语言的执行模型到特定机器/操作系统/编译器组合的映射。 It makes no sense to define one in the language specification because that runs the risk of excluding C implementations on some architectures.在语言规范中定义一个是没有意义的,因为这会带来在某些架构上排除 C 实现的风险。

C has no standard ABI in principle, but in practice, this rarely matters: You do what your OS-vendor does. C 原则上没有标准的 ABI,但在实践中,这很少重要:你做什么你的操作系统供应商做什么。

Take the calling conventions on x86 Windows, for example: The Windows API uses the so-called 'standard' calling convention (stdcall).以 x86 Windows 上的调用约定为例:Windows API 使用所谓的“标准”调用约定 (stdcall)。 Thus, any compiler which wants to interface with the OS needs to implement it.因此,任何想要与操作系统交互的编译器都需要实现它。 However, stdcall doesn't support all C90 language features (eg calling functions without prototypes, variadic functions).然而,stdcall 并不支持所有的 C90 语言特性(例如调用没有原型的函数、可变参数函数)。 As Microsoft provided a C compiler, a second calling convention was necessary, called the 'C' calling convention (cdecl).由于 Microsoft 提供了 C 编译器,因此需要第二个调用约定,称为“C”调用约定 (cdecl)。 Most C compilers on Windows use this as their default calling convention, and thus are interoperable. Windows 上的大多数 C 编译器使用它作为它们的默认调用约定,因此是可互操作的。

In principle, the same could have happened with C++, but as the C++ ABI (including the calling convention) is necessarily far more elaborate, compiler vendors did not agree on a single ABI, but could still interoperate by falling back to extern "C" .原则上,C++ 也可能发生同样的情况,但由于 C++ ABI(包括调用约定)必然要复杂得多,编译器供应商并未就单个 ABI 达成一致,但仍然可以通过回退到extern "C"互操作.

The ABI for C is platform specific - it covers issues such as register allocation and calling conventions, which are obviously specific to a particular processor. C 的 ABI 是特定于平台的——它涵盖了诸如寄存器分配和调用约定等问题,这些问题显然是特定于特定处理器的。 Here are some examples:这里有些例子:

x86 has had many calling conventions, which extensions under Windows to declare which one is used. x86 有很多调用约定,Windows 下的哪些扩展来声明使用哪一个。 Platform ABIs for embedded Linux have also changed over time, leading to incompatible user space.嵌入式 Linux 的平台 ABI 也随着时间而改变,导致用户空间不兼容。 See some history of the ARM Linux port here , which shows the problems in the transition to a newer ABI.在此处查看ARM Linux 移植的一些历史,其中显示了向更新的 ABI 过渡过程中的问题。

An ABI, even for C, has parts which are quite platform independent, parts which depend on the processor (which registers should be saved, which are used for passing parameters,...) and parts which depend on the OS (more or less the same factors as for the processor as some choices are not imposed by the architecture but are the result of trade-offs, plus some OS's have a language independent notion of exception and so a compiler for any language has to generate the right thing to handle those, handling of threads may also impose things on the ABI -- if a register points to TLS, you can't use it for what you want). ABI,即使对于 C,也有完全独立于平台的部分,依赖于处理器的部分(应该保存哪些寄存器,用于传递参数,...)和依赖于操作系统的部分(或多或少)与处理器相同的因素,因为有些选择不是由架构强加的,而是权衡的结果,加上一些操作系统具有与语言无关的异常概念,因此任何语言的编译器都必须生成正确的东西来处理那些,线程的处理也可能对 ABI 强加一些东西——如果寄存器指向 TLS,你不能将它用于你想要的)。

In theory, every compiler may have its own ABI.理论上,每个编译器都可能有自己的 ABI。 But usually, for a couple processor/OS, the ABI is fixed by the OS vendor which often also provide a C compiler and common libraries which use that ABI and competitors prefer to be compatible.但通常,对于几个处理器/操作系统,ABI 由操作系统供应商修复,该供应商通常还提供 C 编译器和使用 ABI 和竞争对手更喜欢兼容的公共库。 (I'd not be surprised if there are exceptions for some OS for which C isn't a major programming language). (如果 C 不是主要编程语言的某些操作系统存在例外情况,我不会感到惊讶)。

But the OS vendor may switch ABI for one reason or the other (new versions of processors may have features that you want to use in the ABI for one - for instance some have asked for a 32bit ABI for x86_64 allowing to use all the registers).但是操作系统供应商可能会出于某种原因切换 ABI(新版本的处理器可能具有您想在 ABI 中使用的功能之一——例如,有些人要求 x86_64 的 32 位 ABI 允许使用所有寄存器) . During the migration phase - which may be for a very long time - you may have to handle two ABI.在迁移阶段(可能会持续很长时间),您可能需要处理两个 ABI。

neither does C, right? C 也没有,对吧?
Right

On any given platform it pretty much does.在任何给定的平台上,它几乎都可以。 It wouldn't be useful as the lingua franca for inter-language communication if it lacked one.如果缺少一种语言,它就无法用作跨语言交流的通用语言。
Pretty much might refer to architecture-specific defaults chosen by C compiler vendors being adapted within other languages.几乎可能指的是 C 编译器供应商选择的特定于体系结构的默认值在其他语言中进行了调整。 So if Keil's ARM C compiler will use left to right little endian parameter ordering and stack to pass arguments and some predetermined register for return value, then extern "C" from other compilers will assume compatibility with such scheme.因此,如果 Keil 的 ARM C 编译器将使用从左到右的小端参数排序和堆栈来传递参数和一些预定的返回值寄存器,那么来自其他编译器的 extern "C" 将假定与这种方案兼容。

While such agreement maybe considered part of ABI, unlike managed execution context such as JVM browser sandbox, this is far from being complete standard ABI by itself.虽然此类协议可能被视为 ABI 的一部分,但与 JVM 浏览器沙箱等托管执行上下文不同,这本身远非完整的标准 ABI。

Although several attempts have been made at defining a single ABI for a given architecture across multiple operating systems (Particularly for i386 on Unix Systems), the efforts have not met with such success.尽管为跨多个操作系统(尤其是 Unix 系统上的 i386)的给定体系结构定义单个 ABI 已进行了多次尝试,但这些努力并未取得如此成功。 Instead, operating systems tend to define their own ABIs ...相反,操作系统倾向于定义自己的 ABI ...

Quoting ... Linux System Programming page 4.引用 ... Linux 系统编程第 4 页。

C does not have a standard ABI. C 没有标准的 ABI。 This is easily illustrated by all the calling conventions (cdecl, fastcall and stdcall) that are used out there.这可以通过所有使用的调用约定(cdecl、fastcall 和 stdcall)轻松说明。 Each is a different ABI.每个都是不同的 ABI。

Prior to the C89 Standard, C compilers for many platforms used essentially the same ABI, save for variations in data sizes.在 C89 标准之前,许多平台的 C 编译器使用基本相同的 ABI,除了数据大小的变化。 For machines whose stack grows downward, code which calls a function would push the arguments on the stack in order from right to left and then call the function (pushing the return address in the process).对于堆栈向下增长的机器,调用函数的代码会将参数按从右到左的顺序压入堆栈,然后调用该函数(在进程中压入返回地址)。 A called function would leave its arguments on the stack, and the caller would at its leisure adjust the stack pointer to remove them [or, on some architectures, might adjust the stacked values in place].被调用的函数会将其参数留在堆栈中,调用者会在闲暇时调整堆栈指针以删除它们[或者,在某些体系结构上,可能会调整堆栈值到位]。 While <stdarg.h> made it unnecessary for most programs to rely upon that convention, it remained in use for many years because it was simple and worked pretty well.尽管<stdarg.h>使大多数程序不必依赖该约定,但它仍然使用了很多年,因为它简单且运行良好。 While there was no "official" document establishing that as a cross-platform "standard", most compilers targeting machines with downward-growing stacks worked that way, leading to a greater level of consistency than exists today.虽然没有“官方”文件将其确定为跨平台“标准”,但大多数针对具有向下增长堆栈的机器的编译器都以这种方式工作,从而导致比今天更高的一致性。

There's no standard ABI because C has always been about maximum runtime performance and the ABI with the highest performance depends on the underlying hardware.没有标准的 ABI,因为 C 一直是关于最大运行时性能,而具有最高性能的 ABI 取决于底层硬件。 As a result, the ABI may use only stack or prefer registers for passing function call arguments and return values as needed for any given hardware.因此,ABI 可能仅使用堆栈或首选寄存器来根据任何给定硬件的需要传递函数调用参数和返回值。

For example, even amd64 (aka x86-64) has two calling conventions: Microsoft x64 and System V AMD64 ABI.例如,即使是 amd64(又名 x86-64)也有两个调用约定:Microsoft x64 和 System V AMD64 ABI。 The former puts 4 first arguments to registers and the rest into the stack.前者将 4 个第一个参数放入寄存器,其余放入堆栈。 The latter puts 6 first arguments to registers and the rest into the stack.后者将 6 个第一个参数放入寄存器,其余放入堆栈。 I have no idea why Microsoft created non-compatible calling convention for amd64 hardware.我不知道为什么 Microsoft 为 amd64 硬件创建了不兼容的调用约定。 For all I know, the Microsoft variant has a slightly worse performance and was created later.据我所知,Microsoft 变体的性能稍差,并且是后来创建的。

For more information, see https://en.wikipedia.org/wiki/X86_calling_conventions有关更多信息,请参阅https://en.wikipedia.org/wiki/X86_calling_conventions

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

相关问题 C标准是否有缺陷报告的网站? - Does the C standard have a website for defect reports? 如果C / C ++定义了标准的ABI,会怎样? - What could C/C++ “lose” if they defined a standard ABI? C或C ++有标准的正则表达式库吗? - Does C or C++ have a standard regex library? C 标准是否对使用的堆栈空间量有任何保证? - Does the C standard have any guarantees on the amount of stack space used? Sys V ABI规范(i386和AMD64)中描述的标准“函数调用序列”是否适用于静态C函数? - Does the standard “Function Calling Sequence” described in Sys V ABI specs (both i386 and AMD64) apply to the static C functions? C LLI与LLVM - C ABI with LLVM C头文件和ABI - C Header Files and ABI 与使用该语言的标准操作相比,用C语言对数字电路建模是否具有任何实际好处? - Does modeling digital circuits in C have any practical benefits as opposed using the language's standard operations? 将f(mystruct * a)更改为f(const mystruct * a)是否会破坏C中的API / ABI? - Does changing f(mystruct *a) to f(const mystruct *a) breaks API/ABI in C? C标准是否指定编译器必须遵循的标准? - Does “the” C standard specify which standard a compiler has to adhere to?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM