Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Architecture des ordinateurs Jérémy Fix CentraleSupélec [email protected] 2016-2017 Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Petit retour sur l’architecture v0 00 00800008 00000000 00000000 00000000 04 00000000 00000000 00000000 00000000 08 00000c00 01401900 00000000 00000000 +1 0c 0080000c 00000000 00000000 00000000 10 00000c00 00084100 00c01800 00000000 MicroPC 14 00000c00 00080500 00084100 00c01800 D 18 00000000 00000000 00000000 00000000 00 @Adr 01 [8:15] 1c 00000c00 00080500 00002200 00c01800 00 Mux 10 Adr 20 00000c00 00090100 00c01800 00000000 ··· ··· ··· ··· ··· 30 00b0e000 00000000 00000000 00000000 ··· ··· ··· ··· ··· [0:7] 11 MuxSel 70 00000c00 00881100 00000000 00000000 74 01802076 00c01800 00000c00 00881100 78 0188807a 00c01800 00000c00 00881100 CodeMCount 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 CodeMCount UAL SetB ReadB SetA ReadA SetPC ReadPC SetRADM SetMem ReadMem @Adr Bus B Bus A ReadMem 0x1000 0x0010 0x2000 0x0001 0x3000 0x1c00 0x000A 0x0000 Do ReadA RADM Adr 0x0000 0x0000 0x0000 0x0000 ReadB A B PC 0x0000 0x0000 0x0000 0x0000 SetRADM SetA SetB SetPC ReadPC A UAL Di SetMem B Z C S V Bus S Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Architecture à Jeu d’instructions (ISA) Code instruction 0x0c00 0x1000 0x1400 0x1c00 0x2000 0x2400 0x2c00 0x3000 0x3400 0x3800 0x3c00 0x4000 0x4400 0x4800 0x5000 0x5400 0x5800 0x5c00 0x6000 0x6400 0x7000 0x7400 0x7800 Architecture Nom END LDAi LDAd STA LDBi LDBd STB ADDA ADDB SUBA SUBB MULA MULB DIVA ANDA ANDB ORA ORB NOTA NOTB JMP JZA JZB Mots 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 Description Fin du programme Charge la valeur de l’opérande dans le registre A. [A:=opérande] Charge la valeur dans la RAM pointée par l’opérande dans le registre A. [A:=Mem Sauvegarde en mémoire la valeur du registre A à l’adresse donnée par l’opérande. Charge la valeur de l’opérande dans le registre B. [B:=opérande] Charge la valeur dans la RAM pointée par l’opérande dans le registre B. [B:=Mem Sauvegarde en mémoire la valeur du registre B à l’adresse donnée par l’opérande. Ajoute le contenu des registres A et B et mémorise le résultat dans le registre A. [ Ajoute le contenu des registres A et B et mémorise le résultat dans le registre B. [ Soutstrait le contenu des registres A et B et mémorise le résultat dans le registre A Soutstrait le contenu des registres A et B et mémorise le résultat dans le registre B Multiplie le contenu des registres A et B et mémorise le résultat dans le registre A Multiplie le contenu des registres A et B et mémorise le résultat dans le registre B Divise le contenu du registre A par deux et mémorise le résultat dans A. [A:=A/2] Calcule un ET logique entre le contenu des registres A et B et mémorise le résulta Calcule un ET logique entre le contenu des registres A et B et mémorise le résulta Calcule un OU logique entre le contenu des registres A et B et mémorise le résulta Calcule un OU logique entre le contenu des registres A et B et mémorise le résulta Mémorise dans A la négation de A. [A:=!A] Mémorise dans B la négation de B. [B:=!B] Saute inconditionnellement à l’adresse donnée par l’opérande. [PC:=operande] Saute à l’adresse donnée par l’opérande si le contenu du registre A est nul. [PC:= Saute à l’adresse donnée par l’opérande si le contenu du registre B est nul. [PC := Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Automate à états finis du séquenceur 0 × 10 0 × 11 ReadPC=1 UAL=0000 SetRADM=1 ReadMem=1 UAL=0001 SetA=1 0 × 20 0 × 21 ReadPC=1 UAL=0000 SetRADM=1 ReadMem=1 UAL=0001 SetB=1 0 × 1c 0 × 1d 0 × 1e ReadPC=1 ReadMem=1 ReadA=1 UAL=0000 UAL=0001 UAL=0000 SetRADM=1 SetRADM=1 SetMem=1 0 × 00 0 × 08 ReadPC=1 CodeMCount=001 UAL=0000 @Adr=0x08 SetRADM=1 0 × 09 0 × 22 ReadPC=1 UAL=1000 SetPC=1 CodeMCount=001 @Adr=0x00 0 × 1f ReadPC=1 UAL=1000 SetPC=1 CodeMCount=001 @Adr=0x00 0 × 30 ReadA=1 ReadB=1 UAL=0110 SetA=1 CodeMCount=001 @Adr=0x00 ReadMem=1 CodeMCount=010 ReadPC=1 SetPC=1 UAL=1000 0 × 14 0 × 15 0 × 16 ReadPC=1 ReadMem=1 ReadMem=1 UAL=0000 UAL=0001 UAL=0001 SetRADM=1 SetRADM=1 SetA=1 Architecture 0 × 12 ReadPC=1 UAL=1000 SetPC=1 CodeMCount=001 @Adr=0x00 0 × 17 ReadPC=1 UAL=1000 SetPC=1 CodeMCount=001 @Adr=0x00 Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Séquenceur et programme Séquenceur • Sémantique des instructions • Générique • Automate à états finis : état dans MicroPC, signaux de contrôle ROM[MicroPC] Programme • Qu’est ce que je veux calculer ? • Spécifique • Séquence de codes d’instructions et de données en RAM Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau La v0 est conçue, programmons la ! Conception • Chemin de données • Jeu d’instructions • Séquenceur Programmation • Code machine (instructions/données) • Calcul des adresses “à la main” • adresses des branchements? • adresses des données ? Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau C’est dur et long pour le moment de programmer Calculer la suite de Syracuse ∗ ∀n ∈ N , un+1 ( un /2 = 3un+1 + 1 si un est pair sinon u0 = 127; un =? ⇔ Code machine 1000 007f 1c00 0024 1c00 1000 1400 0024 2000 0001 5000 7400 001b 1400 0024 2000 0003 4000 2000 0001 3000 1c00 0024 1c00 1000 7000 0006 1400 0024 4800 1c00 0024 1c00 1000 7000 0006 si si, je vous assure. Donc, c’est dur et long. Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau C’est dur et long pour le moment de programmer Calculer la suite de Syracuse ∗ ∀n ∈ N , un+1 ( un /2 = 3un+1 + 1 si un est pair sinon u0 = 127; un =? ⇔ Code machine [LDAi 007f STA 0024 STA 1000] [LDAd 0024 LDBi 0001 ANDA JZA 001b] [LDAd 0024 LDBi 0003 MULA LDBi 0001 ADDA STA 0024 STA 1000 JMP 0006] [LDAd 0024 DIVA STA 0024 STA 1000 JMP 0006] si si, je vous assure. Donc, c’est dur et long. Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Comment faire pour simplifier la programmation ? Ne plus écrire en code machine1 Code machine (arg..) 1000 0001 2000 0002 3000 ??? ←−− Assemblage (cool!) LDAi 1 LDBi 2 ADDA ??? ←−− Python (super cool!) a=1 b=2 a=a+b • Langage d’assemblage ? LDAi, STA, ADDA, .. • Langages de haut-niveau (architecture indépendant) : C++, Python, .. ? et bien sûr comment faire la conversion vers le langage machine 1 Architecture parfois utile tout de même Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Comment faire pour simplifier la programmation ? Les procédures (ou fonctions) Définition : succession d’opérations à exécuter pour accomplir une tâche déterminée [Larousse] Exemple de Syracuse en Python: Sans procédures un = 127 if(un % 2 == un = un/2 else: un = 3 un if(un % 2 == un = un/2 else: un = 3 un if(un % 2 == un = un/2 else: Architecture Avec procédures 0): + 1 0): + 1 0): def f(u): if(u % 2 == 0): return u/2 else: return 3 * u + 1 u = 127 u = f(u) u = f(u) Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau On a presque des procédures Syrarcuse 0x0000 1000 007E 7000 0014 7000 0014 7000 0014 ··· 0x000A 0x0014 2000 0001 5400 7800 001F 2000 0003 4400 2000 0001 3400 0x001F 4800 0000 0000 0000 0000 .. . 0x0000 0x000A 0x0014 0x001F ⇔ 007E JMP 0014 JMP 0014 JMP 0014 ··· LDBi 0001 ANDB JZB 001F LDBi 0003 MULB LDBi 0001 ADDB DIVA 0000 0000 0000 0000 LDAi } }f .. . • programme de f : 0 × 0014 • on utilise ici explicitement le registre A pour stocker les arguments et le résultat • retour ? Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Nous avons donc trois problèmes à résoudre : • comment passer les arguments à la routine ? • Registres dédiés : combien ?? • comment revenir au programme appelant ? • sauvegarder l’adresse de retour dans un registre dédié : link register; que faire lors d’appels cascadés (A appelle B qui appelle C qui appelle ...) • comment récupérer le résultat ? • un registre dédié ? Ces trois questions trouvent leur réponse dans l’utilisation d’une structure particulière : la pile Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Procédures, pile et pointeur de pile Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Spécifications d’une pile Une pile en mémoire • structure de données en mémoire principale (RAM) • empiler, dépiler une valeur : sommet de pile • ou est le sommet de pile : registre Stack Pointer Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Ajout de SP dans le chemin de données 00 00800008 00000000 00000000 00000000 04 00000000 00000000 00000000 00000000 08 00000c00 01401900 00000000 00000000 +1 0c 0080000c 00000000 00000000 00000000 MicroPC ··· ··· ··· ··· D ··· 00 @Adr 01 [8:15] 00 Mux 10 Adr 90 [0:7] ··· 11 MuxSel 00c60000 00000000 00000000 00000000 ··· ··· B0 00020400 00002200 B4 00460400 00884100 B8 00000c00 00320500 BC 000000c0000320500 CodeMCount 32 ··· ··· 00ce0000 00000000 00002200 00084100 00000000 00000000 00C01800 00c01800 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 CodeMCount UAL SetSP ReadSP SetB ReadB SetA ReadA SetPC ReadPC SetRADM SetMem ReadMem @Adr Bus B Bus A ReadMem 0x1000 0x0010 0x2000 0x0001 0x3000 0x1c00 0x000A 0x0000 Do ReadA RADM Adr 0x0000 0x0000 0x0000 0x0000 ReadB ReadPC A B PC SP 0x0000 0x0000 0x0000 0x0000 0x0000 SetRADM SetA SetB SetPC SetSP ReadSP A UAL Di SetMem B Z C S V Bus S Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Ajout d’instructions de manipulation de la pile Spécifications • ou placer la pile en mémoire ? • quelle est l’adresse du sommet de la pile en mémoire ? • comment empiler/dépiler, écrire/lire des éléments de la pile ? Instructions particulières • pour manipuler le registre SP : LDSPi, STSP, INCSP, DECSP • pour empiler/dépile : PUSH{A,B}, POP{A, B} • pour lire/écrire relativement à SP : POKE{A,B}, PEEK{A,B} Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau PUSH, POP, POKE, PEEK, Hum?! Exemple de POPA Exemple de PUSHA Après l'opération 0x0010 0x0000 0x0010 0x0000 0x0010 0x0000 0x0010 0x0000 0x0011 0x0000 0x0011 0x0000 0x0011 0x0000 0x0011 0x0000 0x0012 0x0000 0x0012 0x0000 0x0012 0x0000 0x0012 0x0013 0x0000 0x0013 0x0000 0x0013 0x0000 0x0014 0x0000 0x0014 0x0004 0x0014 0x0015 0x0003 0x0015 0x0003 0x0016 0x0002 0x0016 0x0017 0x0001 0x0017 Registre A SP = 0x0014 Registre A 0x0004 SP = 0x0013 0x0000 0x0013 0x0000 0x0004 0x0014 0x0004 0x0015 0x0003 0x0015 0x0003 0x0002 0x0016 0x0002 0x0016 0x0002 0x0001 0x0017 0x0001 0x0017 0x0001 SP = 0x0013 Registre A 0x0004 Registre A 0x0000 Après l'opération 0x0004 Après l'opération Avant l'opération 0x0000 0x0010 0x0000 0x0010 0x0000 0x0010 0x0000 0x0011 0x0000 0x0011 0x0000 0x0011 0x0000 0x0011 0x0000 0x0012 0x0000 0x0012 0x0000 0x0012 0x0000 0x0012 0x0013 0x0000 0x0013 0x0000 0x0013 0x0000 0x0014 0x0000 0x0014 0x0000 0x0014 0x0015 0x0003 0x0015 0x0003 0x0015 SP = 0x0014 Adresses 0x0010 SP = 0x0014 SP = 0x0013 0x0000 0x0013 0x0000 0x0004 0x0014 0x0004 0x0003 0x0015 0x0003 0x0016 0x0002 0x0016 0x0004 0x0016 0x0002 0x0016 0x0002 0x0017 0x0001 0x0017 0x0001 0x0017 0x0001 0x0017 0x0001 Registre A 0x0004 Registre A 0x0004 SP = 0x0014 Exemple de PEEKA 0x0002 Exemple de POKEA 0x0002 Avant l'opération Adresses Après l'opération Avant l'opération Adresses Adresses Avant l'opération Registre A 0x0000 Registre A SP = 0x0013 0x0003 → Machines à états (b0, b4, b8, bc)? Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Utilisons la pile pour passer des arguments 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: Architecture function somme(N) Soient i, res deux variables locales i ←N −1 res ← 0 while i 6= 0 do res ← res + i i ←i −1 return res function main somme(3) Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Somme: Une première tentative main : // On initialise le registre SP somme : // On réserve de la place pour // les variables locales i et res LDSPI 0x010F DECSP DECSP // On effectue les calculs de la routine // en utilisant PEEKA 0x0001 et PEEKA 0x0002 // pour accder aux variables locales // en utilisant PEEKA 0x0003 pour l’argument // On dépile les variables locales // On empile l’argument LDAi 0x0003 JMP PUSHA Appel de somme // On dépile l’argument POPA ???? INCSP INCSP // On retourne au programme principal LDAi 0x0003 PUSHA DECSP DECSP On empile l’argument ··· ··· 0 × 010B 0 × 0000 0 × 0000 0 × 010D 0 × 0000 0 × 0000 0 × 010C 0 × 010E 0 × 010F Registre A Registre SP 0 × 0000 0 × 0000 0 × 0000 ··· 0 × 0000 0 × 010F ··· 0 × 0000 0 × 0000 SP 0 × 0000 0 × 0003 ··· 0 × 0003 0 × 010E Programme main : Appelant Architecture On réserve de la place pour les variables locales 0 × 0000 SP 0 × 0000 0 × 0000 0 × 0003 ··· 0 × 0003 0 × 010C INCSP INCSP On supprime les variables locales POPA On dépile l’argument et le résultat ··· SP var res var i ··· 0 × 0000 0 × 0000 0 × 0000 0 × 0006 0 × 0004 0 × 0003 ··· 0 × 0006 0 × 010E Programme somme : Appelé 0 × 0000 SP 0 × 0006 0 × 0004 SP 0 × 0003 ··· 0 × 0006 0 × 010F Programme main Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Appel et retour de routines Spécifications • Quand on part exécuter le code d’une procédure, il faut sauvegarder là où retourner (marque page) • Quand on termine une procédure, il faut poursuivre le programme appelant Instructions particulières • CALL (0xA000): “CALL op” Empile l’adresse de la prochaine instruction et branche • RET (0xA800): “RET” Dépile dans PC l’adresse de retour Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Réalisation de ces instructions main : // On initialise le registre SP LDSPI 0x010F // On empile l’argument LDAi 0x0003 PUSHA CALL somme // On dépile l’argument POPA somme : // On réserve de la place pour // les variables locales i et res DECSP DECSP // On effectue les calculs de la routine // en utilisant PEEKA 0x0001 et PEEKA 0x0002 // pour accder aux variables locales // en utilisant PEEKA 0x0003 pour l’argument // On dépile les variables locales INCSP INCSP // On retourne au programme principal RET Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Réalisation de ces instructions 00 00800008 00000000 00000000 00000000 04 00000000 00000000 00000000 00000000 08 00000c00 01401900 00000000 00000000 +1 0c 0080000c 00000000 00000000 00000000 MicroPC ··· ··· ··· ··· D ··· 00 @Adr 01 [8:15] 00 Mux 10 Adr 90 [0:7] ··· 11 MuxSel 00c60000 00000000 00000000 00000000 ··· ··· B0 00020400 00002200 B4 00460400 00884100 B8 00000c00 00320500 BC 000000c0000320500 CodeMCount 32 ··· ··· 00ce0000 00000000 00002200 00084100 00000000 00000000 00C01800 00c01800 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 SetT ReadT CodeMCount UAL SetSP ReadSP SetB ReadB SetA ReadA SetPC ReadPC SetRADM SetMem ReadMem @Adr Bus B Bus A ReadMem 0x1000 0x0010 0x2000 0x0001 0x3000 0x1c00 0x000A 0x0000 Do ReadT RADM Adr 0x0000 0x0000 0x0000 0x0000 0x0000 ReadA ReadB ReadPC Temp A B PC SP 0x0000 0x0000 0x0000 0x0000 0x0000 ReadSP A SetMem SetRADM SetT SetA SetB SetPC B Z C UAL Di S V SetSP Bus S Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Réalisation de ces instructions main : // On initialise le registre SP LDSPI 0x010F // On empile l’argument LDAi 0x0003 PUSHA CALL somme // On dépile l’argument POPA somme : // On réserve de la place pour // les variables locales i et res DECSP DECSP // On effectue les calculs de la routine // en utilisant PEEKA 0x0001 et PEEKA 0x0002 // pour accder aux variables locales // en utilisant PEEKA 0x0003 pour l’argument // On dépile les variables locales INCSP INCSP // On retourne au programme principal RET et le résultat au fait? La pile ! Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Somme : une deuxième tentative main : // On initialise le registre SP LDSPI 0x0020 // On réserve de la place pour le résultat somme : // On réserve de la place pour // les variables locales i et res DECSP DECSP DECSP // On effectue les calculs de la routine // en utilisant PEEKA 0x0001 et PEEKA 0x0002 // pour accder aux variables locales // en utilisant PEEKA 0x0003 pour l’argument // On dépile les variables locales // On empile l’argument LDAi 0x0003 PUSHA CALL somme // On dépile l’argument POPA // On récupère le résultat INCSP INCSP // On sauvegarde le résultat dans la pile POKEA 0x0002 // On retourne au programme principal RET INCSP POKEA 0x0002 POPA POPA DECSP On réserve de la place pour le résultat 0 × 010B 0 × 010C 0 × 010D 0 × 010E 0 × 010F Registre A Registre SP ··· ··· 0 × 0000 0 × 0000 0 × 0000 ··· 0 × 0000 0 × 010F 0 × 0000 SP 0 × 0000 0 × 0000 ··· 0 × 0000 0 × 010E Programme main Architecture ··· 0 × 0000 0 × 0000 0 × 0000 DECSP DECSP On réserve de la place pour les variables locales ··· 0 × 0000 0 × 0000 LDAi 0x0003 PUSHA On empile l’argument 0 × 0000 SP 0 × 0000 0 × 0003 0 × 0000 ··· 0 × 0003 0 × 010D 0 × 0000 SP 0 × 0000 0 × 0000 0 × 0003 0 × 0000 ··· 0 × 0003 0 × 010B SP var res var i POPA INCSP On supprime les variables locales On sauvegarde le résultat dans la pile ··· ··· 0 × 0000 0 × 0006 0 × 0004 0 × 0003 0 × 0000 ··· 0 × 0006 0 × 010D Programme somme ··· 0 × 0000 SP 0 × 0006 0 × 0004 0 × 0003 0 × 0006 ··· 0 × 0006 0 × 010D On dépile l’argument et le résultat 0 × 0000 SP 0 × 0006 0 × 0004 0 × 0003 SP 0 × 0006 ··· 0 × 0006 0 × 010F Programme main Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Déroulement d’un appel de routine Le programme appelant • réserve de la place pour le résultat (DECSP) • empile les arguments (PUSH) • sauvegarde la valeur PC après lecture de l’adresse de la routine et branche sur la routine (CALL) Programme appelé • lit les arguments dans la pile (PEEK), • calcule son résultat éventuel et le sauvegarde dans la pile (POKE) • retourne au programme appelant (RET) : le registre SP doit être restauré! Programme appelant • dépile les arguments (INCSP ou POP) • dépile le résultat (POP) et se poursuit Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Qui met/enlève quoi dans la pile ? Qui met quoi dans la pile ? Qui enlève quoi dans la pile ? Adresses Variables locales Programme appelé Adresse de retour (PC) CALL Arguments de la routine Programme appelant Place pour le résultat Sauvegarde éventuelle des registres Adresses Programme appelé RET Programme appelant Variables locales Adresse de retour (PC) Arguments de la routine Place pour le résultat Sauvegarde éventuelle des registres Attention! Dans cette version d’architecture, les accès PEEK, POKE sont relatifs au sommet de pile ! Autre possibilité : registre Base Pointer (BP) Pour restaurer le registre SP, on pourrait ajouter un registre Frame Pointer (FP) Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau C’est parti pour le code machine de : 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: Architecture function somme(N) Soient i, res deux variables locales i ←N −1 res ← 0 while i 6= 0 do res ← res + i i ←i −1 return res function main somme(3) Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Procédures Les procédures permettent : • de factoriser le code • d’éviter des bugs puisqu’on ne réécrit pas plusieurs fois le “même” code • de rendre le code plus compact mais avec un petit surcoût à l’exécution (parfois inévitable) Pile La pile permet : • de passer des arguments à une procédure • de récupérer le résultat d’une procédure • de sauvegarder l’adresse de retour d’une procédure • de sauvegarder des variables locales à la procédure Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Des fonctions récursives : Hanoı̈ Pilier 1 Pilier 2 Pilier 3 Pilier 1 Pilier 2 Pilier 3 ? Configuration initiale Configuration cible Problème Caluler le nombre de déplacement minimum nécessaires : ( 1 si n = 1 h(n) = 2h(n − 1) + 1 sinon h(4) =? Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Des fonctions récursives : Hanoı̈ 0x0006 CALL 0x000D 0x0FF3 0x0FF4 0x0FF5 0x0FF6 0x0FF7 0x0FF8 0x0FF9 0x0FFA 0x0FFB 0x0FFC 0x0FFD 0x0FFE 0x0FFF Adr. Mem. 0x0008 0x0004 0x0000 SP Adr. de retour de h(4) Argument de h(4) Résultat de h(4) 0x0018 0x0003 0x0000 0x0008 0x0004 0x0000 0x0016 CALL 0x000D 0x0016 CALL 0x000D 0x0018 0x0002 0x0000 0x0018 0x0003 0x0000 0x0008 0x0004 0x0000 0x0018 0x0001 0x0000 0x0018 0x0002 0x0000 0x0018 0x0003 0x0000 0x0008 0x0004 0x0000 Adr. de retour de h(3) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) Adr. de retour de h(2) Argument de h(2) Résultat de h(2) Adr. de retour de h(3) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) Adr. de retour de h(1) Argument de h(1) Résultat de h(1) Adr. de retour de h(2) Argument de h(2) Résultat de h(2) Adr. de retour de h(3) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) Pile 0x0027 RET 0x0018 0x0001 0x0001 0x0018 0x0002 0x0000 0x0018 0x0003 0x0000 0x0008 0x0004 0x0000 Architecture 0x0016 CALL 0x000D Argument de h(1) Résultat de h(1) Adr. de retour de h(2) Argument de h(2) Résultat de h(2) Adr. de retour de h(3) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) 0x0022 RET 0x0022 RET 0x0022 RET 0x0018 0x0001 0x0001 0x0018 0x0002 0x0003 0x0018 0x0003 0x0000 0x0008 0x0004 0x0000 0x0018 0x0001 0x0001 0x0018 0x0002 0x0003 0x0018 0x0003 0x0007 0x0008 0x0004 0x0000 0x0018 0x0001 0x0001 0x0018 0x0002 0x0003 0x0018 0x0003 0x0007 0x0008 0x0004 0x000F Argument de h(2) Résultat de h(2) Adr. de retour de h(3) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) Argument de h(3) Résultat de h(3) Adr. de retour de h(4) Argument de h(4) Résultat de h(4) Argument de h(4) Résultat de h(4) Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Au fait .. Comment passer de la formalisation du problème à un algorithme efficace permettant de le résoudre ?? Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Au fait .. Comment passer de la formalisation du problème à un algorithme efficace permettant de le résoudre ?? Cours FISDA: Fondement de l’Informatique, Structures de Données et Algorithmie Cours Génie logiciel: Etude des méthodes et bonnes pratiques pour le développement logiciel Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Simplifions la programmation de la machine Souhaits • un programme moins long, moins répétitif, mois sujet aux bugs : procédures et pile • mais on programme toujours en code machine ?!?! 8000 0FFF 1000 0001 2000 0002 .. . Architecture LDSPi 0x0FFF LDAi 0x0001 LDBi 0x0002 .. . Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau La couche d’assemblage Couche ISA LDAd LDAi Couche logique JMP STA Couche physique - circuits électroniques D JZA E PUSH Q - circuits optiques - autres technologies ? UAL SUBA POP ADDA Couche physique Vout Couche logique A B S 0 0 1 1 0 1 0 1 0 1 1 0 Couche ISA Registres : A, B, PC LDA : 0x1000 STA : 0x1c00 JMP : 0x7000 LDBi Couche d’assemblage main: LDAi 0x0003 STA 0x1000 JMP 0x0020 Langage de haut niveau C Python x = 3 print(x) for i in range(3): x = x - 1 int x = 3; printf(”%i”, x); while(x != 0) { x = x - 1; } Vin Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Langage d’assemblage et assembleur Adresse mémoire 0x0000 0x0002 0x0003 0x0005 0x0006 0x0008 0x0009 ........... 0x0020 0x0021 0x0022 0x0023 0x0024 0x0025 0x0026 ........... Programme assembleur LDSPi 0x0030 DECSP LDAi 0x0007 PUSHA LDAi 0x0008 PUSHA CALL sum .......... sum: PEEKA 0x0003 PEEKB 0x0002 ADDA POKEA 0x0004 RET Programme machine 8000 30 9400 1000 7 b000 1000 8 b000 a000 20 ......... bc00 3 cc00 2 3000 b800 4 a800 Assembleur : programme traduisant langage d’assemblage → code machine. Abus : programme assembleur = programme en langage d’assemblage Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Quelques éléments de syntaxe de notre assembleur • On utilise les mnémoniques LDAi, LDBi, STA, CALL, ... • les valeurs en hexadécimal sans préfixe 0x • “;” commentaire • étiquettes : pour les branchements, pour les variables; spécial @stack@ • pseudo-instructions : e.g. • DSW : allocation de variables globales; par convention en début de programme! Les variables et les étiquettes ne doivent pas être interprétables en hexadécimal Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Disposition du programme et des données en mémoire (chez nous) 0x0000 Programme ··· Pile ··· Variables globales (DSW) 0x0FFF Architecture 0x1000 Premier afficheur 0x1001 Deuxième afficheur 0x1002 Troisième afficheur ··· Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Traduction de quelques structures de contrôle while i 6= 0 do res ← res + i 3: i ←i −1 1: 2: loop: LDAd JZA LDBd ADDB STB LDBi SUBA STA JMP end: ... Architecture i end res res 1 i loop Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Traduction de quelques structures de contrôle for ⇔ while 1: for i = 0; i < N; i = i + 1 do 2: res ← res + i 1: i ← 0 2: while i 6= N do 3: res ← res + i 4: i ←i +1 ⇔ for ⇔ while 1: for (init; condition ; incrément) do 2: action 1: init 2: while condition do 3: action 4: incrément Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Traduction de quelques structures de contrôle if x! = 0 then x ←1 3: x ← x + 1 1: 2: end: Architecture LDAd JZA LDAi STA LDBi ADDA STA x end 1 x 1 x Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Traduction de quelques structures de contrôle if x == 10 then x ←0 3: else 4: x ←x +1 1: 2: LDAd LDBi SUBB JZB else: LDBi ADDA STA JMP if: LDAi STA end: .... Architecture x A if 1 x end 0 x Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau L’assembleur : traduction en code machine Exercice : Assembler le programme 1: u ← 127 2: while True do 3: u ← next(u) 4: print(u) 5: function next(u) 6: if u pair then return u/2 7: elsereturn 3u + 1 Compteur d’emplacement, table des symboles, variables globals; cf syr.asm Démo : python assemble.py Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Langage de haut niveau (Python, C, C++, Scala, ..) ++ Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Mais pourquoi ? Assembleur • spécifique à une architecture • encore dur à programmer (LDAd b; LDBd c; ADDA; STA a) • peu de vérification syntaxique: on peut ajouter des choux et des carottes Langage de haut niveau • indépendant de l’architecture • langage plus intuitif, e.g. a = b + c, structures de contrôle, définition de fonctions • vérification syntaxique Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Langage : Interprété ou compilé Langage compilé Un programme (compilateur) convertit le code source en code machine qui peut ensuite être exécuté Ex : C++/g++ g++ -S main.cc g++ -o main main.cc ; hexdump main ./main Langage interprété Un programme (interpréteur) interprète “à la volée” le code source Ex : Python/ python python main.py ⇒ Machine virtuelle python Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Brève Anatomie d’un compilateur C/C++ int main() { int x = 3; int y = 3 + x; } return x; Code machine 1000 0003 Analyse (frontend) Langage intermédiare (CFG) Synthèse (backend) 1c00 00FF 1000 0003 2400 00FF 3000 1c00 0100 Référence : “The dragon book” Aho, Lam, Sethi, Ullman Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau La phase d’analyse (frontend) Analyse lexicale Ségmentation et identification des lexèmes i n t x = y + 3 ; (”int”, type) (”x”, identifiant) (”=”, opérateur binaire) (”y”, identifiant) (”+”, opérateur binaire) ··· Analyse syntaxique Construction d’un arbre syntaxique à partir des lexèmes et d’une grammaire du langage. Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau La phase d’analyse (frontend) racine opérateur = x = 3; while(x > 0) { x = x - 1; } Analyse lexicale (”x”, identifiant) (”3”, constante) (”while”, mot clef) (”(”, parenthese) (”x”, identifiant) ··· while condition Analyse syntaxique variable x constante 3 opérateur > variable x constante 0 corps opérateur = variable x opérateur − variable x Architecture constante 1 Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Génération et optimisation d’une représentation intermédiaire Représentation intermédiaire • indépendante du langage source (C, C++, ..) et de l’architecture (x86, ARM, CentraleSupelec) • facile à produire, facile à convertir en code machine • optimisable Ex : register transfer language, gimple, generic, three adress code, single static assignment, control flow graph, ... Référence : “The dragon book” Aho, Lam, Sethi, Ullman Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Exemple de représentation intermédiaire : Three Adress code Eléments de syntaxe • opérations binaires : x := y op z • opérations unaires : x:= op y • copies : x := y • sauts (in)conditionnels : goto L; If x relop y goto L • procédures : param x1,.. call p, return y • ... Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Exemple de représentation intermédiaire : Three Adress code int x = 3; int y = 2 + 7 + x ; i n t z = 2∗ y ; if (x < y) { z = x /2 + y / 3 ; } else { z = x ∗ y + y; } Architecture x = 3; _t1 = 2 + 7; y = _t1 + x; z = 2 * y; _t2 = x < y; IfZ _t2 Goto _L0; _t3 = x / 2; _t4 = y / 3; z = _t3 + _t4 Goto _L1 _L0: _t5 = x * y; z = _t5 + z; _L1: Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Exemple de représentation intermédiaire : Control Flow Graph (CFG) Début x=3 y=x+7 z=2*y if(x < y) Faux Vrai t1 = x/2 t2 = y/3 z = t1 + t2 t3 = x*y z = t3 + y Fin Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Optimisation d’un CFG Application répétée de quelques règles de simplification • supprimer des affectations inutiles • remplacer des constantes : int x = 3; int y = x + 2 ⇒ int x = 3 ; int y = 3 + 2; • calculer des expressions constantes : int y = 3 + 2; ⇒ int y = 5 jusqu’à ce que plus aucune des règles ne soit applicable Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Optimisation d’un CFG Début Début Constante à remplacer x=3 y=x+7 z=2*y if(x < y) x=3 y=3+7 Affectation inutile if(3 < y) Faux Vrai t1 = x/2 t2 = y/3 z = t1 + t2 t3 = x*y z = t3 + y t1 = 3/2 t2 = y/3 z = t1 + t2 Fin Début Début Affectation inutile y = 10 Expression évaluable if(3 < y) if(3 < y) Faux Faux Vrai t3 = 3*y z = t3 + y t1 = 3/2 t2 = y/3 z = t1 + t2 t3 = 3*y z = t3 + y Fin x=3 y=3+7 Vrai Faux Vrai t3 = 3*y z = t3 + y t1 = 3/2 t2 = y/3 z = t1 + t2 Fin Fin ··· Début Après plusieurs passes z=4 Fin Architecture Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau La phase de synthèse (backend) Représentation intermédiaire ⇒ Code machine • génération du code machine de chacun des blocs • disposition en mémoire des blocs • optimisations éventuelles res = 1 n=4 bloc 0 res = res * n n=n-1 if(n == 0) faux bloc 1 vrai print res bloc 2 BL0: LDAi 1 STA @res LDBi 4 STB @n JMP BL1 BL1: LDBd @res LDAd @n MULB STB @res LDBi 1 SUBA STA @n JZA BL2 JMP BL1 BL2: LDAd @res STA 1000 Architecture BL0: LDAi 1 STA @res LDBi 4 STB @n JMP BL1 BL1: LDBd @res LDAd @n MULB STB @res LDBi 1 SUBA STA @n JZA BL2 JMP BL1 BL2: LDAd @res STA 1000 Code machine Jérémy Fix Petite synthèse Procédure, pile et pointeur de pile La couche d’assemblage Langages de haut niveau Et voila C/C++ int main() { int x = 3; int y = 3 + x; } return x; Code machine 1000 0003 Analyse (frontend) Langage intermédiare (CFG) Synthèse (backend) 1c00 00FF 1000 0003 2400 00FF 3000 1c00 0100 Référence : “The dragon book” Aho, Lam, Sethi, Ullman Architecture Jérémy Fix