RDV+DIAL chat illimit� dans ta r�g!
no save
Assistance
Achat
News

FAQ | x86

Exercice assembleur x86 occurence d'un caractère
Publié par kilian, dernière mise à jour lun. 16 nov. 2009 à 13:14:08 par marlalapocket



Introduction
Notions abordées dans cet exercice
Enoncé
Corrigé
Explication


Introduction
Ce petit exercice d'assembleur vise les architectures x86 (Processeurs Intel et Amd 32 bits) et utilise la syntaxe de Nasm, un assembleur libre, gratuit et utilisable sur différentes plateformes telles que Windows ou Linux.
De même les fonctions externes utilisées sont issues de la bibliothèque C standard.

Ainsi vous n'aurez pas de problèmes liés à votre machine pour faire cet exercice: il n'est pas dépendant du système d'exploitation utilisé. Il est uniquement dépendant de l'architecture x86.

NOTE: Pour utiliser nasm afin de tester cet exercice, vous trouverez un tutoriel d'utilisation/installation de nasm pour Windows et Linux en cliquant ici.
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à :-)
Version Web
Réalisé par RedShift
no save