Après réflexion et un premier test, je décide d’afficher le
contenu de 6 registres sur 2 lignes et d’indiquer dans la macro le N° du
premier registre à afficher. Ainsi en indiquant affregtit Libellé 0, la macro
affichera le texte Libellé puis le contenu des registres x0 à x5. Si nous
voulons d’autres registres, nous indiquerons affregtit toto1 10 et la macro
affichera les contenus des registres x10 à x15. Il est inutile de prévoir une
macro pour les registres w0 à w30 puisqu’ils sont inclus dans les registres 64
bits.
Un petit problème se pose : il faut afficher les
registres x0 et x1 et il faut passer à la routine d’affichage l’adresse du
libellé et le N° du premier registre à afficher : Je décide de les passer
dans x0 et x1 et de passer les valeurs de xo x1 précédentes sur la pile (à la
réflexion c’était peut être mieux de faire le contraire).
Tout d’abord, j’écris dans le fichier routinesARM64.s, les
routines pour afficher le libellé, le nom des registres et leur contenu : affRegistres16,
prepRegistre16 et prepNumRegistre. Pour calculer la position d’affichage il
faut utiliser les instructions de multiplication et de division. Elles sont
identiques à celles en 32 bits et donc ne posent aucun problème. Pour convertir
le N° de registre en caractères ascii, je fais simple : une seule division par
10 et calcul du reste grâce à l’instruction msub x4,x3,x5,x0 qui soustrait de
x0 le résultat de la multiplication de x3 * x5 et qui met le résultat dans x4.
Et tout d’un coup, je m’aperçois que je commence les
libellés des adresses par iAdr i pour integer alors que maintenant elles sont
décrites en .quad et donc doivent commencer par qAdr. Et reste une
question : faut-il bien les déclarer avec le mot clé .quad comme c’était
le cas en 32 bits ? : il faudra le vérifier.
Quand ces routines sont prêtes, j’écris la macro pour
appeler la routine principale : il faut manipuler la pile pour passer
correctement les valeurs (et sauvegarder aussi le registre d’état). Après
quelques tests, la macro fonctionne bien.
Il reste 2 petits problèmes : la macro n’affiche pas le
contenu de la pile et le contenu du registre 30 (lr) affiche le contenu qu’il a
dans la routine d’affichage et pas la valeur qu’il a avant l’appel de la macro.
Si on veut avoir les contenus de ces 2 registres, il faut les copier avant
l’appel dans 2 registres inutilisés mais l’expérience du 32 bits m’a montré que
les contenus de ces 2 registres sont rarement utiles !!
Tant que je suis sur l’écriture des macros, j’écris aussi
celle qui affiche les drapeaux du registre d’état en utilisant les instructions
mrs x5,nzcv et msr nzcv,x5. Vous noterez que le nom du registre n’est pas le
même qu’en 32 bits.
Pour l’utilisation de ces nouvelles macros, je crée le
programme testaffreg.s qui verifie le contenu des registres et pour vérifier
aussi que l’adresse de la pile en fin de routine est égale à celle du début.
Je crée aussi un autre programme verifinst.s pour vérifier
un certain nombre d’instructions en 64 bits : les mov, cbz cbnz tbz et
tbnz. Je remarque que l’instruction teq n’existe plus en 64 bits.
Je teste aussi l’écriture de registres sur la pile en
diminuant l’adresse de la pile à chaque instruction. Cela me parait plus
satisfaisant car on peut ajouter des écritures de paires de registres plus
facilement.
Je poursuis l’écriture des macros en recopiant et modifiant
la macro de vidage des zones de la mémoire. Comme il faut aussi afficher en
premier un libellé, je réorganise les autres macros pour appeler la même
sous-routine d’affichage.
Je décide aussi de dupliquer la routine d’affichage d’une
chaine pour permettre le passage de la longueur de la chaine dans le registre x1.
En effet, je me suis aperçu que la longueur des chaines à afficher étaient très
souvent connue et donc qu’il est inutile de passer par une boucle de calcul de
cette longueur.
Je teste ces améliorations et l’affichage des zones mémoires
dans le programme debutaffmem1.
AFFICHAGE D'UN REGISTRE EN DECIMAL SIGNE ET NON SIGNE
AFFICHAGE D'UN REGISTRE EN DECIMAL SIGNE ET NON SIGNE
J’ai réussi à trouver une synthèse des instructions arm64
au format pdf :
https://courses.cs.washington.edu/courses/cse469/18wi/Materials/arm64.pdf
Pour terminer cette première partie, j’écris les 2 routines
qui permettent de convertir la valeur d’un registre en un nombre décimal signé
et non signé. Le résultat sera une chaine de caractères ascii cadrée à gauche
et se terminera donc par un zéro final. Cette solution est un peu différente de
celle que j’avais proposée pour le 32 bits. Suivant le besoin, c’est donc le
programme appelant qui utilisera la chaine comme il conviendra.
La chaine contiendra donc par exemple « 12345 » en
non signé et « +12345 » ou « -12345 » en signé.
Remarque : c’est le programme appelant qui doit fournir
la place de la zone réceptrice soit 21 caractères. Quand j’aurais testé les
allocations de place sur le tas, c’est la routine qui allouera la place nécessaire
(ce qui me semple mieux). La routine retourne dans le registre x0, la longueur
de la chaine (hors zéro final)
La conversion s’effectue en utilisant les instructions udiv
et msub dans une boucle.
Le programme de test fait appel à ces routines et affiche
les résultats en appelant la nouvelle version de l’affichage de chaine donc en
passant la longueur.
Quelques remarques : contrairement à ce que je pensais
au début, les instructions de l’assembleur 64 bits ne font pas 64 bits de long
mais seulement 32. La manipulation des zones en mémoire peut se faire en 8bits,16
bits 32 bits et 64 bits et il est conseillé que ces zones soient alignées sur
leur frontière(si ce n’est pas le cas, il n’y a pas d’erreur mais une
augmentation du nombre de cycles internes). La pile doit être toujours alignée
sur une frontière de double mot (donc se terminer par 4 bits à zéro).
Tous les sources se trouvent ici : https://github.com/vincentARM/ARMassembly64
dans le projet64_001.
dans le projet64_001.
Aucun commentaire:
Enregistrer un commentaire