Histoire des machines
Le modèle de von Neumann
Le modèle d'architecture de von Neumann est caractérisé par deux traits qui le différencient nettement des organisations antérieures :
- une organisation de processeur séparant l’unité de commande, qui organise le flot de séquencement des instructions, et l’unité arithmétique, chargée de l’exécution proprement dite de ces instructions ;
- une mémoire unique contenant à la fois les programmes et les données ; programmes et données sont codés selon des conventions spécifiques
Un emplacement de mémoire peut contenir indifféremment des instructions et des données, et une conséquence majeure (dont toute la portée n’avait probablement pas été perçue à l’époque) est qu’un programme peut être traité comme une donnée par d’autres programmes : ainsi fonctionnent les interprètes, compilateurs, analyseurs, et autres outils.
Pour plus de détails sur l’histoire de la genèse du modèle de von Neumann, voir ici et ici.
L’animation ci-contre illustre le fonctionnement d’une machine très simple construite selon le modèle de von Neumann. La taille des emplacements de mémoire est de 16 bits. Le format des instructions est dit "à une adresse” : il comporte un code d’opération sur 5 bits, spécifiant l’opération à exécuter et une adresse sur 11 bits qui est celle de l’opérande de cette instruction. Ainsi il peut y avoir 25=32 opérations différentes, et on peut adresser au plus 211=2048 emplacements.
Soit à réaliser l'opération c ← a+b (donner à c la valeur de la somme a+b), où a, b, c sont des données contenues dans des emplacements de mémoire dont l'adresse est notée A, pour la donnée a, B pour la donnée b, et C pour la donnée c. Cette opération est réalisée par la séquence de programme LOAD A ; ADD B ; STO C, où LOAD, ADD et STO dénotent des instructions dont l’effet est le suivant :
- LOAD A charge dans l’accumulateur le contenu de l’emplacement d’adresse A (soit a)
- ADD B ajoute au contenu de l’accumulateur celui de l’emplacement d’adresse B (soit b)
- STO C range le contenu de l’accumulateur (soit a+b) dans l’emplacement d’adresse C
Attention : Il faut bien distinguer ici l’adresse d’un emplacement de son contenu. Les adresses sont A, B, C ; les contenus sont a, b, c. Ici, A=1027 (10000000011 en binaire), B=1152 (10010000000) et C=681 (01010101001). Les instructions désignent les données par leur adresse (en binaire) et les codes d’opération par un numéro (également en binaire) attribué une fois pour toutes par convention (ici LOAD est 10, ou 01010 en binaire), ADD est 23 (10111) et STO est 14 (01110). Cette séquence d’instructions, ainsi codées, est contenue dans les emplacements de mémoire consécutifs d’adresses 465, 466 et 467. Dans l’unité de commande, un compteur ordinal de 11 bits contient à chaque instant l’adresse de l’instruction à exécuter. Une fois l’instruction exécutée, il désigne l’adresse de la prochaine instruction (celle de l’emplacement suivant en mémoire, sauf si l’instruction exécutée était un branchement, c’est à dire un déroutement vers une adresse différente). Initialement, nous supposons que le compteur ordinal contient l‘adresse de LOAD A (soit 465, ou 00111010001).
À partir de là, on peut suivre le déroulement de notre séquence de programme. L’instruction à exécuter, désignée par le compteur ordinal, est chargée dans un registre d’instruction où son contenu est décodé : la partie code opération indique l’opération à effectuer, et la partie adresse l’adresse de l’opérande. Ces deux informations sont transmises à l’unité arithmétique qui va exécuter l’instruction. Le compteur ordinal est alors incrémenté, et le cycle recommence : voir l’animation ci-contre, où les flèches rouges indiquent le choix d’un emplacement de mémoire (que ce soit celui d’une instruction ou d’une donnée), et les flèches bleues des transferts d’information.
Même un morceau de programme aussi simple peut donner lieu à des incidents. Ainsi, il se peut que le résultat de l’opération a+b soit trop grand pour “tenir” dans un emplacement de mémoire. Dans ce cas, un message d’erreur est émis pour signaler l’incident et peut activer un programme de “récupération d’erreur” ... à condition que le programmeur ait prévu un tel programme. C'est précisément une omission de cette nature (combinée avec d’autres fautes) qui a causé en 1996 la perte de la fusée Ariane 501.