Du point de vue historique, le rapport de von Neumann sorti en 1945 ( "First Draft of a Report on the EDVAC" ) constitue un moment-clé, puisqu'il propose une architecture pour une machine informatique autonome ( c'est à dire avec programme enregistré en mémoire; auparavant la programmation se faisait en connectant et déconnectant des dizaines de cables ! ), architecture qui est toujours celle utilisée dans les machines actuelles.
On dispose donc de circuits électroniques capables de faire des calculs arithmétiques et logiques, capables de mémoriser des données, etc...
Les ordinateurs construits avec l’architecture de von Neumann sont constitués de quatre composants utilisant ces circuits :
La particularité de cette architecture est que les programmes et les données qu'ils manipulent partagent la même mémoire; dans certaines architectures ( comme celle dite de Harvard ), programmes et données disposent au contraire de mémoires séparées.
Tous ces composants communiquent les uns avec les autres par l'intermédiaire d'un ensemble de connexions appelées bus ( en jaune sur la figure ).
On peut se représenter la mémoire comme une série de cellules, chaque cellule étant capable de stocker 1 octet.
Chacune de ces cellules possède une adresse, exprimée sous forme de valeur numérique.
Les opérations sur la mémoire sont de 2 types : lecture / écriture. Une opération de lecture consiste à aller lire l’octet situé à l’adresse mémoire XXXXX et une opération d’écriture consiste à écrire un octet
donné à l’adresse mémoire YYYYY.
Toute donnée informatique ne peut y être représentée que par un nombre ( binaire, de surcroît...), puisque c'est la seule information qu'une machine peut traiter.
Cependant, du fait de l'architecture de von Neumann, qui stocke aussi bien programmes que données dans la même mémoire, ces nombres peuvent représenter diverses informations :
Différents types de mémoire existent dans une machine : selon les cas, le processeur peut avoir besoin d'une mémoire très rapide pour exécuter les opérations les plus courantes, ou alors de mémoires pas forcément rapides mais de grande capacité.
Si l'unité arithmétique et logique (UAL) est chargée d'effectuer les opérations arithmétiques (addition, soustraction, changement de signe etc.), les opérations logiques (and, or, xor, not etc.) et les tests (test d'égalité, de supériorité etc.), c'est l'unité de contrôle d'un processeur qui en est le "chef-d'orchestre" et qui gère le déroulement des opérations ayant successivement lieu, ce que l'on appelle le séquençage.
Elle est "pilotée" par une horloge très stable qui lui envoie un "top" régulièrement toutes les XXXX secondes ( ou plutôt ms, voire ns : c'est la fréquence du processeur qui indique cette durée; plus la fréquence est élevée, plus les "top" sont rapprochés dans le temps ).
Chaque "top" correspond à un "pas" de fonctionnement du microprocesseur; un pas de fonctionnement peut correspondre à une opération :
Un registre particulier du processeur, nommé compteur programme ou PC ( Program Counter ), contient l’adresse-mémoire de la prochaine instruction à exécuter ( ce qui lui permet de savoir "où il en est du programme"...); au démarrage du processeur, le registre PC est normalement initialisé à l'adresse 0, début de la mémoire, puis il est automatiquement incrémenté par l'unité de contrôle après chaque opération.
Les programmes sont donc lus linéairement par le processeur, instruction après instruction.
Le CPU a un fonctionnement cyclique :
La capacité du processeur à exécuter tous les programmes s’explique par ce fonctionnement très souple
Un processeur donné est capable d’exécuter un certain nombre d’opérations de base, celles pour lesquelles il dispose d’un circuit électronique qui les réalise.
L’ensemble des instructions exécutables directement par le microprocesseur (instructions machines) constitue ce que l’on appelle le langage machine du processeur.
Chaque instruction machine correspond à une configuration électronique binaire composée principalement de 2 parties :
Voila donc comment était programmé les premières machines : des interrupteurs, ou des connexions filaires, étaient "basculés" pour "entrer" les interminables successions de "0" et de "1" nécessaires pour réaliser la programmation; inutile de préciser le temps que cela pouvait prendre, et les innombrables erreurs que cela engendrait...
Une amélioration pour l'ergonomie du codage a été, dans les listings de programme, de remplacer les nombres binaires par des mnémoniques, courts ensembles de quelques lettres qui indiquent de manière non ambiguë le rôle de l'instruction.
Le mnémonique du code de l'opération vue dans l'exemple précédent est ainsi "ADDA"; l'instruction complète s'écrira alors : "ADDA $2".
L'assembleur n'est pas un autre langage, distinct du langage machine; c'est simplement une "traduction" pour que la compréhension humaine des programmes et leur correction devienne plus facile; bien entendu, c'est toujours des "0" et des "1" qu'il faut coder dans la machine.
Le langage machine/assembleur est toujours utilisé aujourd'hui quand on a besoin d'un accès bas-niveau à une machine, comme lorsqu'on code le pilote d'un périphérique. Ce terme de bas-niveau
n'a rien de péjoratif, mais signifie "au plus près de la machine"; c'est lui qui permet en effet de manipuler directement le processeur et la mémoire.
Les langages haut-niveau permettent au contraire de les utiliser de manière "transparente" avec un langage beaucoup plus proche de la pensée humaine.
Une autre énorme différence entre langages de haut et bas-niveau et la suivante :
Une des premières difficultés est déja de connaître le langage machine du processeur sur lequel on veut travailler, et de devoir s'adapter en cas de changement d'architecture.
Ensuite, une des propriétés des UAL est qu'elles ne travaillent en pratique qu'avec deux opérandes.
Conséquence, on ne peut pas demander à une UAL de faire par exemple directement le calcul : 2 + 7 - 5 + 99
En effet ce calcul comporte quatre opérandes (ou quatre valeurs). Il va donc falloir décomposer le travail en demandant à l'UAL trois calculs successifs avec deux opérandes :
De plus, pour des raisons d'optimisation diverses , les valeurs des opérandes doivent être chargées explicitement dans des registres avant de faire un calcul, et la valeur du résultat devra être mémorisée explicitement dans un registre ou un emplacement mémoire; c'est ainsi par exemple par le registre A appelé accumulateur que "transitent" tous les calculs.
Par exemple, pour réaliser la simple opération d'addition suivante : R = S + 2, il faudra en fait écrire quelque chose comme :
Moralité : un processeur ne pouvant effectuer que des taches "de base", il va donc falloir en assembleur ( ou en langage machine...) décomposer au maximum le travail à faire, de façon à lui "mâcher" le travail...
Aujourd'hui, vous allez coder une machine en langage machine et en assembleur pour que vous compreniez bien ce qu'est la programmation bas-niveau, et à quoi on échappe en utilisant des langages haut-niveau comme Python !
Programmer en assembleur sur un PC est possible, mais compliqué...Des simulateurs logiciels existent, mais nous vous proposons d'utiliser une vraie machine, très simplifiée, dont les entrées/sorties sont visualisées grâce à des LED, exactement comme pour les premiers kits de micro-ordinateurs des années 70 qui ont lancé la vague de l'informatique personnelle ( Altair 8800 et IMSAI 8080. ).
Cette machine se nomme le Digirule 2A, se programme en assembleur / langage machine, et peut s' acheter pour une dizaine d'euros sur le web; vous disposez dans la salle de quelques "clones" de la machine d'origine.
Caractéristiques :
Vous l'aurez compris...il va falloir vous mettre dans la peau des pionniers de l'informatique des années 40 pour entrer les 0 et les 1 qui constitueront votre programme...
Heureusement, vous serez aidé par une feuille de tableur LibreOffice, dans laquelle vous écrirez votre code en assembleur et qui vous donnera automatiquement le code
binaire des instructions et opérandes correspondants.
Enregistrez cette feuille de calcul sur votre zone personnelle / clé USB.
Dans cette feuille de calcul, seule la colonne "Instruction
" doit être complétée avec, à chaque ligne, l'instruction ou l'opérande à entrer; ne touchez pas aux autres colonnes.
Pour programmer réellement le Digirule, vous utiliserez les nombres binaires de la colonne "Code machine (binaire)
".
Les instructions du langage machine du Digirule que vous utiliserez par la suite sont présentées dans ce document.
Pour bien comprendre comment on programme le Digirule, vous allez entrer le programme correspondant à l'exemple de la feuille de calcul, dont voici le listing complet :
Adresse Opcode Opérande Commentaire
0 SPEED 124 règle la vitesse d'éxécution ( 0 = le plus rapide / 255 = le plus lent )
2 COPYLA 170 copie la valeur 170 ( 10101010 ) dans l'accumulateur A
4 COPYAR 255 copie l'accumulateur vers le registre LEDs de donnée
6 SHIFTRL 255 décale vers la gauche les bits du registre LEDs de données ( = adresse 255 )
8 JUMP 6 saut vers l'adresse 6
( En réalité, les opcodes et opérandes apparaissent les uns en dessous des autres dans la feuille de calcul puisqu'il est possible de n'en mettre qu'une seule par adresse mémoire.)
SPEED
= 00000010 ), puis appuyer sur STORE pour l'enregistrer; le PC augmente automatiquement de 1Si vous ne vous êtes pas trompés, vous devez voir une "animation" qui fait "défiler" les LEDs de données vers la gauche.
SPEED
, dont l'opérande est un nombre entre 0 et 255 ( 0 = le plus rapide / 255 = le plus lent ).DataLEDRegister
situé à l'adresse 255JUMP
correspond à un saut inconditionnel à une adresse mémoire ( ici, 6 ), et permet de réaliser dans ce cas une boucle infinie.Apporter des modifications au programme pour faire défiler vers la droite, partir d'un affichage différent, etc...
Sur la feuille d'exercices, vous trouverez quelques programmes à écrire/modifier/programmer selon la situation.
Il vous sera demandé de tracer l'exécution des programmes ( on dit aussi dérouler la séquence d'instructions ), c'est à dire de déterminer à chaque pas du programme le contenu de certains registres ou adresses mémoires, ou le résultat d'une opération.
Quand on vous demande d'écrire un programme, il faudra bien entendu le faire d'abord sur papier, puis sur la feuille de calcul et enfin le programmer sur le Digirule.
Aidez-vous du document pour déterminer les instructions à utiliser et la manière de les écrire.