Tecnológico Nacional de México
Instituto Tecnológico de Tijuana
Materia:
Lenguajes de interfaz
Docente:
M.C. Rene Solis Reyes
Unidad:
2
Título del trabajo:
Integración de código Assembly con C
Estudiantes:
Aganza Molina Abraham Armando #19210455
Martinez Castellanos Santy Francisco #21211989
Ortega Medina Abner Nahum #20211819
Reynoso Rosales Eduardo Guadalupe #21212036
Soto Sanchez Yahir Jasiel #21212055
Semestre:
Enero - Junio 2024
RAZONES PARA MEZCLAR C CON ASSEMBLY
Mezclar C con ensamblador (Assembly) puede ser beneficioso en ciertas situaciones donde se requiere un control preciso sobre el hardware o se necesita un rendimiento optimizado.
RAZONES
Ensamblador proporciona un control fino sobre el hardware y las instrucciones de la CPU, lo que puede ser útil para optimizar el rendimiento en partes críticas del código. Al mezclar C con ensamblador, puedes escribir rutinas optimizadas para operaciones específicas que pueden ser más eficientes que el código generado por el compilador.
A veces, es necesario interactuar directamente con dispositivos de hardware o periféricos. El ensamblador permite un control preciso sobre el acceso a estos dispositivos, lo que puede ser esencial en aplicaciones embebidas o de bajo nivel.
En aplicaciones de tiempo real, donde cada ciclo de CPU cuenta, el uso de ensamblador puede ayudar a garantizar que las operaciones críticas se realicen en el menor tiempo posible y de manera predecible.
En algunos entornos incrustados o sistemas embebidos, el compilador de C puede ser limitado en términos de optimizaciones o características disponibles. En estos casos, escribir partes críticas del código en ensamblador puede ser necesario para lograr el rendimiento deseado.
A veces, las estructuras de datos complejas o algoritmos específicos pueden ser más eficientes de implementar en ensamblador. Esto es especialmente cierto para algoritmos altamente optimizados, como algoritmos de cifrado o compresión.
Escribir código en ensamblador puede ayudar a los desarrolladores a comprender mejor cómo funcionan realmente las computadoras a nivel de bajo nivel. Esto puede ser útil para propósitos educativos o para comprender mejor el rendimiento y las limitaciones del hardware.
Sin embargo, es importante tener en cuenta que el uso excesivo de ensamblador puede complicar el código, hacerlo menos legible y más propenso a errores. Por lo tanto, se debe usar con precaución y solo en partes críticas donde realmente se justifique su uso. Además, el código en ensamblador es menos portable y puede ser difícil de mantener, por lo que se debe considerar cuidadosamente si los beneficios justifican los costos asociados.
VENTAJAS
El código Assembly puede ser mucho más rápido que el código C, especialmente para tareas intensivas en CPU.
Assembly te da acceso directo al hardware y te permite controlar con precisión el comportamiento del programa.
Assembly puede ser más eficiente en el uso de memoria que C, especialmente para programas pequeños.
Algunas funcionalidades del hardware solo son accesibles a través de Assembly.
DESVENTAJAS
El código Assembly es mucho más complejo y difícil de escribir y leer que el código C.
El código Assembly no es portable entre diferentes plataformas de hardware.
El código Assembly es más difícil de mantener y actualizar que el código C.
CASOS EN LOS QUE SE PUEDE MEZCLAR C CON ASSEMBLY
Los controladores de dispositivos necesitan un alto rendimiento y un control preciso del hardware, por lo que a menudo se escriben en Assembly.
Las bibliotecas matemáticas que necesitan un alto rendimiento a menudo se escriben en Assembly.
Los juegos necesitan un alto rendimiento y un control preciso del hardware, por lo que a menudo se escriben en Assembly.
USO DE LA DIRECTIVA EXTERN PARA LLAMAR FUNCIONES ASSEMBLY DESDE C
La directiva extern en C se utiliza para declarar una función o variable que se define en otro archivo. Esta declaración le permite al compilador saber que la función o variable está definida en otro lugar y que será enlazada en tiempo de ejecución.
Para llamar funciones escritas en lenguaje ensamblador desde un programa en C, primero se tiene que escribir la función en ensamblador y luego declararla como extern en el programa C.
EJEMPLO
Para este ejemplo, se lleva a cabo un programa simple que suma dos numeros.
Escribir la función en ensamblador y guardarla en un archivo separado, digamos funcion_asm.s.
;.global factorial @ Define factorial como global
;.type factorial, %function @ Define el tipo de factorial como una función
factorial: @ Inicio de la función factorial
CMP r0, #0 @ Compara el valor en r0 con cero
MOVEQ r0, #1 @ Si r0 es igual a cero (flag Z establecido), r0 se mueve a 1 (factorial de 0 es 1)
BEQ .end @ Si r0 es igual a cero, salta a .end (final de la función)
MOV r1, r0 @ Mueve el valor de r0 a r1 (r1 se utilizará como un contador para el bucle)
MOV r2, #1 @ Mueve el valor 1 a r2 (r2 se utilizará para almacenar el resultado del factorial)
.loop: @ Etiqueta: Inicio del bucle
MUL r2, r1 @ Multiplica r2 por r1 y almacena el resultado en r2 (cálculo parcial del factorial)
SUBS r1, r1, #1 @ Decrementa el valor de r1 en 1 (r1--), y actualiza los flags
BNE .loop @ Si el flag Z no está establecido (r1 no es igual a cero), salta a .loop (sigue el bucle)
.end:
MOV r0, r2 @ Mueve el valor en r2 (resultado del factorial) a r0 (registro de retorno)
BX lr @ Regresa de la función al origen
Compilar el archivo de ensamblador usando un ensamblador apropiado para ARM32, como as o arm-linux-gnueabi-as.
as -o factorial.o factorial.s
En el programa en C, incluir un prototipo de la función ensamblador usando extern.
extern int factorial(int n);
Llamar a la función desde el programa en C.
#include <stdio.h>
int main(){
int n;
printf("Indica el número que quieras calcular su factorial: ");
scanf("%d", &n);
int result = factorial(n);
printf("El factorial de %d es %d\n", n, result);
return 0;
}
Compilar el programa C junto con el archivo de objeto generado por el ensamblador, utilizando un compilador apropiado para ARM32.
gcc -o programaFactorial factorial.o factorial_c.o
PROGRAMA EJEMPLO
PROGRAMA EN C QUE UTILIZA UNA FUNCION DE ASSEMBLY PARA CALCULAR EL FACTORIAL DE UN NUMERO