Université de Bordeaux U.F. Informatique Licence Informatique 2ème année Année 2016 -- 2017 ARCHITECTURE DES ORDINATEURS Devoir Surveillé 1 1 heure 20 minutes sans documents * QUESTION 1 [5 points] ============ * Question 1.1 [1 point] Ceux qui sont négatifs sont ceux dont le bit de poids le plus fort (bit de signe) est à 1, c'est-à-dire dont le premier demi-octet est compris entre 8 et F. Les nombres négatifs sont donc : N = F00D, P = DADA et R = 8080, qui répondent à ces critères. * Question 1.2 [1 point] Le plus petit nombre négatif est 8000 (en tant que nombre signé), le plus grand nombre négatif est FFFF, le plus petit nombre positif est 0000, et le plus grand nombre positif est 7FFF. On a donc : 8000 < FFFF < 0000 < 7FFF. On a donc : R = 8080 < P = DADA < N = F00D < M = 1418 < Q = 3945, soit : R < P < N < M < Q. * Question 1.3 [1 point] P = 1101 1010 1101 1010 + Q = 0011 1001 0100 0101 = 1 0001 0100 0001 1111 = 1 4 1 F On a une retenue ("carry"), mais on n'a pas débordement ("overflow"), car le résultat n'est pas sorti du domaine représentable en machine. En effet, en ajoutant un nombre négatif à un nombre positif, on ne peut pas déborder. On pourrait avoir débordement en ajoutant deux nombres négatifs (cela donnerait un nombre négatif trop petit en valeur signée, qui apparaîtrait comme un nombre positif), ou en ajoutant deux nombres positifs (cela donnerait un nombre positif trop grand en valeur signée, qui apparaîtrait comme un nombre négatif). * Question 1.4 [2 points] N = 1111 0000 0000 1101 Le complément à deux de N est : /N = 0000 1111 1111 0010 +1 = 0000 1111 1111 0011 donc : -N = 0 F F 3 qui est un nombre positif. M-N = M+(-N) M = 0001 0100 0001 1000 +-N = 0000 1111 1111 0011 = 0 0010 0100 0000 1011 = 2 4 0 B Il n'y a pas débordement ("overflow") parce que l'ajout de ces deux nombres positifs n'a pas conduit à faire apparaître un 1 dans le bit de poids le plus fort, qui aurait conduit à avoir un nombre négatif. * QUESTION 2 [5 points] ============ * Question 2.1 [1 point] 00 = 0 (tous les bits à zéro) 01 = 1 (nombre positif, immédiatement supérieur à 00) 11 = -1 (nombre négatif, complément à deux de 01) 10 = -2 (nombre négatif, inférieur à 11) * Question 2.2 [2 points] On rappelle le câblage de l'addition entre deux valeurs binaires a et b, donnant la somme s et la retenue c : s = a XOR b c = a AND b Pour faire le complément à deux, on doit inverser les valeurs binaires de X et ensuite ajouter 1 au bit de poids faible, puis ajouter la retenue obtenue au bit de poids fort. On commence par inverser : x0' = NOT (x0) x1' = NOT (x1) Puis on calcule la somme entre le bit de poids faible et 1 : n0 = (x0' XOR 1) = (NOT (x0) XOR 1) = NOT (NOT (x0)) = x0, car faire un "XOR 1" revient à faire un NOT et les deux NOT s'annulent. La retenue propagée est pour sa part : c = x0' AND 1 = x0' = NOT (x0) On a donc n1 = (x1' XOR c) = (NOT (x1) XOR NOT (x0)) = (x1 XOR x0) par simplification. Au final : n0 = x0 n1 = x1 XOR x0 On peut le vérifier : 0 = 00 -> 00 = 0 1 = 01 -> 11 = -1 -2 = 10 -> 10 = -2 ("overflow") -1 = 11 -> 01 = 1 * Question 2.3 [2 points] On veut une fonction qui renvoie : 0 = 00 -> 00 = 0 1 = 01 -> 01 = 1 -1 = 11 -> 01 = 1 -2 = 10 -> ?? Le dernier cas est non représentable, donc on peut signaler l'erreur par une valeur négative, qui peut être "-1" ou "-2". On peut utiliser un multiplexeur 4x1 pour chaque bit, en câblant les bonnes valeurs de sortie pour chaque valeur d'entrée. On peut aussi câbler un circuit simple, en se rendant compte de la régularité des valeurs. En particulier, si on code le résultat "??" par "10", alors on a simplement : a0 = x0 a1 = x1 AND (NOT (x0)) : valeur à 1 dans la configuration "10" * QUESTION 3 [10 points] ============ * Question 3.1 [2 points] En prenant les paramètres dans l'ordre inverse de leur empilage, à partir du "call mystere" (adresses 0x006 à 0x015), on a : - l'adresse de t, qui semble être le début d'un tableau ; - l'adresse de m, qui semble être une valeur isolée. * Question 3.2 [1 point] Cette instruction, en incrémentant le pointeur de pile d'autant d'octets que la taille totale des paramètres qui ont été empilés, permet de remettre la pile dans son état initial d'avant l'appel, sans avoir à dépiler les valeurs une par une. * Question 3.3 [1 point] "irmovl 0,%eax", qui place la valeur 0 dans le registre %eax, et prend 6 octets, effectue la même action que l'instruction "xorl %eax,%eax", qui s'écrit de façon plus compacte en mémoire, car elle ne prend que 2 octets. * Question 3.4 [4 points] La fonction "mystere" calcule a somme des valeurs positives d'un tableau dont le dernier élément est 0, et place cette somme à une adresse passée en paramètre. Elle renvoie le nombre de cellules du tableau parcourues. Utilisation des registres : - %esi : pointeur sur la cellule courante du tableau, initialisé à partir de l'adresse passée en paramètre ; - %eax : nombre d'éléments du tableau parcourus avant le retour de la fonction ; - %edx : somme cumulée des éléments strictement positifs du tableau, initialisée à 0 au début de la fonction ; - %ecx : valeur courante de la cellule du tableau, lue à partie du pointeur %esi ; Utilisation des étiquettes : - et1 : début du corps de boucle ; - et2 : destination permettant de sauter l'accumulation dans la somme, lorsque la valeur de la cellule est négative. Indique le début du code de l'itérateur ; - et3 : marque le code de fin de la routine, dans lequel la somme est écrite à l'adresse passée en paramètre et le nombre de cellules renvoyé (sans travail supplémentaire) en tant que valeur de retour. * Question 3.5 [1 point] int mystere (int * t, int * m); * Question 3.6 [1 point] Les valeurs positives du tableau sont : 0x11310122 0x31114120 donc la valeur placée à l'adresse indiquée est leur somme : 0x42424242