¿Cuáles son las convenciones de llamadas para llamadas al sistema UNIX y Linux en i386 y x86-64?

Los siguientes enlaces explican las convenciones de llamada al sistema x86-32 para UNIX (sabor BSD) y Linux:

  • http://www.int80h.org/bsdasm/#system-calls

  • http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html

¿Pero cuáles son las convenciones de llamada al sistema x86-64 en UNIX y Linux?

Verifiqué estos usando GNU Assembler (gas) en Linux.

Interfaz Kernel

x86-32 Convención del sistema Linux Call:

En los parámetros x86-32 para el sistema Linux, las llamadas se pasan usando 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 int $0x80 .

Tomé el siguiente fragmento del Tutorial de la Asamblea de Linux, pero tengo dudas al respecto. Si alguien puede mostrar un ejemplo, sería genial.

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

Para un ejemplo y un poco más de lectura, consulte http://www.int80h.org/bsdasm/#alternate-calling-convention

Hay una manera más rápida de hacer 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 , que tiene que cooperar con el kernel para que pueda encontrar la dirección de retorno. arg to register mapping es lo mismo que para int $0x80 , pero en lugar de esa instrucción, el código debe llamar a una función en el vdso. (TODO: actualizar esto con un enlace y / o información específica).

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

Los parámetros se pasan en la stack. Presione los parámetros (último parámetro que se presionó primero) en la stack. A continuación, inserte datos ficticios adicionales de 32 bits (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


Convenio de convocatoria de sistema Linux x86-64:

x86-64 Mac OS X es similar pero diferente . TODO: verifique qué * BSD hace.

Consulte la sección: “Convenciones A.2 AMD64 Linux Kernel” del System V Application Binary Interface Suplemento del procesador de architecture AMD64 . Las últimas versiones de las psABI del sistema V i386 y x86-64 se pueden encontrar enlazadas desde esta página en el repository del mantenedor de ABI . (Consulte también la wiki de la etiqueta x86 para obtener enlaces actualizados de ABI y muchas otras cosas buenas acerca de x86 asm).

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

  1. Las aplicaciones de nivel de usuario usan 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 de la instrucción syscall . Este clobbers% rcx y% r11, así como% rax, pero se conservan otros registros.
  3. El número de syscall se debe pasar en el registro% rax.
  4. Las llamadas al sistema están limitadas a seis argumentos, ningún argumento se pasa directamente a la stack.
  5. Al regresar de syscall, registrarse% 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 class MEMORY se pasan al kernel.

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

Interfaz de usuario

convención de llamada de función x86-32:

En x86-32, los parámetros se pasaron a la stack. El último parámetro se presionó primero en la stack hasta que se hayan realizado todos los parámetros y luego se haya ejecutado la instrucción de call . Esto se usa para llamar a las funciones de biblioteca C (libc) en Linux desde el ensamblado.


Convención de llamada de función x86-64:

x86-64 pasa args en los registros, que es más eficiente que la convención de args de stack del System V de i386. Evita la latencia y las instrucciones adicionales de almacenar archivos en memoria (caché) y luego cargarlos de nuevo 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 importan. (El i386 ABI es muy antiguo).

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

Para obtener información completa, consulte: “3.2 Función de secuencia de llamada” de System V Application Binary Interface Suplemento del procesador de architecture AMD64 que dice, en parte:

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

  1. Si la clase es MEMORIA, pasa el argumento en la stack.
  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 utilizados para pasar los parámetros entero / puntero (es decir, clase INTEGER) a cualquier función libc desde el ensamblaje. % rdi se usa para el primer parámetro INTEGER. % rsi para 2nd,% rdx para 3rd y así sucesivamente. Entonces se debe dar instrucción de call . La stack ( %rsp ) debe estar alineada con 16B cuando se ejecuta la call .

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

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

Las funciones variables ( como printf ) siempre necesitan %al = la cantidad de registros de registro FP.

Hay reglas para cuando empacar estructuras en registros ( rdx:rax en retorno) vs. en la memoria. Consulte la ABI para obtener más información y verifique la salida del comstackdor para asegurarse de que su código concuerde con los comstackdores sobre cómo se debe pasar / devolver algo.

¿Quizás estás buscando el x86_64 ABI?

Si eso no es exactamente lo que buscas, utiliza ‘x86_64 abi’ en tu buscador preferido para encontrar referencias alternativas.

Las convenciones de llamada definen cómo se pasan los parámetros en los registros al llamar o al ser llamados por otro progtwig. Y la mejor fuente de estas convenciones es en forma de estándares ABI definidos para cada uno de estos hardware. Para facilitar la comstackción, el mismo espacio de usuario y el progtwig kernel también utilizan el mismo ABI. Linux / Freebsd siguen el mismo 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 diferencia las llamadas del sistema de las “llamadas a funciones” normales. Es decir, aquí hay un ejemplo particular de convenciones de llamadas x86_64 y es el mismo tanto para el espacio de usuario de Linux como para kernel: 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 uno de los motivos de estos ABI (por ejemplo, pasar parámetros a través de registros en lugar de guardarlos en stacks 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 incrustado está el PPC EABI:

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

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

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

Además del enlace que Jonathan Leffler proporciona en su respuesta, también puede serle útil la versión pdf de Calling Conventions de Agner Fog.