mardi 17 décembre 2019

Chapitre 76 : assembleur ARM 64 bits : utilisation de X11


Je n’ai pas encore trouvé de solution pour la résolution de l’absence de /dev/mem dans le container 64 bits. De plus je n’ai pas réussi à installer le périphérique pour lire les compteurs relatifs à la mesure de performance. En effet il faut créer un module kernel en utilisant un package contenant les headers linux et il n’existe pas pour la version 64 bits !!. 

Donc nous allons voir l’utilisation de X11 pour générer des fenêtres graphiques. Pour cela nous reprenons la démarche utilisée pour le 32 bits : installation sur le raspberry du package X11   , installation d’un serveur X11 sur le PC (par exemple Xming), création d’une connexion au raspberry avec le top X11 dans putty. Pour plus de précisions je vous renvoie au chapitre 30 de ce blog.
J’effectue un premier test en 32 bits avec un des programmes anciens pour vérifier si la fenêtre s’affiche bien sur le PC : ok pas de problème.
Je reprends le programme de création d’une simple fenêtre creafen641.s. Il faut déjà recalculer les positions des données dans les structures car les définitions des zones doivent avoir une longueur de 8 octets. Enfin pas toutes !! Il faut donc reprendre chaque structure, passer tous les pointeurs et les entiers longs en 8 octets et laisser les entiers en 4 octets. Mais il y a des réalignements à faire s’il y a un nombre d’entiers impairs, il faut ajouter une zone de 4 octets pour que la zone pointeur suivante soit toujours bien alignée.
En conclusion, les structures du fichier defstruct64.inc sont toutes à revoir de très prés avant toute utilisation sérieuse.

Ensuite le passage des paramètres à la fonction XCreateSimpleWindow doit être revu. Nous pouvons passer les 8 premiers paramètres dans les registres x0 à x7 et le dernier est à passer par la pile. Celle çi doit toujours être alignée, c’est la raison de l’instruction str x8,[sp,-16]! Avant l’appel et de l’instruction add sp,sp,16 après l’appel.
Après modification du script de compil pour intégrer les librairies X11, exécution de la compilation et correction des erreurs !! lancement du programme.
Et bing erreur : PuTTY X11 proxy: Unsupported authorisation protocol
Longues recherches sur internet pour trouver l’origine de l’erreur, sans succès mais une piste apparait en explorant les logs : une ligne indique que le port 22 est déjà utilisé par un autre service !! Et en effet à la réflexion j’ai déjà une connexion entre Raspberry et Putty en 32 bits !! Donc il faut modifier le fichier /etc/ssh/sshd_config dans le container 64 bits  pour mettre un autre port par exemple 3222 au lieu de 22. Et cela fonctionne !

Maintenant, nous allons passer à un programme plus complet. En 32 bits, j’avais écrit au chapitre 62 un programme qui affichait des images jpeg et donc suivant le même principe je décide d’écrire un afficheur 64 bits des images png !! source du programme afficheurPNG.s
Pour cela il faut charger les packages X11 (X11-common,X11-apps etc.) et le package libpng-dev qui permet d’avoir accès à la librairie libpng dont on va se servir pour convertir les images PNG. En effet comme pour le jpeg, il n’est pas question de réécrire toutes les fonctions nécessaires en assembleur.

La documentation de la libpng peut se trouver ici :

Dans un premier temps, je repars du programme d’affichage jpeg 32 bits que je transforme en 64 bits à l’aide des consignes du chapitre précédent. J’effectue aussi les modifications des appels des fonctions X11 et je crée la même image des 3 cercles colorés utilisée pour jpeg au format png avec myPaint.
A l’aide de la documentation de la librairie, j’écris la partie de chargement de l’image jpeg, ouverture du fichier, lecture des 8 premiers octets pour vérifier la signature du fichier ( la fonction à appeler est différente de celle de la doc car il y a un paramètre supplémentaire qui est masqué par la redéfinition de la fonction dans png.h). Ensuite création des structures nécessaires, puis liaison entre ces structures et le FD du fichier à lire, puis lecture des données.
Ensuite le décodage de l’image est un peu plus complexe car il faut créer une table de pointeurs qui pointe chaque début de ligne de l’image en mémoire. Un exemple m’indique que l’image png est inversée, donc les pointeurs doivent être initialisés en ordre inverse (mais mes tests montrent que cela n’est pas exact ou alors j’ai fait une erreur lors des affichages X11).
Puis j’adapte le programme pour prendre l’image convertie en mémoire et l’afficher dans une fenêtre X11.
Après quelques tests et corrections des erreurs, je tombe sur l’erreur classique dans la fonction de lecture png_read_image que je n’arrive pas à résoudre. Quelques jours après, je me rappelle que le mélange des fonctions d’ouverture de fichier en assembleur ne fait pas bon ménage avec les fonctions de lecture du C utilisées par les librairies. Je récris donc les ouvertures/ fermetures pour appeler les fonctions du C et le programme fonctionne correctement.
Enfin presque, car les couleurs de l’image sont inversées dont j’ajoute une fonction d’inversion pour chaque pixel de l’image.

En lisant la documentation, je découvre qu’il est possible de convertir des images png à partir d’un buffer en mémoire.
Dans le deuxième programme afficheurPNG2.s, je remets l’ouverture et la lecture du fichier par des appels system en assembleur et je passe l’adresse du buffer à la fonction de décodage. Il faut la modifier pour prendre en compte la lecture depuis le buffer en créant une sous fonction de recopie png_read_from_memPNG. J’en profite pour modifier les zones réceptrices (pointeurs et pixels images) en allouant leurs places nécessaires sur le tas.
La lecture et le décodage se passe bien mais l’affichage de l’image entraine une erreur X11. Si je remets la zone des pixels de l’image en mémoire et pas sur le tas, l’affichage se passe bien !! L’allocation de la table des pointeurs elle ne génère pas d’erreurs.
Donc quelques jours après (la réflexion est lente !!) il me vient que le mélange de l’allocation de place entre ma fonction allocPlace et les fonctions de la libraire pour créer les structures doivent être incompatibles surtout que dans l’enchainement je libère la place des structures par png_destroy_read_struct avant d’afficher l’image X11.
Donc je déporte l’allocation de place de la zone des pixels de l’image dans la fonction de lecture du fichier car nous pouvons trouver au début du buffer lu les dimensions en pixel de l’image puis je passe l’adresse de la zone crée à la fonction de conversion par l’intermédiaire du registre x23 : c’est pas terrible comme programmation !! c’est à améliorer mais pour les tests, cela fonctionne bien : voir le programme afficheurPNG3.s
Que reste-il à faire ?  améliorer la programmation entre les différentes fonctions !! regarder d’un peu plus prés certaines fonctions annexes de conversion d’images png particulières (niveau de gris) et vérifier le bon fonctionnement de plusieurs lectures successives d’images différentes.
Il faudrait aussi vérifier la libération de la place du buffer de lecture, des zones des pointeurs et des pixels dans le cas ou il faudrait charger un grand nombre d’images. Çà me fait penser que j’avais écrit un programme de jeu qui se passait dans un labyrinthe et où les murs et le personnage étaient plus que succincts. Il faudrait que je le réécrive en utilisant des textures et des images png : du boulot pour l’année 2020 !!!

Aucun commentaire:

Enregistrer un commentaire