Pile et récursivité
sp
est initialisé à0x7FFFEFFC
Quelle est la valeur du registre sp
au moment du ebreak
? (pour fib(3)
)
sp
est de “retour” à sa valeur initiale, ici 0x7FFFEFFC
.
Les routines ont la responsabilité (ABI RISC-V) de rendre le pointeur de pile dans l’état où ils l’ont trouvé.
Combien de fois la première instruction de la routine fib
est exécutée ?
- fib(0) et fib(1) ne font pas d’appel
- pour n>1, fib(n) appelle récursivement fib(n-1) et fib(n-2)
On a donc 5 appels en tout pour fib(3):
fib(3)
|- fib(2)
| |- fib(1)
| \- fib(0)
\-fib(1)
Au moment du ebreak
, quel est le contenu des 48 octets en mémoire à partir de l’adresse 0x7FFFEFCC
?
Cette zone mémoire est dans la partie “libre” de la pile, on y trouve les reliquats des cadres d’appels des appels de routines précédents: les octets ne sont pas remis à zéro, mais simplement écrasés par de nouvelles valeurs.
Utilisez RARS pour inspecter la mémoire et avoir le détail des octets.
Quelle est la valeur du registre sp
au moment du ebreak
? (pour fib(10)
)
Pareil, la valeur de sp
est “inchangée” entre avant et et après.
Quelle est la valeur minimale prise par sp
lors l’exécution (récursive) de fib
?
fib(10) appelle fib(9), qui appelle fib(8) et ainsi de suite jusqu’à fib(1). On a donc au cas le plus profond 10 appels imbriqués, chaque appel consomme 24 octets.
Ce qui donne: 0x7FFFEFFC - 10*24 = 0x7FFFEF0C
Combien de fois la première instruction de la routine fib
est exécutée en tout (extra) ?
On peut dessiner l’arbre d’appel comme pour fib(3) mais à fib(10) ça devient gros. On nomme nfib(n) le nombre d’appels de fib(n).
- Selon l’implémentation de fib
- nfib(0) = 1
- nfib(1) = 1
- pour n>1, nfib(n) = 1 + nfib(n-1) + nfib(n-2)
- Théorème: pour n>=0, nfib(n) = 2 * fib(n+1) - 1
Preuve par induction:
- nfib(0)
= 2 * fib(1) - 1 // par hypothèse d’induction
= 2 * 1 - 1 // par la définition mathématique de fib
= 1
Hypothèse vérifiée pour le cas n=0 - nfib(1)
= 2 * fib(2) - 1 // par hypothèse d’induction
= 2 * 1 - 1 // par la définition mathématique de fib
= 1
Hypothèse vérifiée pour le cas n=1 - nfib(n+1)
= 1 + nfib(n) + nfib(n-1) // par l’implémentation de fib
= 1 + (2 * fib(n+1) - 1) + (2 * fib(n) - 1) // par hypothèse d’induction
= 2 * (fib(n+1) + fib(n)) - 1 // factorisation et simplification
= 2 * fib(n+2) - 1 // par la définition mathématique de fib
Hypothèse vérifiée pour le cas n>1
On calcule nfib(10) pour avoir la réponse:
- nfib(10) = 2 * fib(11) - 1 = 2 * 89 - 1 = 177 // on est bien content de pas l’avoir dessiné à la main
Flottants
Les 2^4 = 16 valeurs de binary4
0 00 0
+0 (cas spécial zéro)0 00 1
+0b0.1 * 2^0 = 0b0.1 = 0.5 (dénormalisé)0 01 0
+0b1.0 * 2^0 = 0b1 = 10 01 1
+0b1.1 * 2^0 = 0b1.1 = 1.50 10 0
+0b1.0 * 2^1 = 0b10 = 20 10 1
+0b1.1 * 2^1 = 0b11 = 30 11 0
+inf (cas spécial infini)0 11 1
nan (cas spécial nan)1 00 0
-0 (cas spécial zéro)1 00 1
-0b0.1 * 2^0 = -0.5 (dénormalisé)1 01 0
-0b1.0 * 2^0 = -11 01 1
-0b1.1 * 2^0 = -1.51 10 0
-0b1.0 * 2^1 = -21 10 1
-0b1.1 * 2^1 = -31 11 0
-inf (cas spécial infini)1 11 1
nan (cas spécial nan)
Les valeurs
- -0.667 -> -0b0.101… arrondi au plus proche à
-0b0.1
= -0.5, donc1001
- 7/4 ->
0b1.11
équidistant entre0b1.1
(1.5) et0b10.0
(2), celui qui a le dernier chiffre à 0 gagne (le “pair” gagne), on prend donc 2, donc0100
en binary4. - 2.5 ->
0b10.1
équidistant entre0b10
(2) et0b11
(3), celui qui a le dernier chiffre à 0 gagne (le “pair” gagne), on prend donc 2 à nouveau, donc0100
en binary4. - pi -> 3.145,
0b11
(3) est plus proche que0b100
(4), on prend0b11
, donc0101
: note on est à la frontière entre le plus grand nombre représentable et l’infini.
Plus de détails
Tous les nombres de 0 à 4 (inclus) par pas de 0.125. Cela peut aider à visualiser la droite (verticale ici) des nombres (mais si ça vous mélange, ignorez le)
0 = 0b000.000 |X: +zéro (0000)
0.125 = 0b000.001 |X
0.25 = 0b000.010 |X (équidistant, 0 gagne)
0.375 = 0b000.011 | X
0.5 = 0b000.100 | X: 0.5 (0001)
0.625 = 0b000.101 | X
0.75 = 0b000.110 |X (équidistant, 1 gagne)
0.875 = 0b000.111 |X
1 = 0b001.000 |X- 1 (0010)
1.125 = 0b001.001 |X
1.25 = 0b001.010 |X (équidistant, 1 gagne)
1.375 = 0b001.011 | X
1.5 = 0b001.100 | X: 1.5 (0011)
1.625 = 0b001.101 | X
1.75 = 0b001.110 |X (équidistant, 2 gagne)
1.875 = 0b001.111 |X
2 = 0b010.000 |X: 2 (0100)
2.125 = 0b010.001 |X
2.25 = 0b010.010 |X
2.375 = 0b010.011 |X
2.5 = 0b010.100 |X (équidistant, 2 gagne)
2.625 = 0b010.101 | X
2.75 = 0b010.110 | X
2.875 = 0b010.111 | X
3 = 0b011.000 | X: 3 (0101)
3.125 = 0b011.001 | X
3.25 = 0b011.010 | X
3.375 = 0b011.011 | X
3.5 = 0b011.100 |X: (équidistant avec 4, +inf gagne)
3.625 = 0b011.101 |X
3.75 = 0b011.110 |X
3.875 = 0b011.111 |X
4 = 0b100.000 |X
:X
:X
|X: +infini (0110)