## page was renamed from WebHome/TrabajosPracticos/Tutoriales/EjemploC
= Ejemplo de proyecto en lenguale C y ensamblador =
Se muestra un ejemplo de proyecto que incluye archivos fuentes en lenguaje C y en ensamblador.<
>
El proyecto consiste en:
* Una función '''suma''' escrita en ensamblador que recibe como parámetros 2 enteros, los suma y retorna su resultado.
* Una función principal '''main()''' escrita en C, que utiliza la función '''suma''' para sumar dos enteros inicializados con una constante.
Para poder realizar el llamado de una función escrita en ensamblador desde C, se debe realizar lo siguiente:
* En el archivo en C se debe declarar la función '''suma''' como externa, esto define el prototipo de la función (recibe dos enteros y devuelve un entero) y al declararlo como externo, el compilador no devuelve error al no encontrar la implementación de la función.
* El archivo ensamblador no tiene cambios importantes, si es necesario respetar las reglas de pase de parámetros ('''R0..R3''') para parámetros, y devolver en '''R0''', además de salvar los registros preservados.
Código en lenguaje C
{{{#!highlight c
#include
extern int suma(int a, int b);
int main(void)
{
int a = 71;
int b = 29;
int c;
c = suma(a,b);
return c;
}
}}}
Código en lenguaje ensamblador
{{{#!highlight nasm
.text
.arm
.global suma
suma:
add r2, r0, r1
mov r0, r2
mov pc, lr
}}}
== Construcción del proyecto ==
Es común en sistemas embebidos, realizar la compilación y enlace del proyecto en una arquitectura diferente a la cual el proyecto de ejecutará, por ejemplo es habitual realizar el proyecto en una PC (arquitectura x86) para luego correrlo en un microcontrolador ARM, esto se denomina cross compiler o complicación cruzada.
En nuestro caso utilizaremos una Raspberry para los prácticos, la cual posee un SO Linux y todas las herramientas para realizar una aplicación directamente en la arquitectura ARM, de todas maneras y para aquellos prácticos en donde no se posee Raspberry o no se justifica su uso por ser muy simples, explicamos ambos métodos para realizar un proyecto.
== Proyecto usando compilación cruzada ==
{{{#!highlight console
arm-none-eabi-gcc -Wall -mcpu=arm7tdmi -g -c main.c -o main.o
arm-none-eabi-as -mcpu=arm7tdmi -g suma.s -o suma.o
arm-none-eabi-gcc -Ttext=0 -nostartfiles -g main.o suma.o -o suma.elf
}}}
* La primer línea compila el código fuente del archivo '''main.c''' y genera el archivo objeto '''main.o'''
* La segunda línea ensambla el archivo fuente '''suma.s''' y genera el archivo '''suma.o'''
* La última línea enlaza los dos archivos objetos ('''main.o''' y '''suma.o''') y genera el archivo '''suma.elf'''
Las diferentes opciones utilizadas son:
* '''-c ''' para detener la construcción luego de la etapa de compilación y tiene como salida el archivo objeto ('''.o''').
* '''-o ''' para indicar el nombre del archivo de salida.
* '''-Wall ''' para habilitar todos las advertencias (warnings) del compilador.
* '''-mcpu=arm7tdmi ''' para indicar la arquitectura del procesador.
* '''-g ''' para incluir información de depuración en los archivos de salida.
=== Simulación en PC con gdb ===
Al terminar de compilar un proyecto, y ante la imposibilidad de poder correrlo en una PC por ser de otra arquitectura, debemos recurrir a un simulador, en este caso usamos el provisto por las GNU binutils, el cual simula solamente el núcleo del ARM, permitiendo ver como se modifican los registros y la memoria del micro por cada instrucción de la aplicación probada.
==== gdb --tui ====
Para realizar un debug con esta herramienta no es necesario instalar nada.
Se debe ejecutar
{{{
arm-elf-eabi-gdb --tui
}}}
luego dentro de este programa se escribe.
{{{
target sim
file ex1.elf
load
}}}
Aparecerá en una ventana el fuente a depurar, escribiendo.
{{{ break nn}}}
Se realiza un break point (nn es el número de linea que te aparece al costado izquierdo del archivo fuente).
Un tutorial de la herramienta se puede ver en
http://sourceware.org/gdb/onlinedocs/gdb/TUI.html
para recordar los comandos mas usados
[[WebHome/TrabajosPracticos/PracticoASM4/Debug|Comandos Debug]]
=== Construcción utilizando '''make''' ===
Archivo `Makefile` para la compilación cruzada
{{{#!highlight make
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
OBJECTS = main.o suma.o
CFLAGS = -Wall -mcpu=arm7tdmi -g -c
ASFLAGS = -mcpu=arm7tdmi -g
LDFLAGS = -Ttext=0 -nostartfiles -g
suma.elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o suma.elf
suma.o: suma.s
$(AS) $(ASFLAGS) suma.s -o suma.o
main.o: main.c
$(CC) $(CFLAGS) main.c
clean:
rm *.o *.elf
}}}
== Proyecto sobre Raspberry ==
{{{#!highlight console
gcc -Wall -g -c main.c -o main.o
as -g suma.s -o suma.o
gcc -g main.o suma.o -o suma.elf
}}}
=== Depurado con gdb ===
En este caso el software correra en forma nativa sobre la arquitectura (ARM de la raspberry) utilizamos entonces el gdb sin ningún simulador.
==== gdb --tui ====
se debe ejecutar
{{{
gdb --tui
}}}
luego dentro de este programa se escribe.
{{{
file ex1.elf
load
}}}
=== Construcción utilizando '''make''' ===
Archivo `Makefile` para la compilación sobre la RPi
{{{#!highlight make
CC = gcc
AS = as
LD = ld
OBJECTS = main.o suma.o
CFLAGS = -Wall -g -c
ASFLAGS = -g
LDFLAGS = -g
suma.elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o suma.elf
suma.o: suma.s
$(AS) $(ASFLAGS) suma.s -o suma.o
main.o: main.c
$(CC) $(CFLAGS) main.c
clean:
rm *.o *.elf
}}}