En informática , una convención de llamada es un esquema de nivel de implementación (bajo nivel) que define cómo las subrutinas o funciones reciben parámetros de quien las llama y cómo devuelven un resultado. [ 1 ] Cuando un código llama a una función, se han tomado decisiones de diseño sobre dónde y cómo se pasan los parámetros a esa función, y dónde y cómo se devuelven los resultados desde esa función, realizándose estas transferencias normalmente a través de ciertos registros o dentro de un marco de pila en la pila de llamadas . Existen decisiones de diseño sobre cómo se dividen las tareas de preparación para una llamada a función y restauración del entorno una vez que la función ha finalizado entre quien llama y quien es llamado. Una convención de llamada especifica la forma en que se debe llamar a cada función. Se debe utilizar la convención de llamada correcta para cada llamada a función, para permitir la ejecución correcta y fiable de todo el programa que utiliza estas funciones.
Introducción
Las convenciones de llamada se consideran generalmente parte de la interfaz binaria de la aplicación (ABI). Pueden considerarse un contrato entre la función que llama y la función llamada. [ 1 ]
Conceptos relacionados
Los nombres o significados de los parámetros y valores de retorno se definen en la interfaz de programación de aplicaciones (API, a diferencia de la ABI), que es un concepto distinto, aunque relacionado, con la ABI y la convención de llamada. Los nombres de los miembros dentro de las estructuras y objetos pasados también se consideran parte de la API, y no de la ABI. En ocasiones, las API incluyen palabras clave para especificar la convención de llamada de las funciones.
Las convenciones de llamada no suelen incluir información sobre cómo gestionar el ciclo de vida de las estructuras y objetos asignados dinámicamente. Otra documentación complementaria puede indicar quién es responsable de liberar la memoria asignada.
Es improbable que las convenciones de llamada especifiquen la disposición de los elementos dentro de las estructuras y los objetos, como el orden de los bytes o el empaquetado de la estructura.
En algunos lenguajes, la convención de llamada incluye detalles sobre el manejo de errores o excepciones (por ejemplo, Go , Java ), y en otros, no (por ejemplo, C++ ).
Para las llamadas a procedimientos remotos , existe un concepto análogo llamado Marshalling .
Las convenciones de llamada pueden estar relacionadas con la estrategia de evaluación de un lenguaje de programación en particular , pero la mayoría de las veces no se consideran parte de ella (o viceversa), ya que la estrategia de evaluación generalmente se define en un nivel de abstracción superior y se considera parte del lenguaje en lugar de un detalle de implementación de bajo nivel del compilador de un lenguaje en particular .
Diferentes convenciones de llamada
Las convenciones de llamada pueden diferir en:
- Dónde se colocan los parámetros. Las opciones incluyen registros , la pila de llamadas , una combinación de ambos o en otras estructuras de memoria.
- El orden en que se pasan los parámetros. Las opciones incluyen el orden de izquierda a derecha, de derecha a izquierda o algo más complejo.
- Cómo se manejan las funciones que aceptan un número variable de argumentos ( funciones variádicas ). Las opciones incluyen pasar los argumentos en orden (suponiendo que el primer parámetro esté en una posición obvia) o las partes variables en un array.
- Cómo se devuelven los valores de retorno desde la función llamada a la función que la llamó. Las opciones incluyen almacenarlos en la pila, en un registro o mediante una referencia a algo asignado en el montón.
- Cómo se manejan los valores largos o complejos, ya sea dividiéndolos en varios registros, dentro del marco de la pila o haciendo referencia a la memoria.
- ¿Qué registros tienen garantizado el mismo valor cuando la función llamada regresa que el que tenían cuando fue llamada? Se dice que estos registros se guardan o conservan , por lo que no son volátiles .
- Cómo se divide la tarea de preparación y limpieza posterior a una llamada a una función entre la función que la llama y la función llamada. En particular, cómo se restaura el marco de pila para que la función que llama pueda continuar después de que la función llamada haya terminado.
- Si se pasan los metadatos que describen los argumentos y cómo se pasan.
- Donde se almacena el valor anterior del puntero de marco , que se utiliza para restaurar el marco de pila cuando finaliza la subrutina. Las opciones incluyen dentro de la pila de llamadas o en un registro específico. A veces, los punteros de marco no se utilizan en absoluto. [ 2 ]
- Donde se colocan los enlaces de ámbito estático para el acceso a datos no locales de la rutina (normalmente en una o más posiciones en el marco de pila, pero a veces en un registro general o, para algunas arquitecturas, en registros de propósito especial).
- En los lenguajes orientados a objetos, cómo se hace referencia al objeto de la función.
Convenciones de llamadas dentro de una misma plataforma
En ocasiones, en una misma plataforma coexisten varias convenciones de llamada; una plataforma y una implementación de lenguaje específicas pueden ofrecer diversas opciones de convenciones. Esto se debe, entre otros motivos, al rendimiento, a la adaptación de las convenciones de otros lenguajes populares y a las restricciones o convenciones impuestas por las distintas plataformas informáticas .
Muchas arquitecturas solo tienen una convención de llamada ampliamente utilizada, a menudo sugerida por el arquitecto. En el caso de las arquitecturas RISC , como SPARC, MIPS y RISC-V , se suelen usar nombres de registros basados en esta convención. Por ejemplo, los registros MIPS $4tienen $7nombres ABI $a0que $a3reflejan su uso para el paso de parámetros en la convención de llamada estándar. (Las CPU RISC tienen muchos registros de propósito general equivalentes, por lo que normalmente no hay ninguna razón de hardware para darles nombres distintos a números).
La convención de llamada del lenguaje de un programa puede diferir de la convención de llamada de la plataforma subyacente, el sistema operativo o alguna biblioteca con la que se enlace. Por ejemplo, en Windows de 32 bits , las llamadas al sistema operativo siguen la convención `stdcall` , mientras que muchos programas en C que se ejecutan allí utilizan la convención `cdecl` . Para adaptarse a estas diferencias en las convenciones de llamada, los compiladores suelen permitir palabras clave que especifican la convención de llamada para una función determinada. Las declaraciones de función incluirán palabras clave adicionales específicas de la plataforma que indican la convención de llamada que se debe utilizar. Si se gestiona correctamente, el compilador generará código para llamar a las funciones de la manera adecuada.
Algunos lenguajes permiten especificar explícitamente la convención de llamada de una función junto con la función misma; otros lenguajes tendrán alguna convención de llamada, pero estará oculta para los usuarios de ese lenguaje y, por lo tanto, normalmente no será una consideración para el programador.
Arquitecturas
x86 (32 bits)
La arquitectura x86 de 32 bits se utiliza con diversas convenciones de llamada. Debido al reducido número de registros arquitectónicos y al enfoque histórico en la simplicidad y el tamaño reducido del código, muchas convenciones de llamada de x86 pasan los argumentos en la pila. El valor de retorno (o un puntero al mismo) se devuelve en un registro. Algunas convenciones utilizan registros para los primeros parámetros, lo que puede mejorar el rendimiento, especialmente para rutinas cortas y sencillas que se invocan con mucha frecuencia (es decir, rutinas que no llaman a otras rutinas).
Ejemplo de llamada:
push EAX ; pasar algún resultado de registro push dword [ EBP + 20 ] ; pasar alguna variable de memoria (sintaxis FASM/TASM) push 3 ; pasar alguna llamada constante calc ; el resultado devuelto ahora está en EAXEstructura típica de la llamada: (algunas o todas (excepto ret) de las instrucciones a continuación pueden optimizarse en procedimientos simples). Algunas convenciones dejan el espacio de parámetros asignado, usando simple reten lugar de ret imm16. En ese caso, la llamada podría add esp,12en este ejemplo, o de otra manera lidiar con el cambio a ESP.
calc: push EBP ; guarda el puntero de marco antiguo mov EBP , ESP ; obtiene el nuevo puntero de marco sub ESP , localsize ; reserva espacio de pila para variables locales . . ; realiza cálculos, deja el resultado en EAX . mov ESP , EBP ; libera espacio para variables locales pop EBP ; restaura el puntero de marco antiguo ret paramsize ; libera espacio de parámetros y regresa.x86-64
La versión de 64 bits de la arquitectura x86, conocida como x86-64 , AMD64 e Intel 64, utiliza dos secuencias de llamada comunes. Una de ellas, definida por Microsoft, se usa en Windows; la otra, especificada en la ABI AMD64 System V, se usa en sistemas tipo Unix y, con algunas modificaciones, en OpenVMS . Dado que x86-64 tiene más registros de propósito general que la arquitectura x86 de 32 bits, ambas convenciones pasan algunos argumentos a través de registros.
ARM (A32)
La convención de llamada estándar ARM de 32 bits asigna los 16 registros de propósito general de la siguiente manera:
- r15: Contador de programa (según la especificación del conjunto de instrucciones).
- r14: Registro de enlace . La instrucción BL, utilizada en una llamada a subrutina, almacena la dirección de retorno en este registro.
- r13: Puntero de pila . Las instrucciones Push/Pop en el modo de operación "Thumb" utilizan únicamente este registro.
- r12: Registro temporal dentro de la llamada al procedimiento.
- r4 a r11: Variables locales.
- r0 a r3: Valores de los argumentos pasados a una subrutina y resultados devueltos por una subrutina.
Si el tipo de valor devuelto es demasiado grande para caber en r0 a r3, o si su tamaño no se puede determinar estáticamente en tiempo de compilación, entonces quien realiza la llamada debe asignar espacio para ese valor en tiempo de ejecución y pasar un puntero a ese espacio en r0.
Las subrutinas deben conservar el contenido de los registros r4 a r11 y el puntero de pila (quizás guardándolos en la pila durante el prólogo de la función , usándolos como espacio temporal y restaurándolos desde la pila durante el epílogo ). En particular, las subrutinas que llaman a otras subrutinas deben guardar la dirección de retorno del registro de enlace r14 en la pila antes de llamar a dichas subrutinas. Sin embargo, estas subrutinas no necesitan devolver ese valor a r14; simplemente necesitan cargarlo en r15, el contador de programa, para regresar.
La convención de llamada de ARM exige el uso de una pila descendente completa. Además, el puntero de pila siempre debe estar alineado a 4 bytes, y siempre debe estar alineado a 8 bytes en una llamada a función con una interfaz pública. [ 3 ]
Esta convención de llamada hace que una subrutina ARM "típica" haga lo siguiente:
- En el prólogo, coloque los valores de r4 a r11 en la pila y la dirección de retorno en r14 en la pila (esto se puede hacer con una sola instrucción STM);
- Copiar cualquier argumento pasado (de r0 a r3) a los registros temporales locales (de r4 a r11);
- Asigne las demás variables locales a los registros locales temporales restantes (r4 a r11);
- Realice los cálculos y llame a otras subrutinas según sea necesario utilizando BL, asumiendo que r0 a r3, r12 y r14 no se conservarán;
- Coloca el resultado en r0;
- En el epílogo, extraiga los valores r4 a r11 de la pila y transfiera la dirección de retorno al contador de programa r15. Esto se puede realizar con una sola instrucción LDM.
ARM (A64)
La convención de llamada ARM de 64 bits ( AArch64 ) asigna los 31 registros de propósito general como: [ 4 ]
- x31 (SP): Puntero de pila o un registro cero , según el contexto.
- x30 (LR): Registro de enlace de procedimiento, utilizado para regresar de subrutinas.
- x29 (FP): Puntero de marco .
- x19 a x28: Llamada guardada.
- x18 (PR): Registro de plataforma. Se utiliza para algún propósito especial específico del sistema operativo o como un registro adicional guardado por el llamador.
- x16 (IP0) y x17 (IP1): Registros temporales dentro de la llamada al procedimiento.
- x9 a x15: Variables locales, llamada guardada.
- x8 (XR): Dirección de valor de retorno indirecto.
- x0 a x7: Valores de los argumentos que se pasan a una subrutina y resultados que esta devuelve.
Todos los registros que comienzan con x tienen un registro correspondiente de 32 bits con el prefijo w . Por lo tanto, un registro x0 de 32 bits se denomina w0.
De manera similar, los 32 registros de punto flotante se asignan como: [ 5 ]
- v0 a v7: Valores de los argumentos que se pasan a una subrutina y resultados que esta devuelve.
- v8 a v15: la función llamada se guarda, pero solo es necesario conservar los 64 bits inferiores.
- v16 a v31: Variables locales, llamador guardado.
ISA de RISC-V
RISC-V tiene una convención de llamada definida con dos variantes, con o sin hardware de punto flotante. [ 6 ] Pasa los argumentos en registros siempre que sea posible.
POWER, PowerPC y Power ISA
Las arquitecturas POWER , PowerPC y Power ISA cuentan con un gran número de registros, lo que permite que la mayoría de las funciones pasen todos sus argumentos en registros para llamadas de un solo nivel . Los argumentos adicionales se pasan en la pila, y siempre se asigna espacio en la pila para los argumentos basados en registros, como conveniencia para la función llamada en caso de que se utilicen llamadas de varios niveles (recursivas o de otro tipo) y sea necesario ahorrar los registros. Esto también resulta útil en funciones variádicas , como printf(), donde se requiere acceder a los argumentos de la función como si fueran un array. Se utiliza una única convención de llamada para todos los lenguajes procedimentales.
Las instrucciones de ramificación y enlace almacenan la dirección de retorno en un registro de enlace especial separado de los registros de propósito general; una rutina regresa a quien la llamó con una instrucción de ramificación que usa el registro de enlace como dirección de destino. Las rutinas hoja no necesitan guardar ni restaurar el registro de enlace; las rutinas que no son hoja deben guardar la dirección de retorno antes de llamar a otra rutina y restaurarla antes de regresar, guardándola mediante la instrucción Mover desde registro de propósito especial para mover el registro de enlace a un registro de propósito general y, si es necesario, guardándolo en la pila, y restaurándola, si se guardó en la pila, cargando el valor del registro de enlace guardado en un registro de propósito general, y luego usando la instrucción Mover a registro de propósito especial para mover el registro que contiene el valor del registro de enlace guardado al registro de enlace.
MIPS
La ABI O32 [ 7 ] es la más utilizada, debido a su condición de ABI original de System V para MIPS. [ 8 ] Es estrictamente basada en pila, con solo cuatro registros disponibles para pasar argumentos. Esta lentitud percibida, junto con un modelo de punto flotante obsoleto con solo 16 registros, ha fomentado la proliferación de muchas otras convenciones de llamada. La ABI se definió en 1990 y no se actualizó desde 1994. Solo está definida para MIPS de 32 bits, pero GCC ha creado una variante de 64 bits llamada O64. [ 9 ]$a0-$a3
Para 64 bits, la ABI N64 (sin relación con Nintendo 64 ) de Silicon Graphics es la más utilizada. La mejora más importante es que ahora hay ocho registros disponibles para el paso de argumentos; también aumenta el número de registros de punto flotante a 32. Existe además una versión ILP32 llamada N32, que utiliza punteros de 32 bits para código más pequeño, análoga a la ABI x32 . Ambas se ejecutan en el modo de 64 bits de la CPU. [ 9 ]
Se han realizado algunos intentos para reemplazar O32 con una ABI de 32 bits que se asemeja más a N32. En una conferencia de 1995 se presentó MIPS EABI, cuya versión de 32 bits era bastante similar. [ 10 ] EABI inspiró a MIPS Technologies a proponer una ABI "NUBI" más radical que reutiliza adicionalmente los registros de argumentos para el valor de retorno. [ 11 ] GCC admite MIPS EABI, pero LLVM no ; ninguno de los dos admite NUBI.
En todos los casos, tanto en O32 como en N32/N64, la dirección de retorno se almacena en un $raregistro. Este se establece automáticamente mediante las instrucciones JALde salto y enlace o JALRde registro de salto y enlace. La pila crece hacia abajo.
SPARC
La arquitectura SPARC , a diferencia de la mayoría de las arquitecturas RISC , se basa en ventanas de registro . Cada ventana de registro tiene 24 registros accesibles: 8 son los registros de entrada (%i0-%i7), 8 son los registros locales (%l0-%l7) y 8 son los registros de salida (%o0-%o7). Los registros de entrada se utilizan para pasar argumentos a la función que se llama, y cualquier argumento adicional debe colocarse en la pila . Sin embargo, la función llamada siempre asigna espacio para gestionar un posible desbordamiento de la ventana de registro, variables locales y (en SPARC de 32 bits) la devolución de una estructura por valor. Para llamar a una función, se colocan los argumentos de la función en los registros de salida; cuando se llama a la función, los registros de salida se convierten en los registros de entrada y la función llamada accede a los argumentos en sus registros de entrada. Cuando la función llamada finaliza, coloca el valor de retorno en el primer registro de "entrada", que se convierte en el primer registro de "salida" cuando la función llamada regresa.
La ABI del Sistema V , [ 12 ] que siguen la mayoría de los sistemas modernos tipo Unix , pasa los primeros seis argumentos en los registros "in" %i0 a %i5, reservando %i6 para el puntero de marco y %i7 para la dirección de retorno.
IBM System/360 y sus sucesores
El IBM System/360 es otra arquitectura sin pila de hardware. Los ejemplos que se muestran a continuación ilustran la convención de llamada original utilizada por OS/360 y sus sucesores antes de la introducción de Enterprise Systems Architecture (ESA), XPLINK y z/Architecture de 64 bits ; otros sistemas operativos para System/360 y posteriores podrían tener convenciones de llamada diferentes.
Programa de llamadas:
LA 1,ARGS Cargar la dirección de la lista de argumentos L 15,=V(SUB) Cargar la dirección de la subrutina 1 BALR 14,15 Saltar a la rutina llamada 2 ... ARGS DC A(PRIMERO) Dirección del primer argumento CC A (SEGUNDO) ... DC A(TERCERO)+X'80000000' Último argumento 3
Programa llamado:
SUB EQU * Este es el punto de entrada del subprograma 4
Secuencia de entrada estándar:
USANDO *,15 5 STM 14,12,12(13) Guardar registros 6 ST 13,SAVE+4 Guardar la dirección del área de guardado del llamador LA 12,SAVE Cadena saveareas ST 12,8(13) LR 13,12 ...
Secuencia de retorno estándar:
L 13, AHORRAR+4 7 LM 14,12,12(13) L 15,RETVAL 8 BR 14 Devolver a la persona que llamó AHORRA DS 18F Área de ahorro 9
Notas:
- Utilice
L 15,=A(SUB)oLA 15,SUBpara subrutinas internas; utiliceL 15,=V(SUB)para subrutinas externas. - La
BALRinstrucción almacena la dirección de la siguiente instrucción (dirección de retorno) en el registro especificado por el primer argumento ( registro 14 ) y salta a la dirección del segundo argumento en el registro 15. Se prefiere BASR en los modelos que lo admiten. BASSM puede utilizarse si se requiere alternar entre los modos de 24 y 31 bits. - El llamador pasa la dirección de una lista de direcciones de argumentos en el registro 1. La última dirección tiene el bit de orden superior activado para indicar el final de la lista. Esto limita los programas que utilizan esta convención a un direccionamiento de 31 bits .
- Para subrutinas externas, incluya
SUB ENTRY ,despuésSUB EQU *o reemplácelo conSUB CSECT ,. - La dirección de la rutina llamada está en el registro 15. Normalmente, esto se carga en otro registro
DROPeUSINGinforma al ensamblador de que el registro 15 ya no debe usarse como registro base. - La instrucción guarda los registros 14, 15 y del 0 al 12 en un área de
STM72 bytes proporcionada por la función que la llama , denominada área de guardado , a la que apunta el registro 13. La rutina llamada proporciona su propia área de guardado para uso de las subrutinas que invoca; la dirección de esta área se mantiene normalmente en el registro 13 durante toda la rutina. Las instrucciones subsiguientes actualizan las cadenas de direcciones hacia adelante y hacia atrás que vinculan esta área de guardado con el área de guardado de la función que la llama.STM - La secuencia de retorno restaura los registros de la función que realizó la llamada.
- El registro 15 se suele usar para pasar un código de retorno. El código que se muestra es incorrecto, pero ilustra el principio.
- Declarar una
saveareavariable de forma estática en la rutina llamada la hace no reentrante y no recursiva ; un programa reentrante utiliza una variable dinámicasavearea, adquirida ya sea del sistema operativo y liberada al regresar, o en un almacenamiento pasado por el programa que realiza la llamada.
En la ABI System/390 [ 13 ] y la ABI z/Architecture , [ 14 ] utilizadas en Linux:
- Los registros 0 y 1 son volátiles.
- Los registros 2 y 3 se utilizan para el paso de parámetros y los valores de retorno.
- Los registros 4 y 5 también se utilizan para el paso de parámetros.
- El registro 6 se utiliza para el paso de parámetros y debe ser guardado y restaurado por la función llamada.
- Los registros del 7 al 13 son para uso del destinatario y deben ser guardados y restaurados por él.
- El registro 14 se utiliza para la dirección de devolución.
- El registro 15 se utiliza como puntero de pila.
- Los registros de punto flotante 0 y 2 se utilizan para el paso de parámetros y los valores de retorno.
- Los registros de punto flotante 4 y 6 son para uso de la función llamada, y deben ser guardados y restaurados por ella.
- En z/Architecture, los registros de punto flotante 1, 3, 5 y del 7 al 15 son para uso de la función llamada.
- El registro de acceso 0 está reservado para uso del sistema.
- Los registros de acceso del 1 al 15 son para uso del llamado.
Los argumentos adicionales se pasan en la pila.
SuperH
Nota: "preservado" reserva al destinatario el ahorro; lo mismo ocurre con "garantizado".
68k
La convención de llamada más común para la serie Motorola 68000 es: [ 18 ] [ 19 ] [ 20 ] [ 21 ]
- d0, d1, a0 y a1 son registros temporales.
- Todos los demás registros se guardan en la persona que llama
- a6 es el puntero de marco, que puede deshabilitarse mediante una opción del compilador.
- Los parámetros se insertan en la pila, de derecha a izquierda.
- El valor de retorno se almacena en d0.
IBM 1130
El IBM 1130 era una pequeña máquina de 16 bits con direccionamiento por palabra. Tenía solo seis registros más indicadores de condición y no tenía pila. Los registros son el Registro de Dirección de Instrucción (IAR) , el Acumulador (ACC) , la Extensión del Acumulador (EXT) y tres registros de índice X1 – X3. El programa que llama es responsable de guardar ACC, EXT, X1 y X2. [ 22 ] Hay dos pseudooperaciones para llamar a subrutinas, CALLpara codificar subrutinas no reubicables vinculadas directamente con el programa principal, y LIBFpara llamar a subrutinas de biblioteca reubicables a través de un vector de transferencia . [ 23 ] Ambas pseudooperaciones se resuelven en una instrucción de máquina IAR de Salto y Almacenamiento ( BSI) que almacena la dirección de la siguiente instrucción en su dirección efectiva (EA) y salta a EA+1.
Los argumentos siguen a la —BSI normalmente son direcciones de una palabra de los argumentos — la rutina llamada debe saber cuántos argumentos esperar para poder omitirlos al regresar. Alternativamente, los argumentos pueden pasarse en registros. Las rutinas de función devolvían el resultado en ACC para argumentos reales, o en una ubicación de memoria denominada Pseudoacumulador de Números Reales (FAC). Los argumentos y la dirección de retorno se direccionaban utilizando un desplazamiento al valor IAR almacenado en la primera ubicación de la subrutina.
* Ejemplo de subrutina 1130 ENT SUB Declara "SUB" como un punto de entrada externo. SUB DC 0 Palabra reservada en el punto de entrada, codificada convencionalmente como "DC *-*" * El código de la subrutina comienza aquí * Si hubiera argumentos, las direcciones se podrían cargar indirectamente desde la dirección de retorno. LDX I 1 SUB Carga X1 con la dirección del primer argumento (por ejemplo) ... * Secuencia de retorno LD RES Cargar el resultado entero en ACC * Si no se proporcionaron argumentos, se realizará una bifurcación indirecta a la dirección de retorno almacenada. BI SUB Si no se proporcionaron argumentos FIN SUB
Las subrutinas en IBM 1130, CDC 6600 y PDP-8 (las tres computadoras se introdujeron en 1965) almacenan la dirección de retorno en la primera ubicación de una subrutina. [ 24 ]
Convenciones de llamadas fuera de las arquitecturas de las máquinas
Código multihilo
El código multihilo traslada toda la responsabilidad de la preparación y la limpieza posterior a una llamada a función al código llamado. El código que realiza la llamada simplemente enumera las subrutinas que se ejecutarán. Esto concentra todo el código de preparación y limpieza de la función en un solo lugar —el prólogo y el epílogo de la función— en lugar de en los múltiples lugares donde se llama a la función. Esto convierte al código multihilo en la convención de llamada más compacta.
El código multihilo pasa todos los argumentos en la pila. Todos los valores de retorno se devuelven en la pila. Esto hace que las implementaciones simples sean más lentas que las convenciones de llamada que almacenan más valores en registros. Sin embargo, las implementaciones de código multihilo que almacenan en caché varios de los valores superiores de la pila en registros —en particular, la dirección de retorno— suelen ser más rápidas que las convenciones de llamada de subrutinas que siempre insertan y extraen la dirección de retorno de la pila. [ 25 ] [ 26 ] [ 27 ]
PL/I
La convención de llamada predeterminada para programas escritos en el lenguaje PL/I pasa todos los argumentos por referencia , aunque opcionalmente se pueden especificar otras convenciones. [ 28 ] Los argumentos se manejan de manera diferente para distintos compiladores y plataformas, pero normalmente las direcciones de los argumentos se pasan a través de una lista de argumentos en memoria. Se puede pasar una dirección final oculta que apunte a un área para contener el valor de retorno. Debido a la amplia variedad de tipos de datos compatibles con PL/I, también se puede pasar un descriptor de datos para definir, por ejemplo, las longitudes de cadenas de caracteres o bits, la dimensión y los límites de los arreglos ( vectores dope ), o la disposición y el contenido de una estructura de datos . Se crean argumentos ficticios para los argumentos que son constantes o que no coinciden con el tipo de argumento que espera el procedimiento llamado. [ 29 ]
Véase también
Notas explicativas
- ↑ Existen otros tamaños cuando se permiten llamadas en modo de registro de acceso (AR) o en modo de dirección de 64 bits.
Referencias
- 1 2 "Convenciones de llamadas" . cs.cornell.edu . Consultado el 5 de marzo de 2024 .
- ↑ "/Oy (Frame-Pointer Omission)" . learn.microsoft.com . 3 de agosto de 2021. Consultado el 14 de junio de 2024 .
- ↑ "Estándar de llamada a procedimiento para la arquitectura ARM" . 2021.
- ↑ "Parámetros en registros de propósito general" . Guía del programador de la serie ARM Cortex-A para ARMv8-A . Consultado el 12 de noviembre de 2020 .
- ↑ "Parámetros en NEON y registros de punto flotante" . developer.arm.com . Consultado el 13 de noviembre de 2020 .
- ↑ "Convención de llamada RISC-V" (PDF) .
- ↑ "Referencia rápida del conjunto de instrucciones MIPS32" .
- ↑ Sweetman, Dominic. Véase MIPS Run (2.ª ed.). Morgan Kaufmann Publishers . ISBN 0-12088-421-6.
- 1 2 "Historial de MIPS ABI" . Archivado del original el 26 de agosto de 2018. Consultado el 17 de agosto de 2020 .
- ↑ Christopher, Eric (11 de junio de 2003). "Documentación de mips eabi" . binutils@sources.redhat.com (Lista de correo) . Consultado el 19 de junio de 2020 .
- ↑ "NUBI" . Archivado del original el 29/07/2021 . Consultado el 16/08/2020 .
- ↑ Interfaz binaria de aplicación del sistema V, suplemento del procesador SPARC (3.ª ed.).
- ↑ "Suplemento de la interfaz binaria de la aplicación ELF S/390" .
- ↑ "Suplemento de la interfaz binaria de la aplicación ELF de la serie z" .
- ↑ "Registros Renesas SH-4" . Microsoft Learn . 9 de julio de 2007.
- ↑ "Interfaz binaria de aplicación SH para GCC" . Archivado del original el 5 de noviembre de 2014.
- ↑ "Manual del usuario del paquete de compilador, ensamblador, editor de enlace optimizador y compilador SuperH RISC engine C/C++" (PDF) . Archivado del original (PDF) el 15 de marzo de 2016.
- ↑ Smith, Dr. Mike. "Comparación de registros SHARC (21k) y 68k" .
- ↑ XGCC: El sistema de lenguaje Gnu C/C++ para desarrollo embebido (PDF) . Embedded Support Tools Corporation. 2000. pág. 59.
- ↑ "COLDFIRE/68K: ThreadX para la familia Freescale ColdFire" . Archivado del original el 2 de octubre de 2015.
- ↑ Moshovos, Andreas. "Subrutinas continuadas: paso de argumentos, retorno de valores y asignación de variables locales" .
Todos los registros, excepto d0, d1, a0, a1 y a7, deben conservarse durante una llamada.
- ↑ IBM Corporation (1967). IBM 1130 Disk Monitor System, Versión 2 System Introduction (C26-3709-0) (PDF) . pág. 67. Consultado el 21 de diciembre de 2014 .
- ↑ IBM Corporation (1968). Lenguaje ensamblador IBM 1130 (C26-5927-4) (PDF) . págs. 24–25 .
- ↑ Smotherman, Mark (2004). "Soporte para llamadas a subrutinas y procedimientos: historia temprana" .
- ↑ Rodríguez, Brad. "Avanzando, Parte 1: Decisiones de diseño en el núcleo Forth" .
En el 6809 o Zilog Super8, DTC es más rápido que STC.
- ↑ Ertl, Anton. "Velocidad de diversas técnicas de envío de intérpretes" .
- ↑ Zaleski, Mathew (2008). "Capítulo 4: Diseño e implementación de interpretación eficiente" . YETI: un intérprete de trazas gradualmente extensible .
Aunque se sabe que los intérpretes de subprocesos directos tienen propiedades de predicción de bifurcaciones deficientes... la latencia de una llamada y retorno puede ser mayor que la de un salto indirecto.
- ↑ "Los sistemas 360 y los primeros 370 de IBM" .
- ↑ "Los sistemas 360 y los primeros 370 de IBM" .
Enlaces externos
- Johnson, Stephen Curtis ; Ritchie, Dennis MacAlistair (septiembre de 1981). "Informe técnico de ciencias de la computación n.° 102: La secuencia de llamadas del lenguaje C" . Bell Laboratories .
- Introducción al lenguaje ensamblador en PowerPC
- Guía de llamadas a funciones ABI de Mac OS X
- Estándar de llamada a procedimiento para la arquitectura ARM
- Programación embebida con el conjunto de herramientas GNU, Sección 10. Inicio de C
- Subrutinas