Vous êtes sur la page 1sur 8

Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Architecture des ordinateurs


Structure d’un programme
Cours 6

3 décembre 2012

Archi 1/30 Archi 2/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Programme en Assembleur Sections de données

B Données initialisées : SECTION .data


programme en assembleur = fichier texte (extension .asm) déclarer des données initialisées avec la directive : dX
X = b (1 octet), w (2 octets) ou d (4 octets = 1 mot).
organisé en plusieurs SECTIONS (= segments)
exemples :
sections différentes pour les données et le code l1: db 0x55 ; l’octet 0x55
directives pour NASM 6= instructions pour le processeur db 0x55,0x66,0x77 ; 3 octets successifs
dw 0x1234 ; 0x34 0x12 (little endian)
une seule instruction par ligne, séparateur = chgt de ligne dw ’a’ ; 0x61 0x00
l2: dw ’ab’ ; 0x61 0x62 (caractères)
1 ligne de code = 4 champs (certains optionnels) :
l3: dw ’abc’ ; 0x61 0x62 0x63 0x00 (string)
étiquette: instruction opérandes ; commentaire définir des constantes non modifiables avec la directive : equ
exemple : nb lettres: equ 26

Archi 3/30 Archi 4/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Sections de données - suite Section de code

répéter une déclaration avec la directive : times B Corps du programme : SECTION .text
exemples : commencer par déclarer global l’étiquette de début de
p0: times 100 db 0 ; 100 fois l’octet 0x00 programme (main) pour qu’elle soit visible :
p1: times 28 dd 0xffffffff ; 28 fois le m^
eme mot
SECTION .text
B Données non initialisées : SECTION .bss global main

déclarer des données non initialisées avec la directive : resX main:


X = b (1 octet), w (2 octets) ou d (4 octets = 1 mot). ...
exemples (étiquettes obligatoires) :
fin de fichier :
input1: resb 100 ; réserve 100 octets
input2: resw 1 ; réserve 2 octets mov ebx, 0 ; code de sortie, 0 = normal
input3: resd 1 ; réserve 1 mot (4 octets) mov eax, 1 ; numéro de la commande exit
int 0x80 ; interruption 80 hex, appel au noyau
! ! ! Étiquette = adresse de la donnée.

Archi 5/30 Archi 6/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Fichier squelette Assembler un programme


%include "asm_io.inc" Assemblage : créer un fichier objet (transformer le programme
SECTION .data écrit en langage d’assemblage en instructions machine)
; données initialisées
; nasm -g -f <format> <fichier> [-o <sortie>]
Exemples :
SECTION .bss nasm -g -f coff toto.asm
; données non initialisées
nasm -g -f elf toto.asm -o toto.o
;
Produire un listing des instructions machine :
SECTION .text nasm -g -f elf toto.asm -l toto.lst
global main ; rend l’étiquette visible de l’extérieur
Édition de lien :
main:
ld -e main toto.o -o toto
; programmme
; En utilisant des bibliothèques C ou écrites en C (par exemple,
mov ebx,0 ; code de sortie, 0 = normal asm io de P. Carter, pour les E/S) :
mov eax,1 ; numéro de la commande exit nasm -g -f elf toto.asm
int 0x80 ; interruption 80 hex, appel au noyau
gcc toto.o asm_io.o -o toto
Archi 7/30 Archi 8/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Interruptions

Le flot ordinaire d’un programme doit pouvoir être interrompu


pour traiter des évènements nécessitant une réponse rapide.
Mécanisme d’interruptions (ex : lorsque la souris est déplacée, le
programme en cours est interrompu pour gérer ce déplacement).
Entrées/Sorties Passage du contrôle à un gestionnaire d’interruptions.
Certaine interruptions sont externes (ex : la souris).
D’autres sont soulevées par le processeur, à cause d’une erreur
(traps) ou d’une instruction spécifique (interruption logicielle).
En général, le gestionnaire d’interruptions redonne le contrôle au
programme interrompu, une fois l’interrupion traitée.
Il restaure tous les registres (sauf eax).
Le programme interrompu s’exécute comme si rien n’était arrivé.
Les traps arrêtent généralement le programme.
Archi 9/30 Archi 10/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Entrées/sorties Affichage par interruption


Entrées-sorties (I/O) : échanges d’informations entre le
processeur et les périphériques.
SECTION .data
Entrées : données envoyées par un périphérique (disque, réseau, msg1:db "message 1",10
clavier...) à destination de l’unité centrale. lg1: equ $-msg1
Sorties : données émises par l’unité centrale à destination d’un
périphérique (disque, réseau, écran...). SECTION .text
global main
Gestion par interruptions :
permet de réagir rapidement à un changement en entrée. main:
le périphérique prévient le processeur par une interruption, ...
le processeur interrompt la tâche en cours, effectue l’action mov edx, lg1
prévue pour cette interruption et reprend l’exécution du mov ecx, msg1
mov ebx, 1 ; stdout
programme principal là où il l’avait laissée.
mov eax, 4 ; write
Gestion “haut-niveau” : int 0x80
...
Bibliothèques standards en C pour les E/S (pas en assembleur).
MAIS, les conventions d’appels utilisées par C sont complexes...
Archi 11/30 Archi 12/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Affichage en utilisant printf Affichage avec ams io.inc

extern printf %include "asm_io.inc"

SECTION .data SECTION .data


msg2: db "msg 2", 10, 0 msg3: db "msg 3", 10, 0

SECTION .text SECTION .text


global main global main

main: main:
... ...
push msg2 mov eax, msg3
call printf call print_string
... ...

Archi 13/30 Archi 14/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Routines d’E/S de P. Carter


print int affiche à l’écran la valeur de l’entier stocké dans eax
print char affiche à l’écran le caractère dont le code ASCII est
stocké dans al
print string affiche à l’écran le contenu de la chaı̂ne de caractères
à l’adresse stockée dans eax. La chaı̂ne doit être une
chaı̂ne de type C (terminée par 0)
print nl affiche à l’écran un caractère de nouvelle ligne Sous-programmes
read int lit un entier au clavier et le stocke dans le registre eax
read char lit un caractère au clavier et stocke son code ASCII
dans le registre eax

%include "asm io.inc"


Pour chaque fonction d’affichage,
il faut charger eax avec la valeur correcte,
utiliser une instruction call pour l’invoquer.
ces fonctions préservent les valeurs de tous les registres,
sauf les deux read qui modifient eax.
Archi 15/30 Archi 16/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Sous-programmes Exemple, sans sous-programme

Les sous-programmes servent à mutualiser du code (éviter les %include "asm_io.inc" cmp eax, 10
copier-coller) jl ok
Exemple : les fonctions des langages haut niveau. SECTION .data
Le code appelant le sous-programme et le sous-programme msg1: db "entier <10 ?",10,0 rate: mov eax, msg3
lui-même doivent se mettre d’accord sur la façon de se passer msg2: db "bravo",10,0 call print_string
les données (conventions d’appel). msg3: db "perdu",10,0 jmp fin

Un saut peut être utilisé pour appeler le sous-programme, mais SECTION .text ok: mov eax, msg2
le retour pose problème. global main call print_string
Le sous-programme peut être utilisé par différentes parties du
programme B il doit revenir au point où il a été appelé ! main: mov eax, msg1 fin: mov ebx, 0
Donc, le retour du sous-programme ne peut pas être codé “en call print_string mov eax, 1
dur” par un saut vers une étiquette. int 0x80
L’étiquette de retour doit être un paramètre du sous-programme. call read_int

Archi 17/30 Archi 18/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Sous-programme “à la main” Instructions call et ret


Problèmes :
%include "asm_io.inc" mov ecx, ret_sb Un peu compliqué
jmp sb Besoin d’autant d’étiquettes que d’appels du sous-programme.
SECTION .data ret_sb: call print_string
msg1: db "entier <10 ?",10,0 Solution : call et ret
msg2: db "bravo",10,0 fin: mov ebx, 0 L’instruction call effectue un saut inconditionnel vers un sous-
msg3: db "perdu",10,0 mov eax, 1 programme après avoir empilé l’adresse de l’instruction suivante
int 0x80 l1: call fonction push l2
SECTION .text l2: ... jmp fonction
global main sb: cmp eax, 10 L’instruction ret dépile une adresse et saute à cette adresse :
jl ok ret pop reg.
main: mov eax, msg1 rate: mov eax, msg3
jmp reg.
call print_string jmp ecx
ok: mov eax, msg2 Lors de l’utilisation de ces instructions, il est très important de
call read_int jmp ecx gérer la pile correctement (dépiler tout ce qu’on a empilé) afin
que l’adresse dépilée par l’instruction ret soit correcte.
Permet d’imbriquer des appels de sous-programmes facilement.
Archi 19/30 Archi 20/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Sous-programme avec call et ret Passage des paramètres

! ! Il est très important de dépiler toute donnée qui a été


%include "asm_io.inc" call sb
empilée dans le corps du sous-programme.
call print_string
SECTION .data Exemple :
msg1: db "entier <10 ?",10,0 fin: mov ebx, 0 plus2: add eax, 2
msg2: db "bravo",10,0 mov eax, 1 push eax
msg3: db "perdu",10,0 int 0x80 ret ; dépile la valeur de eax !!
Ce code ne reviendra pas correctement !
SECTION .text sb: cmp eax, 10
global main jl ok
rate: mov eax, msg3 Autre problème : passage des paramètres par registres
main: mov eax, msg1 ret
limite le nombre de paramètres ;
call print_string ok: mov eax, msg2
ret mobilise les registres pour les conserver.
call read_int Solution : passer les paramètres par la pile (convention de C).

Archi 21/30 Archi 22/30


Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Passer les paramètres par la pile Passer les paramètres par la pile - suite
Les paramètres passés par la pile sont empilés avant le call. Si la pile est également utilisée dans le sous-programme pour
Si le paramètre doit être modifié par le sous-programme, c’est stocker des données, le nombre à ajouter à esp change.
son adresse qui doit être passée. Par exemple, après un push la pile ressemble à :
Les paramètres sur la pile ne sont pas dépilés par le ...
sous-programme mais accédés depuis la pile elle-même : esp donnée du sous-programme
Sinon, comme ils sont empilés avant le call, l’adresse de retour esp+4 adresse de retour
devrait être dépilée avant tout (puis ré-empilée ensuite). esp+8 paramètre
Si les paramètres sont utilisés à plusieurs endroits :
Maintenant, le paramètre est en esp+8, et non plus en esp+4.
B ça évite de les conserver dans un registre ;
B les laisser sur la pile permet de conserver une copie de la esp pour faire référence aux paramètres ⇒ erreurs possibles.
donnée en mémoire accessible à n’importe quel moment.
Pour résoudre ce problème, utiliser ebp (base de la pile).
Lors d’un appel de sous-programme : la pile ressemble à
... La convention de C est qu’un sous-programme commence par
esp adresse de retour empiler la valeur de ebp puis affecte à ebp la valeur de esp.
esp+4 paramètre Permet à esp de changer sans modifier ebp.
Accès au paramètre par adressage indirect : [esp+4] A la fin du programme, la valeur originale de ebp est restaurée.
Archi 23/30 Archi 24/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Passer les paramètres par la pile - suite Passer les paramètres par la pile - fin

Forme générale d’un sous-programme qui suit ces conventions :


Une fois le sous-programme terminé, les paramètres qui ont
etiquette sousprogramme: été empilés doivent être retirés.
push ebp ; empile la valeur originale de ebp
mov ebp, esp ; ebp = esp
La convention d’appel C spécifie que c’est au code appelant
; code du sous-programme de le faire (convention différente en Pascal, par exemple).
pop ebp ; restaure l’ancienne valeur de ebp Un sous-programme utilisant cette convention peut être
ret appelé comme suit :
La pile au début du code du sous-programme ressemble à push param ; passe un paramètre
... call fnc
... esp donnée add esp, 4 ; retire le paramètre de la pile
esp ebp ebp prec. esp+4 ebp ebp prec.
La 3ème ligne retire le paramètre de la pile en manipulant
esp+4 ebp+4 adr. de retour esp+8 ebp+4 adr. de retour
directement l’adresse du sommet de la pile.
esp+8 ebp+8 paramètre esp+12 ebp+8 paramètre
Une instruction pop pourrait également être utilisée, mais
Le paramètre est accessible avec [ebp+8] depuis n’importe quel le paramètre n’a pas besoin d’être stocké dans un registre.
endroit du sous-programme.
Archi 25/30 Archi 26/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Exemple de passage de paramètre par la pile


%include "asm_io.inc" call print_string

SECTION .data fin: mov ebx,0


msg1: db "entier <10 ?",10,0 mov eax,1
msg2: db "bravo",10,0 int 0x80
msg3: db "perdu",10,0
sb: push ebp
Exemple complet
SECTION .text mov ebp, esp
global main cmp dword [ebp+8], 10
main: mov eax,msg1 jl ok
call print_string rate: mov eax, msg3
call read_int pop ebp
ret
push eax ok: mov eax, msg2
call sb pop ebp
add esp, 4 ret
Archi 27/30 Archi 28/30
Structure d’un programme Entrées/Sorties Sous-programmes Exemple Structure d’un programme Entrées/Sorties Sous-programmes Exemple

Afficher des rayures Programme


On souhaite écrire un programme qui affiche k rayures %include "asm_io.inc" mov eax, msg2 ligne:
verticales sur n lignes. Les rayures doivent être dessinées en call print_string push ebp
SECTION .data call read_int mov ebp, esp
utilisant un caractère choisi par l’utilisateur. mov [nbl], eax
msg1:db "nb bandes?",10,0 push ecx
msg2:db "nb lignes?",10,0 mov eax,msg3
msg3:db "caractere?",10,0 call print_string mov ecx, [ebp+8]
blanc: db " ",0 call read_char
call read_char sv: mov eax, [ebp+12]
SECTION .bss mov ecx, [nbl] call print_char
mov eax, blanc
nbb: resd 1 nxt:push eax call print_string
nbl: resd 1 push dword [nbb] loop sv
call ligne
SECTION .text add esp, 4 call print_nl
global main pop eax
pop ecx
main: loop nxt
mov eax, msg1 pop ebp
call print_string fin:mov ebx, 0 ret
call read_int mov eax, 1
mov [nbb], eax int 0x80

Archi 29/30 Archi 30/30

Vous aimerez peut-être aussi