Flux rss
Offres pro des FAI
Collection CommentCaMarche.net

Exercice assembleur x86 inversion de chaîne

Publié par kilian, dernière mise à jour le vendredi 17 octobre 2008 à 23:13:41 par fleursdespyrenees



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

  • Les fonctions avec paramètre d'entrée
  • Les sauts (jmp, jz/je etc...)
  • La pile (et surtout la pile à vrai dire :-)
  • Les chaînes de caractères

Énoncé


Le but est d'écrire une fonction en assembleur capable d'inverser une chaîne de caractères.
Cette fonction devra prendre en paramètre d'entrée un pointeur vers une chaîne de caractères et inverser cette chaîne sur le même pointeur.

Voici ce que donnerait cette fonction en C:
void inverse_chaine(char *str); //Le prototype de cette fonction
//Exemple d'utilisation:
char string[] = "Je suis une chaîne a inverser";
inverse_chaine(string);
printf(string); //Affichera "resrevni a eniahc enu sius eJ"


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

section .data
	chaine db 'Inverse moi! Je te dirais quel programmeur tu es!', 0x0

section .text
	global main, inverse_chaine

inverse_chaine:
		;Mettez votre code ici


main:
		mov eax, chaine ;Adresse de chaîne dans eax
		push eax
                ;Appel de inverse_chaine avec l'adresse de la chaîne à inverser
		call inverse_chaine 
                ;Les deux lignes suivantes sont optionnelles car l'adresse 
                de la chaîne (maintenant inversée) est toujours dans la pile. 
                mov eax, chaine ;Adresse de chaîne dans eax
		push eax
                ;Affichage de la chaîne avec printf
		call printf
		add esp, 4 ;On sort de la fonction main
		mov eax, 0

Essayez de résoudre cet exercice par vous-même dès maintenant sans regarder les sections suivantes. Plus on réfléchit par soi-même, plus on évolue. Si vous avez du mal, regardez la section qui suit (Indices) puis réessayez.
Bonne chance! C'est en forgeant que l'on devient forgeron ;-)

Rappel

  • Un caractère ascii standard est codé sur un octet. Une chaîne de caractères est donc une suite de caractères de 1 octet et non pas 4 comme les entiers.
  • Une chaîne se termine par le caractère 0 (la valeur 0 et non pas le caractère '0').
  • Vous ne pouvez empiler que des éléments de 2 ou 4 octets dans la pile (à moins qu'il s'agisse de constante d'un octet).

Indices


Vous n'avez pas une idée? Allez, un petit indice pour vous faire démarrer : vous savez probablement que la pile est une mémoire dont l'accès est de type Last In First Out. Ce qui signifie que si vous poussez dans la pile trois lettres les unes après les autres comme a puis b puis c, vous les récupèrerez dans l'ordre inverse: c puis b puis a.

Corrigé


J'espère que vous avez réussi à faire quelque chose, même si vous pensez ne pas avoir utilisé la bonne manière, ce n'est pas grave, c'est comme ça qu'on apprend.

Voici une solution:
inverse_chaine:
                ;Prologue de la fonction
		push ebp
		mov ebp, esp
	
                ;On charge le pointeur passé en paramètre dans eax
		mov eax, [ebp+8]
                ;On push le caractère de fin de chaîne dans la pile
		push word 0

	chaine_dans_pile:
                ;On va empiler chaque caractère de la chaîne

                ;Récupération caractère courant
		mov bl, byte [eax]
                ;Est-ce la fin de chaîne? (bl = 0 ?)
		test bl, bl
                ;Si oui on passe à l'étape suivante
		jz fin_chaine_dans_pile
                ;Sinon on empile le caractère suivant
		push bx
                ;On incrémente le pointeur de 1 pour traiter le caractère suivant
		inc eax
                ;On passe au caractère suivant
		jmp chaine_dans_pile

	fin_chaine_dans_pile:
                ;On recharge le pointeur de la chaîne pour dépiler un à un chaque caractère
		mov eax, [ebp + 8]

	inversion:
                ;On dépile le caractère courant
		pop bx
                ;On le charge dans le pointeur de chaîne
		mov byte [eax], bl
                ;On incrémente l'adresse
		inc eax
                ;C'était la fin de la chaîne? (le 0 qu'on a empilé au début?)
		test bl, bl
                ;Non alors on continue
		jnz inversion
                ;C'est la fin de la chaîne, on marque la conclusion de la fonction
		leave
		ret

Explication


Comme suggéré dans la section "indices", l'idéal est d'utiliser la pile. On empile chaque caractère de la chaîne. Lorsqu'ils seront dépilés, on les récupèrera dans l'ordre inverse.
Voici donc ce qui se passe: on empile d'abord 0 qui sera donc dépilé plus tard, en dernier, pour marquer la fin de chaîne.
Ensuite, on empile un à un chaque caractère de la chaîne en passant par bl (les 8 caractères de poids faibles de ebx) qui est suffisant pour un caractère. Lorsqu'on empile, on prend bx (16 bits de poids faible de ebx) qui contient lui-même bl car on est obligé d'empiler au moins 2 octets.
Durant ces empilements successifs, on fera bien attention de ne pas empiler le caractère de fin.

A l'étape suivante, on recharge le pointeur à l'adresse du début de la chaîne. Puis, on dépile successivement chaque caractère dans la chaîne en écrasant les anciennes valeurs. Lorsqu'on a dépilé le 0 de fin de chaîne, on l'insère également dans la chaîne puis on arrête. Et le tour est joué.
Liens utiles assembleur x86 Voici quelques liens utiles pour l'assembleur x86. Le but étant de compiler des documents pertinents autant pour ceux qui débutent que pour ceux qui sont à l'aise dans ce domaine. Tutoriels Références complètes Assembleur sous... www.commentcamarche.net/faq/sujet-9899-liens-utiles-assembleur-x86
Exercice assembleur x86 occurence d'un caractère 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,... www.commentcamarche.net/faq/sujet-10330-exercice-assembleur-x86-occurence-d-un-caractere
8600 GT 512 mo, asus ou XFX ? (Résolu) Bonjour, Je vais bientôt changé de carte graphique et j'en ai repéré 2 qui me semble équivalentes. J'aurai voulu avoir des avis sur ces 2 cartes ; ASUS 8600 GT 512 mo http://www.topachat.com/... ou XFX 8600 GT 512mo... www.commentcamarche.net/forum/affich-5904012-8600-gt-512-mo-asus-ou-xfx
Exercice assembleur x86 nombre premierIntroduction Notions abordées dans cet exercice Enoncé Rappel 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... www.commentcamarche.net/faq/sujet-9863-exercice-assembleur-x86-nombre-premier
[Logiciels] Rassembler un fichier XTMUn fichier XTM est un fichier coupé en morceaux avec le logiciel XtremSplit, téléchargeable à l'adresse suivante : Télécharger Xtremsplit www.commentcamarche.net/faq/sujet-3794-logiciels-rassembler-un-fichier-xtm
[Systèmes d'exploitation] Programmation d'un Noyau / OSProgrammer son propre noyau Introduction I. Prérequis II. Ressources en français II.1 PoorOS II.2 Pépin (ex BosoKernel) II.3 SimpleOs II.4 Autres liens III. Ressources en anglais III.1 Liens/documentations divers III.2 Minix III.3... www.commentcamarche.net/faq/sujet-4680-systemes-d-exploitation-programmation-d-un-noyau-os
8600GT au dessus de 100 degrés celsius (Résolu)Bonjour, j'ai une carte graphique NVIDIA XFX 8600GT avec 256 MB, et en jouant à World of Warcraft, sa température a monté au dessus de 100 degrés celsius tantôt... il fait très chaud en ce moment, mais je doute que 100 degrés soit une température... www.commentcamarche.net/forum/affich-7292918-8600gt-au-dessus-de-100-degres-celsius
[VS C++ .Net] Liste chaînée (linked list) (Résolu)bonjour, dans un exercice je dois creer une liste chainée d'une classe (acteurs) les classes que j'ai créé sont les suivantes : liste - element - acteurs - listacteurs mon probleme est que je bloque au niveau de la classe listacteurs.... www.commentcamarche.net/forum/affich-1497421-vs-c-net-liste-chainee-linked-list
Besoin d'aide sur les chaine de caractere (Résolu)Bonjours; Voila je debute en programmation C++ et j'aurai besoin d'un petit coup de main J'utilise Dev C++ j'ai trouvé un exercice sur le web sur les chaine de caractere qui m'a l'aire d'etre assez complet pour les... www.commentcamarche.net/forum/affich-2540863-besoin-d-aide-sur-les-chaine-de-caractere
Télécharger ZSNES Si vous avez toujours voulu d'un émulateur pour Super Nintendo, celui ci vous plaira sûrement ! ZSNES est un émulateur open source de super Nintendo. Il a été écrit avec l'assemblage x86, C et C++. Pour le plus grand bonheur de ceux qui utilisent... www.commentcamarche.net/telecharger/telecharger-34055750-zsnes
Télécharger Linux Display Driver - x86Linux Display Driver - x86 est un driver pour les cartes graphiques Geforce de la version 8 : 8800 Ultra, 8800 GTX, 8800 GTS, 8600 GTS, 8600GT, 8600 GS, 8500 GT, 8400 GS, 8400 SE, 8300 GS, Quadro FX 1600M, Quadro FX 570M, Quadro NVS 320M. Il présente... www.commentcamarche.net/telecharger/telecharger-34056857-linux-display-driver-x86
Télécharger NasmNasm est un logiciel assembleur libre et disponible sur plusieurs systèmes comme Linux ou Windows. Toutefois il ne fonctionne que sur les architectures x86. Il demande une syntaxe légère et compte donc parmi le choix de nombreux programmeurs. www.commentcamarche.net/telecharger/telecharger-34055381-nasm
Epson Perfection 3490 PhotoUSB 2.0, Divers:1 year Replacement or Repair, Optional Extension to 3 years warranty, Dimensions (w x d x h): 275 x 419 x 86mm, PRINT Image Matching™ II, dust removal, colour restoration, optimised auto exposure, unsharp mask with noise reduction, de... www.commentcamarche.net/guide-achat/epson-perfection-3490-photo-390877-fiche-technique
Epson Perfection 3590 PhotoUSB 2.0, Divers:1 year Replacement or Repair, Optional Extension to 3 years Warranty, Dimensions (w x d x h): 275 x 419 x 86mm, PRINT Image Matching™ II, dust removal, colour restoration, optimised auto exposure, unsharp mask with noise reduction, de... www.commentcamarche.net/guide-achat/epson-perfection-3590-photo-390876-fiche-technique
SMC TigerSwitch 1000 Standalone L3 12 SFP port Managed Switch with 4 fixed gigabit copper uplinks (SL 3 8612 XL 8612XL 8612XL, Type:Switch, Administrable, Divers:5 years warranty, Indicateurs de statut:Link activity, power LED's, Modes de communication:Full-Duplex, Nb. de ports RJ-45 10/100 Mbps: , Nb. de ports RJ-45 10/100/1000Mbps:4 RJ-45, Nombre de.. www.commentcamarche.net/guide-achat/smc-tigerswitch-1000-standalone-l3-12-sfp-port-managed-switch-with-4-fixed-gigabit-copper-uplinks-smc8612xl3-533504-fiche-technique
Liste des instructions en assembleurTableau des principales instructions en assembleur Voici une liste (non exhaustive) des principales instructions en assembleur des processeurs 80x86, ainsi que du code machine qui leur est associé et de leur taille en mémoire. Les valeurs val et... www.commentcamarche.net/contents/asm/liste.php3
Instructions arithmétiques et logiques en assembleurLes instructions arithmétiques et logiques sont effectuées par l'unité arithmétique et logique. Il s'agit d'opérations directement effectuées sur les bits de la donnée que l'on traite. Sont comprises dans cette appellation : les instructions... www.commentcamarche.net/contents/asm/logique.php3