Dans cet article, nous allons voir plusieurs routines très
utiles pour traiter les chaines de caractères (string). Une chaine de caractères
est toujours stockée en mémoire et est accessible par son adresse de début
contenu dans un pointeur ou un registre. Il existe plusieurs manières de gérer une chaine soit par exemple comme le C
en terminant celle çi par un zéro binaire soit en mettant dans le premier octet
(ou le demi mot ou le mot) sa longueur.
Ici nous utiliserons la définition comme le C cad avec un
zéro final. Nous avons vu qu’une chaine se définissait en mémoire par la
directive .asciz (ou aussi .string)qui mettra le zéro binaire automatiquement à
la fin de la chaine. Pour des suites de caractères sans 0 final, il faut
utiliser la directive .ascii.
Ces routines peuvent être utiliser tel quel mais elles
serviront surtout de base pour écrire des fonctions plus intégrables ou répondant
à d’autres besoins spécifiques. Par exemple le calcul de la longueur peut être
fait directement dans le code soit avoir à appeler la routine ( pour alléger le
nombre d’instructions et réduire le temps d’exécution).
La première fonction permet de vérifier et de corriger une
chaine de caractère si celle ci n’est pas correcte. Elle force un zéro binaire
à la rencontre du premier caractère non alphanumérique au sens strict. En
effet, sur mon système les programmes sont encodés avec l’option uft8 et donc
les caractères accentués ne sont pas considérés comme des caractères ascii mais
sont codées sur 2 caractères (ou plus pour des alphabets exotiques). Donc
suivant les cas, il faudra adapter cette fonction pour gérer vos besoins. Elle
peut être utile pour la lecture des lignes d’un fichier car chaque ligne ne se
termine pas par un 0 binaire mais par les caractères 0x0D0A.
La deuxième fonction permet de calculer la longueur d’une
chaine. Il s’agit d’une boucle simple qui compte le nombre de caractères
jusqu’à trouver le zéro final.
Ensuite nous trouvons les fonctions de copie d’une chaine
entière et de copie de n caractères d’une chaine
Puis 2 fonctions de concaténation de chaines, la première oblige la fourniture par le code
appelant de la zone de réception . La seconde utilise le tas (heap) Linux
pour réserver la zone de réception et retourne son adresse au code appelant.
De même 2 fonctions de comparaison de chaine, la première
qui tient compte de la casse (majucules-minuscules) et l’autre qui n’en tient
pas compte.
Puis 2 fonctions de recherche, une pour chercher un seul
caractère et l’autre pour chercher une sous-chaine à l’intérieur d’une chaine.
Ces fonctions s’arrêtent au premier caractère ou sous chaine trouvé et sont
donc à adapter pour rechercher d’autres occurrences.
Enfin une fonction d’insertion d’une sous chaine dans une
autre puis une fonction de tri. Pour cela toutes les chaines qui ont servies
dans les tests précédents sont identifiées par un pointeur stocké dans une
table. Cette table permet l’affichage des chaines puis leur tri et enfin un
affichage après le tri pour vérification. Dans notre exemple nous appelons la
fonction de comparaisonsanscasse mais vous pouvez la remplacer par l’autre
fonction de comparaison. Le tri utilisé est un tri shell dans lequel seuls les
pointeurs des chaines sont déplacés. Ainsi les chaines quelle que soit leur
longueur ne sont pas déplacées ce qui permet au tri d’être efficace. Attention,
ce tri utilise une gestion des incréments simplifiée ce qui peut entrainer pour
des grosses quantités de chaine une dégénérescence du tri (pour plus de
détails, voir la théorie et les multiples analyses du tri shell).
Pour terminer, une fonction permet d’éclater une chaine en
plusieurs sous chaines en fonction d’un séparateur. La fonction retourne
l’adresse d’une table qui contient dans le premier poste, le nombre de zones
extraites puis ensuite dans chaque poste l’adresse de la sous-chaine. Dans ce
programme, nous découpons la chaine avec un séparateur espace. Nous affichons
le résultat dans une boucle qui balaye la table fournie en retour de la
fonction.
La table des zones est aussi stockée sur le tas grâce
à l’appel system linux Brk.Exercice : écrire une fonction qui inverse une chaine
améliorer la recherche d'un caractère pour trouver le 2ième, 3iéme etc.
Le fichier routchaines.s a été mis à jour le 6/10/2018 pour corriger 2 erreurs. Dans une des routines, le registre r3 n'était pas sauvegardé car j'utilisais l'instruction push {r2,r4] à la place de push {r2-r4}.
RépondreSupprimerLa deuxième correction concerne la réservation de place sur le tas : en effet une chaine peut avoir une longueur quelconque et la réservation de sa place pouvait entrainer un non alignement des données suivantes sur le tas.