Conception et exploitation des processeurs Chargé de cours : Frédéric Pétrot Équipe pédagogique : Stéphane Mancini, Luc Michel, Olivier Muller, Christophe Rippert, Sebastien Viardot Année universitaire 2012-2013 Conception et exploitation des processeurs Structure du cours C1 C2 C3 C4 Introduction aux langages d’assemblage pour les ISA x86_64 et MIPS Présentation du projet CEP VHDL Conventions pour les appels de fonctions en assembleur x86_64 et MIPS 2 / 30 Conception et exploitation des processeurs Introduction Plan 1 Introduction 2 Introduction à l’assembleur x86_64 3 Rappels concernant l’assembleur MIPS 4 Vue mémoire 5 Modes d’adressage 3 / 30 Conception et exploitation des processeurs Introduction Introduction Étude du langage d’assemblage de 2 processeurs Intel x86_64 (AMD64, CoreIx) Évolution de l’ISA hégémonique pour desktops, laptops et serveurs Constructeur Intel a , compatibilité ascendante depuis 1979 Machine avec ISA CISC : Complex Instruction Set Computer a. www.intel.com MIPS R3000 ISA symbolique RISC : Reduced Instruction Set Computer Constructeur MIPS a , 1988 Importante part de marché dans l’embarqué (networking en particulier), mais nettement moins que ARM b , favori des smartphones et autres tablettes. a. www.mips.com b. www.arm.com 4 / 30 Conception et exploitation des processeurs Introduction Introduction CISC Intel x86_64 jeu d’instruction « prolifique », près de 500 instructions destiné à être programmé par un humain vise un code « compréhensible » et dense nombreux modes d’adressage opérandes peuvent être des cases mémoire bonne partie des registres spécialisés par le matériel cherche à optimiser la taille du programme par l’utilisation d’instructions complexes 5 / 30 Conception et exploitation des processeurs Introduction Introduction RISC MIPS R3000 jeu d’instruction minimaliste, 65 dans le R3000, moins de 80 dans ses évolutions destiné à être la cible d’un compilateur instruction de taille fixe menant à une occupation mémoire du programme plus grande registres à usage général, utilisation logicielle conventionnelle un mode d’adressage unique, architecture load/store opérande = registre 6 / 30 Conception et exploitation des processeurs Introduction Introduction Programmation assembleur Langage traduit en binaire compréhensible par la machine Transformation fondamentalement syntaxique caractéristiques différentes important de connaître les deux types Attention ! Ne pas confondre les 2 assembleurs ! ! ! 7 / 30 Conception et exploitation des processeurs Introduction Rappel sur les types de données Types entiers de tailles fixes Types C99 (inttypes.h) int64_t, uint64_t int32_t, uint32_t int16_t, uint16_t int8_t, uint8_t Taille en octets 8 4 2 1 Cas des pointeurs (adresses) Forcément dépendant de l’ISA : MIPS R3000 = 4 octets, x86_64 = 8 octets... quelque-soit le type de la donnée pointée (ex. : char *, int64_t *, ...) ! Attention ! Ne pas utiliser les types standards du C (int, long, ...) dont la taille peut varier selon l’ISA ! 8 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 Plan 1 Introduction 2 Introduction à l’assembleur x86_64 3 Rappels concernant l’assembleur MIPS 4 Vue mémoire 5 Modes d’adressage 9 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 ISA x86_64 : Registres Utilisable sous forme des 2n × 8 bits de poids faibles, 0 ≤ n ≤ 3 64 bits %rax %rbx %rcx %rdx %rsi %rdi %rbp %rsp %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 %rflags %rip 32 bits %eax %ebx %ecx %edx %esi %edi 16 bits %ax %bx %cx %dx %si %di 8 bits %al %bl %cl %dl %sil %dil %r8d %r9d %r10d %r11d %r12d %r13d %r14d %r15d %r8w %r9w %r10w %r11w %r12w %r13w %r14w %r15w %r8b %r9b %r10b %r11b %r12b %r13b %r14b %r15b Usage parfois spécialisé parfois spécialisé parfois spécialisé parfois spécialisé général général pointeur de contexte pointeur de pile général général général général général général général général indicateurs (ex. : C, Z) compteur-programme Il existe des conventions d’utilisation des registres (vues au CM4) : en TP, on n’utilisera au début que %rax, %r10 et %r11 Attention, peuvent être utilisés implicitement par certaines instructions que nous n’étudierons pas 10 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 ISA x86_64 Adresses Sur 64 bits, de 0x0000000000000000 à 0xFFFFFFFFFFFFFFFF Ou de 0 à 264 − 1 Données Sur n ∈ {64, 32, 16, 8} bits Contraintes d’alignement des adresses : divisibles par n 8 Instruction contient information de taille Organisation mémoire little endian Exemple : valeur 0xDEADBEEF8BADF00D stockée en 0xABC8 Représentation adresses croissantes : Adresse 0xABC8 0xABC9 0xABCA Valeur 0x0D 0xF0 0xAD Représentation adresses décroissantes Adresse 0xABCF 0xABCE 0xABCD Valeur 0xDE 0xAD 0xBE 0xABCB 0x8B : 0xABCC 0xEF 0xABCC 0xABCD 0xABCE 0xABCF 0xEF 0xBE 0xAD 0xDE 0xABCB 0xABCA 0xABC9 0xABC8 0x8B 0xAD 0xF0 0x0D 11 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 Instructions Quelques généralités Suffixes possibles Précisent la taille de la valeur manipulée par l’instruction q (quad) : 64 bits l (long) : 32 bits w (word) : 16 bits (héritage du 8086 de 1979...) b (byte) : 8 bits Indiquez systématiquement le suffixe dans votre code ! Copies entre éléments mémorisants movsuffixe source, destination entre registres considérés 64 bits : movq %rax, %r10 r 10 ← rax registre vers mémoire : movb %al, v(%rip) mem[v ]7..0 ← al mémoire vers registre : movw u(%rip), %r10w r 1015..0 ← mem[u]15..0 constante vers registre : movb $45, %r11b r 117..0 ← 45 const. vers mém. : movl $0xBABE, t(%rip) mem[t]31..0 ← 0x0000BABE mémoire vers mémoire : impossible ! 12 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 Instructions Petit sous-ensemble des plus courantes Arithmétiques %ax, %r10w $20, %al %eax $1, %eax $4, %r11d %r10b, %rax r 10w ← r 10w + ax al ← al − 20 eax ← −eax eax ← eax30..0 || 0 r 11d ← 04 || r 1131..4 r 105..0 rax ← rax63 || rax63..r 105..0 andl $0xFED0D0, %r11d orb $0xFA, %al xorq %r11, %rax notw %r10w r 11d ← r 11d ∨ 0x00FED0D0 al ← al ∧ 0xFA rax ← rax ⊕ r 11 r 10w ← r 10w addw subb negl shll shrl sarq Logiques 13 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 Instructions Les plus courantes, en plus compliquées saut rip ← label jmp label Comparaisons cmpq %rax, %r11 testb $0x01, %r10b rflags ← flags(r 11 − eax) rflags ← flags(1 and r 10b) Branchements Décision prise en fonction du contenu des flags ( label jxx label rip ← adresse instruction suivante si xx est vraie, si non xx 14 / 30 Conception et exploitation des processeurs Introduction à l’assembleur x86_64 Instructions Les plus courantes, ... Branchements Comparaison > ≥ < ≤ = 6 = Entiers naturels ja, jnbe jae, jnb jb, jnae jbe, jna je, jz jne, jnz Entiers signés jg, jnle jge, jnl jl, jnge jle, jng n not, a above, b below, g greater, l less, e equal, z zero 15 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS Plan 1 Introduction 2 Introduction à l’assembleur x86_64 3 Rappels concernant l’assembleur MIPS 4 Vue mémoire 5 Modes d’adressage 16 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS ISA MIPS Registre 32 bits $0 $1-$30 $31 Remarque registre trash (peut être écrit, zéro en lecture) non spécialisés contient l’adresse de retour de fonction Adresses Sur 32 bits, de 0x0000_0000 à 0xFFFF_FFFF Données Sur 32, 16 ou 8 bits Seules les instructions de chargement ou de stockage mémoire contiennent information de taille Organisation mémoire little endian 17 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS ISA MIPS Sous-ensemble pour commencer, ... Suffixes pour les chargements/stockages mémoire Précisent la taille de la valeur manipulée par l’instruction w (word) : 32 bits h (half) : 16 bits b (byte) : 8 bits Copies entre éléments mémorisants entre registres : add $3, $2, $0 reg. vers mém. : sw $12, 96($5) mém. vers reg. : lbu $2, -15($1) const. vers reg. : ori $3, $0, 0xBEEF const. vers demi-mot poids fort reg. : lui $4, 0xDEAD const. vers mém. : impossible mém. vers mém. : impossible $3 ← $2 mem[$5 + 96]31..0 ← $12 $2 ← 024 ||mem[$1 − 15]7..0 $3 ← 016 ||0xBEEF $4 ← 0xDEAD||016 18 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS Instructions Les plus courantes, ... Arithmétiques add $4, $12, $23 sub $14, $9, $30 addi $2, $17, -1 sllv $1, $12, $7 sra $4, $3, 9 $4 ← $12 + $23 $14 ← $9 − $30 $2 ← $17 − 1 $1 ← $1231−$74...0 ...0 k 0$74...0 $4 ← $3931 k $331...9 Logiques and $14, $9, $30 ori $4, $3, 0xFF xori $1, $12, 0xAAAA nor $4, $12, $23 $14 ← $9 and $30 $4 ← $3 or 016 ||0x00FF $1 ← $12 xor 016 ||0xAAAA $4 ← $12 or $23 19 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS Instructions Les plus courantes, ... Comparaisons ( sltu $4, $12, $23 slti $2, $17, -1 031 k 1 si 0||$12 < 0||$23, $4 ← 032 sinon ( 31 0 k 1 si $17 < 116 ||0xFFFF , $2 ← 032 sinon Branchements inconditionnels (sauts) j label jr $31 pc ← label pc ← $31 20 / 30 Conception et exploitation des processeurs Rappels concernant l’assembleur MIPS Instructions Les plus courantes, ... Branchements conditionnels ( beq $2, $3, label pc ← label adresse instruction suivante si $2 = $3, sinon ( bne $2, $3, label blez $2, label bgtz $2, label label si $2 6= $3, adresse instruction suivante sinon ( label si $2 ≤ 0, pc ← adresse instruction suivante sinon ( label si $2 > 0, pc ← adresse instruction suivante sinon pc ← 21 / 30 Conception et exploitation des processeurs Vue mémoire Plan 1 Introduction 2 Introduction à l’assembleur x86_64 3 Rappels concernant l’assembleur MIPS 4 Vue mémoire 5 Modes d’adressage 22 / 30 Conception et exploitation des processeurs Vue mémoire Exécutable en mémoire Exécutable constitué de 4 parties Code Directive .text En lecture seulement Commence « en bas » de la mémoire Données connues statiquement Directive .data Variables globales initialisées au lancement En lecture/écriture Directive .comm Variables globales non explicitement initialisées, initialisées à zéro au lancement En lecture/écriture 23 / 30 Conception et exploitation des processeurs Vue mémoire Exécutable en mémoire Données connues statiquement Directive .rodata (sur certains systèmes) Constantes initialisées au lancement En lecture seulement Placées à la suite du code Données allouées dynamiquement Variables globales dont les adresses sont définies à l’exécution : tas ou heap Placées à la suite des données initialisées Pile Gérée par le matériel et/ou le logiciel lors des appels de fonctions Commence « à la fin » de la mémoire, « va » dans le sens des adresses décroissantes 24 / 30 Conception et exploitation des processeurs Vue mémoire Résumé 0xFFFFFFFF 0x........ 0x........ 0x........ 0x........ 0x........ 0x........ 0x........ 0x00000000 .. . pile ⇓ .. . .. . ⇑ tas ⇑ données ⇑ code .. . 0x00000000 0x........ 0x........ 0x........ 0x........ .bss .data .rodata .text 0x........ 0x........ 0x........ 0xFFFFFFFF .. . code ⇓ données ⇓ tas ⇓ .. . .. . ⇑ pile .text .rodata .data .bss .. . 25 / 30 Conception et exploitation des processeurs Modes d’adressage Plan 1 Introduction 2 Introduction à l’assembleur x86_64 3 Rappels concernant l’assembleur MIPS 4 Vue mémoire 5 Modes d’adressage 26 / 30 Conception et exploitation des processeurs Modes d’adressage Modes d’adressage Ou comment accéder aux données en mémoire Constantes : placées dans l’instruction elle-même C: x86_64 : (int32_t)0x8BADF00D movl $0x8BADF00D, %r9d MIPS : lui $1, 0x8BAD ori $1, $1, 0xF00D Variables scalaires globales ou statiques : adresse case mémoire MIPS : relatif + dép. C: x86_64 : relatif à pc int64_t dice = 421; void pwet(void) { ... dice++; ... } .text pwet: ... addq $1, dice(%rip) ... .data dice: .quad 421 .text pwet ... lui $4,%hi(dice) lw $2,%lo(dice)($4) lw $3,%lo(dice+4)($4) addiu $5,$2,1 sltu $6,$5,$2 addu $6,$6,$3 sw $5,%lo(dice)($4) sw $6,%lo(dice+4)($4) ... .data dice : .quad 421 27 / 30 Conception et exploitation des processeurs Modes d’adressage Modes d’adressage Horreur ! Variable identifiée par adresse = pointeur ! Variables de tous types globales ou statiques : adresse case mémoire Si connue statiquement (constante dans le code) : (en supposant qu’on laisse les variables _1, five et _9 dans des registres) C: int32_t p[] = { 1, 3, 0, 7, 9, 11, 13, 17}; int32_t _1 = p[0]; int32_t *five = &p[2]; *five = 5; int32_t _9 = p[4]; x86_64 : base + dep. MIPS : relatif + dép. .text leaq p(%rip), %rax movl (%rax), %rax leaq p+8(%rip), %r11 movl $5, (%r11) movl 16(%rax), %r10d .data p: .long 1,3,0,7, 9,11,13,17 .text la $1,p lw $2,($1) li $4, 5 addiu $3, $1, 8 sw $4, ($3) lw $5, 16($1) .data p:.long 1,3,0,7, 9,11,13,17 28 / 30 Conception et exploitation des processeurs Modes d’adressage Modes d’adressage En fait, hormis pour celles étant dans les registres : Variables de tous types : adresse case mémoire Accès indicé : (en supposant qu’on laisse les variables i et s dans des registres) C: int32_t p[] = {1, 3, 5, 7, 9, 11, 13, 17}, i, s = 0; for (i = 7; i >= 0; i -= 2) s += p[i] + p[i-1]; x86_64 : base + index × type + dep. .text leaq p(%rip), %r11 movl $0, %eax // s movl $7, %r10d // i for: cmpl $0, %r10d jl endfor addl (%r11, %r10d, 4), %eax addl -4(%r11, %r10d, 4), %eax subl $1, %r10d jmp for endfor: .data p:.long 1,3,0,7, 9,11,13,17 MIPS : relatif + dép. .text li $1, 28 ; i la $2, p li $3, -1 li $4, 0 ; s for: beq $1, $3, endfor addi $6, $2, $1 lw $5, ($6) addi $4, $4, $5 lw $5, -4($6) addi $4, $4, $5 addi $1, $1, -8 j for endfor: ... .data p:.long 1,3,0,7, 9,11,13,17 29 / 30 Conception et exploitation des processeurs Modes d’adressage Résumé x86_64 assembleur 2 adresses, 1er opérande est à droite, aussi résultat, 2ème opérande à gauche un des opérandes peut être l’adresse d’une case mémoire modes d’adressage variés et puisssants conditions variées pour branchement MIPS assembleur 3 adresses, résultat à gauche suivi du 1er puis 2ème opérande seules 2 instructions, load et store, peuvent avoir l’adresse d’une case comme opérande mode d’adressage unique conditions pour branchement très restreintes 30 / 30