Site WWW de Laurent Bloch
Slogan du site

ISSN 2271-3905
Cliquez ici si vous voulez visiter mon autre site, orienté vers des sujets moins techniques.

Pour recevoir (au plus une fois par semaine) les nouveautés de ce site, indiquez ici votre adresse électronique :

Programmation en assembleur ARM
Article mis en ligne le 4 février 2017
dernière modification le 4 mars 2021

par Laurent Bloch

*Tablettes décevantes

Sur ce site un article proclamait, il y a déjà six ans, que les processeurs les plus répandus au monde étaient les processeurs ARM, et un autre plus récent annonçait qu’ils étaient destinés à supplanter les processeurs Intel x86, d’architecture périmée, lourde et vorace en électricité, dissipatrice de trop de calories. J’attends avec impatience la sortie d’ordinateurs portables à processeurs ARM, dont j’espère pour mes vertèbres qu’ils pèseront moins de 800g. Le marketing d’Intel fait ce qu’il faut pour que cela n’advienne pas, parce que techniquement ce serait possible, les tablettes le prouvent. Justement, j’avais cru pouvoir m’en tirer avec une tablette, après tout sous Android il y a Linux, mais j’ai été déçu : il me faut au moins Emacs, gcc et LaTeX, or à part un Emacs qui ne fonctionne pas je n’avais pas ce qu’il me fallait. Et après vingt ans de logiciels libres j’ai complètement perdu l’habitude que le marchand de mon ordinateur décide de ce que je peux ou ne peux pas en faire.

*Du livre la lumière

J’en étais là lorsqu’en rodant dans les allées de la bibliothèque de Jussieu j’aperçus un titre prometteur : Learning Computer Architecture with Raspberry Pi [1]. Je le feuilletai une demi-heure, il existait sous forme électronique, je l’achetai aussitôt. L’habile libraire en ligne me proposa en sus, pour un prix modique, Raspberry Pi Assembly Language de Bruce Smith : je cédai.

Le Raspberry Pi est un petit ordinateur qui tient dans le creux de la main et coûte une quarantaine d’euros, avec un processeur ARM quatre cœurs 64 bits, quatre connecteurs USB, un connecteur Ethernet RJ45, un connecteur HDMI, un circuit WiFi et un circuit Bluetooth. Il faut compter en plus un boîtier, une alimentation et, par prudence, un jeu de radiateurs pour le processeur et un autre circuit. Compter 70 à 80 euros. Il est sans doute prudent d’ajouter un disque USB, sur lequel on peut d’ailleurs installer le système en suivant cet excellent mode d’emploi de François Mocq. Pour moi l’avenir de l’informatique est là. Je me retins de l’acheter tout de suite parce que j’avais un peu de travail à terminer, et je commençai par lire les bouquins.

Les auteurs du manuel d’architecture sont à peu près de ma génération, leur livre peut être considéré jusqu’à un certain point comme un livre d’histoire de l’architecture des ordinateurs, j’y ai retrouvé avec nostalgie les mémoires à tores de ferrite, tellement plus pédagogiques que les DRAM modernes... Bon, les matériels modernes sont décrits eux aussi dans ce livre, mais j’avoue avoir craint de m’y égarer pour des jours. Je suis donc passé au manuel d’assembleur, et au bout d’une centaine de pages (la moitié du bouquin) je n’y tins plus et commandai le matériel.

*Architecture RISC vs. CISC

Les processeurs ARM actuels sont issus d’une lignée de micro-ordinateurs purement britannique [2] dont les premiers représentants sont l’Acorn Atom, l’Archimedes et le BBC Micro. L’Archimedes fut le premier micro-ordinateur RISC (pour Reduced Instruction Set Computer) grand public. Sa conception commença en 1984, je me souviens d’articles qui le décrivaient, ses caractéristiques étaient tellement extraordinaires par rapport à la concurrence que l’on sentait que les journalistes n’y croyaient pas vraiment. Il fut la première machine basée sur un processeur 32 bits à technologie RISC ARM développé en interne par seulement trois ingénieurs d’Acorn (Sophie Wilson, Steve Furber et Robert Heaton) à partir de 1983 (source Wikipédia).

Les architectures RISC, par opposition aux architectures CISC (pour Complex Instruction Set Computer), se caractérisent par un jeu d’instructions plus simples et plus régulières, ce qui leur confère une plus grande efficacité en termes de vitesse de calcul, de consommation électrique et de dissipation thermique. Pour un historique et des détails on pourra se reporter à l’article de ce site Histoire et avenir des processeurs RISC.

*Attaquer l’assembleur

**Assembleur IBM

L’assembleur IBM 360/370 fut mon langage de prédilection pendant une dizaine d’années, de 1972 au début des années 1980. Auparavant je programmais en PL/1, mais lorsque mon employeur bien-aimé décida que l’on passerait de PL/1 à Cobol, cette régression me parut intolérable et je demandai ma mutation à l’équipe système pour avoir une bonne raison de passer à l’assembleur. C’était l’informatique qui me passionnait, et Cobol était un langage conçu (excellemment !) pour l’évacuer.

Rétrospectivement, l’assembleur 360 était une bonne bête. Vous trouverez son jeu d’instructions sous le titre IBM System/360 Principles of Operation ; on le trouve en ligne, malheureusement sous forme d’image scannée, mais lisible. La version z/OS contemporaine, qui en est un sur-ensemble, est en ligne ici. Ce savoir est toujours d’actualité parce que les grands systèmes IBM ont toujours un marché vaste et lucratif, leur système z/OS ressemble comme deux gouttes d’eau à ceux que j’ai connus, et même si le processeur a changé il émule toujours la même architecture. J’observe d’ailleurs que les articles de Wikipédia qui pourraient nous éclairer sur le sujet sont soigneusement supervisés par des zélateurs d’IBM, qui font tout pour que le sujet reste le plus obscur possible. Pour programmer des vraies choses il faut utiliser les macro-instructions qui déclenchent des appels système : GETMAIN (équivalent de malloc), ATTACH (resp. execve), etc., bref, l’équivalent de la Libc (cf. http://www.ibm.com/support/knowledg... et http://www.ibm.com/support/knowledg...).

La lecture de l’assembleur 360 n’est pas trop ardue, la principale difficulté tient au fait qu’il y a trois longueurs d’instruction possibles : un demi-mot (deux octets), un mot ou un mot et demi. À l’époque les adresses étaient sur 24 bits, et beaucoup de programmeurs avaient imaginé des usages astucieux pour le quatrième octet du mot, d’où résultèrent des difficultés multiples lorsqu’il fallut passer à 32 bits. On tourna l’obstacle avec des adresses négatives, ce qui repoussait une vraie solution à l’horizon 64 bits.

L’architecture IBM 360 n’est pas une architecture à pile. Dans une interview récente aux Communications of the ACM (CACM) de novembre 2015, Fred Brooks, architecte en chef du système pour le logiciel (Gene Amdhal était son vis-à-vis pour le matériel) explique pourquoi : au début ils étaient partis pour une architecture à pile, en suivant l’exemple de Burroughs. Mais le problème était la gestion des adresses pour les plus petites machines de la gamme, dont le chemin de données était large de 8 bits et qui n’avaient en réalité que deux registres, les autres étant simulés par le microcode. La manipulation d’adresses de 24 bits aurait entraîné trop de chargements et déchargements de données en fait inutiles.

La solution retenue afin d’avoir, pour toutes les opérations courantes, des adresses courtes, fut un adressage « registre de base (4 bits) + déplacement (12 bits) ». À l’intérieur d’une section de contrôle (CSECT, l’unité de programme élémentaire) les adresses relatives étaient sur 12 bits et le registre de base était toujours le même. Ainsi l’opération de déplacement de données de mémoire à mémoire (MVC) a le format suivant :

 code opération (D2) 8bits ;
 longueur de la zone à copier 8 bits (limite à 256 octets) ;
 registre de base de la cible 4 bits ;
 déplacement à ajouter à la base pour la cible 12 bits ;
 registre de base de la destination 4 bits ;
 déplacement à ajouter à la base pour la destination 12 bits.

Tout cela semble aujourd’hui bien de l’énergie gaspillée pour pas grand-chose, mais à l’époque les bits étaient rares et chers !

**Assembleurs indigestes

En quittant le monde IBM pour le monde DEC (Digital Equipment Corporation) au début des années 1980 je découvris un monde nouveau, passionnant à bien des égards, mais doté d’un assembleur bien indigeste, d’abord sur PDP (machines 16 bits, 6 modes d’adressage), puis sur VAX (32 bits, 8 modes d’adressage). La syntaxe des modes d’adressage me sembla particulièrement biscornue.

Beaucoup d’ingénieurs qui ont conçu les architectures et les langages des systèmes ultérieurs avaient fait leurs premières armes sur PDP, à commencer par les concepteurs d’Unix (Thompson et Ritchie) et de C (Kernighan et Ritchie). C’était une excellent école... sauf pour la syntaxe de l’assembleur, à moins de la considérer comme un jeu, ce qui fut probablement le cas pour certains de ces concepteurs. En tout cas on retrouve la trace de l’assembleur PDP dans C.

Je ne sais pas si le langage machine des processeurs x86 Intel a une dette envers le PDP, mais en tout cas il porte le fardeau de la rétro-compatibilité avec les premiers processeurs Intel x86, 16 bits, avec pour conséquence une gymnastique entre partie haute et partie basse de chaque registre qui augmentait singulièrement le risque d’erreur de programmation. Bref, je n’ai pas vraiment pris pied sur ces architectures, ce que je regrette.

**Enfin vint ARM

J’étais dépité d’avoir perdu le contact avec le langage machine, l’arrivée au premier plan d’une nouvelle architecture me donnait donc l’occasion d’y revenir. J’ai commencé à faire les exercices présentés par M. Bruce Smith. L’usage des registres, les codes condition et les noms des instructions me rappellent l’assembleur IBM. La syntaxe de l’adressage indirect me semble plus agréable que chez Intel. Bon, il y a toute une collection de caractères de suffixe qui peuvent venir s’adjoindre au nom de l’instruction pour traiter les codes conditions et pour incrémenter ou décrémenter des registres avant ou après son exécution.

Programmer en assembleur procure un contact en quelque sorte physique avec l’ordinateur, qui n’a rien à voir avec les sensations, certes agréables, que l’on peut avoir avec un langage de programmation plus abstrait. En outre la connaissance du langage machine, qui tombait en désuétude, redevient nécessaire pour la cybersécurité. En effet les auteurs de virus et de backdoors n’ont généralement pas l’amabilité de donner leur code source aux ingénieurs de sécurité chargés de les déminer, qui doivent analyser le code machine retrouvé dans les débris laissés par l’attaque. Ce type d’analyse post mortem pourrait s’appeler autopsie, mais le terme anglais forensics est tellement entré dans les mœurs que je propose le néologisme forensique [3], qui ne sonne pas trop mal.