Le but de ce TP noté est de réaliser un programme assembleur implantant le crible d’Ératosthène. Ce TP demande l’application de toutes les techniques et éléments vus au cours des séances précédentes.
1 Consignes générales
Le cours ainsi que toutes les ressources de la page du cours sont autorisés. Les notes personnelles sur papier sont également autorisées.
Les appareils numériques sont interdits.
Vous devez travailler dans le répertoire
EXAM
de votre répertoire personnel. Tout document hors de ce dossier ne sera pas évalué.Les fichiers nécessaires pour travailler sont les suivants : Fichiers.zip
Vous disposez d’un script
Compile.sh
pour compiler le programme à compléter. Ce dernier produit également un exécutable./testeur
qui teste les fonctions de votre programme. Si le programme complet est attendu, le testeur teste sur quelques cas le bon fonctionnement de vos fonctions même si vous ne les avez pas toutes écrites, profitez en.Un programme complet doit passer tous les tests du testeur.
Le code réalisé doit être commenté.Z
2 Algorithme
L’algorithme du crible d’Ératosthène permet de calculer tous les nombres premiers inférieurs à un nombre \(n\) fixé. Il procède ainsi :
on commence par générer une liste d’entiers \(L := [2, 3, 4, \dots, n]\). Chaque entier de cette liste possède un état : il peut être marqué ou bien non marqué. Initialement, tous les entiers de \(L\) sont non marqués ;
ensuite, tant qu’il existe des nombres non marqués dans la liste \(L\) :
on marque le plus petit nombre \(k\) de \(L\) non encore marqué ;
pour tout nombre \(\ell > k\) de la liste \(L\) :
- si \(k\) est un diviseur de \(\ell\), alors on supprime l’élément \(\ell\) de la liste ;
la liste \(L\) — qui contient maintenant exclusivement des nombres marqués — est la liste des nombres premiers inférieurs à \(n\).
Par exemple, si on applique cet algorithme pour \(n := 30\), on obtient successivement les valeurs de \(L\) suivantes (les nombres marqués sont soulignés) :
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 2 3 5 7 11 13 17 19 23 25 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29 2 3 5 7 11 13 17 19 23 29
3 Implantation
On peut se servir de la bibliothèque asm_io.inc
pour gérer les entrées/sorties. Le programme doit définir une
constante N
de valeur 128
. Ceci est
réalisé par la déclaration
128 %define N
Le programme doit également réserver N-1
octets à
partir d’une adresse tab
et un octet à l’adresse
pgm
. Ceci est réalisé par les déclarations
: resb N-1
tab : resb 1 pgm
à disposer dans la section .bss
.
La suite de N
octets tab
peut être
vue comme un tableau. Celui-ci est utilisé pour mémoriser les
nombres effacés pendant l’exécution de l’algorithme. Pour cela,
l’octet à l’adresse tab + i - 2
vaut 1
si le nombre i
n’est pas effacé et 0
s’il est effacé.
Il s’agit pour débuter de bien comprendre l’adresse spécifée
par la formule précédente. En effet, comme la liste des entiers à
considérer commence par \(2\)
(car aucun nombre strictement inférieur à \(2\) n’est premier), l’octet à
l’adresse tab + 2 - 2 = tab
est dédié à coder la
présence/absence de 2
. En poursuivant le
raisonnement, c’est bien l’octet à l’adresse
tab + 3 - 2 = tab + 1
qui est dédié à coder la
présence/absence de 3
. Et ainsi de suite, ce qui
explique la formule générale.
Par ailleurs, en plus de tout cela, la variable à l’adresse
pgm
contient la valeur du plus
grand nombre marqué
(c’est-à-dire donc le dernier nombre marqué).
Toutes les fonctions implantées par la suite doivent respecter la convention d’appel du C.
Chaque fonction implantée doit être documentée en mentionnant son rôle, ses arguments attendus et son renvoi.
On utilisera le fichier
Squelette.asm
qui contient un squelette du code a fournir. Il suffit de le remplir ses parties manquantes conformément aux questions suivantes.
\(\blacksquare\) Écrire une fonction
effacer
qui prend en argument un nombrei
et positionne la case correspondante du tableautab
à0
, signifiant que le nombrei
est effacé.Note : il se peut que la réponse à cette question figure déjà dans le fichier
Squelette.asm
. Il est important de bien la comprendre avant d’aller plus loin.\(\blacksquare\) Écrire une fonction
ajouter
qui prend en argument un nombrei
et positionne la case correspondante du tableautab
à1
, signifiant que le nombrei
n’est pas effacé.\(\blacksquare\) Écrire une fonction
lire
qui prend en argument un nombrei
et renvoie danseax
la valeur de la case correspondante dans le tableautab
.Dorénavant, on utilisera uniquement les trois fonctions précédentes pour accéder au tableau
tab
, que ce soit en lecture ou en écriture.\(\blacksquare\) Écrire une fonction
initialiser
qui positionne tous les octets du tableautab
à1
. Cette fonction doit aussi positionner la variablepgm
à la valeur0
pour spécifier qu’aucun nombre du tableau n’est marqué.\(\blacksquare\) Écrire une fonction
effacer_multiples
qui prend un argumentp
et qui positionne à0
les cases du tableautab
correspondant aux entiers qui sont multiples dep
.\(\blacksquare\) Écrire une fonction
premier_suivant
qui prend un argumenti
et renvoie danseax
la valeur du premier nombre supérieur ài
tel que l’octet correspondant dans le tableautab
vaut1
. Si une telle valeur n’existe pas, la fonction renvoieN + 1
.\(\blacksquare\) Écrire une fonction
afficher
qui affiche dans l’ordre croissant les nombres qui sont codés comme présents par le tableautab
.\(\blacksquare\) Rassembler et utiliser les fonctions écrites en un programme complet qui implante l’algorithme d’Ératosthène. Le programme, lorsqu’il est exécuté, doit afficher les nombres premiers inférieurs à
N
.\(\blacksquare\) Améliorer le programme afin qu’il sorte de la boucle principale (instruction 2.) lorsque le plus grand nombre marqué dépasse \(\sqrt{N}\).
Note : Il n’est pas nécessaire de savoir calculer la racine carrée de \(N\).