J'ai suivi un cours sur les compilateurs dans mes études de premier cycle dans lequel nous avons écrit un compilateur qui compile les programmes source dans un langage Java similaire à un langage d'assemblage de jouets (pour lequel nous avions un interprète). Dans le projet, nous avons fait quelques hypothèses sur la machine cible étroitement liées aux "vrais" exécutables natifs, notamment:
- une pile d'exécution, suivie par un registre de pointeur de pile dédié ("SP")
- un tas pour l'allocation dynamique d'objets, suivi par un registre de pointeur de tas dédié ("HP")
- un registre de compteur de programme dédié ("PC")
- la machine cible a 16 registres
- les opérations sur les données (par opposition aux sauts, par exemple) sont des opérations de registre à registre
Lorsque nous sommes arrivés à l'unité sur l'utilisation de l'allocation des registres comme optimisation, je me suis demandé: quel est le nombre minimum théorique de registres pour une telle machine? Vous pouvez voir par nos hypothèses que nous avons utilisé cinq registres (SP, HP, PC, plus deux pour utilisation comme stockage pour les opérations binaires) dans notre compilateur. Bien que les optimisations telles que l'allocation de registres puissent certainement utiliser plus de registres, existe-t-il un moyen de s'en sortir avec moins tout en conservant des structures comme la pile et le tas? Je suppose qu'avec l'adressage des registres (opérations de registre à registre), nous avons besoin d' au moins deux registres, mais en avons-nous besoin de plus de deux?
la source
Réponses:
Si vous autorisez l'accès direct à la mémoire par adresse mémoire, vous n'avez pas besoin de "registres" car vous pouvez utiliser des emplacements mémoire à la place. Par exemple, la mémoire à l'emplacement 0 peut être le compteur de programme, à l'emplacement 1, nous avons le pointeur de pile, etc. Mais c'est de la triche.
Donc, pour nous empêcher de tricher, supposons qu'il n'y ait pas d'accès direct à la mémoire, car nous pourrions utiliser des emplacements de mémoire fixes comme registres. Ensuite, nous pouvons nous en sortir avec deux registres, un compteur de programme et un pointeur de pile, comme expliqué dans l'article Wikipedia sur les machines à pile . La pile est uniquement accessible via le pointeur de pile, et le programme est uniquement accessible via le compteur de programme.
Une autre possibilité consiste à utiliser des guichets automatiques. Une machine à deux compteurs est Turing complète, c'est-à-dire qu'elle peut calculer n'importe quelle machine Turing. Ceci est à nouveau joliment expliqué dans l'article Wikipedia sur machines à sous .
la source
L'architecture PIC qui a été introduite par General Instruments dans les années 1970 et qui est toujours utilisée aujourd'hui avait les registres suivants:
Une instruction typique lira un registre, effectuera un calcul en utilisant la valeur lue et W, puis stockera le résultat du calcul dans W ou dans le registre qui a été lu. L'un des calculs disponibles donne "la valeur lue en ignorant W"; un autre est "prendre W, en ignorant la valeur lue". Les modèles de bits qui correspondraient à "lire XX, puis prendre W, en ignorant la valeur lue et stocker le résultat dans W" sont utilisés pour NOP ainsi que pour une variété d'instructions spéciales.
Pour permettre les calculs d'adresse, l'unité d'exécution du processeur surveillera les instructions qui codent une adresse de 00 et substituera le contenu du fichier File Register à l'adresse.
Bien que devoir fournir toutes les valeurs via le registre W puisse être un goulot d'étranglement, l'architecture PIC a un ensemble de travail plus grand que les autres architectures utilisant le même mot d'instruction de longueur. Sur le PIC16C54 (toujours fabriqué aujourd'hui, et très similaire aux PIC des années 1970), les instructions sont de 12 bits. Sur de nombreuses autres parties 16Cxx ou 16Fxx, les instructions ont une longueur de 14 bits et peuvent accéder directement à un espace d'adressage de 128 octets. Si l'ensemble de travail d'un programme correspond bien à l'ensemble de travail de l'ensemble d'instructions, une instruction comme "total + = valeur", où "total" et "valeur" sont de type
unsigned char
, serait compilée pour:Sur quelque chose comme l'ARM, même si l'on a un registre préchargé avec l'adresse de base de ses variables, le code serait plus comme:
Dans de nombreux cas, un compilateur serait en mesure d'éviter de faire des chargements et des stockages à chaque opération, mais sur quelque chose comme le PIC, les avantages d'un plus grand ensemble de travail peuvent parfois l'emporter sur les limitations d'avoir à passer par W tout le temps.
la source