Exercice assembleur x86 occurence d'un caractère

Septembre 2016


Notions abordées dans cet exercice

  • Ecriture d'une fonction avec gestion des paramètres d'entrée
  • Gestion des tableaux

Enoncé

Imaginons un tableau de caractères (qui ne se termine pas nécessairement par 0). On possède sa taille et on voudrait pouvoir tester la présence d'un caractère donné dans ce tableau. Le but va donc être d'écrire une fonction qui prend en entrée un tableau de caractères, sa taille et un caractère. Si ce caractère est présent dans le tableau, on retourne une valeur différente de zero, sinon on retourne zero.

Voici ce que donnerait cette fonction en C:
//Le prototype de cette fonction
int est_dans_tableau(char *tableau, int taille, char c);
//Exemple d'utilisation:
char tab[] = {'n', 'e', 'u', 'e'};
est_dans_tableau(tab, sizeof(tab), 'u'); //Retournera autre chose que 0
est_dans_tableau(tab, sizeof(tab), 'a'); //Retournera 0


Il vous faudra insérer ce code là dedans:
extern printf

section .data
tableau db 'dadedidadedavivoufufifamasibifisaz'
oui db 'oui', 10, 0
non db 'non', 10, 0

section .text
global main

est_dans_tableau:
;Insérez votre code ici!!


main:
push ebp
mov ebp, esp

;On va tester si m est présent dans le tableau
push dword 'm'
;La longueur du tableau (ici 34)
push dword 34
;Adresse de chaine dans eax
push tableau

;Appel de est_dans_tableau avec l'adresse du tableau,
;sa taille, et la valeur à chercher
call est_dans_tableau
test eax, eax
jnz est_dedans ;Si eax != 0 alors on affiche oui
push non ;Sinon on affichera non
jmp affichage
;Affichage de la chaine avec printf
est_dedans:
push oui
affichage:
call printf

mov eax, 0
leave
ret


C'est parti! Reflechissez un peu quelques dizaines de minutes s'il le faut. Faites une recherche sur les instructions en rapport avec les chaines. Pas d'indice pour cet exercice :-)

Corrigé

Voici une solution:
est_dans_tableau:
;On récupère l'adresse du tableau (premier paramètre) dans edi
mov edi, [esp + 4]
;On récupère la taille du tableau (second paramètre) dans ecx
mov ecx, [esp + 8]
;On récupère le caractère à trouver (troisième paramètre) dans eax
mov eax, [esp + 12]

;Recherche du caractère
repne scasb
;Si le flag ZERO (ZF) est à 1 c'est qu'on a trouvé le caractère
;Sinon c'est qu'on ne l'a pas trouvé
;Il nous suffit donc de mettre la valeur de ZF dans eax
mov eax, 0
;Si ZF = 1 alors al = 1 (al étant les 8 bits de poid faible d'eax)
setz al

ret

Explication

Le but était de vous faire utiliser la combinaison des instructions de type "rep" et "scas". Ici nous utilisons "repne". Cette instruction répète l'instruction qui la suit en faisant décrémenter ecx à chaque itération. Cette boucle s'arrête lorsque ecx = 0 ou lorsque le Flag Zero (ZF) est à 1. L'instruction scasb, quant à elle, recherche la présence d'un caractère (logé dans al, partie basse de eax) dans l'emplacement mémoire pointé par edi. Si al est égal à la valeur pointée par edi, alors le Flag Zero est mis à 1. Ensuite, dans tous les cas, edi est incrémenté de 1.
Voici donc ce qui se passe, vu que ce qui vient d'être expliqué ne doit pas être très parlant, avouons le :-)
ZF = 0
ecx = longueur
eax = caractère
edi = tableau
//Boucle qui représente le "repne scasb"
Tant que ecx != 0 ET ZF = 0 Faire
Si al == [edi] Alors
ZF = 1
FinSi
ecx = ecx - 1
edi = edi + 1
FinTantQue

eax = 0
//Condition qui représente le "setz"
Si ZF = 1 Alors
eax = 1
FinSi


Et voilà :-)

A voir également :

Ce document intitulé «  Exercice assembleur x86 occurence d'un caractère  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.