\chapter{Partie assembleur} \section{Assembleur} \paragraph{} L'assembleur que nous avons choisi de concevoir se décrit suivant le modèle ci-dessous: \\ \includegraphics{Compilo.eps} \paragraph{} L'assembleur en lui-même est constitué de quatre parties distinctes: \begin{itemize} \item Le parser de code source assembleur. Il va lire le fichier source et effectuer les premiers traitements nécessaires pour que l'analyseur syntaxique n'ait à traiter que des éléments simples. \item Le méta parser du métalangage descriptif des instructions. Il sera exécuté au tout début afin de créer les structures de données nécessaires à l'analyseur syntaxique. \item L'analyseur syntaxique chargé d'effectuer la première phase de l'assemblage. Il va lire le fichier source et va produire un premier "flux" binaire. Seules les instructions et les valeurs immédiates seront encodées. Toutes les adresses seront laissées de coté. \item Le solveur de symboles qui va effectuer la deuxième phase de l'assemblage. Il va simplement lire le résultat de l'analyseur syntaxique et tenter de remplir tous les trous laissés par celui-ci. \end{itemize} La lecture du fichier est donc effectuée en une seule passe, sans besoin d'une quelconque relecture ultérieure. Il s'agit donc d'un assembleur une passe. Les machines actuelles n'ont plus la nécessité d'un assembleur deux passes car la puissance et la mémoire sont telles que le programme peut être assemblé entièrement en mémoire. De plus, l'abstraction du microprocesseur que nous simulons est suffisamment simple pour nous éviter les problèmes sur le calcul des adresses en avant: en effet il n'existe qu'une seule forme d'adressage possible, alors que sur i386 par exemple, un JMP en avant peut se coder sur 16, 24, 32 ou même 56 bits. \paragraph{} Nous avons choisi d'implémenter un système de métalangage servant à décrire les instructions assembleur, ceci afin de servir deux buts: \begin{itemize} \item Alléger l'analyseur syntaxique. \item Simplifier le travail d'une éventuelle évolution. \end{itemize} \paragraph{} Ce système est très simple, et a été imaginé à partir du langage de programmation CAML. Il permet de décrire le langage assembleur par "\textit{pattern}". Le méta langage supporte principalement quatre types de définitions: \begin{itemize} \item la définition d'un champ de bits, \item la définition d'une \textit{pattern}, \item la définition d'une instruction, \item et la définition d'un phonème entre deux instructions. \end{itemize} \paragraph{} L'assembleur en lui-même va lire le fichier texte en entrée, tenter de trouver une instruction qui correspond à une des instructions décrites dans le méta langage, et créer le champ de bits décrit dans le méta langage. \paragraph{} La sortie de l'assembleur est un fichier objet dont le format est quasiment identique à celui de l'éditeur de liens, à la différence près qu'une table des symboles internes et externes est présente. \paragraph{Encodage du fichier objet} \subparagraph{} Voici l'encodage du fichier objet:\\ \begin{center} \begin{tabular}{|c|c|l|} \hline %il faut recentrer la ligne de titre pour la troisième colonne... \textbf{Emplacement} & \textbf{Taille} & \textbf{Signification} \\ \hline 0 & 1 & Signature\footnotemark[1]\\ \hline 1 & 1 & Taille totale du fichier binaire\\ \hline 2 & 1 & Offset du point d'entrée du programme ($=-1$ si pas de point d'entrée)\\ \hline 3 & 1 & Taille de la partie \textit{text} $(=nb)$\\ \hline 4 & 1 & Taille des données statiques $(=ns)$\\ \hline 5 & 1 & Taille des données non initialisées\\ \hline 6 & 1 & Taille de la table des symboles $(=nr)$\\ \hline 7 & $nr$ & Table des symboles\\ \hline $7+nr$ & $nb$ & Segment "\textit{text}"\\ \hline $7+nr+nb$ & $ns$ & Segment des données statiques\\ \hline \end{tabular} \end{center} \footnotetext[1]{Nous avons fixé la signature d'un fichier objet a : 0x4f424e4e.} \subparagraph{} Organisation de la table des symboles:\\ \begin{center} \begin{tabular}{|c|c|l|} \hline \textbf{Emplacement} & \textbf{Taille} & \textbf{Signification} \\ \hline 0 & 1 & Nombre d'entrées\\ \hline 1 & $nr-1$ & Entrées\\ \hline \end{tabular} \end{center} \subparagraph{} Format d'une entrée:\\ \begin{center} \begin{tabular}{|c|c|l|} \hline \textbf{Emplacement} & \textbf{Taille} & \textbf{Signification} \\ \hline 0 & 1 & Type du symbole\\ & & 0 = symbole interne de type \textit{text}\\ & & 1 = symbole externe de type \textit{text}\\ & & 2 = symbole interne de type \textit{data}\\ & & 3 = symbole externe de type \textit{data}\\ & & 4 = symbole interne de type \textit{bss}\\ \hline 1 & 1 & Décalage du symbole dans le segment de \textit{text}\\ \hline 2 & 1 & Taille du nom du symbole $(=st)$\\ \hline 3 & $st$ & Symbole\\ \hline \end{tabular} \end{center} \subparagraph{} Si un symbole est externe, alors le décalage indique l'endroit où il y est fait référence. Il peut donc y avoir plusieurs symboles externes dans un même fichier objet. Si un symbole est interne, alors le décalage indique son emplacement soit dans le segment \textit{text}, soit dans le segment \textit{data}. \section{Éditeur de liens} L'éditeur de liens fonctionne selon un mode simple. Il va cumuler ensemble tous les fichiers objets, en concaténant tous les segments \textit{text} et segments \textit{data}, puis en remplaçant tous les symboles externes par leur valeur correcte. Puis il produira un fichier exécutable comme défini à la section~\ref{encodage_binaire}, page~\pageref{encodage_binaire}. \section{MiniOS} \paragraph{} \label{MiniOS} Pour pouvoir charger un binaire, effectuer le travail de relogement et effectuer quelques travaux d'entrées/sorties avec le simulateur, nous avons besoin d'un tout petit "système d'exploitation". Comme il ne s'agit pas de simuler un "vrai" système d'exploitation, il sera programmé en C et non en langage d'assemblage. Son utilité étant très limitée, nous n'avons pas besoin de créer quelque chose de très complexe: quelques appels systèmes très simples seront mis en place pour permettre les entrées/sorties\footnote{voir l'interface, section~\ref{Interface}, page~\pageref{Interface}}. Nous aurions pu intégrer directement ces fonctions dans le code source C du simulateur, mais nous avons décidé de le dissocier du module simulateur pour une éventuelle extension. \paragraph{} \label{relogement} Le relogement effectué par le MiniOS fonctionne sur un principe très simple: il va lire la table de relogement présente dans le fichier exécutable et pour chaque entrée, il va rajouter l'offset auquel l'exécutable aura été chargé. Ceci aura pour effet de reloger toutes les références absolues dans le code.