Enoncés difficiles

Transcription

Enoncés difficiles
Organisation des ordinateurs
Énoncés – Série difficile
Remarques : Cette série d’exercices difficiles est destinée uniquement aux étudiants qui souhaitent
approfondir les notions étudiées au cours. Ces exercices ne sont pas matière d’examen !
Il n’est pas nécessaire d’être capable de les réaliser, ni de les étudier, pour réussir
l’épreuve. L’examen ne portera pas sur des exercices d’un tel niveau de difficulté.
N’hésitez pas à nous transmettre vos idées de solutions ou vos questions concernant ces exercices.
1. Construire un circuit séquentiel capable de déterminer si un nombre entier z est divisible ou
non par 7.
Le circuit comprendra deux entrées r et i, et une sortie s. L’entrée r sert à initialiser le circuit,
et l’entrée i à recevoir la valeur de z, encodée selon la technique du complément à deux.
Pour déterminer si z est divisible par 7, on commence par activer l’entrée r pendant au moins
un coup d’horloge. Ensuite, lors des coups d’horloge suivants, on désactive r et on fournit
successivement à l’entrée i les bits de la représentation binaire de z, en commençant par le
plus significatif (c’est-à-dire le bit de poids fort). Après le coup d’horloge correspondant au
dernier bit entré, la sortie s est activée par le circuit si et seulement si z est divisible par 7.
2. Le code C suivant est extrait des sources du jeu video Quake 3 .
1
2
3
4
5
6
7
8
9
: float IS(float x)
: {
:
float xhalf = 0.5f*x;
:
int i = *(int*)&x;
:
i = 0x5f3759df - (i >> 1);
:
x = *(float*)&i;
:
x = x*(1.5f - xhalf*x*x);
:
return x;
: }
Déterminer quelle est la fonction implémentée par ce code et expliquer, dans les grandes lignes,
les principes du calcul effectué, ainsi que l’intérêt éventuel qu’il présente.
Notes :
– Ce code définit une fonction IS, prenant comme argument un nombre réel x, et retournant
une valeur réelle (à la ligne 8). Les réels sont supposés être représentés selon le standard
IEEE 754 simple précision.
– La variable entière i définie à la ligne 4 est supposée être représentée sur 32 bits, selon la
technique du complément à deux. La ligne 4 place dans i les 32 bits de la représentation
réelle de x. La ligne 8 effectue l’opération réciproque.
– L’expression (i >> 1) utilisée à la ligne 5 retourne la valeur obtenue en décalant chaque
bit de la représentation de i d’une position vers la droite. Lors de cette opération, le bit de
poids faible est perdu, et le bit de poids fort devient égal au bit de signe de i.
1
3. Ecrire un programme assembleur 80x86 capable de compter le nombre de nœuds accessibles
d’un graphe binaire fini dirigé.
Un graphe binaire fini dirigé est un objet (Q, δ, q0 ) composé
– d’un ensemble fini Q de nœuds ;
– d’une fonction de transition δ : Q × {G, D} → Q. Pour chaque nœud q ∈ Q, le nœud δ(q, G)
(s’il est défini) est appelé fils gauche de q. De même, le nœud δ(q, D) est le fils droit de q ;
– d’un nœud initial q0 .
Un nœud est dit accessible s’il est le nœud initial, ou s’il est le fils d’un nœud accessible.
Chaque nœud n du graphe est représenté par une structure composée de quatre octets consécutifs dans le segment de données : Les deux premiers octets donnent l’offset de la structure
représentant le fils gauche de n, et les deux derniers octets pointent vers son fils droit. Si un
fils n’est pas défini, le pointeur correspondant prend la valeur 0 (“pointeur vide”).
Le programme prendra en entrée, dans le registre BX, l’adresse de la structure représentant le
nœud initial du graphe à explorer. A l’issue de son exécution, le programme retournera dans
AX le nombre de nœuds accessibles calculé.
Remarques :
– On peut supposer que l’on dispose d’une pile de taille suffisante pour effectuer le calcul ;
– Il n’est pas nécessaire que la représentation du graphe fournie en entrée soit préservée par
le programme.
2