Introduction - L'architecture de Von Neumann • • • • Inventé par John Von Neumann in 1950 Idée: fonctionnalité traitée comme les données Suivre une recette (programme) Appliquer chaque étape au ingrédients (données) Frigo/Table Comptoir ? Recette/ Memory Input/Output Programme Bus Cuisinier / outils Processor 1 Introduction - Microprocesseur • Exécute des instructions simples – Arithmétique – Logique – Branchement (condition) • Accompli des tâches complexes • Programmable • Centre de la majorité des systèmes numériques – Aussi appelé CPU (Central Processing Unit) – ou UCT (Unité Centrale de Traitement) • Types plus spécialisés: – Microcontrôleur • Emphase sur autosuffisance et faible coût – DSP (Digital Signal Processor) 2 Introduction - Mémoire Memory Input/Output Bus Processor DIMM: Dual In-Line Memory Module 3 4 Introduction - Entrées/Sorties Memory Input/Output Bus Processor 4 Introduction - Logique électronique numérique • Portes logiques – non (inverseur), et, ou, ou-exclusif … – anglais: not, and, or, xor … • Bascule bistable (D) • Porte 3 états: 0, 1, Z – Z=Haute impédance (grande résistance) • Basé sur les transistors – Plus utilisé présentement: CMOS – Transistors NMOS et PMOS sur la même puce MOS = metal oxide semiconductor • – « Taille »: 180nm … 65nm … 26nm (réalisé; pas disponible) 5 Introduction - Logique électronique numérique Copyright © 2000 by Prentice Hall, Inc. Digital Design Principles and Practices, 3/e Copyright © 2000 by Prentice Hall, Inc. Digital Design Principles and Practices, 3/e 6 Copyright © 2000 by Prentice Hall, Inc. Digital Design Principles and Practices, 3/e Table de vérité tampon inverseur à trois états: En 1 0 0 IN * 1 0 | Out | Z | 0 | 1 A,B,C pour que la sortie sera à Z (haute impédance)? C=0 A=1 B=1 7 Introduction - Périphériques: disques rigides © 2007 M. Murdocca and V. Heuring • Vitesse de rotation constante (RPM) • Plusieurs plateaux – Deux surfaces par plateau • Un bras – avec une tête par surface • Chaque surface est divisée: – Pistes (« track »): cercles concentriques – Secteur: partie de piste • Cylindre – Pistes de toutes surfaces situées à la même distance du centre • Zone Source: pcguide.com – Cylindres ayant le même nombre de secteurs • Temps d’accès d’une information (moyenne: déplacement de 1/3, rotation de ½) – Déplacement du bras (tête): « seek time » (moyen: 8ms (disque rapide)) – Temps de rotation: « rotational latency » (latence de rotation moy.: 4ms (7200RPM) • Taux de transfert au disque: – Vitesse de rotation * secteurs/piste * données/secteur(=512B/secteur) 8 Introduction - Périphérique: CD • Initialement fait pour le son: – 44100 échantillons/seconde * 2 canaux * 16 bits – 75 secteurs/seconde (donc 2352 octets/secteur) – Une piste en spirale ; vitesse linéaire constante • Pour les données: source: A.S. Tanenbaum, Structured Computer Organization, – Choix de 2048 (mode1) ou 2324 (mode2 form2) octets/secteur – + correction d’erreurs 4e édition, Prentice-Hall • Encodage: – 1 = transition (trou-à-plat ou plat-à-trou), 0 = constant uns séparés d’au moins 2 zéros; pas plus de 10 zéros de suite 9 Introduction - Périphériques • écran • Affiche les lignes une par une • Réaffiche l’écran X fois par seconde (50 à 120Hz) • Données viennent d’une mémoire • Intensité du pixel: conversion numérique analogique • interface analogique 10 Architecture UCT/CPU Cache (I+D) Unité de contrôle (pipeline) Bloc (d’instructions instructions ou de Cache données) Mémoire principale instruction données R0 R4 R1 R5 R2 R6 R3 R7 données Cache données Page Mémoire virtuelle Registres Temps d’accès (ns) 0.25-0.5 0.25-25 50-250 5 000 000 Taille <1KB < 16 MB < 215 GB > 1 TB Coût $$$$$ $$$$ $$ $ Source: J. Hennessy, D. Patterson – «Computer Architecture. A quantitative approche», 4-e édition (2006) 11 Architecture - Les niveaux d'abstraction d'un ordinateur 12 Architecture - Instruction Set Architecture (L3) • Interface entre matériel et logiciel • Ce que c’est visible pour programmeur • Consiste en: – instructions (opérations et la façon que les opérations sont codées) – informations sur les unités composants (taille, adressage etc.) – description de registres accessibles (l’ état du processeur) – contrôle des entrées/sorties Donc ISA donne au programmeur en assembleur une « image » de la machine qui inclut le matériel accessible et les instructions qui permettent la manipulation de données à l’ intérieur du matériel. 13 Architecture des instructions Source : wikipedia.org add r1 = r2 + r3 Operand – destination/source Opcode – code operation, addition ici 14 Architecture des instructions Nombre d’opérandes spécifiées: 1 à 3 selon le processeur 1: accumulateur ou pile (co-pro Intel x86) • 1 adresse add A acc ←acc + mem[A] 2: une source sert aussi de destination (Intel x86, AVR, …) • 2 adresses add A B EA(A) ←EA(A) + EA(B) 3: destination distincte des deux sources (MIPS, SPARC, …) • 3 adresses add A B C EA(A) ←EA(B) + EA(C) Taille d’instruction fixe (MIPS – 32 bits, SPARC – 32 bits , AVR(±) – 16 bits variable (Intel x86, MC68000, …) 15 Architecture - Mémoire Grand « tableau » de cases ayant chacune une adresse Lors d’une écriture: Présenter l’adresse binaire à la puce Présenter la donnée binaire à la puce Mettre actif le signal d’écriture Donnée Donnée 0 01100111 1 10011100 2 00000000 … Lors d’une lecture: Présenter l’adresse binaire à la puce Mettre actif le signal de lecture Un certain temps après, la puce répond avec la donnée Adresse 1023 11110000 Enable Read/Write Mémoire Adresse 16 Architecture - Mémoire ● Ordre placer les octets – Grosboutiste/groboutien (« big-endian »): gros bout (MSB) à petite adresse – Petitboutiste/petitboutien (« little-endian »): petit bout (LSB) à petite adresse – Ex: placer deux entiers de 32bits dans une mémoire à mots de 32bits: – 0x12345678 à l’adresse 0, et 0x123 à l’adresse 4 (vue par le programme Adr. sur puce Adr. vue par prog. 0 0 1 2 3 12 34 56 78 1 4 5 6 7 00 00 01 23 « big-endian » Adr. sur puce Adr. vue par prog. 0 3 2 1 0 12 34 56 78 1 7 6 5 4 00 00 01 23 « little-endian » 17 Architecture - la machine de Von Neumann La séquence d’opérations pour exécuter un programme 1) Récupérer les instructions de la mémoire 2) Décoder la représentation numérique des instructions 3)Charger les données de la mémoire ou des entrées vers l’accumulateur Entrées/ 4) Exécuter l’opération correspondante sur Mémoire les données Sorties 5) Sauvegarder le résultat 6) Revenir à 1) et répéter L’accumulateur est une petite mémoire proche du processeur Unité arithmetiquelogique (ALU) Accumulateur Unité de contrôle Processeur 18 Architecture - Exécution des instructions mémoire Donnée mémoire Instruction Circuit de contrôle Mémoire ● Boucle d’exécution: – Lire la prochaine instruction; pointer vers la suivante – Chercher les données selon l’instruction – Exécution de l’opération Compteur – Écriture du résultat d’instructions Adresse ● Ex. sur architecture à un bus: Banque de registres A Unité arith. (UAL) C 19 Architecture - Exécution des instructions -1 bus 32 bits – occupé par un registre à la fois - MA – le CPU copie l’ adresse mémoire dans MA - MD – les données sont lues de ou écrites dans MD - Le premier opérande ALU toujours en A, le résultat en C - Le deuxième opérande vient toujours du bus - L’informations du bus va toujours en IR et MA - Un décodeur interprète l’info envoyée au IR - MA communique l’ adresse à la mémoire et non au CPU Source: Heuring&Jordan 20 Architecture - 1 bus - Informations sur l’architecture: ALU doit être capable d’additionner 2 valeurs de 32 bits ALU doit être capable d’incrémenter l’ entrée B avec 4 Pour lire la mémoire: l’adresse se trouve en MA et les données sont mises en MD Le premières 3 étapes (recherche d’instructions) sont le mêmes pour toutes les instructions – architecture un bus 21 Architecture - 2 bus – A données qui entrent dans les registres, B – données qui sortent. – C=B – fonction d’ALU permettant les transferts simples Source: Heuring&Jordan 22 Architecture - Description abstraite vs. concrète ● RTN (Register Transfer Notation) (source: Heuring&Jordan; pas Atmel) – A ← B Écrit B dans A – A[B] Prend le mot B du tableau/mémoire A – A ‹B› Prend le(s) bits B de A ●n..m Spécifie une plage d’index (pour bits ou mots) A → B Si A, alors exécuter et retourner B A#B Concaténation des bits de A et B (A étant de poids fort) (A:B dans Atmel) A@B Répétition A fois du bit B : Séparateur parallèle (: pendant le même cycle d’horloge – l’ordre ne compte pas) – ; Séparateur séquentiel (; cycles d’horloge successifs – l’ordre est importante) – := Définition – Opérateurs arithmétiques et logiques standards… 23 – – – – Architecture - conversation avec périphérique ● Certains périphériques demandent de l’attention ● Deux méthodes « d’attente » – Scrutation (« polling »): aller voir souvent – Interruption: aller voir lorsqu’on « sonne » ● Étapes d’un interruption – Un circuit dédié reçoit les requêtes – Le processeur arrête ce qu’il fait pour les traiter – Une routine est exécutée par le processeur – Le processeur reprend où il était ● Attention – Interruption n’importe où – Sections critiques: possible d’empêcher les interruptions 24 Architecture - sélection, banque de registre ● Supposons un jeu d’instructions à 3 opérandes (abstract RTN): – OP ra, rb, rc ⇔ R[ra] ← R[rb] ⊗ R[rc] (où ⊗ est l’opération) – op := IR〈〈31..27〉〉 : ra := IR〈〈26..22〉〉 : rb := IR〈〈21..17〉〉 : rc := IR〈〈16..12〉〉 〈31..27〉〉 〈26..22〉〉 〈21..17〉〉 〈16..12〉〉 5 Activer écriture Décodeur 5 vers 32 32 Vers bascules pour écrire 5 〈11..0〉〉 inutilisés 5 Mulitplexeur 2 vers 1 Select b/c 5 Décodeur 5 vers 32 Activer lecture 32 Vers portes trois-états ● Contrôle: 3 fils 25 Architecture - Contrôle Source: Heuring&Jordan 26 Architecture - UAL ● Un circuit par opération logique, puis un MUX – and, or, xor, not + MUX 4:1 ● Un circuit pour toutes opérations « bitwise » – 16 possibilités d’opérations de 2 entrées booléennes Table de vérité – Donc, MUX 4:1 a b MUX 4:1 a résultat ● Un circuit pour ‘plus’ et pour ‘moins’ – A - B = A + (-B) – En complément à deux: -B = not(B)+1 b sub/add n n n additionneur n+1 27 Architecture - UAL ● Décaleur de N bits (« Shifter ») - Pour manipulation de bits – extraire bits individuels dans mots - Multiplication et division puissances de 2 - A*4 = A<<2 - A/8 = A>>3 - A*5=(A<<2) + A - A << B (décaler A de B bits vers la gauche, 0 ≤ A < 2N , 0 ≤ B < N) - Décaleur logique: – i.e. A<<3 A>>3 11010110 -> 10110000 11010110 -> 00011010 - Décaleur aritmetique: – i.e. A<<3 11010110 -> 10110000 A>>3 11010110 -> 11111010 (le bit de signe du nombre initial) 28 Architecture 29 Exercice architecture IR IR IR 32 Q IR IR CLR re ct u C E D Q Registres [0..7] (soit eax, ebx, …) e Donnée D SET 2 ur r it éc IR Mémoire1 mux 1B le Circuit de contrôle 0 IR eax:=R[0] : ebx:=R[1] : ecx:=R[2] : edx:=R[3] : esi:=R[4] : edi:=R[5] : ebp:=R[6] : esp:=R[7] F Adresse D SET Q X EIP CLR Q Q 0 mux H1 + 0 IR 1 4 mux A SET T Q UALY D G Mémoire2 Donnée CLR Adresse L’UAL permet entre autres les opérations suivantes : 0→X : 1→Y : 2→X + Y : 3→X - Y : 4→X << Y : 5→X >> Y ; 6→Y + 4 : 7→Y - 4 : … 30 Exercice architecture Donnez le RTN concret pour: Memoire2[123+eax] ← ecx T ← 123; T ← T + eax; Memoire2[123+eax] ← ecx; IR 0 IR IR IR 32 SET Q IR IR CLR ct ur e C E D Q Registres [0..7] (soit eax, ebx, …) e ur rit Donnée D 2 éc IR Mémoire1 mux 1B le Circuit de contrôle F Adresse D SET Q X UALY EIP CLR Q Q 0 mux H1 + T 0 IR 1 4 mux A SET Q D G Mémoire2 Donnée CLR Adresse 31 Exercice architecture b) Donnez le RTN abstrait, pour «MOV %esi, 3(%eax, %ebx, 2)» Mémoire2[3+eax+ebx*2] ← esi c) Indiquez comment pourrait être codée en langage machine une instruction qui fait l’opération en b). eax:=R[0] : ebx:=R[1] : ecx:=R[2] : edx:=R[3] : esi:=R[4] : edi:=R[5] : ebp:=R[6] : esp:=R[7] IR<23..21> = 4 : IR<20..18> = 0 : IR<17..15> = 1 : IR<14..13> = 1 : IR<12..0> = 3 32 ur u rit re le ct éc e IR ← Mémoire1[EIP] : EIP ← EIP + 4 ; T ← ebx ; T ← Mémoire2[T] ; ecx ← T + ecx ; Après écriture IR〈12..0〉=3 : IR〈14..13〉=1 : IR〈17..15〉=3 : IR〈20..18〉=1 : IR〈23..21〉=2 A B C D E F G UAL wEIP wIR wT wR 1 1 1 1 1 1 1 1 1 1 0 1 2 1 33 Assembleur - Les données • • • • • • • • • • Byte = 1 octet (8 bits) - char Word = 2 octets (16 bits) - short Doubleword (dword) = 4 octets (32 bits) - int, long, * Quadword (qword) = 8 octets (64 bits) - long long Entiers non-signés de N bits, [0 , 2N-1] - unsigned Entiers signées de N bits, [-2N-1 , 2N-1-1] - signed Float = 4 octets (32 bits) - float Double = 8 octets (64 bits) - double Temporary float (tfloat) = 10 octets (80 bits) - long double Chaine de caractères ascii 34 Assembleur - Les données Etiquette (label) Type (.word bits16) .data # directive on est dans le segment données (comme déclarations) val: # location etiquette .word 10, -14, 30 # trois mots .text # on est dans le segment texte – instructions assembleur .global main # mais est publique main: addi $sp, $sp, -8 # additione immédiate Valeurs 35 Assembleur - donnés, déclarations .data unbyte: .byte 9,8,0b111 1112 unword: .word 1,2,10%3 M16[1007]=10mod3=1 unshort: .short 0x9C, 077 unentier: .int 52+4, unword-2 .float 12.54 .double 67.34 # espace initialisé, lisible, écrivable # Si cet espace commence à 1000 # unbyte = 1000 # Mem[1000] = 9, Mem[1001] = 8, Mem[1002] = # unword = 1003 # M16[1003]=1, M16[1005]=2, # unshort = 1009 # M16[1009]=9C16, M16[1011]=778 # unentier = 1013 # M32[1013]=56, M32[1017]=1003-2=1001 # M32[1021]=12.54 en IEEE-754 sur 32-bits # M64[1025]=67.34 en IEEE-754 sur 64-bits 36 Exercice placement de données .data debut_data: a: .ascii ‘a’ .byte 3, 16 .word 0 .equ c, a - b .int -2, b + 1 b: .byte 010, 0b10 .skip 2 fin_data: 0x1000 0x1004 0x1008 0x100C a : 0x1000 Donnez la valeur de chaque octet en mémoire à partir de l’adresse debut_data (incluse), jusqu’à l’adresse fin_data (non incluse), en hexadécimal. Le code ASCII de ‘a’ est 0x61. debut_data 0x1000 Quelles sont les valeurs associées à a, b, c et fin_data Octet 0 Octet 1 Octet 2 Octet 3 0x61 0x00 0xFF 00 0x03 0xFE 0x0E 0x08 0x10 0xFF 00 0x02 0x00 0xFF 00 00 b : 0x100D c : -13 fin_data : 0x1011 37 Assembleur - Instructions - - 3 classes: Déplacement de données mémoire registre chargement (load) registre<- mémoire stockage (store) mémoire <- registre Operation arithmetiques/logiques (UAL) Addition, shift Branchement (instruction control flot de donnees) Branchement, jump, call 38 Assembleur - Les indicateurs (eflags) 15 - 14 NT 13 12 IOPL •Information 11 OF 10 DF 9 IF 8 TF 7 SF 6 ZF 5 - 4 AF 3 - 2 PF 1 - 0 CF sur le résultat de la dernière instruction effectuée ― vrai := 1 : faux := 0 ― CF := eflags〈0〉 carry; retenue/emprunt; débordement non signé ― PF := eflags〈2〉 parity; vrai si le nombre de bits à 1 est pair ― AF := eflags〈4〉 auxiliary carry; pour le BCD (binary coded decimal) ― ZF := eflags〈6〉 zero; vrai si le résultat est zéro ― SF := eflags〈7〉 sign; vrai si le résultat est négatif ― DF := eflags〈10〉 direction; (DF=faux → inc) : (DF=vrai → dec) ― OF := eflags〈11〉 overflow; débordement signé •Toutes les opérations arithmétiques/logiques modifient eflags ― Les instructions « cmp » et « test » ne modifient que eflags •Eflag pas modifié par ― Branchements (jmp, j?, call, ret, loop) ― Copies/déplacent de données (mov, xchg, push, pop, lea) 39 Exercice Quelles seront les valeurs de %al , du ZeroFlag (ZF), du SignFlag (SF), du CarryFlag (CF) et du OverflowFlag (OF)? mov $0b00100011,%al sub $0b01001001,%al 00100011 – 01001001 %al = 11011010 ou 00100011 + 10110111 = 11011010 ZF = 0 (le résultat n’est pas zéro), SF = 1 (bit de poids fort est à 1), CF = 0 (sans retenue ou emprunt) OF = 0 (le signe du résultat est bon) 40 Assembleur - Transferts de données •mov source, destination destination ← source •xchg a, b échange a et b •lea source, destination destination ← adr. de source ― « lea » pour « load effective address » ― Source doit être de type mémoire, destination de type registre 32-bits ― Donc: lea dep(%r1,%r2,k), %rd RTN: R[rd] ← dep+R[r1]+R[r2]*k ― Ex: lea (%ebx,%ecx), %eax RTN: R[eax] ← R[ebx] + R[ecx] •push/pop (voir – Introduction à IA-32) •pusha (push all) push(eax);push(ecx);push(edx);push(ebx);push(esp);push(ebp);push(esi); push(edi) •popa (pop all) edi←pop; esi←pop; ebp←pop; esp←pop; ebx←pop; edx←pop; ecx←pop; eax←pop 41 Assembleur - Opérations arithmétiques : additions • • • • • Affectent tous eflags selon le résultat de l’opération add source, dest dest ← dest + source (M, R; R, M; R,R) adc source, dest dest ← dest + source + CF sub source, dest dest ← dest – source sbb source, dest dest ← dest – source – CF Eflag affectés: OF, SF, ZF, PF, CF … • cmp source, dest dest – source (seulement eflag est affecté) • neg dest dest ← 0 – dest (M; R - SF, ZF, PF, CF … ) • inc dest dest ← dest + 1 (M; R) dec dest dest ← dest – 1 (M; R ) Eflag affectés: OF, SF, ZF, PF … • 42 Assembleur - Opérations arithmétiques : multiplications mul source8 ax ← al * source8 (non signé) mul source16 dx#ax ← ax * source16 mul source32 edx#eax ← eax * source32 Attention – dans cette forme source ne peux pas être immédiate edx dx ne peuvent pas être immédiat CF et OF si résultat prend plus de place que la source imul source8 … (même chose mais signé) imul source16 … imul source32 … imul source, dest dest ← dest * source imul const, source, dest dest ← const * source const est immédiat; source est registre ou mémoire; dest est registre 43 Assembleur - Instructions logiques Affectent eflags selon le résultat OF ← 0 : CF ← 0 : SF ← résultat〈31〉 : ZF ← (résultat=0) : PF ← ((nombre de bits à 1 dans résultat) +1) mod 2 Opérations bit par bit (A#B#C) ⊗ (D#E#F) = (A⊗D)#(B⊗E)#(C⊗F) or source, dest dest ← dest ∨ source Peut servir à forcer des bits à 1 and source, dest dest ← dest ∧ source Peut servir à forcer des bits à 0 xor source, dest dest ← dest ⊕ source Peut servir à inverser des bits Peut servir à mettre à 0 un registre: xor %eax, %eax 44 Assembleur - Instructions de décalage Affectent eflags (CF, OF, ZF) CF ← dernier bit sorti Si source est $1, OF ← résultat<signe> != valeur_décalée<signe> Opérandes Source: immédiat ou %cl Dest: registre ou mémoire (8, 16 ou 32 bits) Décale d’un maximum de 32 bits Décale de src5 bits src5 := source<4..0> shr source, dest – dest#CF ← src5@0 # dest<31..src5-1> Shift right # division par 2 ou puissance de 2 sar source, dest – dest#CF ← src5@dest<31> # dest<31..src5-1> Shift arithmetic right shrd source, source2, dest - dest#CF ← source2<src5-1..0> # dest<31..src5-1> 45 source2 doit être registre Assembleur - Instructions de décalage ror source, dest dest#CF ← dest〈src5-1..0〉 # dest〈31..src5-1〉 Rotate right rcr source, dest dest#CF ← (dest#CF)〈src5-1..0〉 # (dest#CF)〈32..src5〉 Rotate (through) carry right shl source, dest (arithmetic) left CF#dest ← dest〈32-src5..0〉 # src5@0 # Shift (sal := shl) multiplication par 2 ou puissance de 2 shld source, source2, dest src5〉 rol source, dest CF#dest ← dest〈32-src5..0〉 # source2〈31..32CF#dest ← dest〈32-src5..0〉 # dest〈31..32-src5〉 Rotate left rcl source, dest src5〉 CF#dest ← (CF#dest)〈32-src5..0〉 # (CF#dest)〈32..33- Rotate (through) carry left 46 Assembleur - Instructions sur les indicateurs (contrôle) stc clc cmc cld std pushf popf lahf sahf cli sti CF ← 1 (set carry) CF ← 0 (clear carry) CF ←!CF (complement carry) DF ← 0 (clear direction, direction positive) DF ← 1 (set direction, direction négative) push(eflags) (push flags) eflags ← pop (pop flags) AH ← eflags<7..0> (load ah flags) eflags<7..0> ← AH (store ah flags) IR ← 0 (clear interrupt request) IR ← 1 (set interrupt request) 47 Assembleur - Opérations arithmétiques : divisions div source8 al ← ax / source8 : (non signé) ah ← ax mod source8 div source16 ax ← dx#ax / source16 : dx ← dx#ax mod source16 div source32 eax ← edx#eax / source32 : edx ← edx#eax mod source32 Attention source – registre en mémoire mais non immédiate edx, ed ne peuvent pas être immédiat idiv source8 … (même chose mais signé) idiv source16 … idiv source32 … N’existe pas: idiv source, dest 48 Exercice lecture d’assembleur fin_data: .text .global main main: mov $0x1001, %ebx mov (%ebx), %ecx mov $c, %esi mov b(%esi), %edx lea b+8(,%edx,2), %edi mov 0x1000, %dh mov $0b10100010,%eax xor $0b01010100,%al pushl $ici ici: inc %bh ret .data debut_data: a: #0x1000 .ascii ‘a’ .byte 3, 16 .word 0 .equ c, a - b .int -2, b + 1 b: #0x100D .byte 010, 0b10 .skip 2 fin_data: %al suite à xor, ainsi que la valeur des bits ZF et SF du registre eflags %al : 11110110 ZF : 0 SF : 1 49 Exercice lecture d’assembleur .data debut_data: a: #0x1000 .ascii ‘a’ .byte 3, 16 .word 0 .equ c, a - b .int -2, b + 1 b: #0x100D .byte 010, 0b10 .skip 2 fin_data: a : 0x1000 b : 0x100D c : -13 fin_data : 0x1011 fin_data: .text .global main main: mov $0x1001, %ebx mov (%ebx), %ecx mov $c, %esi mov b(%esi), %edx lea b+8(,%edx,2), %edi mov 0x1000, %dh mov $0b10100010,%eax xor $0b01010100,%al pushl $ici ici: inc %bh ret %ebx, %ecx, %edx, %esi, et %edi (en hexadécimal) après l’exécution de la routine main %ebx : 0x1101 %ecx : 0x1003 %edx : 0x106161 %esi : 0Xfffffff3 %edi : 0x2016D7 50 Assembleur - Branchements •Sans condition: jmp quelquepart ― quelquepart est un entier/adresse/étiquette ― RTN: R[eip] ← quelquepart ― quelquepart peut aussi être « *opérande » jmp *%eax RTN: R[eip] ← R[eax] jmp *4(%eax) RTN: R[eip] ← M32[4 + R[eax]] •Conditions: j? quelquepart ― Où ? est le nom de la condition: c, nc, z, nz, o, no, s ns, p, np, a ― Condition sur eflags ou %ecx ― RTN: condition_vrai → (R[eip] ← quelquepart) •Appel/retour de sous-routine: ― call quelquepart RTN: push(R[eip]) : R[eip] ← quelquepart 51 ― ret RTN: R[eip] ← pop Assembleur - Conditions •Toujours selon indicateurs (sauf cas de %ecx) ― Noms selon: indicateurs, comparaison non signée , comparaison signée ― jecxz/jcxz jump if ecx/cx is zero condition ecx = 0 ou cx = 0 •Noms selon indicateurs: ― jc jump if carry CF = 1 → (R[eip] ← quelquepart) ― jnc jump if no carry CF = 0 " ― jz jump if zero ZF = 1 ― jo jump if overflow OF = 1 ― jno jump if no overflow OF = 0 ― js jump if sign SF = 1 ― jns jump if no sign SF = 0 ― jp jump if parity PF = 1 ― jnp jump if no parity PF = 0 ― jpo jump if parity odd PF = 0 (même chose que « jnp ») 52 Assembleur - Conditions •Comparaison: cmp y, x ― affecte eflags selon l’opération x-y •Noms suivant une comparaison non signée: (above/below) ― jb jump if below CF = 1 (comme jc) ― jnb jump if not below CF = 0 (comme jnc) ― jbe jump if below or equal CF = 1 ∨ ZF = 1 ― jnbe jump if not below or equal CF = 0 ∧ ZF = 0 ― ja jump if above CF = 0 ∧ ZF = 0 (comme jnbe) ― jna jump if not above CF = 1 ∨ ZF = 1 (comme jbe) ― jae jump if above or equal CF = 0 (comme jnb) ― jnae jump if not above or equal CF = 1 (comme jb) ― je jump if equal ZF = 1 (comme jz) ― jne jump if not equal ZF = 0 (comme jnz) 53 Assembleur - Conditions •Noms suivant une comparaison signée: (greater/lower) ― jl jump if lower SF ≠ OF ― jnl jump if not lower SF = OF ― jle jump if lower or equal SF ≠ OF ∨ ZF = 1 ― jnle jump if not lower or equal SF = OF ∧ ZF = 0 ― jg jump if greater SF = OF ∧ ZF = 0 (comme jnle) ― jng jump if not greater SF ≠ OF ∨ ZF = 1 (comme jle) ― jge jump if greater or equal SF = OF (comme jnl) ― jnge jump if not greater or equal SF ≠ OF (comme jl) ― je jump if equal ZF = 1 (comme en non signé) ― jne jump if not equal ZF = 0 " •Comment se rappeler above/below vs. greater/lower ― jb = jc ― « carry » est un débordement non signé 54 Assembleur - Boucles •Instructions spéciale: loop, loopz, loopnz ― N’affectent pas eflags ― loop quelquepart ecx ← ecx – 1 ; (ecx ≠ 0) → (eip ← quelquepart) ― loopz quelquepart ecx ← ecx – 1 ; (ecx ≠ 0 ∧ ZF = 1) → (eip ← " ) ● Pour « loop while zero » ― loopnz quelquepart ecx ← ecx – 1 ; (ecx ≠ 0 ∧ ZF = 0) → (eip ← " ) ● Pour « loop while not zero » 55 Exemple while #repeter.s .text .global _start _start: xorl %eax,%eax movl $6,%ecx repeter: addl %ecx,%eax cmpl $36,%eax jna repeter # eax = 0 # instructions # jump si %eax <= 36 movl $1,%eax xorl %ebx,%ebx ret 56 Assembleur - Boucles En C: do b; while(a); – En assembleur: boucle: # code de b # code de a j? boucle En C: while(a) b; – En assembleur: jmp test_au_debut boucle: # code de b test_au_debut: # code de a j? boucle 57 Assembleur - Boucles En C: for(a; b; c) d; – Équivalent au C: (s’il n’y a pas de « continue » dans le corps) a; while(b) { d; c; } En C: break; et continue; En assembleur: boucle: #… j? break #… j? continue #… continue: # (code de l’incrémentation) # code de la condition j? boucle break: – 58 Exercice Quel est le contenu du registre %eax à la fin de la sousroutine suivante? Expliquez. mystere: mov $4, %eax boucle: add %al,%ah sub $1, %al jnz boucle ret 4+3+2+1 = 10; %eax = 0x0A00 59 Assembleur - Directives ● ● ● Remplissage de mémoire – .fill répétitions, NBoctets, valeur(=0) – .skip répétitions, valeur Équivalent à .fill répétitions, 1, valeur .space synonyme de .skip Alignement – .balign val1, val2(=0 ou nop), val3(=infini) Aligne sur un multiple de val1 en utilisant val2 pour remplir Si le nombre d’octet à placer n’est pas > val3 – .p2align val1, val2, val3 Fait un .balign 2val1, val2, val3 Alignement selon Intel (recommandations) – Aligner les données sur des multiples de leur taille – Aligner les étiquettes du code, sur 16 octets, si c’est a moins de 8 octets Étiquette de boucle Étiquette suit un saut inconditionnel 60 Conventions du C • • • • Les variables globales sont dans la section .data Les variables locales et paramètres sont sur la pile – En C les paramètres sont empilés de droite à gauche avant le ‘call’ (dépilés au retour du ‘call’) – L’espace pour les variable est alloué au début de la sous-routine – On utilise souvent %ebp pour pointer vers ces variables/paramètres La valeur de retour – Dans %eax pour les entiers (char/short/int…) et pointeurs (edx:eax pour 8 octets) – Dans %st(0) pour les float/double (registres larges pour operations point flotant) – En mémoire pour les objets/structures • Le pointeur où placer le résultat est donné par la routine appelante Registres qu’ une routine peut modifier: %eax, %ecx, %edx – Doit sauver/restaurer les autres si on les modifies 61 La pile – paramètres, valeurs, variables Responsabilités “caller” (main) - push les paramètres en ordre inverse (le dernier dans la pile le premier) - call - pop les paramètres (pop ou incrémentation %esp pour les enlever) - la valeur de retour en %eax Responsabilités “callee” (procédure) - stocke %ebp d’appeleur dans la pile # prologue procédure push %ebp - sauvegarde le %esp courant dans %ebp # prologue procédure mov %esp, %ebp - codage, stockage variables locales dans la pile - sortie rapide – load %esp de %ebp (sinon pop élément par élément) #épilogue procédure mov %ebp, %esp # retour aux valeurs initiales (clean up) pile - pop ancien %ebp et return – stocke valeur de retour en %eax #épilogue procédure pop %ebp # retour aux valeurs initiales (clean up) pile 62 Exercice écriture assembleur Soit la fonction fun qui appelle la routine fun1, qui appelle la routine fun2, qui appelle la routine fun2, qui appelle la routine fun3 qui appelle la fonction taille_pile. La fonction taille_pile retourne le nombre de cadres de pile (stack frames), la fonction fun incluse, la fonction taille_pile non incluse. Pour l’exemple donné, la fonction retourne la valeur 5. Écrire en assembleur la fonction taille_pile qui retourne le nombre de cadres de la pile. Le %ebp sauvegardé pour la fonction fun est supposé d’être 0. Indice : La fonction commence avec son propre %ebp et trace les anciens %ebp jusqu’au 0. 63 Solution taillepile: push %ebp mov %esp, %ebp xorl %eax, %eax #eax a 0 movl (%ebp), %ecx # premier ancien ebp sauvegardé boucle: cmpl $0, %ecx je bouclefin incl %eax movl (%ecx), %ecx jmp boucle #prochain ancien ebp sauvegardé bouclefin: # compteur déjà en %eax mov %ebp, %esp pop %ebp ret 64 Exercice écriture assembleur int g(unsigned int x); int somme(unsigned int n, int *valeurs) { int val; val = g(n) - valeurs[n+1]; if(n > 0) val = val + valeurs[n-1]; return val; } Écrivez la sous-routine somme en assembleur. 65 4 somme : push 4(%esp) #n call g add $4, %esp mov 4(%esp), %ecx mov 8(%esp), %edx sub 4(%edx, %ecx, 4), %eax jecxz add faux : ret faux #n # enlève le paramètre # int n # int *valeurs # val = valeurs[n+1] # branche si n == 0 -4(%edx, %ecx, 4), %eax 66