LdB Seance 7

De Ensiwiki
Aller à : navigation, rechercher
AttentionCette page est maintenue uniquement par les enseignants. Afin de ne pas perturber le déroulement des cours, elle n'a pas vocation à être modifiée par les élèves. Mais si vous avez des modifications à proposer, merci d'en discuter ou d'envoyer un e-mail aux auteurs de la page (cf. historique)

Laptop.png  Première Année  CDROM.png  Informatique 

Introduction

Le but de cette séance est de travailler sur différents modes d'adressage du Pentium. On n'utilisera pas ici tous les modes fournis par le processeur, mais la plupart peuvent facilement être dérivés les uns des autres.

Attention : dans tout l'exercice, vous n'avez le droit d'utiliser que les registres %eax, %ecx et %edx. On comprendra pourquoi lors de la prochaine séance de TD. TODO : en fait c'est inutile car on ne revient jamais à crt0.

Vous pouvez récupérer les sources fournies dans cette archive Zip.

Vous compilerez les programmes grace à la commande : gcc -o BINAIRE -m32 -g -gstabs SOURCE.

Manipulation de chaînes de caractères

Dans ce premier exercice, on va écrire des petits programmes de manipulation de chaînes de caractères.

Ouvrez le fichier chaines.S qui contient le squelette du programme à compléter dans cet exercice.

Dans ce squelette, on commence par stocker l’adresse de la chaine dans le registre %edx : dans tout l’exercice, on se servira toujours de ce registre comme adresse de base.

Calcul de la longueur de la chaine

Dans cette question, on utilisera un deuxième registre (par exemple %ecx) pour calculer le déplacement par rapport à la base (dans %edx). Le mode d’adressage utilisé sera donc le mode indirect avec index : par exemple, movl %eax, (%edx, %ecx).

Compléter le squelette fourni pour calculer dans un registre la taille de la chaine. On rappelle qu’une chaine de caractères est terminée par le caractère ’\0’ (c’est à dire l’octet zéro) et qu’on ne compte pas ce caractère de fin dans la taille de la chaine. Attention, les caractères sont codés sur 8 bits : on ne manipule pas ici des entiers.

En C, le code demandé s’écrirait par exemple :

unsigned taille;
for (taille = 0; chaine[taille] != 0; taille++);

Tester ce programme avec gdb sur les chaines "azerty", "aze", "a" et "". On rappelle qu'on peut facilement suivre la valeur d'un registre sous gdb avec la commande display $ecx (pour voir %ecx par exemple).

Inversion de chaine

Dans cette question, en plus d'utiliser un registre d'index, on pourra modifier la base dans %edx. Le mode d’adressage utilisé sera donc le mode indirect avec ou sans index : par exemple, movl %eax, (%edx, %ecx) ou movb (%edx), %al.

Ajouter au squelette fourni le code permettant d’inverser la chaine de caractère (e.g. "azerty" donne "ytreza"). On utilisera la taille de la chaine calculée précédemment pour écrire ce code. Le code C correspondant pourrait être par exemple :

int dep = taille - 1;
char *ptr = chaine;
while (dep > 0) {
    char tmp = *ptr;
    *ptr = ptr[dep];
    ptr[dep] = tmp;
    dep = dep - 2;
    ptr++;
}

On pourra se servir de l’instruction xchg src, dst qui échange les valeurs de src et dst : attention, src et dst ne peuvent pas être tous les deux des valeurs en mémoire.

Déboguer le programme en utilisant gdb et en affichant la chaine résultat à la fin, sur les chaines "azerty", "aze", "a" et "". On rappelle que si par exemple %al contient un caractère, on peut facilement afficher son contenu grâce à la commande display /c $eax. Pour afficher la chaine au fur et a mesure de son inversion, le plus simple est d'utiliser la commande x /7c (char[])chaine (si la chaine contient 7 caractères).

Manipulation de tableaux d'entiers

On va maintenant travailler sur des tableaux d’entiers strictement positifs.

Ouvrez le fichier tableaux.S qui contient le squelette de départ qu'on va compléter dans cet exercice.

Recherche du maximum

Écrire le code assembleur cherchant dans un registre l’entier maximum du tableau tab. On note que le tableau ne contient que des entiers strictement positifs et qu’il est terminé par l’entier 0.

Le code C correspondant pourrait être :

unsigned max, i;
for (max = i = 0; tab[i] != 0; i++) {
    if (tab[i] > tab[max]) {
        max = i;
    }
}

On n’utilisera dans cette question que l’adressage indirect avec index typé et déplacement : par exemple, movl %eax, tab(, %edx, 4). On demande d’écrire le code de façon naïve, en accédant autant de fois que nécessaire à la case courante du tableau. Tester le code avec gdb, et vérifier aussi qu’il fonctionne avec un tableau vide et un tableau contenant un seul élément.

On peut afficher si besoin le contenu du tableau grace a la commande x /11uw (unsigned [])tab où 11 est le nombre de mots (unsigned word) à afficher.