Saltar al contenido

¿Cuáles son las convenciones de llamada para las llamadas al sistema UNIX y Linux (y las funciones de espacio de usuario) en i386 y x86-64?

Luego de de nuestra larga selección de información solucionamos esta aprieto que pueden tener ciertos usuarios. Te dejamos la solución y nuestro deseo es que resulte de mucha apoyo.

Solución:

Más información sobre cualquiera de los temas aquí: La guía definitiva para las llamadas al sistema Linux


Los verifiqué usando GNU Assembler (gas) en Linux.

Interfaz del kernel

x86-32 también conocido como i386 Linux System Call convention:

En x86-32, los parámetros para la llamada al sistema Linux se pasan mediante registros. %eax para syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp se utilizan para pasar 6 parámetros a las llamadas al sistema.

El valor de retorno está en %eax. Todos los demás registros (incluido EFLAGS) se conservan en el int $0x80.

Tomé el siguiente fragmento del Tutorial de ensamblaje de Linux, pero tengo dudas sobre esto. Si alguien puede mostrar un ejemplo, sería genial.

Si hay más de seis argumentos,
%ebx debe contener la ubicación de memoria donde se almacena la lista de argumentos, pero no se preocupe por esto porque es poco probable que use una llamada al sistema con más de seis argumentos.

Para ver un ejemplo y leer un poco más, consulte http://www.int80h.org/bsdasm/#alternate-calling-convention. Otro ejemplo de Hello World para i386 Linux usando int 0x80: Hola, mundo en lenguaje ensamblador con llamadas al sistema Linux?

Hay una forma más rápida de realizar llamadas al sistema de 32 bits: usando sysenter. El kernel mapea una página de memoria en cada proceso (el vDSO), con el lado del espacio de usuario del sysenter dance, que tiene que cooperar con el kernel para poder encontrar la dirección de retorno. Arg para registrar el mapeo es el mismo que para int $0x80. Normalmente debería llamar al vDSO en lugar de utilizar sysenter directamente. (Ver La guía definitiva para las llamadas al sistema Linux para obtener información sobre cómo vincular y llamar al vDSO, y para obtener más información sobre sysentery todo lo demás relacionado con las llamadas al sistema).

x86-32 [Free|Open|Net|DragonFly]Convención de llamadas al sistema BSD UNIX:

Los parámetros se pasan a la pila. Empuje los parámetros (el último parámetro empujado primero) a la pila. Luego, inserte 32 bits adicionales de datos ficticios (en realidad no son datos ficticios. Consulte el siguiente enlace para obtener más información) y luego proporcione una instrucción de llamada al sistema. int $0x80

http://www.int80h.org/bsdasm/#default-calling-convention


Convención de llamadas al sistema Linux x86-64:

(Nota: x86-64 Mac OS X es similar pero diferente de Linux. TODO: compruebe lo que hace * BSD)

Consulte la sección: “A.2 AMD64 Linux “Convenciones del kernel” de la interfaz binaria de la aplicación de System V Complemento del procesador de arquitectura AMD64. Las últimas versiones de las psABI de System V i386 y x86-64 se pueden encontrar enlazadas desde esta página en el repositorio del mantenedor de ABI. enlaces ABI actualizados y muchas otras cosas buenas sobre x86 asm.)

Aquí está el fragmento de esta sección:

  1. Las aplicaciones a nivel de usuario se utilizan como registros enteros para pasar la secuencia% rdi,% rsi,% rdx,% rcx,% r8 y% r9. La interfaz del kernel usa% rdi,% rsi,% rdx,% r10,% r8 y% r9.
  2. Una llamada al sistema se realiza a través del syscall instrucción. Esto bloquea% rcx y% r11, así como el valor de retorno de% rax, pero se conservan otros registros.
  3. El número de syscall debe pasarse en el registro% rax.
  4. Las llamadas al sistema están limitadas a seis argumentos, ningún argumento se pasa directamente a la pila.
  5. Al regresar de la llamada al sistema, el registro% rax contiene el resultado de la llamada al sistema. Un valor en el rango entre -4095 y -1 indica un error, es -errno.
  6. Solo los valores de la clase INTEGER o la clase MEMORY se pasan al kernel.

Recuerde que esto es del apéndice específico de Linux a la ABI, e incluso para Linux es informativo, no normativo. (Pero de hecho es exacto).

Este 32 bits int $0x80 ABI es utilizable en código de 64 bits (pero no se recomienda). ¿Qué sucede si usa la ABI de Linux int 0x80 de 32 bits en código de 64 bits? Todavía trunca sus entradas a 32 bits, por lo que no es adecuado para punteros y pone a ceros r8-r11.

Interfaz de usuario: llamada de función

Convención de llamada a función x86-32:

En x86-32, los parámetros se pasaron a la pila. El último parámetro se empujó primero a la pila hasta que todos los parámetros estén listos y luego call se ejecutó la instrucción. Se utiliza para llamar a funciones de la biblioteca C (libc) en Linux desde el ensamblaje.

Las versiones modernas del i386 System V ABI (utilizado en Linux) requieren una alineación de 16 bytes de %esp antes de call, como el x86-64 System V ABI siempre ha requerido. Los Callees pueden asumir eso y usar cargas / almacenes SSE de 16 bytes que fallan en no alineados. Pero, históricamente, Linux solo requería una alineación de pila de 4 bytes, por lo que se necesitaba un trabajo adicional para reservar un espacio alineado naturalmente incluso para un espacio de 8 bytes. double o algo.

Algunos otros sistemas modernos de 32 bits todavía no requieren una alineación de pila de más de 4 bytes.


x86-64 System V función de espacio de usuario convención de llamada:

x86-64 System V pasa argumentos en los registros, que es más eficiente que la convención de args de pila de i386 System V. Evita la latencia y las instrucciones adicionales de almacenar argumentos en la memoria (caché) y luego volver a cargarlos en el destinatario. Esto funciona bien porque hay más registros disponibles y es mejor para las CPU modernas de alto rendimiento donde la latencia y la ejecución fuera de orden son importantes. (El i386 ABI es muy antiguo).

En esto nuevo mecanismo: Primero los parámetros se dividen en clases. La clase de cada parámetro determina la forma en que se pasa a la función llamada.

Para obtener información completa, consulte: “3.2 Secuencia de llamada de función” del Suplemento del procesador de la arquitectura AMD64 de la interfaz binaria de la aplicación System V que dice, en parte:

Una vez clasificados los argumentos, los registros se asignan (en orden de izquierda a derecha) para pasar de la siguiente manera:

  1. Si la clase es MEMORIA, pase el argumento a la pila.
  2. Si la clase es INTEGER, se utiliza el siguiente registro disponible de la secuencia% rdi,% rsi,% rdx,% rcx,% r8 y% r9

Entonces %rdi, %rsi, %rdx, %rcx, %r8 and %r9 son los registros en orden se utiliza para pasar parámetros enteros / punteros (es decir, clase INTEGER) a cualquier función libc desde el ensamblaje. % rdi se utiliza para el primer parámetro INTEGER. % rsi para el segundo,% rdx para el tercero y así sucesivamente. Luego call se deben dar instrucciones. La pila (%rsp) debe estar alineado con 16B cuando call ejecuta.

Si hay más de 6 parámetros INTEGER, el séptimo parámetro INTEGER y posteriores se pasan a la pila. (La persona que llama aparece, igual que x86-32.)

Los primeros 8 argumentos de coma flotante se pasan en% xmm0-7, más adelante en la pila. No hay registros de vectores preservados de llamadas. (Una función con una combinación de FP y argumentos enteros puede tener más de 8 argumentos de registro en total).

Funciones variadas (como printf) siempre necesito %al = el número de argumentos de registro FP.

Hay reglas sobre cuándo empaquetar estructuras en registros (rdx:rax al regreso) vs.en la memoria. Consulte la ABI para obtener más detalles y verifique la salida del compilador para asegurarse de que su código esté de acuerdo con los compiladores sobre cómo se debe pasar / devolver algo.


Tenga en cuenta que la convención de llamada de función de Windows x64 tiene varias diferencias significativas con respecto a x86-64 System V, como el espacio de sombra que debe ser reservado por la persona que llama (en lugar de una zona roja), y llamada preservada xmm6-xmm15. Y reglas muy diferentes para las que arg va en qué registro.

¿Quizás está buscando la ABI x86_64?

  • www.x86-64.org/documentation/abi.pdf (404 en 2018-11-24)
  • www.x86-64.org/documentation/abi.pdf (a través de Wayback Machine en 2018-11-24)
  • ¿Dónde se documenta la ABI de System V x86-64? – https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI se mantiene actualizado (por HJ Lu, uno de los mantenedores de ABI) con enlaces a archivos PDF de la versión oficial actual.

Si eso no es precisamente lo que busca, use ‘x86_64 abi’ en su motor de búsqueda preferido para encontrar referencias alternativas.

Las convenciones de llamada definen cómo se pasan los parámetros en los registros cuando se llama o es llamado por otro programa. Y la mejor fuente de esta convención es en forma de estándares ABI definidos para cada uno de estos hardware. Para facilitar la compilación, el espacio de usuario y el programa del kernel también utilizan la misma ABI. Linux / Freebsd siguen la misma ABI para x86-64 y otro conjunto para 32 bits. Pero x86-64 ABI para Windows es diferente de Linux / FreeBSD. Y, en general, ABI no distingue la llamada al sistema de las “llamadas a funciones” normales. Es decir, aquí hay un ejemplo particular de convenciones de llamada x86_64 y es el mismo para el espacio de usuario y el kernel de Linux: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 / (observe la secuencia a, b, c, d, e, f de parámetros):

Una buena representación de las convenciones de llamadas frente al uso de registros

El rendimiento es una de las razones de estas ABI (por ejemplo, pasar parámetros a través de registros en lugar de guardar en pilas de memoria)

Para ARM hay varios ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

Convención ARM64:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

Para Linux en PowerPC:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

Y para embebidos está el PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

Este documento es una buena descripción general de todas las diferentes convenciones:

http://www.agner.org/optimize/calling_conventions.pdf

Sección de Reseñas y Valoraciones

Si para ti ha resultado provechoso nuestro artículo, sería de mucha ayuda si lo compartieras con otros seniors de esta forma contrubuyes a dar difusión a nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *