Inserto de montaje

En programación , ensamblador en línea se refiere a la capacidad del compilador para incrustar código de bajo nivel escrito en ensamblador en un programa escrito en un lenguaje de alto nivel , como C o Ada . El uso de insertos ensambladores puede perseguir los siguientes objetivos:

Un ejemplo de optimización y uso de instrucciones especiales del procesador

Este ejemplo de inserción de ensamblador en el lenguaje de programación D , que implementa el cálculo de la tangente de x, utiliza instrucciones FPU x86 . Este código se ejecuta más rápido que el código que podría generar el compilador. Además, aquí se usa la instrucción , que carga la aproximación numérica más cercana para la arquitectura x86. fldpi

// Calcular la tangente de x real tan ( real x ) { asm { fld x [ EBP ] ; // carga x fxam ; // prueba de valores extraños fstsw AX ; sahf ; jc trigerr ; // x es NAN, infinito o vacío // Los 387 pueden manejar denormales SC18 : fptan ; fstp ST ( 0 ) ; // volcar X, que siempre es 1 fstsw AX ; sahf ; jnp Lret ; // C2 = 1 (x está fuera de rango) // Reducir el argumento para llevar x al rango fldpi ; fxch ; SC17 : fprem1 ; fstsw AX ; sahf ; jpSC17 ; _ fstp ST ( 1 ) ; // elimina pi de la pila jmp SC18 ; } trigerr : devuelve real . nana ; Lret : ; }

Ejemplo de llamada al sistema

Por lo general, no es posible acceder directamente al sistema operativo con la memoria protegida. El sistema operativo se ejecuta en un nivel más privilegiado (modo kernel) que el usuario (modo de usuario). Para realizar solicitudes al sistema operativo, se utilizan interrupciones de software. Rara vez los lenguajes de alto nivel admiten esta función, por lo que las interfaces de llamadas al sistema se escriben utilizando un ensamblador en línea [1] .

El siguiente ejemplo en C contiene una interfaz de llamada del sistema escrita con la sintaxis GNU Assembler de AT&T . Primero, veamos el formato de inserción del ensamblador usando un ejemplo simple:

asm ( "movl %ecx, %eax" ); /* mueve el contenido de ecx a eax */

Los identificadores asmy __asm__son equivalentes. Otro ejemplo de inserción simple:

__asm__ ( "movb %bh, (%eax)" ); /* mueve el byte de bh a la memoria apuntada por eax */

Un ejemplo de implementación de la interfaz de llamada al sistema:

externo interno errno ; int nombrefunción ( int arg1 , int * arg2 , int arg3 ) { int res ; __asm__ volátil ( "int $0x80" /* realiza la solicitud al SO */ : "=a" ( res ), /* devuelve el resultado en eax ("a") */ "+b" ( arg1 ), /* pasar arg1 en ebx ("b") */ "+c" ( arg2 ), /* pasar arg2 en ecx ("c") */ "+d" ( arg3 ) /* pasar arg3 en edx ("d") */ : "a" ( 128 ) /* pasa el número de llamada del sistema en eax ("a") */ : "memoria" , "cc" ); /* anunciar al compilador que la memoria y los códigos de condición han sido modificados */ /* El sistema operativo devolverá un valor negativo en caso de error; * los contenedores devuelven -1 en caso de error y establecen la variable global errno */ si ( -125 <= resolución && resolución < 0 ) { número de error = -res ; _ resolución = -1 ; } devuelve res ; }

Crítica

Desde principios del siglo XXI, el uso de insertos ensambladores ha sido cada vez más condenado por una variedad de razones [2] [3] :

  • Los compiladores de optimización modernos pueden generar un código ensamblador mejor que el que puede escribir un programador promedio. Por sí mismas, las inserciones del ensamblador pueden interferir con la optimización de otras partes del código. Algunos trucos que permitieron optimizar la ejecución de código en procesadores de los años 80-90 en procesadores posteriores pueden provocar una ralentización significativa en la ejecución debido a una organización diferente de los cálculos. Al igual que con cualquier optimización , las inserciones del ensamblador deben probarse para probar la hipótesis sobre su efectividad. Debido al aumento en el rendimiento de los sistemas informáticos, muchas optimizaciones pueden ser irrelevantes y la legibilidad del código, la facilidad de mantenimiento y la prevención de errores pasan a primer plano.
  • El código ensamblador requiere más tiempo para escribir. Es fácil cometer un error en el inserto del ensamblador, que es difícil de notar. Por ejemplo, el lenguaje ensamblador no admite la verificación de tipos . El código ensamblador ya generado es más difícil de mantener .
  • El código ensamblador no es portátil. Los insertos de ensamblaje están justificados para acceder a mecanismos específicos de la plataforma. Cuando se utilizan inserciones de ensamblador en programas multiplataforma , es necesario duplicar las inserciones de ensamblador para diferentes plataformas y también, si es posible, mantener una implementación alternativa en un lenguaje de alto nivel, pero esta práctica crea problemas al mantener el programa debido a la necesita hacer cambios en paralelo a varias secciones de código escritas en diferentes lenguajes y para diferentes plataformas.

Notas

  1. 1 2 "Programación Linux" Capítulo 5. Cómo funcionan las llamadas al sistema . Red abierta. Fecha de acceso: 29 de septiembre de 2013. Archivado desde el original el 2 de octubre de 2013.
  2. Análisis del uso de insertos de ensamblador en el código de proyectos abiertos . red abierta Consultado el 3 de mayo de 2022. Archivado desde el original el 3 de mayo de 2022.
  3. Razones por las que NO debe usar asm en línea . Consultado el 3 de mayo de 2022. Archivado desde el original el 28 de abril de 2022.

Enlaces