<?xml version="1.0" encoding="utf-8"?><!DOCTYPE article  PUBLIC '-//OASIS//DTD DocBook XML V4.4//EN'  'http://www.docbook.org/xml/4.4/docbookx.dtd'><article><articleinfo><title>WebHome/TrabajosPracticos/EjemploC</title><revhistory><revision><revnumber>8</revnumber><date>2019-09-11 00:17:47</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>7</revnumber><date>2019-09-10 17:53:18</date><authorinitials>GuillermoSteiner</authorinitials><revremark>Se cambia nombre desde &quot;WebHome/TrabajosPracticos/Tutoriales/EjemploC&quot;</revremark></revision><revision><revnumber>6</revnumber><date>2019-09-09 20:50:43</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>5</revnumber><date>2019-09-09 20:50:09</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>4</revnumber><date>2019-09-06 14:49:48</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>3</revnumber><date>2019-09-06 14:40:51</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>2</revnumber><date>2019-09-06 14:25:42</date><authorinitials>GuillermoSteiner</authorinitials></revision><revision><revnumber>1</revnumber><date>2019-09-06 13:47:47</date><authorinitials>GuillermoSteiner</authorinitials></revision></revhistory></articleinfo><section><title>Ejemplo de proyecto en lenguale C y ensamblador</title><para>Se muestra un ejemplo de proyecto que incluye archivos fuentes en lenguaje C y en ensamblador.</para><para> El proyecto consiste en: </para><itemizedlist><listitem><para>Una función <emphasis role="strong">suma</emphasis> escrita en ensamblador que recibe como parámetros 2 enteros, los suma y retorna su resultado. </para></listitem><listitem><para>Una función principal <emphasis role="strong">main()</emphasis> escrita en C, que utiliza la función <emphasis role="strong">suma</emphasis> para sumar dos enteros inicializados con una constante. </para></listitem></itemizedlist><para>Para poder realizar el llamado de una función escrita en ensamblador desde C, se debe realizar lo siguiente:  </para><itemizedlist><listitem><para>En el archivo en C se debe declarar la función <emphasis role="strong">suma</emphasis> 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. </para></listitem><listitem><para>El archivo ensamblador no tiene cambios importantes, si es necesario respetar las reglas de pase de parámetros (<emphasis role="strong">R0..R3</emphasis>) para parámetros, y devolver en <emphasis role="strong">R0</emphasis>, además de salvar los registros preservados.  </para></listitem></itemizedlist><para>Código en lenguaje C </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><![CDATA[#include ]]><lineannotation><![CDATA[<stdio.h>]]></lineannotation>

<token><![CDATA[extern]]></token><![CDATA[ ]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[suma]]></methodname><![CDATA[(]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[a]]></methodname><![CDATA[, ]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[b]]></methodname><![CDATA[);]]>

<token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[main]]></methodname><![CDATA[(]]><token><![CDATA[void]]></token><![CDATA[)]]>
<![CDATA[{]]>
<![CDATA[  ]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[a]]></methodname><![CDATA[ = 71;]]>
<![CDATA[  ]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[b]]></methodname><![CDATA[ = 29;]]>
<![CDATA[  ]]><token><![CDATA[int]]></token><![CDATA[ ]]><methodname><![CDATA[c]]></methodname><![CDATA[;]]>

<![CDATA[  ]]><methodname><![CDATA[c]]></methodname><![CDATA[ = ]]><methodname><![CDATA[suma]]></methodname><![CDATA[(]]><methodname><![CDATA[a]]></methodname><![CDATA[,]]><methodname><![CDATA[b]]></methodname><![CDATA[);]]>

<![CDATA[  ]]><token><![CDATA[return]]></token><![CDATA[ ]]><methodname><![CDATA[c]]></methodname><![CDATA[;]]>
<![CDATA[} ]]>
</programlisting><para>Código en lenguaje ensamblador </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><methodname><![CDATA[.text]]></methodname>
<methodname><![CDATA[.arm]]></methodname>
<methodname><![CDATA[.global]]></methodname><![CDATA[ ]]><methodname><![CDATA[suma]]></methodname>

<methodname><![CDATA[suma:]]></methodname>
<![CDATA[  ]]><methodname><![CDATA[add]]></methodname><![CDATA[   ]]><methodname><![CDATA[r2]]></methodname><![CDATA[, ]]><methodname><![CDATA[r0]]></methodname><![CDATA[, ]]><methodname><![CDATA[r1]]></methodname>
<![CDATA[  ]]><methodname><![CDATA[mov]]></methodname><![CDATA[   ]]><methodname><![CDATA[r0]]></methodname><![CDATA[, ]]><methodname><![CDATA[r2]]></methodname><![CDATA[                    ]]>
<![CDATA[  ]]><methodname><![CDATA[mov]]></methodname><![CDATA[   ]]><methodname><![CDATA[pc]]></methodname><![CDATA[, ]]><methodname><![CDATA[lr]]></methodname><![CDATA[  ]]>
</programlisting><section><title>Construcción del proyecto</title><para>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. </para><para>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. </para></section><section><title>Proyecto usando compilación cruzada</title><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><![CDATA[arm-none-eabi-gcc -Wall -mcpu=arm7tdmi -g -c main.c -o main.o]]>
<![CDATA[arm-none-eabi-as -mcpu=arm7tdmi -g suma.s -o suma.o]]>
<![CDATA[arm-none-eabi-gcc -Ttext=0 -nostartfiles -g main.o suma.o -o suma.elf]]>

</programlisting><itemizedlist><listitem><para>La primer línea compila el código fuente del archivo <emphasis role="strong">main.c</emphasis> y genera el archivo objeto <emphasis role="strong">main.o</emphasis> </para></listitem><listitem><para>La segunda línea ensambla el archivo fuente <emphasis role="strong">suma.s</emphasis> y genera el archivo <emphasis role="strong">suma.o</emphasis> </para></listitem><listitem><para>La última línea enlaza los dos archivos objetos (<emphasis role="strong">main.o</emphasis> y <emphasis role="strong">suma.o</emphasis>) y genera el archivo <emphasis role="strong">suma.elf</emphasis> </para></listitem></itemizedlist><para>Las diferentes opciones utilizadas son: </para><itemizedlist><listitem><para><emphasis role="strong">-c </emphasis> para detener la construcción luego de la etapa de compilación y tiene como salida el archivo objeto (<emphasis role="strong">.o</emphasis>).  </para></listitem><listitem><para><emphasis role="strong">-o </emphasis> para indicar el nombre del archivo de salida.  </para></listitem><listitem><para><emphasis role="strong">-Wall </emphasis> para habilitar todos las advertencias (warnings) del compilador.  </para></listitem><listitem><para><emphasis role="strong">-mcpu=arm7tdmi </emphasis> para indicar la arquitectura del procesador. </para></listitem><listitem><para><emphasis role="strong">-g </emphasis> para incluir información de depuración en los archivos de salida.  </para></listitem></itemizedlist><section><title>Simulación en PC con gdb</title><para>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. </para><section><title>gdb --tui</title><para>Para realizar un debug con esta herramienta no es necesario instalar nada. </para><para>Se debe ejecutar  </para><screen><![CDATA[arm-elf-eabi-gdb --tui]]></screen><para>luego dentro de este programa se escribe. </para><screen><![CDATA[target sim
file ex1.elf
load ]]></screen><para>Aparecerá en una ventana el fuente a depurar, escribiendo.  <code> break nn</code>  Se realiza un break point (nn es el número de linea que te aparece al costado izquierdo del archivo fuente). </para><para>Un tutorial de la herramienta se puede ver en  </para><itemizedlist><listitem override="none"><para><ulink url="http://sourceware.org/gdb/onlinedocs/gdb/TUI.html"/> </para></listitem></itemizedlist><para>para recordar los comandos mas usados  </para><para><ulink url="https://ciii.frc.utn.edu.ar/TecnicasDigitalesII/WebHome/TrabajosPracticos/EjemploC/TecnicasDigitalesII/WebHome/TrabajosPracticos/PracticoASM4/Debug#">Comandos Debug</ulink> </para></section></section><section><title>Construcción utilizando '''make'''</title><para>Archivo <code>Makefile</code> para la compilación cruzada  </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><methodname><![CDATA[CC]]></methodname><![CDATA[ = arm-none-eabi-gcc]]>
<methodname><![CDATA[AS]]></methodname><![CDATA[ = arm-none-eabi-as]]>
<methodname><![CDATA[LD]]></methodname><![CDATA[ = arm-none-eabi-ld]]>

<methodname><![CDATA[OBJECTS]]></methodname><![CDATA[ = main.o suma.o]]>

<methodname><![CDATA[CFLAGS]]></methodname><![CDATA[ = -Wall -mcpu=arm7tdmi -g  -c]]>
<methodname><![CDATA[ASFLAGS]]></methodname><![CDATA[ = -mcpu=arm7tdmi -g ]]>
<methodname><![CDATA[LDFLAGS]]></methodname><![CDATA[ = -Ttext=0 -nostartfiles -g ]]>

<methodname><![CDATA[suma.elf]]></methodname><![CDATA[: ]]><token><![CDATA[$(]]></token><methodname><![CDATA[OBJECTS]]></methodname><token><![CDATA[)]]></token>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[CC]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[LDFLAGS]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[OBJECTS]]><token><![CDATA[)]]></token><![CDATA[ -o suma.elf]]>

<methodname><![CDATA[suma.o]]></methodname><![CDATA[: ]]><methodname><![CDATA[suma]]></methodname><![CDATA[.]]><methodname><![CDATA[s]]></methodname><![CDATA[ ]]>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[AS]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[ASFLAGS]]><token><![CDATA[)]]></token><![CDATA[ suma.s -o suma.o]]>

<methodname><![CDATA[main.o]]></methodname><![CDATA[: ]]><methodname><![CDATA[main]]></methodname><![CDATA[.]]><methodname><![CDATA[c]]></methodname>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[CC]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[CFLAGS]]><token><![CDATA[)]]></token><![CDATA[ main.c]]>

<methodname><![CDATA[clean]]></methodname><![CDATA[:]]>
<![CDATA[        rm *.o *.elf ]]>
</programlisting></section></section><section><title>Proyecto sobre Raspberry</title><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><![CDATA[gcc -Wall -g -c main.c -o main.o]]>
<![CDATA[as -g suma.s -o suma.o]]>
<![CDATA[gcc -g main.o suma.o -o suma.elf]]>

</programlisting><section><title>Depurado con gdb</title><para>En este caso el software correra en forma nativa sobre la arquitectura (ARM de la raspberry) utilizamos entonces el gdb sin ningún simulador. </para><section><title>gdb --tui</title><para>se debe ejecutar  </para><screen><![CDATA[gdb --tui]]></screen><para>luego dentro de este programa se escribe. </para><screen><![CDATA[file ex1.elf
load ]]></screen></section></section><section><title>Construcción utilizando '''make'''</title><para>Archivo <code>Makefile</code> para la compilación sobre la RPi </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><methodname><![CDATA[CC]]></methodname><![CDATA[ = gcc]]>
<methodname><![CDATA[AS]]></methodname><![CDATA[ = as]]>
<methodname><![CDATA[LD]]></methodname><![CDATA[ = ld]]>

<methodname><![CDATA[OBJECTS]]></methodname><![CDATA[ = main.o suma.o]]>

<methodname><![CDATA[CFLAGS]]></methodname><![CDATA[ = -Wall -g  -c]]>
<methodname><![CDATA[ASFLAGS]]></methodname><![CDATA[ = -g ]]>
<methodname><![CDATA[LDFLAGS]]></methodname><![CDATA[ = -g ]]>

<methodname><![CDATA[suma.elf]]></methodname><![CDATA[: ]]><token><![CDATA[$(]]></token><methodname><![CDATA[OBJECTS]]></methodname><token><![CDATA[)]]></token>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[CC]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[LDFLAGS]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[OBJECTS]]><token><![CDATA[)]]></token><![CDATA[ -o suma.elf]]>

<methodname><![CDATA[suma.o]]></methodname><![CDATA[: ]]><methodname><![CDATA[suma]]></methodname><![CDATA[.]]><methodname><![CDATA[s]]></methodname><![CDATA[ ]]>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[AS]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[ASFLAGS]]><token><![CDATA[)]]></token><![CDATA[ suma.s -o suma.o]]>

<methodname><![CDATA[main.o]]></methodname><![CDATA[: ]]><methodname><![CDATA[main]]></methodname><![CDATA[.]]><methodname><![CDATA[c]]></methodname>
<![CDATA[        ]]><token><![CDATA[$(]]></token><![CDATA[CC]]><token><![CDATA[)]]></token><![CDATA[ ]]><token><![CDATA[$(]]></token><![CDATA[CFLAGS]]><token><![CDATA[)]]></token><![CDATA[ main.c]]>

<methodname><![CDATA[clean]]></methodname><![CDATA[:]]>
<![CDATA[        rm *.o *.elf ]]>
</programlisting></section></section></section></article>