Il y a plusieurs mois, j’avais acheté un Raspberry pi 3B+ en
pensant pouvoir apprendre l’assembleur arm 64 bits. J’avais échoué à le faire
fonctionner avec un Linux 64 bits suite à de nombreux problèmes de configuration.
Par exemple avec une version Barnani améliorée, le Wifi ne fonctionnait
pas !!.
Mais je gardais un œil sur les évolutions des OS 64 bits
pour le Raspberry et il y a quelques jours j’ai découvert une version https://github.com/sakaki-/raspbian-nspawn-64.
Il m’a fallu moins de 2 heures pour
faire fonctionner celle çi sur le Raspberry puis d’arriver à compiler un
programme assembleur en 64 bits mais il
m’a fallu plus de temps pour que le programme se termine sans erreur !!
Voyons la démarche : tout d’abord, j’ai suivi la
documentation (en anglais) pour télécharger l’image sur un pc windows 10 et la flasher grâce à Etcher sur une carte SD
de 16GO.
Ensuite pour éviter les problèmes rencontrés avec mon écran
LCD et mon petit clavier, j’ai relié le Raspberry au PC grâce au câble de
liaison TTL /USB. Dans le fichier config.txt accessible depuis le PC dans la
partition boot j’ai ajouté l’option enable_uart=1. Puis j’ai inséré cette
nouvelle carte dans le Rapsberry qui a booté sans problème. Dans le logiciel Putty
du PC, j’ai vu apparaitre tous les messages d’installation et la demande du
user et du mot de passe (j’ai saisi ceux par défaut). J’ai modifié le fichier /etc/wpa_supplicant/wpa_supplicant.conf
pour prendre en compte ma livebox et rebooter. Hélas, j’avais oublié d’autoriser
le ssh et donc il a fallu à partir de la console Putty série redémarrer le raspberry
après avoir autoriser le ssh (dans sudo raspi-config) et créer un fichier ssh
dans la partition boot. Il est aussi préférable de modifier le mot de passe de l'utilisateur pi.
Ensuite j’ai pu me connecter par une connexion ssh wifi avec Putty et supprimer le câble de liaison TTL. J’ai donc vérifié quelques commandes
unix, crée les répertoires de travail, transféré un source assembleur 32 bits
puis le compiler avec as et l’exécuter sans problème. Donc je pourrais toujours
écrire et tester des programmes 32 bits.
Ensuite j’ai écrit un premier programme qui utilise les
registres x0 et w0 pour le 64 bits. Évidement
la compilation habituelle génère des erreurs. Mais comment compiler en assembleur
64 bits ? Une relecture complète de la documentation de cette version m’indique
qu’il faut utiliser un container spécial pour lancer des programmes 64 bits. Il
faut donc taper
ds64-shell
pour lancer debian-buster-64.
Les commandes unix habituelles se déroulent sans problème mais
pas le compilateur as !! Après recherche, je m’aperçois qu’il faut
installer les packages 64 bits en restant dans ce container. Le compilateur as
se trouve dans le package binutils qu’il suffit d’installer comme les autres
packages 32 bits (sudo apt-get install binutils).
Cette fois ci la compilation as accepte bien les nouveaux
registres mais rejette les commentaires qui commencent par @. Je les remplace
par les // et la compilation se termine sans erreur.
Lancement de l’exécution et bien entendu l’erreur bien
connue Segmentation fault apparait.
Evidemment, il n'y a aucune visibilité pour savoir d’où vient
le problème mais en supprimant toutes les instructions une à une, je trouve qu'il s’agit d’une
erreur de l’appel système svc pour terminer le programme. Bien sûr, les codes des
call system Linux sont différents entre le 32 bits et le 64 bits. Sur Internet
je trouve différentes tables dont les codes pour le EXIT sont différents et ne
fonctionnent pas. Puis la recherche sur le fichier unistd.h du raspberry ne
donne rien dans le container 64 bits.
Après plusieurs heures de recherche et de test, je trouve
enfin un site qui me donne le bon code 93 et j’arrive enfin à terminer
normalement le programme. L’affichage d'un message standard devient un jeu d’enfant.
Vous pouvez aussi vérifier que le code retour est bien 5
avec la commande echo $?
Voici le programme ici.
On remarque déjà que les valeurs immédiates ne sont plus précédées
du signe #, que les adresses ne sont plus de la forme .int mais .quad (double soit
64 bits ce qui est normal).
Le code du call système doit être passé dans le registre A8
(et non plus r7 comme en 32 bits).
Maintenant il nous reste à découvrir tout le reste !! Mais
déjà je découvre que nous avons 31 registres de 64 bits et 31 registres de 32
bits à notre disposition. On va pouvoir s’amuser !! Non,non Grosse erreur : il n’y a que 31
registres, les registres 32 bits ne sont que la partie basse des registres 64
bits (cf chapitre suivant où j’ai effectué la vérification).
Ah, j’oubliais tous les messages sont en anglais et l’heure
n’est pas bonne. Il faut aller à nouveau dans raspi-config pour mettre en place
le bon paramétrage local !!
Pour continuer, dans le programme affTexte, nous allons
créer une routine pour calculer la longueur de la chaine avant de l’afficher. Je
découvre que les instructions push et pop n’existent plus et même les instructions
stm et ldm. On ne peut utiliser que des ldr et ldp, cette dernière permettant
de stocker 2 registres d’un coup. Il faut de plus gérer l’avancement (ou plutôt
le retrait) de la pile donc ici 2 fois 8 octets.
Un petit mot sur les registres : ceux de 64 bits
commencent par la lettre x, ceux de 32 bits par la lettre w. Le registre lr est
le x30, et le fp est le x29. La pile sp est un registre supplémentaire. Pour
les appels de routines, les registre x0 à x7 servent pour le passage des
paramètres et ne sont pas conservés. Les registre x8 à x18 servent pour les
calculs temporaires et ne sont pas sauvegardés. Les registres x19 à x28 sont
sauvegardés. Tout cela est encore à vérifier !!
Autre surprise lors de l’écriture de la routine, l’instruction
ldrb n’est valide que si le registre récepteur est un registre 32 bits. Il n’est
plus possible de mettre les instructions de calcul de manière conditionnelle
(addeq n’est pas autorisée) mais les branch peuvent l’être.
Le retour de la sous procédure se fait simplement par l’instruction
ret qui utilise le registre lr (r30) comme adresse de retour.
Prochaine étape : affichage d’un registre.
Aucun commentaire:
Enregistrer un commentaire