c abi

¿C tiene un ABI estándar?



(8)

Aunque se han realizado varios intentos para definir una ABI única para una arquitectura determinada en múltiples sistemas operativos (en particular para i386 en sistemas Unix), los esfuerzos no han tenido tanto éxito. En cambio, los sistemas operativos tienden a definir sus propias ABIs ...

Cotizando ... Programación del sistema Linux página 4.

De una discusión en otro lugar :

C ++ no tiene ABI estándar

Pero tampoco lo hace C, ¿verdad?

En cualquier plataforma dada prácticamente lo hace. No sería útil como la lengua franca para la comunicación interlenguaje si careciera de una.

¿Cuál es su opinión sobre esto?


Antes de la norma C89, los compiladores de C para muchas plataformas usaban esencialmente el mismo ABI, salvo las variaciones en el tamaño de los datos. Para las máquinas cuya pila crece hacia abajo, el código que llama a una función empujaría los argumentos en la pila en orden de derecha a izquierda y luego llamaría a la función (empujando la dirección de retorno en el proceso). Una función llamada dejaría sus argumentos en la pila, y la persona que llama ajustaría el puntero de la pila para eliminarlos [o, en algunas arquitecturas, podría ajustar los valores apilados en su lugar]. Si bien <stdarg.h> hizo innecesario que la mayoría de los programas confiaran en esa convención, se mantuvo en uso durante muchos años porque era simple y funcionaba bastante bien. Si bien no había un documento "oficial" que lo estableciera como un "estándar" multiplataforma, la mayoría de los compiladores dirigidos a máquinas con pilas de crecimiento descendente funcionaban de esa manera, lo que lleva a un mayor nivel de coherencia que el que existe actualmente.


C define ningún ABI. De hecho, se desvía para evitar la definición de un ABI. Aquellas personas que, como yo, que han pasado la mayor parte de su programación en vivo programando en C en arquitecturas de 16/32/64 bits con bytes de 8 bits, aritmética de complemento a 2 y espacios de direcciones planas, generalmente se sorprenderán al leer el lenguaje complicado de El estándar C actual.

Por ejemplo, lea las cosas sobre los punteros. El estándar no dice nada tan simple como "un puntero es una dirección", ya que eso sería hacer una suposición sobre el ABI. En particular, permite que los punteros se encuentren en diferentes espacios de direcciones y que tengan ancho variable.

Una ABI es una asignación del modelo de ejecución del lenguaje a una combinación de máquina / sistema operativo / compilador particular. No tiene sentido definir una en la especificación de lenguaje porque eso conlleva el riesgo de excluir implementaciones de C en algunas arquitecturas.


C no tiene un ABI estándar en principio, pero en la práctica, esto rara vez importa: usted hace lo que hace su proveedor de sistema operativo.

Tome las convenciones de llamadas en Windows x86, por ejemplo: la API de Windows usa la llamada convención de llamadas "estándar" (stdcall). Por lo tanto, cualquier compilador que quiera interactuar con el sistema operativo debe implementarlo. Sin embargo, stdcall no es compatible con todas las funciones del lenguaje C90 (por ejemplo, funciones de llamada sin prototipos, funciones variadas). Como Microsoft proporcionó un compilador de C, fue necesaria una segunda convención de llamada, llamada "convención de llamada C" (cdecl). La mayoría de los compiladores de C en Windows usan esto como su convención de llamada predeterminada, y por lo tanto son interoperables.

En principio, lo mismo podría haber ocurrido con C ++, pero como el ABI de C ++ (incluida la convención de llamada) es necesariamente mucho más elaborado, los proveedores de compiladores no estuvieron de acuerdo en un solo ABI, pero aún podrían interoperar extern "C" .


C no tiene un ABI estándar. Esto se ilustra fácilmente mediante todas las convenciones de llamada (cdecl, fastcall y stdcall) que se usan por ahí. Cada uno es un ABI diferente.


La ABI para C es específica de la plataforma: cubre temas como la asignación de registros y las convenciones de llamada, que obviamente son específicas de un procesador en particular. Aquí hay unos ejemplos:

x86 ha tenido muchas convenciones de llamadas, extensiones en Windows para declarar cuál se usa. Las ABI de plataforma para Linux incorporado también han cambiado con el tiempo, lo que lleva a un espacio de usuario incompatible. Vea un poco de la historia del puerto ARM Linux aquí , que muestra los problemas en la transición a una nueva ABI.


Un ABI, incluso para C, tiene partes que son bastante independientes de la plataforma, partes que dependen del procesador (los registros deberían guardarse, que se usan para pasar parámetros, ...) y partes que dependen del sistema operativo (más o menos) los mismos factores que para el procesador, ya que algunas opciones no están impuestas por la arquitectura, sino que son el resultado de concesiones, además de que algunos sistemas operativos tienen una noción de excepción independiente del lenguaje y, por lo tanto, un compilador para cualquier idioma debe generar lo correcto para manejar esos, el manejo de hilos también puede imponer cosas en el ABI (si un registro apunta a TLS, no puede usarlo para lo que quiere).

En teoría, cada compilador puede tener su propio ABI. Pero por lo general, para un par de procesadores / sistemas operativos, el proveedor del sistema operativo corrige el ABI, que a menudo también proporciona un compilador de C y bibliotecas comunes que usan ese ABI y los competidores prefieren ser compatibles. (No me sorprendería si hay excepciones para algunos sistemas operativos para los que C no es un lenguaje de programación importante).

Pero el proveedor del sistema operativo puede cambiar el ABI por una razón u otra (las nuevas versiones de los procesadores pueden tener características que usted desea usar en el ABI para una, por ejemplo, algunos han solicitado un ABI de 32 bits para x86_64 permitiendo el uso de todos los registros) . Durante la fase de migración, que puede durar mucho tiempo, es posible que tenga que manejar dos ABI.


tampoco C, ¿verdad?
Derecha

En cualquier plataforma dada prácticamente lo hace. No sería útil como la lengua franca para la comunicación interlenguaje si careciera de una.
Bastante podría referirse a los valores predeterminados específicos de la arquitectura elegidos por los proveedores de compiladores de C que se adaptan en otros idiomas. Por lo tanto, si el compilador ARM C de Keil usa ordenamiento de parámetros little endian de izquierda a derecha y se apila para pasar los argumentos y algún registro predeterminado para el valor de retorno, entonces la "C" externa de otros compiladores asumirá la compatibilidad con dicho esquema.

Si bien tal acuerdo puede considerarse parte de ABI, a diferencia del contexto de ejecución administrada como el sandbox del navegador JVM, esto dista mucho de ser un ABI estándar completo por sí mismo.