10

BeagleBoard : débuts difficiles

déc

Une fois votre BeagleBoard installée et configuré, vous vous dites que tout va bien et que vous allez pouvoir vous lancer dans les petits programmes et vous avez patiemment élaborés pendant des semaines ! Et bien non.

Le premier problème rencontré a consisté à trouver un assembleur.
Sur Internet, on trouve des tas d’exemples qui utilisent les commandes “as”, “nasm”, “gas” ou je ne sais quoi. Mais en fait aucune ne marche et surtout ne correspondent à aucun package Linux Ubuntu.
La palme revient à “nasm” puisque cet assembleur ne semble pas prendre en compte l’ARM (en tout cas sur le site web ils n’en parlent pas) alors qu’on trouve des exemples sur le net l’utilisant.
Finalement, après 1 jour de désespoir, je ne suis résigné à utiliser l’assembleur en ligne de commande avant de m’apercevoir que gcc est lui aussi un assembleur (ce qui semble finalement assez logique).

La deuxième déception à été d’être dans l’incapacité d’utiliser le compteur de cycle de l’ARM. En effet pour l’initialiser il faut écrire un module linux. Hors je n’ai pas pour le moment été capable de la faire car il me manque certains des header linux! Bon je ne désespère pas pour autant. Je vais bien finir par trouver un guru linux capable de me compiler ce module pour ma ubuntu (qui pour info tourne avec le kernel 2.6.35.8-l7).

Premiers tests

Bon c’est pas tout ça, mais faut quand même parler un peu assembleur.
Allons-y de notre première fonction assembleur. Il s’agit de réaliser la fonction addition qui retourne la somme de deux entiers.

Le version C de notre fonction est la suivante : addition.c

int addition(int a, int b)
{
	return (a+b);
}

La version assembleur (minimale est la suivante) : addition.s

	.global		addition
	.align		2
addition:
	add			r0, r0, r1
	mov			pc, lr

Alors quelques explications s’impose.

  • .global addition : indique au linker que addition est un label (ici une fonction) qui pourra être utilisé par un autre fichier (c, assembleur ou autre)
  • .align 2 : indique que ce qui suit devra être aligné sur un multiple de 4 (2^2). Alors là aussi, c’est étonnant mais la littérature sur Internet semble dire que l’alignement (.align n) se fait sur un multiple de n alors qu’en fait il se fait sur un multiple de 2^n.
  • addition: : est un label. Un label sert principalement à nommer une adresse mémoire afin de pouvoir l’utiliser ultérieurement (via un saut ou via un accès mémoire)
  • add r0, r0, r1 : Voilà finalement la principale instruction de notre programme… r0 va recevoir la valeur de a et r1 celle de b. r0 contient au terme de l’instruction la somme des deux valeurs.
  • mov pc, lr : force le programme à continuer juste après l’appel de la fonction addition..

Voilà.
A présent nous avons besoin d’un fichier c pour appeler notre fonction : test.c

#include < stdio.h >
void main()
{
	printf("addidion = %d\n", addition(7, 19));
}

Il ne nous reste plus qu’a compiler tout ça!

gcc addition.s test.c -o mon_programme

Normalement l’execution du programme devrait retourner 19 !

Petit point sur les registres

Pour rappel, l’ARM dispose de 16 registres nommés r0, r1, …, r15.
Les quatorze premiers sont génériques et peuvent être utilisés comme vous le voulez.
r14 s’appelle aussi lr (link return). Lorsqu’un appel à une fonction est exécuté, l’ARM stocke dans ce registre l’adresse de retour de la fonction, c’est à dire l’adresse de l’instruction qui suit l’appel.
r15 s’appelle aussi pc (program counter). Il contient l’adresse de la prochaine instruction à exécuter.

On comprend mieux à présent ce que fait l’instruction mov pc, lr. Elle indique à l’ARM qu’il faut poursuivre le programme à l’instruction qui suit l’appel de la fonction addition. D’une manière générale vous aurez rarement l’occasion d’utiliser autrement les registres pc et lr (bien que lr puisse être sauvé puis utilisé comme un autre registre, ce qui n’est pas le cas de pc).

Certain registres ont aussi une utilisation particulière, mais cette fois-ci il s’agit de convention. Il n’y a rien dans le hardware qui impose cette utilisation.
r13 est appelé sp (stack pointer). Il s’agit du pointeur de pile.
r12 et r11 sont appelés ip et fp. J’avoue que je ne maîtrise pas tellement leur usage donc j’aurai du mal à vous indiquer à quoi il servent.
r10 est appelé sl (stack limit). Il contient (enfin je suppose) une adresse permettant de s’assurer que la pile ne se met pas à écrire en dehors de la zone mémoire qui lui a été allouée.
r5, r6, r7, r8 et r9 sont des registres de variable. C’est à dire qu’il n’ont aucun usage particulier.
r0, r1, r2 et r3 sont les registres de paramètres. Lors qu’un appel à une fonction est réalisé les 4 premiers paramètres sont fournis dans ces registres (il s’agit la encore d’une convention d’usage). Au cas on la fonction utiliserai un 5eme paramètres il serait alors poussé sur la pile.
r0 enfin a un double usage puisque c’est lui qui doit contenir la valeur de retour de la fonction.

r1, r1, r2 et r3 ont aussi une caractéristique particulière (encore par convention), ils ne sont pas censés être utile au programme qui appelle votre fonction. Cela veut dire que vous pouvez les modifier autant que vous le voulez sans avoir besoin de les enregistrer avant leur utilisation pour les restaurer après.

Remarque importante : il faut bien comprendre que tous les registres à l’exception de r15 (pc) et r14 (lr) peuvent être utilisé de façon indifférente. Si votre fonction a besoin de nombreux registres pour fonctionner plus rapidement, vous pouvez toujours sauver ces registres les utiliser comme vous le voulez, puis les restaurer avant de sortir de votre fonction. r14 (lr) peut lui aussi être utilisé, car sa seule spécificité est de recevoir l’adresse de retour d’un appel. Une fois sauvegardé, il peut être utiliser comme les autres registres.

Voilà. Il n’y a plus qu’a coder à présent.

 | Tags:

2 Responses to “BeagleBoard : débuts difficiles”

  1. [...] ce tutoriel est un peu un redit de ce post que j’ai écris il y a déjà quelques mois… Commentaires [...]

  2. [...] This tutorial is a repeated of this post I wrote few months ago … Commentaires [...]

Répondre

Human control : 4 + 7 =