Architecture des ordinateurs Cours 7 17 décembre 2012 Archi 1/1
Fonctions, suite et fin Archi 2/1
Rappel Forme générale d un sous-programme (fonction) : etiquette sousprogramme: push ebp ; empile la valeur originale de ebp ebp, esp ; ebp = esp ; code du sous-programme pop ebp ; restaure l ancienne valeur de ebp Un sous-programme peut être appelé comme suit : push param ; passe un paramètre fnc ; appelle la fonction fnc add esp, 4 ; ire le paramètre de la pile Le dernier paramètre empilé est désigné par [ebp+8] dans fnc L avant dernier paramètre par [ebp+12], etc... Archi 3/1
Afficher des rayures On souhaite écrire un programme qui affiche k rayures verticales sur n lignes. Les rayures doivent être dessinées en utilisant un caractère choisi par l utilisateur. Archi 4/1
rayures.asm (version commentée sur la page du cours) %include "asm_io.inc" SECTION.data msg1:db "nb bandes?",10,0 msg2:db "nb lignes?",10,0 msg3:db "caractere?",10,0 blanc: db " ",0 SECTION.bss nbb: resd 1 nbl: resd 1 SECTION.text global main main: eax, msg1 print_string read_int [nbb], eax eax, msg2 print_string read_int [nbl], eax eax,msg3 print_string read_char read_char ;!! ecx, [nbl] push eax push dword [nbb] nxt: ligne loop nxt add esp, 4 pop eax fin: ebx, 0 eax, 1 int 0x80 ligne: push ebp ebp, esp push ecx ecx, [ebp+8] sv: eax, [ebp+12] print_char eax, blanc print_string loop sv print_nl pop ecx pop ebp Archi 5/1
Écrire une fonction récursive pas de différence avec une fonction classique MAIS : Bien respecter les règles de préservation de la pile est crucial lors de l écriture d une fonction récursive! Exemple de fonction récursive simple : calculer la somme des entiers de 1 à n. En C : int somme_rec (int n){ if (n = 1) urn 1; else urn n + somme_rec(n-1); } Archi 6/1
somme rec.asm (version commentée sur la page du cours) %include "asm_io.inc" SECTION.data msg1: db "Un entier?",10,0 msg2: db 10,"Somme: ",0 SECTION.text global main main: eax, msg1 print_string read_int ebx, eax eax, msg2 print_string push ebx somme add esp, 4 print_int print_nl fin: ebx, 0 eax, 1 int 0x80 somme:push ebp ebp, esp ebx, [ebp+8] cmp ebx, 1 je stop dec ebx push ebx somme add esp, 4 add jmp stop: eax, 1 fin_somme: pop eax, [ebp+8] fin_somme ebp Archi 7/1
Évolution de la pile s b 3 ### avant le 1er appel à somme_rec s b 3 ### somme_rec s b 3 ### push ebp ebp, esp s b 2 3 ### s b avant le 2e appel à somme_rec 1 2 3 ### s b avant le 3e appel à somme_rec 1 2 3 ### fin de la récursion s b 2 3 ### 1 eax s b 3 ### 1+2=3 eax s b ### 3+3=6 eax Une procédure non récursive aurait-elle été plus efficace? Archi 8/1
Les variables locales... La pile peut être utilisée pour stocker des variables locales. Permet d écrire des sous-programmes ré-entrants pas de registres, ni d adresse fixe. Utiliser la pile pour les variables économise de la mémoire (par opposition aux variables globales) et les registres. Les variables locales sont stockées immédiatement après la valeur de ebp sauvegardée dans la pile. Allocation : soustraire de esp le nombre d octets requis. fct: push ebp ; empile la valeur originale de ebp ebp, esp ; ebp = esp sub esp,??... esp, ebp ; désalloue les variables locales pop ebp ; restaure la valeur de ebp On utilise ebp pour localiser les variables locales. Archi 9/1
Exemple de variables locales fct: push ebp ; empile la valeur originale de ebp ebp, esp ; ebp = esp sub esp, 8 ; 2 variables locales de 4 octets... esp, ebp ; désalloue les variables locales pop ebp ; restaure la valeur de ebp... esp ebp-8 var. locale... ebp-4 var. locale esp ebp ebp prec. ebp ebp prec. ebp+4 adr. de ebp+4 adr. de Les 2 variables locales sont accessibles depuis n importe quel endroit du sous-programme ; pour les utiliser : [ebp-4] et [ebp-8] Archi 10/1
sommes.asm (version commentée sur la page du cours) %include "asm_io.inc" SECTION.data msg1: db "Un entier?",10,0 somme: push ebp ebp, esp sub esp, 4 somme: push ; 2eme version ebp ebp, esp SECTION.text global main main: eax, msg1 print_string read_int print_nl push ecx dword [ebp-4], 0 ecx, [ebp+8] nxt: add [ebp-4], ecx loop nxt push 0 push ecx ecx, [ebp+8] nxt: add [ebp-4], ecx loop nxt push eax somme add esp, 4 pop eax, [ebp-4] ecx pop eax, [ebp-4] ecx fin:... print_int print_nl fin_somme: esp, ebp pop ebp fin_somme: esp, ebp pop ebp Archi 11/1
Les tableaux Archi 12/1
Tableaux en assembleur Pas de structure de tableau à proprement parler. Tableau = bloc contigu de données en mémoire. Tous les éléments occupent le même espace en mémoire. Pour accéder à un élément, on utilise : l adresse du premier élément du tableau : adr le nombre d octets occupés par un élément : taille l indice de l élément : indice [ adr + taille*indice ] Exemple : SECTION.data tab1: db 1,2,3,4,5,6,7,8,9 tab2: dw 10,20,30,40,50,60,70,80,90 SECTION.bss tab3: resd 9 SECTION.text... ecx, 9 next: eax, 0 al, [tab1 + ecx] add ax, [tab2 + 2*ecx] [tab3 + 4*ecx], eax loop next... Archi 13/1
squares.asm (version commentée sur la page du cours) %include "asm_io.inc" SECTION.data msg: db "i<20?",10,0 t1: db "tab[",0 t2: db "]= ",0 blanc: db tab: dw 5,1,23,4,... SECTION.bss tab2: resd 20 SECTION.text global main main: eax, msg print_string read_int ebx, eax eax, t1 print_string eax, ebx print_int eax, t2 print_string eax, 0 ax, [tab+2*ebx] print_int print_nl ebx, 0 nxt: eax, 0 ax, [tab+2*ebx] mul eax [tab2+4*ebx], eax inc ebx cmp ebx, 20 jne nxt fnc fin:... fnc: push ebp ebp, esp ebx, 0 na: eax, [tab2+4*ebx] print_int eax, [blanc] print_char inc ebx cmp ebx, 20 jne na fin_fnc: pop ebp print_nl Archi 14/1
fibo.asm (version commentée sur la page du cours) %include "asm_io.inc" SECTION.data msg1:db "entier <40?",10,0 msg2:db " premiers: ",0 blanc:db SECTION.bss n: resd 1 fibo: resd 40 SECTION.text global main main: ; remplissage du tableau dword [fibo], 1 dword [fibo+4], 1 ecx, 0 nxt: eax, [fibo+4*ecx] ebx, [fibo+4*ecx+4] add eax, ebx [fibo+4*ecx+8], eax inc ecx cmp ecx, 38 jne nxt ; affichage eax, msg1 print_string read_int [n], eax push dword [n] aff_n add esp, 4 fin: ebx, 0 eax, 1 int 0x80 aff_n: push ebp ebp, esp; dword eax, [ebp+8] print_int eax, msg2 print_string ebx, 0 ecx, 40 na: eax, [fibo+4*ebx] print_int eax, [blanc] print_char inc ebx cmp ebx, [ebp+8] loopne na print_nl fin_aff_n: pop ebp Archi 15/1
Les chaînes de caractères sont des tableaux... Chaîne de caractères en assembleur = bloc contigu d octets en mémoire, terminé par un 0. = tableau d octets (caractères en ascii) terminé par un 0. Exemple (lecture du prénom au clavier) : %include "asm_io.inc" SECTION.data msg1: db "Quel est ton nom?",10,0 msg2: db "Bonjour ",0 SECTION.bss prenom: resb 20 SECTION.text global main main: eax, msg1 print_string ecx, 19 ebx, 0 nxt: read_char [prenom+ebx], eax inc ebx cmp eax, 10 loopne nxt byte [prenom+ebx], 0 eax, msg2 print_string eax, prenom print_string Archi 16/1
majuscule.asm %include "asm_io.inc" SECTION.data msg: db "texte?",10,0 lt1: db a lt2: db A blanc:db SECTION.bss min: resb 100 maj: resb 100 lg: resd 1 moins:resd 1 SECTION.text global main main: eax, [lt1] sub eax, [lt2] [moins],eax eax, msg print_string (version commentée sur la page du cours) push min push lg read_string add esp, 8 ebx, 0 nxt: al, [min+ebx] cmp al, [blanc] je espace sub al, [moins] espace: [maj+ebx], al inc ebx cmp ebx, [lg] jne nxt byte [maj+ebx], 0 fin:... print_nl eax, maj print_string print_nl read_string: push ebp ebp, esp pusha edx, [ebp+12] ecx, 99 ebx, 0 nxt_rs: read_char [edx+ebx], al inc ebx cmp al, 10 loopne nxt_rs byte [edx+ebx], 0 edx, [ebp+8] dec ebx [edx], ebx popa fin_read_string: pop ebp Archi 17/1
Vers les langages haut niveau Archi 18/1
Rappel : architecture en couches 5. Langages haut niveau Compilation 4. Langage d assemblage Assembleur 3. Système d exploitation Appels système 2. Jeu d instructions propre à chaque machine (ISA) Microprogrammes : micro-instructions binaires 1. Micro-architecture (UAL, opérations, registres,...) Assemblage physique des portes logiques 0. Circuits logiques Archi 19/1
Exemple de compilation : gcc -S -masm=intel add.c int main(){ int i, sum = 0; for ( i = 1; i <= 10; i++ ) sum += i; printf("sum = %d \n", sum); urn 0; }.file "add.c".intel_syntax noprefix.section.rodata.lc0:.string "sum = %d \n".text.globl main.type main, @function main: lea ecx, [esp+4] and esp, -16 push DWORD PTR [ecx-4] push ebp ebp, esp push ecx sub esp, 36 DWORD PTR [ebp-8], 0 DWORD PTR [ebp-12], 1 jmp.l2.l3: eax, DWORD PTR [ebp-12] add DWORD PTR [ebp-8], eax add DWORD PTR [ebp-12], 1.L2: cmp DWORD PTR [ebp-12], 10 jle.l3 eax, DWORD PTR [ebp-8] DWORD PTR [esp+4], eax DWORD PTR [esp], OFFSET FLAT:.LC0 printf eax, 0 add esp, 36 pop ecx pop ebp lea esp, [ecx-4].size main,.-main.ident "GCC: (Gentoo 4.3.2-r3 p1.6, pie-10.1.5) 4.3.2".section.note.GNU-stack,"",@progbits Archi 20/1