Skip to content

Niveau 4 · Chapitre 4.1

Le cycle fetch–decode–execute

Ce que fait un CPU pour chaque instruction : la lire, la décoder, lire ses opérandes, l’exécuter, écrire le résultat — micro-opération par micro-opération.

Un CPU exécute un programme en répétant une seule boucle, des milliards de fois par seconde :

  1. Fetch : lire l’instruction à l’adresse contenue dans rip (le compteur ordinal), puis avancer rip au-delà.
  2. Decode : la décoder, c’est-à-dire déterminer l’opération et l’emplacement de ses opérandes.
  3. Lecture des opérandes : depuis les registres, depuis l’instruction elle-même, ou depuis la mémoire — ce qui impose d’abord de calculer l’adresse.
  4. Execute : l’ALU calcule le résultat.
  5. Write-back : écrire le résultat dans un registre, ou le ranger en mémoire.

rip avance dès que l’instruction a été lue : pendant une instruction, rip contient donc déjà l’adresse de la suivante — c’est sur cette valeur que s’appuient l’adressage relatif à rip et call. Un saut se contente de l’écraser avec une nouvelle cible.

Chaque instruction — un mov, un add, un call — combine ces étapes. Au niveau de l’assembleur, on ne voit que l’instruction. Un niveau plus bas, dans la microarchitecture, on voit les étapes.

Les démos de ce chapitre s’ouvrent sur l’onglet CPU & buses du simulateur. À chaque Step, il rejoue les micro-opérations de l’instruction qui vient de s’exécuter, une par une, sur un schéma du CPU, du bus système et de la mémoire. Utilisez les flèches ◀ ▶ à côté de µop pour les parcourir à votre rythme. Pour garder le schéma lisible, le simulateur montre la mise à jour de rip comme dernière micro-opération de chaque instruction, une fois la décision de saut connue ; le résultat est le même.

L’instruction la plus simple : mov eax, 5

Live · mov eax, 5
program— ▸ is the next instruction
  1. mov eax, 5
step 0
Loading emulator…

Cinq micro-opérations :

#ÉtapeCe qui se passe
1Fetchrip est copié dans le MAR (registre d’adresse mémoire) et placé sur le bus d’adresses ; l’unité de contrôle active MEMR (lecture mémoire) ; la mémoire répond sur le bus de données avec l’instruction, qui arrive dans l’IR (registre d’instruction).
2DecodeL’unité de contrôle décode l’IR : opération mov, destination eax, source une valeur immédiate.
3OpérandeLa valeur immédiate 5 fait partie de l’instruction — elle vient directement de l’IR, sans accès mémoire.
4Write-back5 est écrit dans eax.
5Suivanterip avance à l’instruction suivante.

Un seul cycle de bus au total : le fetch. Tout le reste se passe à l’intérieur du CPU.

Le nom des signaux de contrôle varie selon les bus : MEMR/MEMW sont les noms du bus ISA utilisés ici, alors que beaucoup de bus de manuel utilisent une ligne de requête mémoire (MREQ) et deux lignes RD et WR. Même idée : une ligne signale un accès mémoire, une autre en donne le sens.

Un cycle complet : add eax, DWORD PTR [rbp-4]

Voici maintenant une instruction qui utilise toutes les étapes. La démo range d’abord 10 en [rbp-4] et charge 5 dans eax, puis exécute le add :

Live · add avec un opérande mémoire
program— ▸ is the next instruction
  1. mov DWORD PTR [rbp-4], 10
  2. mov eax, 5
  3. add eax, DWORD PTR [rbp-4]
step 0
Loading emulator…

Le add prend huit micro-opérations :

  1. Fetch de l’instruction dans l’IR.
  2. Decode : un add, destination registre, source mémoire.
  3. Lecture de eax (5) depuis le banc de registres sur le bus interne.
  4. Calcul d’adresse : l’AGU calcule rbp − 4 = 0x7fffffdc. Avant de lire la mémoire, le CPU doit savoir où.
  5. Lecture mémoire : 0x7fffffdc passe dans le MAR et sur le bus d’adresses, MEMR est activé, et la mémoire place 10 sur le bus de données, dans le MDR (registre de données mémoire). Le simulateur met en évidence la région stack, où se trouve cette adresse.
  6. Execute : l’ALU calcule 5 + 10 = 15 et positionne les drapeaux.
  7. Write-back : 15 va dans eax.
  8. Suivante : rip avance.

Deux cycles de bus : la lecture de l’instruction et la lecture de la donnée. Le compteur bus cycles sous le schéma affiche 2 R · 0 W.

Écrire en mémoire : push rbx

Live · push rbx
program— ▸ is the next instruction
  1. mov rbx, 42
  2. push rbx
step 0
Loading emulator…

Une écriture parcourt l’étape mémoire dans l’autre sens :

  1. Fetch et 2. decode, comme d’habitude.
  2. Lecture de rbx (42).
  3. Mise à jour de rsp : rsp ← rsp − 8, pour faire de la place sur la pile. Le nouveau rsp est l’adresse où écrire.
  4. Écriture mémoire : l’adresse va dans le MAR, la valeur dans le MDR, les deux sortent sur les bus, et l’unité de contrôle active MEMW (écriture mémoire). La donnée va du CPU vers la mémoire.
  5. Suivante.

Une lecture (le fetch) et une écriture : 1 R · 1 W.

Les sauts : l’exécution décide du prochain rip

Live · jl : la dernière étape choisit la destination
program— ▸ is the next instruction
  1. mov eax, 3
  2. cmp eax, 5
  3. jl smaller
  4. mov ecx, 0
  5. smaller:
  6. mov ecx, 1
step 0
Loading emulator…

Un saut conditionnel n’a aucune donnée à lire ou écrire. Son étape d’exécution est une décision : l’unité de contrôle teste les drapeaux (ici SF ≠ OF : 1 ≠ 0, donc le saut est pris), et la dernière étape écrit l’adresse cible dans rip au lieu de la suivante. Remplacez 3 par 7 (Edit → Load) et la même dernière étape redevient un simple « instruction suivante ».

À ce niveau, un saut n’est rien d’autre qu’une instruction dont le résultat est écrit dans rip. Le niveau au-dessus explique quels drapeaux teste chaque saut.

Code et données partagent le bus

Regardez à quoi le bus passe son temps. Dans cette boucle de trois itérations, chaque instruction est lue en mémoire, et seul le add touche aussi aux données :

Live · Où partent les cycles de bus ?
program— ▸ is the next instruction
  1. mov ecx, 0
  2. loop_top:
  3. add DWORD PTR [rbp-4], 1 ; lecture-modification-écriture : 1 lecture + 1 écriture
  4. inc ecx
  5. cmp ecx, 3
  6. jl loop_top
step 0
Loading emulator…

Appuyez sur Continue et regardez le compteur total : 19 cycles de bus. 13 sont des lectures d’instructions (une par instruction exécutée), et seulement 6 déplacent des données (3 lectures et 3 écritures de [rbp-4]).

C’est l’architecture de von Neumann : instructions et données vivent dans la même mémoire et empruntent le même bus, si bien que la lecture du code entre en concurrence avec la lecture et l’écriture des données. Ce chemin partagé — le goulot d’étranglement de von Neumann — explique pourquoi les CPU réels ajoutent des caches, et pourquoi ils séparent le cache de premier niveau en un cache d’instructions et un cache de données (un cache séparé, ou conception Harvard au niveau L1), pour pouvoir lire les deux dans le même cycle.

Ce que ce simulateur simplifie

Le modèle présenté ici exécute une instruction à la fois, du début à la fin. Les vrais processeurs, non :

  • Longueur des instructions : ici, chaque instruction occupe une adresse et le fetch transporte son texte. Les vraies instructions x86 font de 1 à 15 octets de code machine, et le CPU en lit 16 ou plus à la fois.
  • Pipeline : pendant qu’une instruction s’exécute, la suivante est décodée et celle d’après est lue. Plusieurs instructions sont en cours en même temps.
  • Micro-opérations et exécution dans le désordre : les cœurs x86 modernes traduisent les instructions en micro-opérations internes, les exécutent dans le désordre dès que leurs entrées sont prêtes, puis les retirent dans l’ordre.
  • Caches : la plupart des lectures d’instructions et de données sont servies par des caches internes au CPU, pas par la mémoire principale via le bus système.

Rien de tout cela ne change la séquence logique observée : chaque instruction est toujours lue, décodée, exécutée et son résultat écrit. Pipelines et caches servent à effectuer ces étapes pour plusieurs instructions à la fois, et plus vite.

À retenir

  • Chaque instruction passe par fetch (et avancée de rip), decode, lecture des opérandes, execute et write-back.
  • Le MAR contient l’adresse et le MDR la donnée de chaque cycle de bus ; MEMR et MEMW indiquent le sens.
  • L’AGU calcule les adresses mémoire ; l’ALU calcule les résultats et les drapeaux.
  • Un saut est une instruction dont le résultat est écrit dans rip.
  • Dans une machine de von Neumann, code et données partagent un seul bus — et les lectures d’instructions représentent l’essentiel du trafic.

Dans ce niveau

  1. 4.1Le cycle fetch–decode–execute
  2. 4.2Chemin de données et bus
  3. 4.3Unité de contrôle et microcode
  4. 4.4Pipeline et aléasPrévu
  5. 4.5Caches et hiérarchie mémoirePrévu
  6. 4.6Prédiction de branchement et exécution dans le désordrePrévu
  7. 4.7Multicœurs et machines parallèlesPrévu