L’architecture de Von Neumann décompose l’ordinateur en 4 parties distinctes :
Intel CPU Core i7 6700K
Le microprocesseur (ou unité centrale de traitement, UCT, en anglais Central Processing Unit, CPU) est un composant essentiel qui exécute les instructions machine des programmes informatiques.
Remarque : il est le plus souvent amovible, placé sur un support appelé socket, et équipé d’un radiateur et d’un ventilateur (c’est le composant de la carte mère le plus gourmand en énergie).
Il est schématiquement constitué de 3 parties :
source : https://fr.wikipedia.org/wiki/Mémoire_(informatique)
La mémoire permet de stocker des données et des programmes.
La mémoire se divise entre mémoire volatile (programmes et données en cours de fonctionnement) et mémoire permanente (programmes et données de base de la machine)
Dans la plupart des mémoires, les informations sont classées par adresses : chaque octet est accessible par une adresse unique.
Pour des raisons économiques, les mémoires sont en général divisées en plusieurs familles :
HDD
SSD
sert à stocker à long terme des grandes quantités d’informations. Les technologies les plus courantes de mémoires de masse sont électromécaniques (disques durs – HDD) ou à semi-conducteurs (SSD, clefs USB, …), elles visent à obtenir une capacité de stockage élevée à faible coût et ont généralement une vitesse inférieure aux autres mémoires.
ordres de grandeur :
SDRAM
espace principal de stockage du microprocesseur, mais dont le contenu disparaît lors de la mise hors tension de l’ordinateur.
ordres de grandeur :
Différents niveaux de mémoire
sert à conserver un court instant des informations fréquemment consultées. Les technologies des mémoires caches visent à accélérer la vitesse des opérations de consultation. Elles ont une très grande vitesse, et un coût élevé pour une faible capacité de stockage.
ordres de grandeur :
intégré au processeur. Ce type de mémoire est très rapide mais aussi très cher et est donc réservé à une très faible quantité de données.
ordres de grandeur :
Dans les microprocesseurs, les opérations booléennes sont réalisées par des transistors formant ce que l’on appelle des circuits logiques.
Un circuit logique prend en entrée et donne en sortie des signaux électriques à deux états (HAUT et BAS). Il existe deux catégories de circuit logique :
On représente les circuits logiques à l’aide de schémas appelés logigrammes (voir l’article sur les booléens pour le détail des symboles).
Voici quelques actions élémentaires que l’on peut réaliser à l’aide de circuits logiques :
Le transistor est l'élément de base des circuits logiques. Un circuit logique permet de réaliser une opération booléenne. Ces opérations booléennes sont directement liées à l'algèbre de Boole (Georges Boole, mathématicien Britanique 1815-1864). L'étude de l'algèbre de Boole dépasse le cadre de ce cours, vous devez juste savoir qu'un circuit logique prend en entrée un ou des signaux électriques (chaque entrée est dans un état "haut" (symbolisé par un "1") ou à un état "bas" (symbolisé par un "0")) et donne en sortie un ou des signaux électriques (chaque sortie est aussi dans un état "haut" ou à un état "bas"). Il existe deux catégories de circuit logique :
Le plus simple des circuits combinatoires est la porte "NON" ("NOT" en anglais) qui inverse l'état en entrée : si l'entrée de la porte est dans un état "bas" alors la sortie sera dans un état "haut" et vice versa. Si on symbolise l'état "haut" par un "1" et l'état "bas" pour un "0", on peut obtenir ce que l'on appelle la table de vérité de la porte "NON" :
E (Entrée) | S (Sortie) |
1 | 0 |
0 | 1 |
La porte "NON" est symbolisée par le schéma suivant :
La porte "OU" a deux entrées (E1 et E2) et une sortie S
Table de vérité porte "OU" :
E1 | E2 | S |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
La porte "ET" ("AND") a deux entrées (E1 et E2) et une sortie S
Table de vérité porte "ET" :
E1 | E2 | S |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
La porte "OU EXCLUSIF" ("XOR") a deux entrées (E1 et E2) et une sortie S
Table de vérité porte "XOR" :
E1 | E2 | S |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
En combinant les portes logiques, on obtient des circuits plus complexes. Par exemple en combinant 2 portes "OU EXCLUSIF", 2 portes "ET" et une porte "OU" on obtient un additionneur :
L’addition de deux bits peut être « simplement » réalisée grâce à une porte XOR :
|
Mais cette opération ne prend pas en compte la retenue, car elle donne le résultat sur un seul bit, :
Pour additionner des nombres codés sur plusieurs bits (comme les entiers naturels par exemple), il faut réaliser plusieurs additions de bits, mais en tenant compte de la retenue :
Cet additionneur permet d’additionner 2 bits (E1 et E2) en tenant compte de la retenue entrante (« Cin » , carry in en anglais). En sortie on obtient le résultat de l’addition (S) et la retenue sortante (« Cout », carry out).
0 | 0 | 0 | ||
0 | 0 | 1 | ||
0 | 1 | 0 | ||
0 | 1 | 1 | ||
1 | 0 | 0 | ||
1 | 0 | 1 | ||
1 | 1 | 0 | ||
1 | 1 | 1 |
Pour réaliser une addition sur des nombres de plusieurs bits, on combine plusieurs circuits logiques d’addition :
Le langage machine est une succession de bits qui est interprétable par le processeur d'un ordinateur.
Comme ces successions de bits sont très peu gérable par un humain, un langage de programmation de bas niveau est nécessaire :
Un langage assembleur est le langage machine machine ou des 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.
Un langage assembleur est souvent spécifique un type de processeur.
On considère ici un processeur de type x86.
On veut faire comprendre à un processeur de ce type l'instruction suivante : écrire le nombre 97 dans le registre AL.
Voici comment écrire cette instruction en langage assembleur : movb 0x61,%al
.
Pour comprendre :
la partie movb %al
signifie écrire dans le registre AL,
la partie $0x61
correspond au nombre 97 écrit en hexadécimal car
97=61(16).
Voici comment un programme assembleur va convertir en binaire : 10110000 01100001
.
Pour comprendre :
la partie movb %al
est codée en 10110000
,
le nombre 97, donc le code hexadécimal $0x61
, s'écrit en binaire
01100001
car 97=64+32+1.
En langage assembleur, on peut rencontrer :
des calculs simples (addition, soustraction, multiplication, ...),
des affectations (placer telle valeur de la mémoire vive dans tel registre et vice versa)
des instructions de saut qui permettent de coder des instructions conditionnelles par exemple.
De plus, il y a trois possibilités pour accéder à un opérande (valeur sur laquelle va être opérée une opération) :
Dans les années 40 et 50, les programmes étaient surtout écrits en langage assembleur. Cependant, c'était long, fastidieux et les erreurs étaient fréquentes.
Ensuite, des langages de plus haut niveau ont permis des codes plus simples à écrire et à comprendre par des humains tandis que les progrès des puissances des ordinateurs permettait de compiler ces langages de haut niveau en langage machine en assez peu de temps.
Des programmes tel que le système d'exploitation DOS (le plus utilisé sur PC jusque vers 1990) ou les jeux vidéos pour console comme Super Nintendo ou Mega Drive ont été écrits en langage assembleur.
Source : "INTERROS des LYCEES-Les VRAIS EXOS donnés dans les lycées"-"numérique et sciences informatiques"-Stéphane PASQUET-Nathan
On imagine un ordinateur constitué d'une mémoire centrale et d'un jeu d'instructions.
Voici le tableau d'instructions :
Instruction | Effet |
---|---|
LD X | Lit le contenu de la cellule X (ACC ← #X) |
STO X | Enregistre dans la cellule X (#X ← ACC) |
ADD X | Ajoute le contenu de la cellule X (ACC ← ACC + #X) |
SUB X | Soustrait le contenu de la cellule X (ACC ← ACC - #X) |
JMP ADR | Saute à l'adresse ADR (CO ← A) |
JMPZ ADR | Saute à l'adresse ADR si nul |
JMPP ADR | Saute à l'adresse ADR si positif |
JMPN ADR | Saute à l'adresse ADR si négatif |
On considérera qu'un programme commence à l'adresse 8, les adresses 0 à 7 étant réservées au stockage des données.
Voici un exemple de programme :
Adresse | Contenu |
---|---|
0 | 25 |
1 | 14 |
..... | ...... |
8 | LD 0 |
9 | SUB 1 |
10 | STO 2 |
11 | END |
Que fait ce programme ?
Écrire un programme qui traduit l'expression x=4;x=x+5
.
On suppose que les variables x
et y
sont liées aux adresses 0 et 1.
Il existe autant de langages machines que de types de processeurs. Les commandes de base sont assez faciles à transposer d'un langage à l'autre.
Par exemple, l'instruction qui permet de copier le contenu d'un registre dans une mémoire donnée par son
adresse peut
s'appeler suivant les processeurs STO
, STR
ou STA
.
Afin de pouvoir mieux visualiser le fonctionnement d'un processeur et de pouvoir tester ses lignes de code en langage assembleur, nous allons désormais utiliser le simulateur accessible avec ce lien.
Voici un visuel de ce simulateur :
Voici une présentation en vidéo de ce simulateur.
Voici un nouvel exercice de programmation en assembleur. Cependant, le jeu d'instructions n'est pas le même que celui de l'exercice 1 car ce jeu correspond désormais à celui du simulateur précédemment présenté ; dans toute la suite du chapitre, c'est ce jeu d'instructions qui sera utilisé.
Voici le tableau d'instructions de ce simulateur :
Instruction | Effet |
---|---|
INP | Lire une valeur à partir de la console d'entrée |
OUT | Ecrire une valeur sur la console d'affichage |
ADD | Addition |
SUB | Soustraction |
MOV | Affectation |
LDR | Affectation |
STR | Affectation |
B | Aller à |
HALT | Fin du programme |
CMP | Comparaison |
BEQ | Comparaison (égalité) puis saut à une adresse |
BNE | Comparaison (égalité) puis saut à une adresse |
BGT | Comparaison (supérieur) puis saut à une adresse |
BLT | Comparaison (inférieur) puis saut à une adresse |
#
pour le différencier d'une adresse mémoire Le nombre 25 est précédé d'un #
pour le différencier d'une adresse mémoire.
Pour les instructions de saut, on donne un label, ici test, à la place d'une adresse.
Vous pouvez obtenir un détail sur le jeu d'instructions de ce simulateur à cette endroit de la page .
Observer le programme écrit en langage machine :
Indiquer la signification de cette suite d’instructions.
Quel est le contenu de R0,R1,R2 à la fin de ces instructions ?
Que signifie la commande OUT R2,4
Voici une image plus complète du programme dans le simulateur :
Écrire en langage assembleur du simulateur le programme suivant :
x=15
y=12
z=x-y
print(z)
Voici un script en langage assembleur :
INP R0,2
INP R1,2
CMP R1,R0
BGT VRAI
OUT R0,4
B DONE
VRAI:
OUT R1,4
DONE:
HALT
Essayer de deviner ce que fait ce programme sans lancer le simulateur
Vous pouvez vous aider du détail sur le jeu d'instructions du simulateur présent à cet endroit de la page .
Tester le programme en langage assembleur en utilisant le simulateur accessible à cette adresse avec comme saisie 4 puis 8
Tester le programme en langage assembleur en utilisant le simulateur accessible à cette adresse avec comme saisie 7 puis 2
Que fait ce programme écrit en langage assembleur ?
Voici un programme Python très simple :
x = 4
y = 8
if x == 10:
y = 9
else :
x=x+1
z=6
et voici maintenant voici son équivalent en assembleur :
MOV R0, #4
STR R0,30
MOV R0, #8
STR R0,75
LDR R0,30
CMP R0, #10
BNE else
MOV R0, #9
STR R0,75
B endif
else:
LDR R0,30
ADD R0, R0, #1
STR R0,30
endif:
MOV R0, #6
STR R0,23
HALT
Après avoir analysé très attentivement le programme en assembleur ci-dessus, vous essaierez d'établir une correspondance entre les lignes du programme en Python et les lignes du programme en assembleur. À quoi sert la ligne "B endif" ? À quoi correspondent les adresses mémoires 23, 75 et 30 ?
Voici la liste des instructions de ce simulateur, instructions traduites en français :
Compléments pour les instructions DAT, INP et OUT :
La liste d'instructions en anglais :
The AQA Instruction Set.
Un langage compilé est un langage de programmation qui lors de son exécution utilise un compilateur, c'est-à-dire un programme qui traduit le code source écrit dans ce langage de programmation en langage assembleur ou en langage machine afin de créer un programme directement exécutable sur la machine.
Ensuite, c'est ce fichier intermédiaire créé qui est exécuté sur la machine.
Par contre, un langage interprété est un langage de programmation qui lors de l'exécution fait appel à un interpréteur qui va exécuter le programme instruction par instruction ainsi :
lire et analyser l'instruction,
si l'instruction est syntaxiquement correcte dans la langage de programmation, l'exécuter,
passer à l'instruction suivante.
Ici, pas de fichier intermédiaire.
Le langage Python est un langage interprété un peu hybride, c'est-à-dire que le code en Python est déjà compilé en un bytecode, un code intermédiaire qui n'est pas directement exécutable par un processeur mais qui est ensuite interprété par un interpréteur.
Pour comprendre comment un programme (simple) écrit dans le langage de haut-niveau Python va être traduit
en langage machine, il est intéressant d'utiliser le module dis
qui permet d'examiner le
bytecode
intermédiaire.
Voici le code en Python que l'on va étudier :
x = 4
x = x + 5
Pour étudier ce code, il suffit d'excuter le code suivant
import dis # importation du module permettant l'étude
dis.dis('x = 4; x = x + 5; print(x)')
Voici ce qui est affiché ; c'est le bytecode désassemblé :
1 0 LOAD_CONST 0 (4)
2 STORE_NAME 0 (x)
4 LOAD_NAME 0 (x)
6 LOAD_CONST 1 (5)
8 BINARY_ADD
10 STORE_NAME 0 (x)
12 LOAD_CONST 2 (None)
14 RETURN_VALUE
Les lignes affichées ont respectivement la signification suivante :
0 :Le nombre 4 est stocké dans un registre,
2 : le contenu de ce registre est copié dans la mémoire au niveau de la case dont l'adresse est x,
4 : la valeur de x est copiée dans un registre,
6 : le nombre 5 est copié dans un autre registre,
8 : l'addition des deux nombres (ceux en haut de la "pile" c'est-à-dire repéés par les nombres 0 et 1 de la troisième colonne),
10 : le résultat de l'addition est copié dans la mémoire au niveau de la mémoire dont l'adresse est x,
12 : la valeur None est copiée dans un troisième registre,
14 : cette valeur None est renvoyée.
Ce code est proche de ce que l'on pourrait écrire dans le langage assembleur du simulateur :
MOV R0, #4
STR R0, x
LDR R0, x
MOV R1, #5
ADD R0, R0, R1
STR R0,x
HALT
0
0
0
x: 0