Aller au contenu

Chapitre 3.2 - Architecture Von Neumann/Assembleur⚓︎

image

image

John Von Neumann (1903-1957) est un mathématicien et physicien (et bien d'autres choses) américano-hongrois. Il a le premier théorisé l'architecture des processeurs, tels qu'ils fonctionnent encore aujourd'hui.

1. Architecture von Neumann⚓︎

image

On distingue 4 zones essentielles :

  • le CPU (Central Processing Unit) qui contient lui-mĂŞme :
    • l'UnitĂ© ArithmĂ©tique et Logique (UAL) dans laquelle sont effectuĂ©es les opĂ©rations de base (addition, multiplication...) Cette zone comporte notamment les registres (peu nombreux, de l'ordre de la dizaine) qui sont les espaces de travail ultra-rapides dans lesquels l'UAL va effectuer ses calculs. Une fois ceux-ci effectuĂ©s, les valeurs des registres repartent dans la mĂ©moire.
    • l'UnitĂ© de contrĂ´le, qui va sĂ©quencer les opĂ©rations. Lorsqu'on parle d'un processeur Ă  3 GHz, cela signifie (approximativement) que UnitĂ© de ContrĂ´le va envoyer l'ordre d'une nouvelle opĂ©ration Ă  l'UAL 3 milliards de fois par seconde.
  • la mĂ©moire, qui contient Ă  la fois les donnĂ©es Ă  traiter et les instructions du programme. Cette idĂ©e de stocker au mĂŞme endroit donnĂ©es et programme est l'idĂ©e centrale de l'architecture von Neumann.
  • les bus de communication (des fils Ă©lectriques permettant de transporter les donnĂ©es entre les diffĂ©rents composants).
  • les EntrĂ©es/Sorties, permettant de gĂ©rer les informations avec l'extĂ©rieur.

2. Activité : simulation d'un programme en assembleur⚓︎

On l'a vu, dans l'architecture de Von Neumann, la mémoire vive (RAM) contient à la fois les données et les programmes (suite d'instructions).

Dans la mémoire d'un ordinateur on peut donc stocker des données (Entiers, flottants, booléens, caractères,...) sous forme binaire. Par exemple 00100110 correspond au nombre entier 38. Mais on peut également y stocker des instructions à destination de l'unité de traitement (UAL).

Ce même code binaire 00100110 pourrait très bien correspondre au code d'une instruction machine, par exemple "Stopper le programme".

C'est le rôle du système d'exploitation (windows,linux,...) et du programmeur de faire en sorte de distinguer en mémoire ce qui correspond à des instructions ou des donnéees.

Les instructions machine⚓︎

Une instruction machine se présente de la façon suivante :

A retenir

Champ de code de l'opération | Champ de l'opérande

Remarque : chaque processeur possède ses propres codes d'opération (opcode). C'est son jeu d'instructions.

Exemple

Additionner | Valeur contenue dans le registre R1, Nombre 37

Chaque instruction peut occuper un ou plusieurs mots dans la mémoire d'un ordinateur.

Remarque : un mot correspond à l'unité de base pouvant être traitée par le processeur. Avec un proceseur 8 bits la taille du mot correspond à 8 bits soit 1 octet. Avec un processeur 64 bits la taille du mots correspond à 64 bits soit 8 octets.

Au début de l'informatique les programmeurs devaient coder leur programme directement en binaire : le langage machine.

Par exemple, le langage machine suivant est une instruction :

Exemple

01001100 00100101

  • le premier octet 01001100 correspond au code de l'opĂ©ration Ă  effectuer (opcode) : "ajouter la valeur suivante au registre R1".
  • le second octet 00100101 (37 en dĂ©cimal) est l'opĂ©rande : la valeur Ă  ajouter Ă  celle contenue dans le registre R1.

Le langage assembleur⚓︎

La programmation en binaire étant loin d'être évidente pour un humain, on a inventé le langage assembleur qui permet d'écrire les instructions de manière plus compréhensible. Dans notre exemple le code 0100110000100101 est remplacé par :

0100110000100101

ADD R1,37

Ce qui est tout de même déjà beaucoup plus lisible !

Voici un exemple de programme assembleur :

Programme

Text Only
INP R0,2
INP R1,2
ADD R2,R1,R0
OUT R2,4
HALT

Le langage assembleur est donc une simple traduction brute du langage machine. Pour résumer :

  • Le langage machine est une succession de bits qui est directement interprĂ©table par le processeur d'un ordinateur.
  • Un langage assembleur est le langage machine oĂą les combinaisons de bits sont reprĂ©sentĂ©es par des "symboles" qu'un ĂŞtre humain peut mĂ©moriser.
  • Un programme assembleur convertit ces "symboles" en la combinaison de bits correspondante pour que le processeur puisse traiter l'information. Le programme assembleur traduit donc le langage assembleur en langage machine.

Remarques : - Un langage assembleur est souvent spécifique à un type de processeur. - Un langage assembleur est appelé "langage de bas niveau" car il est très proche du langage machine.

Les compilateurs / interpréteurs⚓︎

Le langage assembleur n'est toutefois pas facile à manipuler. C'est pourquoi il a été conçu des langages de programmation plus agréable à utiliser : les langages de haut niveau (Ex : C, Python, Javascript,...).

On parle également de niveau d'abstraction d'un langage. Plus celui-ci est proche de notre langage naturel et plus son niveau d'abstraction est élevé. Plus le langage est proche de la machine (binaire) plus celui-ci est de bas niveau.

image

Mais tout langage de programmation, pour être exécuté par une machine, doit être à un moment où à un autre traduit en langage binaire.

image

Il existe plusieurs manières de procéder :

  • La première consiste Ă  traduire le programme dans son ensemble une fois pour toute et gĂ©nĂ©rer un fichier avec le code binaire prĂŞt Ă  ĂŞtre exĂ©cutĂ©. Il s'agit de la mĂ©thode dĂ®te de compilation, rĂ©alisĂ©e par un compilateur. Le langage C est un exemple de langage compilĂ©.
  • La deuxième mĂ©thode consiste Ă  traduire les instructions en langage binaire au fur et Ă  mesure de la lecture du programme. Il s'agit de la mĂ©thode dĂ®te d'interprĂ©tation, rĂ©alisĂ©e par un interprĂ©teur. Le langage Basic est un exemple de langage interpĂ©tĂ©.
  • Enfin il existe des mĂ©thodes mixtes qui consistent Ă  traduire le programme en pseudo-code (bytecode). Ce pseudo-code est interprĂ©tĂ© par une machine virtuelle au moment de l'execution. L'intĂ©rĂŞt de cette approche est que l'execution et la traduction du pseudo-code en langage binaire est plus rapide. Mais Ă©galement, le fait que ce pseudo-code permet une certaine indĂ©pendance vis Ă  vis du processeur sur lequel il est exĂ©cutĂ©. En effet, il suffit juste de disposer d'une machine virtuelle spĂ©cifique au processeur en question. Python et Java sont des exemples de langages utilisant cette technique.

3. L'assembleur, en pratique⚓︎

Présentation du simulateur de processeur AQA⚓︎

Nous allons utiliser un simulateur d’architecture de Von Neumann, réalisé par Peter Higginson pour préparer des étudiants anglais à leur examen de Computer Science. Il se nomme AQUA et on peut l’exécuter en ligne.

Quelques principes de base :

  • On ne peut pas dĂ©finir de variables. Les donnĂ©es manipulĂ©es sont soient stockĂ©es Ă  un endroit prĂ©cis en mĂ©moire soit dans un des registres R0 Ă  R12.
  • Pour calculer avec une donnĂ©e en mĂ©moire, il faut d’abord la transfĂ©rer dans un registre.
  • L’interface se divise verticalement en trois zones :
  • Ă€ gauche, l’éditeur de programme en assembleur.
    • On remplit le formulaire et on le soumet avec submit.
    • Puis on assemble le programme en mĂ©moire avec assemble (parfois fait automatiquement).
    • On l’exĂ©cute avec run (Plusieurs vitesses d’exĂ©cution sont disponibles).
  • Au centre, le processeur, avec :
    • les treize registres de donnĂ©es de R0 Ă  R12.
    • le Compteur de Programme PC.
    • l’ UnitĂ© de ContrĂ´le avec son Registre d’Instruction CIR.
    • l’ALU avec ses quatre drapeaux de test (Z pour zĂ©ro, N pour nĂ©gatif, C pour carry, retenue et V pour overflow).
    • les bus reliant les diffĂ©rents composants du processeur et la mĂ©moire (en bleu).
    • Les registres MAR et MBR servent Ă  transfĂ©rer des donnĂ©es entre la mĂ©moire et les registres :
    • MAR contient l’adresse (en dĂ©cimal) oĂą l’on veut lire ou Ă©crire.
    • MBR la valeur lue ou Ă  Ă©crire (en hexadĂ©cimal).
  • Ă€ droite, la mĂ©moire divisĂ©e en mots de largeur 32 bits et dont les adresses commencent Ă  0. Dans "OPTIONS" on peut choisir le format d’affichage (dĂ©cimal signĂ© ou non, binaire, hexadĂ©cimal).

Remarque : il n’existe pas de structure de contrôle conditionnelle comme le "if... then... else" ou les boucles "while", "for". Pour les implémenter, on utilise des instructions de saut inconditionnel ou conditionnel en fonction du résultat de la comparaison précédente. Les points de chute de saut sont repérés par des étiquettes placées dans le programme.

AQA et le modèle de Von Neumann⚓︎

Ci-dessous, sont encadrés les quatre éléments constitutifs d'une architecture de Von Neumann :

image

Légende des encadrements : - En rouge, le processeur (CPU), comprenant : - En rose, l'unité de contrôle (UC) - En bleu, l'untité arithmétique et logique (UAL) - En vert, la mémoire vive (RAM)

La RAM⚓︎

Le contenu des différentes cellules de la mémoire peut être affiché dans différents formats ![AQA_options_RAM.image

  • base 10 (entier signĂ©, signed) – par dĂ©faut
  • base 10 (entier non-signĂ©, unsigned),
  • base 16 (hex),
  • base 2 (binary).
  • ...

Chaque cellule de la mémoire est accessible par son adresse. Il existe deux formats d’adressage des cellules de la mémoire : - 32 bits – format mot (option word mode) (par défaut) les adresses vont de 000 à 199 (codée en base 10). - 8 bits – format octet (option byte mode) les adresses vont de 000 à 799 (codée en base 10).

image

Le CPU⚓︎

Dans la partie centrale du simulateur, on trouve les différent composants du microprocesseur : - les registres (Registers) : 13 registres (R0 à R12) image - 1 registre spécial (PC) qui contient l’adresse mémoire de l’instruction en cours d’exécution image

  • L’unitĂ© de commande (Control Unit) qui contient l’instruction machine en cours d’exĂ©cution (au format hexadĂ©cimal) image
  • l’unitĂ© arithmĂ©tique et logique (Arithmetic and Logic Unit) image

Mon premier programme en assembleur⚓︎

Le jeu d’instructions AQA est précisé dans la documentation.

Remarque préalable : les opérandes ont la syntaxe suivante... - Rn correspond au registre numéro n. - #n correspond à une valeur entière immédiate n (sans passer par une mémoire). - n correspond à une adresse mémoire n (dans la RAM).

Voici quelques exemples d’instructions d’opérations arithmétiques et de transfert de mémoire :

Instruction Traduction
LDR R1, 78 Charge dans le registre R1 la valeur stockée en mémoire à l’adresse 78
STR R1, 123 Stocke le contenu du registre R1 à l’adresse 123 en mémoire
LDR R1, [R2] Charge dans le registre R1 la valeur stockée en mémoire à l’adresse contenue dans le registre R2
ADD R1, R0, #128 Additionne le nombre 128 et la valeur stockée dans le registre R0. Place le résultat dans le registre R1
SUB R1,R0,#128 Soustrait le nombre 128 de la valeur stockée dans le registre R0, place le résultat dans le registre R1
SUB R0,R1,R2 Soustrait la valeur stockée dans le registre R2 de la valeur stockée dans le registre R1, place le résultat dans le registre R0
MOV R1, #23 Place le nombre 23 dans le registre R1
MOV R0, R3 Place la valeur stockée dans le registre R3 dans le registre R0
OUT R1, 4 Affiche en sortie 4 la valeur contenue dans le registre R1
HALT Symbole de fin de programme, indispensable pour que le programme se termine sans erreur
  1. Ouvrir le simulateur AQUA. Régler la mémoire de sorte d’avoir un affichage hexadécimal, avec des cellules au format 32 bits.

  2. Saisir le programme ci-dessous dans la fenêtre d’édition puis le soumettre avec submit .

Text Only
    MOV R0, #42  
    STR R0, 150 
    HALT

Le programme vient d’être mis dans les cellules mémoires d’adresses 000, 001 et 002 : image

L’assembleur a converti les 3 lignes du programme en instructions machines, chacune occupant une cellule de 32 bits :

Text Only
    adresse 000 : MOV R0,#42
    adresse 001 : STR R0,150
    adresse 002 : HALT

Pour exécuter un programme, il suffit de cliquer sur le bouton RUN (exécution en continu) ou STEP (exécution pas à pas).

Par défaut, le simulateur montre comment il « travaille » par une animation. La vitesse d’animation est réglable à l’aide des boutons << et >> apparaissant à coté du bouton STOP qui permet de mettre l’exécution en pause. Tester l’exécution du code, en ralentissant suffisamment la vitesse afin de bien comprendre toutes les étapes de cette exécution.

On constate que deux types de valeurs circulent au sein du système : - des données (valeurs lues/écrites de/vers la mémoire/les registres/l’unité de commande) - des adresses des cellules de mémoire image

Une fois la simulation terminée, on peut constater que la cellule mémoire d’adresse 150, contient bien le nombre 42 (en base 10). il en est de même pour le registre R0.

Pour remettre la mémoire à 0, il faut cliquer sur le bouton OPTIONS et choisir clr memory.

Mon deuxième programme en assembleur⚓︎

Programme

Text Only
MOV R0, #10  
MOV R1, #250  
ADD R2, R1, R0  
OUT R2, 4  
HALT
  1. Constater que...
    • les 5 lignes d'instructions (ligne 0 Ă  4) sont bien enregistrĂ©es dans la RAM aux emplacements mĂ©moire de 0 Ă  4.
    • les emplacements de mĂ©moire de registre sont vides (valeurs nulles).
  2. Répérer...
    • l'UnitĂ© de ContrĂ´le (UC) qui dĂ©code l'instruction en cours.
    • l'UnitĂ© ArithmĂ©tique et Logique (UAL) qui prend deux opĂ©randes en entrĂ©e pour sortir le rĂ©sultat de son calcul.
    • le registre du compteur de programme (PC) qui stocke l'emplacement mĂ©moire de la prochaine instruction Ă  aller chercher.
    • Le champ d'entrĂ©e clavier (input).
    • le champ de sortie qui servira d'affichage (output).
  3. Exécuter le programme pas à pas (step) en vitesse lente ("OPTIONS" : "def slow"). A la fin, relancer l'exécution pour essayer de comprendre au mieux les étapes de ce programme.

  4. Décrire à l'écrit l’enchaînement des opérations élémentaires effectuées lors de l’exécution des instructions.

  5. Pour chaque ligne d'instruction, décrire le rôle du PC, de l'UC, de la RAM, du l'UAL. On considérera l'état avant toute exécution de la ligne étudiée (ex: initialement, on étudie l'état des composants avant le début d'exécution de la ligne 0)
  6. Résumer vos notes dans ce tableau à compléter :
Ligne Instruction en assembleur Instruction en hexadécimal Etat/rôle du PC Etat/rôle de l'UC Etat/rôle de l'UAL Etat/rôle de la RAM Etat/rôle du registre
0 MOV R0, #10 e3a0000a Prochaine adresse Ă  chercher : 0 Vide Aucun rĂ´le Zone 0 en attente de chargement Vide
1 MOV R0, #250 e3a010fa Prochaine adresse à chercher : 1 A décodé l'instruction e3a0000a. En attente de l'instruction e3a010fa Aucun rôle Zone 0 chargée. Zone 1 en attente de chargement valeur 10 affectée au registre R0
... ... ... ... ... ... ... ...

Mon troisième programme en assembleur⚓︎

Comprendre le programme suivant :

Programme

Text Only
MOV R0, #10  
MOV R1, 10  
ADD R2, R1, R0  
STR R2, 11  
HALT

Pour l'étude vous pouvez : Sélectionner l’affichage Unsigned. Exécuter le programme pas à pas (step) en vitesse lente (options puis def slow).

  • Analysez l’enchaĂ®nement d’opĂ©rations Ă©lĂ©mentaires lors de l’exĂ©cution des instructions de transfert de mĂ©moire MOV R0,#10 puis LDR R1,10.
  • Observer l’évolution des registres PC (Compteur de programme), CIR (Registre d’instructions), MAR (adresse d’écriture/lecture en mĂ©moire) et MBR (donnĂ©e Ă  lire/Ă©crire).
  • Observez pour quelle(s) instruction(s), l’ALU est-elle sollicitĂ©e ?

Mon quatrième programme en assembleur⚓︎

Analysez l’enchaînement d’opérations élémentaires lors de l’exécution des instructions

  • OĂą sont stockĂ©es dans la mĂ©moire centrale les quatre valeurs calculĂ©es par ce programme ? Il s’agit des premières valeurs d’une suite cĂ©lèbre, laquelle ?
  • Rajouter les calculs de deux termes supplĂ©mentaires de la suite, par copier-coller (rajouter donc les itĂ©rations 5 et 6), puis exĂ©cuter le programme dans le simulateur. Observer l’état de la mĂ©moire, expliquer l’erreur signalĂ©e par l’UnitĂ© de ContrĂ´le et corriger le programme.
Text Only
//initialisation 
    MOV R0, #30
    MOV R1, #1
    STR R1, [R0]
    ADD R0, R0, #1
    MOV R2, #1
//itération 1
    STR R2, [R0]
    ADD R2, R2, R1
    LDR R1, [R0]
    ADD R0, R0, #1
//itération 2
    STR R2, [R0]
    ADD R2, R2, R1
    LDR R1, [R0]
    ADD R0, R0, #1
//itération 3
    STR R2, [R0]
    ADD R2, R2, R1
    LDR R1, [R0]
    ADD R0, R0, #1
//itération 4
    STR R2, [R0]
    ADD R2, R2, R1
    LDR R1, [R0]
    ADD R0, R0, #1
//fin
    HALT

Mon cinquième programme en assembleur : Entrées - sorties en assembleur (INP ; OUT)⚓︎

Dans le menu "SELECT", choisir le programme "add".

Le programme va se charger dans la zone d'Ă©dition.

Quelles sont les nouvelles instructions utilisées dans ce programme ?

Comme précédemment, décrire précisément la suite des instructions de ce programme d'addition.

Mon sixième programme en assembleur.⚓︎

En assembleur :

else: et fin: sont des étiquettes qui jouent le rôle de repères / points de chute, dans les instructions de branchement / saut.

Text Only
B 45      Structure de rupture de séquence, la prochaine instruction à exécuter se situe en mémoire vive à l'adresse 45

CMP R0, #23  Compare la valeur stockée dans le registre R0 et le nombre 23. Cette instruction CMP doit précéder une                       instruction de branchement conditionnel BEQ, BNE, BGT, BLT

CMP R0, R1  Compare la valeur stockée dans le registre R0 et la valeur stockée dans le registre R1.

CMP R0, #23
BEQ 78     La prochaine instruction à exécuter se situe à l'adresse mémoire 78 si la valeur stockée dans le registre                    R0 est égale à 23


CMP R0, #23
BNE 78     La prochaine instruction à exécuter se situe à l'adresse mémoire 78 si la valeur stockée dans le registre R0                n'est pas égale à 23

CMP R0, #23
BGT 78      La prochaine instruction à exécuter se situe à l'adresse mémoire 78 si la valeur stockée dans le registre R0                est plus grand que 23

CMP R0, #23
BLT 78     La prochaine instruction à exécuter se situe à l'adresse mémoire 78 si la valeur stockée dans le registre R0                est plus petit que 23

B fin est une instruction de branchement / saut inconditionnel : le programme se poursuit à partir de l’étiquette fin, le flux normal (passage à la ligne suivante) est interrompu.

CMP R0,#0 est une instruction de comparaison qui compare le contenu du registre R0 au nombre 0. Elle est suivie d’une instruction de branchement (ou saut) conditionnel BLT else : le programme se poursuit soit à partir de l’étiquette else si R0 est plus petit que 0, sinon avec l’instruction de la ligne suivante (comportement par défaut).

Mon septième programme en assembleur.⚓︎

On considère le programme Python ci-dessous :

Python
    a = int(input()) #entier lu stocké dans le registre R0
    b = int(input()) #entier lu stocké dans le registre R1
    if a > b:
        m = a
    else:
        m = b
    #le maximum m de a et b est stocké dans le registre R2
    #et en mémoire centrale à l’adresse 20
    print(m)
Traduire ce programme en assembleur puis le tester dans le simulateur.

Résumé

Le langage assembleur est donc une simple traduction brute du langage machine. Pour résumer :

  • Le langage machine est une succession de bits qui est directement interprĂ©table par le processeur d'un ordinateur.
  • Un langage assembleur est le langage machine oĂą les combinaisons de bits sont reprĂ©sentĂ©es par des "symboles" qu'un ĂŞtre humain peut mĂ©moriser.
  • Un programme assembleur convertit ces "symboles" en la combinaison de bits correspondante pour que le processeur puisse traiter l'information. Le programme assembleur traduit donc le langage assembleur en langage machine.

Remarques : - Un langage assembleur est souvent spécifique à un type de processeur. - Un langage assembleur est appelé "langage de bas niveau" car il est très proche du langage machine.