El programar en lenguaje ensamblador es una competencia muy importante para programar sistemas embebidos, sobre todo en aplicaciones de procesamiento de señales.

Una ventaja de la tarjeta Raspberry Pi es que incluye todo un entorno de desarrollo en el sistema operativo. Además, permite el interfaz entre el lenguaje C y el ensamblador de una manera muy natural.

Implementaremos un programa extremadamente sencillo en ensamblador con la tarjeta Raspberry Pi en una configuración head-less.

Antes de empezar

Primero requerimos una tarjeta Raspberry Pi 3B+, o similar, con su fuente de poder.

También necesitamos una tarjeta de memoria micro SD de al menos 16 GB con el sistema operativo Raspberry Pi OS. El sistema operativo debe estar configurado para operar sin monitor ni teclado. En la publicación How to Set Up a Headless Raspberry Pi, Without Ever Attaching a Monitor, se muestra como realizar esto. Asumiremos que realizamos las actividades de esta publicación en todo lo que sigue.

En segundo lugar, ocupamos una computadora PC con el sistema operativo Windows 10. Se puede utilizar otro tipo de equipo y sistema operativo; sin embargo, sólo consideraremos el caso para una computadora PC con Windows 10. En ésta necesitamos instalar:

Además, nos hará falta un cable Ethernet cruzado para conectar directamente la PC a la tarjeta por medio del interfaz Ethernet, sin necesidad de un conmutador o concentrador de red. Si disponemos de un concentrador o conmutador, podemos usar un cable directo.

Conexión por medio de SSH

Primero que nada, hay que insertar la tarjeta micro SD en la tarjeta Raspberry Pi. En esta tarjeta de memoria ya tenemos instalado el sistema operativo en configuración head-less. Encendemos la tarjeta Raspberry Pi.

Conectamos la tarjeta Raspberry Pi y la computadora PC por medio del cable Ethernet cruzado.

Iniciamos el cliente de SSH y configuramos para conectarse a la tarjeta Raspberry Pi por medio del nombre raspberrypi.local.

Una vez iniciada la conexión, iniciamos la sesión (log in) en la Raspberry Pi.

Escribiendo el programa

Para escribir el programa en la Raspberry Pi, utilizaremos el editor nano. Este editor es lo suficientemente simple para poder empezar.

Para iniciar el editor nano, en la línea de comando de la Raspberry insertamos el siguiente comando:

pi@raspberrypi:~ $ nano programa1.s                                                                           

Deberá aparecer el editor nano en la terminal PuTTY

Editor `nano`
Figura: Editor nano.

Utilizando el editor nano, insertamos el siguiente código

.global main

main:
    mov r0, #42
    bx lr

El resultado se puede ver en la siguiente figura.

Programa en el editor `nano`
Figura: Programa en el editor nano.

Para salvar el programa, presionamos el conjunto de teclas Ctrl-O (Write Out). Se debe ver una pantalla como en la siguiente figura.

Salvando el programa en el editor `nano`
Figura: Salvando el programa en el editor nano.

Entonces presionamos la tecla Enter para completar el proceso de salvar el archivo.

Finalmente, para salir del editor nano, presionamos las teclas Ctrl-X.

Explicación del programa

A continuación explicaremos renglón por renglón el código. Primero que nada, para ensamblar el código utilizaremos la infraestructura del compilador de C para la Raspberry Pi. Esto nos permite simplificar mucho el desarrollo del código, pero introduce ciertas obligaciones.

La primera obligación viene de que el compilador de C espera que exista una función llamada main. En ensamblador, las funciones se llaman subrutinas. Entonces debemos tener una subrutina con el símbolo main. Pero además, el símbolo main debe ser global. Esto es similar a las declaraciones en el lenguaje C. Para ello usamos la directiva .global, como se ve en el listado siguiente.

.global main

A continuación viene la definición del símbolo main como la dirección de inicio de la subrutina. Para ello, simplemente lo indicamos usando el signo ortográfico de dos puntos, :, después del símbolo. Cuando veamos un símbolo seguido de :, le llamamos etiqueta.

main:

En siguiente renglón tenemos la instrucción mov. Esta instrucción permite cargar a un registro un valor literal o inmediato. En este caso, lo que estamos haciendo es cargar el número 42 en el registro r0. Es importante ponerle al número el prefijo #.

    mov r0, #42

Finalmente, la instrucción bx permite saltar a una dirección que esté almacenada en un registro. El símbolo lr representa al registro r15, que se utiliza para almacenar la dirección de retorno cuando se llama a una subrutina.

    bx lr

Ensamblado

Como ya mencionamos, el compilador de C tiene la capacidad de ensamblar programas. Para ello deben de tener la extensión .s. El compilador llamará al ensamblador y al enlazador. El resultado será el programa a.out. Entonces ejecutamos el compilador de C con la siguiente línea de comando.

pi@raspberrypi:~ $ gcc programa1.s                                                                           

Para ver el archivo a.out, ejecutamos en la línea de comando la siguiente instrucción.

pi@raspberrypi:~ $ ls a.out                                                                           

El resultado deberá ser como en la figura siguiente.

Revisando el archivo `a.out`
Figura: Revisando el archivo a.out.

Finalmente, ejecutamos el programa que se ensambló utilizando la siguiente instrucción.

pi@raspberrypi:~ $ ./a.out

Es importante colocar el el punto y la diagonal al principio. No deberá verse respuesta, ya que el programa como tal no tiene capacidad de imprimir el resultado. Para visualizar el resultado, tecleamos la siguiente instrucción.

pi@raspberrypi:~ $ echo $?

Deberá imprimirse el número 42.

Recursos