``1+1=2''

Et voilà ! Après des siècles de patience, dont je vous remercie, ami lecteur (votre serviteur était parti se faire bronzer au soleil de quelque pays producteur de pétrole pendant presque deux mois!), nous voici prêts à commencer la pièce.

Pour ceux qui ont manqué les prolégomènes de cette monumentale introduction à l'assembleur des processeurs ARM sur RISC PC, sachez que vous pouvez toujours vous replonger dans l'acte zéro, paru dans le numéro zéro de notre modeste bulletin de liaison de l'ARMada. Ce numéro est disponible gratuitement (sauf, bien entendu, les éventuels frais d'envoi) auprès du siège de l'association , sur simple demande (à ce propos... n'oubliez pas d'adhérer, hein?).

Qu'allons-nous faire, aujourd'hui ? Et bien, mon jeune ami, nous allons apprendre à compter! Si, si... Il y a un début à tout, non? De plus, comme c'est en forgeant qu'on devient forgeron...


Je tape donc ce listing...

Voici la démarche à suivre: respirez un grand coup, asseyez-vous face à votre clavier, la revue ARMada sur les genoux, et recopiez scrupuleusement le listing suivant dans un simple fichier-texte, que vous appelerez ``myadd'', et surtout, NE PANIQUEZ PAS!, les explications suivent!

 ;Premiere addition en assembleur sur ARM

R0      RN 0                     ;Definition reg.0
R1      RN 1                     ;Definition reg.1 
R2      RN 2                     ;Definition reg.2

LMAX    EQU 1                    ;1 chiffre max.

        AREA PREMADD ,CODE        ;Zone principale

        ENTRY                    ;Point d'entree
        MOV R0,#1                ;R0=1
        MOV R1,#1                ;R1=1
        
        ADD R0,R0,R1             ;R0=R0+R1
        ADR R1,RESULT            ;Adresse de Result
        MOV R2,#LMAX             ;nb max. chiffres
        SWI &28                  ;OS_BinaryToDecimal
        
        ADR R0,MOUT              ;Adresse message
        SWI 2                    ;OS_Write0
        
        MOV R0,R1                ;Adresse de Result
        MOV R1,R2                ;R1=R2 (nb car.)
        SWI &46                  ;OS_WriteN

        SWI &11                  ;OS_Exit 

MOUT    DCB "Resultat: ",0       ;A afficher
RESULT  % LMAX                   ;Res. Lmax octets

        END                      ;Fin d'assemblage

A présent, sauvegardez le fichier-source ``myadd'', faites-le mouliner un coup par l'assembleur, puis par le linkeur, de façon à produire un exécutable. Puis vous n'aurez plus qu'à le déclencher... Ce qui entraînera, si tout s'est bien déroulé, l'ouverture d'une fenêtre affichant:

Resultat: 2
Press space or click mouse button to exit . . .
...Hmm, c'est bon! Avant de passer à la suite de l'article, je vous autorise à vous éponger le front, pousser un soupir de soulagement (``Pff! Ca marche!''), bondir de joie, réveiller tout l'immeuble, le quartier, et enfin à recommencer cent fois de suite toute l'opération, de la main gauche (parce que la droite sera certainement occupée)...

Ca y est ? C'est fini ?

Bon. Maintenant, il va falloir retrouver notre sang froid. Tâchons un peu de comprendre tout ce charabia...


Qu'est-ce que j'ai tapé ?

La plupart des notions de base qui ne sont pas expliquées ici l'ont été dans l'acte zéro. Si vous éprouvez quelque difficulté lors de la lecture de ce qui va suivre, je vous engage chaudement à vous replonger dans ce dernier.

Prenez des notes...

En étudiants consciencieux que nous sommes, reprenons ligne par ligne le présent listing:
 ;Premiere addition en assembleur sur ARM
Comme nous l'avons déjà vu dans l'acte zéro, une ligne d'assembleur commençant par un point-virgule est un commentaire, et n'a donc aucune conséquence dans l'exécutable résultant, puisque ignorée purement et simplement lors de la compilation.
R0      RN 0                     ;Definition reg.0
R1      RN 1                     ;Definition reg.1 
R2      RN 2                     ;Definition reg.2
La directive RN, en début de code-source, permet de définir le symbole par lequel le n-ième registre (Nous avons vu dans l'acte zéro qu'un registre est une des mémoires internes du processeur, et qu'il permet de stocker un nombre entier pour ``travailler'' dessus. Ce programme donne , avec l'addition , un exemple de traitement de données dans le processeur) sera désigné. Ici, au lieu d'appeler les registres par des noms exotiques du genre ``TOTO'', je me contente d'aller au plus simple: le registre numéro x portera le nom Rx.
LMAX    EQU 1                    ;1 chiffre max.
Ah ! Voici la définition d'une constante. Une constante est un symbole qui porte une valeur numérique (ici, c'est 1), et la constante est LMAX. Lors de l'assemblage, dans toutes les instructions où le symbole LMAX apparaîtra, sa valeur, définie ici, lui sera substituée. Dans ce programme, LMAX est la longueur maximum de la chaîne de caractères dans laquelle le résultat de l'addition sera écrit (en chiffres), avant d'être envoyé à l'écran. L'intérêt de la chose est que vous pourrez vous amuser ultérieurement à modifier le source pour que le programme additionne autre chose que 1 et 1, et donc le résultat pourra faire plus de un chiffre de long. Tout ce que vous aurez à faire pour que cette longueur soit respectée , c'est de modifier LMAX.
        AREA PREMADD,CODE        ;Zone principale
La directive AREA déclare au compilateur une zone dont le nom est PREMADD et qui contiendra du CODE.
        ENTRY                    ;Point d'entree
Cette directive permet de déterminer que, lors de l'exécution, la première instruction exécutée est celle qui suit.
        MOV R0,#1                ;R0=1
        MOV R1,#1                ;R1=1
L'instruction MOV affecte un registre de destination. Sa syntaxe la plus simple est: MOV Rn,#x, c'est à dire que l'entier de 32 bits (En fait , de 8 bits ``extensibles'' sur les 32 du registre , mais nous y reviendrons ultérieurement) x est écrit dans le registre Rn. Ici, les deux registres R0 et R1 sont chacun affectés de la valeur entière 1. Vous pouvez vous amuser à modifier ces valeurs dans le source, de sorte que le résultat affiché ne sera pas toujours 2.
        ADD R0,R0,R1             ;R0=R0+R1
Voici enfin l'instruction d'addition! Sa syntaxe la plus simple est:
        ADD Rc,Ra,Rb
ce qui signifie que les registres Ra et Rb seront additionnés, et que leur somme sera affectée au registre Rc. Ici, les registres R0 et R1 sont additionnés, leur somme est écrite dans le registre R0, qui, de ce fait, perd son ancienne valeur.
        ADR R1,RESULT            ;Adresse de Result
L'instruction ADR permet d'écrire l'adresse que pointe le label RESULT, défini un peu plus loin dans le listing, dans le registre R1.
        MOV R2,#LMAX             ;nb max. chiffres
Tiens tiens... Où l'on voit resurgir le symbole LMAX défini au tout début du listing. Ici, donc, sa valeur est affectée au registre R2.

ATTENTION ! N'oubliez surtout pas le signe ``#'' devant LMAX!

        SWI &28                  ;OS_BinaryToDecimal
La fonction du système d'exploitation &28 (40, en décimal), répondant au joli nom de OS_BinaryToDecimal, permet de convertir le nombre binaire contenu dans le registre R0 en chaîne de caractères dont l'adresse est spécifiée dans le registre R1, et de longueur maximale précisée dans le registre R2. Ici, le résultat de l'addition, contenu dans le registre R0, sera converti en nombre ASCII à partir de l'adresse RESULT, définie plus bas, avec LMAX chiffres de long au maximum. ATTENTION: après l'exécution de cette fonction, la valeur du registre R2 aura été modifiée: au lieu de contenir le nombre maximum de caractères, le registre R2 contiendra le nombre effectif de caractères!
        ADR R0,MOUT              ;Adresse message
L'adresse du message commençant à partir du label MOUT, défini plus bas, est écrite dans le registre R0.
        SWI 2                    ;OS_Write0
La fonction du système d'exploitation 2, appelée OS\_Write0, permet d'écrire à l'écran la chaîne de caractères commençant à l'adresse pointée par le registre R0, et terminée par un octet nul. Ici, c'est de la chaîne de caractères commençant au label MOUT qu'il s'agît, en l'occurence, c'est ``Resultat: '' qui sortira à l'écran.
        MOV R0 ,R1                ;Adresse de Result
        MOV R1 ,R2                ;R1=R2 (nb car.)
Voici une deuxième façon de se servir de l'instruction MOV. Cette fois, ce n'est pas un nombre littéral qui est écrit dans le registre de destination, mais le contenu d'un autre registre. Ici, le contenu de R1 est écrit dans R0, puis celui de R2 est à son tour écrit dans R1. Si nous nous souvenons de ces valeurs, cela revient à transférer la valeur de l'adresse de la chaîne de caractères représentant le résultat de l'addition dans R0, et le nombre de caractères de cette chaîne dans R1.
        SWI &46                  ;OS_WriteN
La fonction du sytème d'exploitation 46 (70, en décimal) permet d'écrire à l'écran la chaîne de caractères qui commence à l'adresse pointée par R0 et de R1 caractères de long. Ici, c'est la chaîne de caractères résultant de la conversion Binaire-->Décimal ASCII que nous venons d'effectuer qui sera affichée.
        SWI &11                  ;OS_Exit 
Voilà. Une fois ceci fait, il ne restera plus qu'à sortir du programme, au moyen de la fonction du système d'exploitation 11 (17, en décimal), que nous connaissons déjà depuis l'acte zéro.
MOUT    DCB "Resultat: ",0       ;A afficher
Voici une ligne qui nous en rappelle une autre, vue dans l'acte zéro: ici, nous déclarons un label, MOUT, et nous forçons le compilateur à écrire directement la chaîne de caractères ``Resultat: '', suivie d'un octet nul, dans le fichier exécutable.
RESULT  % LMAX                   ;Res. Lmax octets
Ici est défini le label RESULT. Il est suivi de la directive % (oui, oui, vous avez bien vu: le signe ``%''), qui permet de reserver un certain nombre d'octets nuls dans le fichier exécutable. Le nombre d'octets à réserver est spécifié juste après. Ici, c'est encore le fameux nombre symbolisé par LMAX, que vous pouvez modifier au début du fichier-source.
        END                      ;Fin d'assemblage
Voici enfin la directive qui arrête la compilation. Tant mieux. Je n'en pouvais plus.


Reposez le crayon

Aaaah... C'est enfin terminé. Epongeons-nous bien le front et ne nous réjouissons pas trop vite, car il reste du boulot. Beaucoup de boulot.

Jetons un coup d'oeil à côté, sur le programme du petit frêre, réalisé en BASIC: c'est beau, c'est plein de couleurs! Revenons alors à notre minable affichage ``1+1=2''. Lequel préférez-vous? Le Tchika-tchika-boum en BASIC? Probablement.

Soyons francs: vous ne pourrez arriver à des résultats de cet ordre qu'au bout d'un long et difficile apprentissage, qui commence à peine. Mais à la fin, si vous savez vous accrocher, réfléchir aux difficultés, poser des questions sur ce qui vous embarrasse, et surtout m'engueuler quand je ne suis pas assez clair, vous serez à même de faire jouer la Marseillaise au disque dur. Si, si, ça viendra, c'est une question de patience, mais, plus encore, de persévérance!

Retour au sommaire