Structure d`un programme

Transcription

Structure d`un programme
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
Structure d’un programme
Entrées/Sorties
1/30
Sous-programmes
Exemple
Programme en Assembleur
Archi
Structure d’un programme
2/30
Entrées/Sorties
Sous-programmes
Exemple
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
organisé en plusieurs SECTIONS (= segments)
X = b (1 octet), w (2 octets) ou d (4 octets = 1 mot).
exemples :
sections différentes pour les données et le code
l1: db
db
dw
dw
l2: dw
l3: dw
directives pour NASM 6= instructions pour le processeur
une seule instruction par ligne, séparateur = chgt de ligne
1 ligne de code = 4 champs (certains optionnels) :
étiquette:
instruction opérandes
; commentaire
;
;
;
;
;
;
l’octet 0x55
3 octets successifs
0x34 0x12 (little endian)
0x61 0x00
0x61 0x62 (caractères)
0x61 0x62 0x63 0x00 (string)
définir des constantes non modifiables avec la directive : equ
exemple :
Archi
0x55
0x55,0x66,0x77
0x1234
’a’
’ab’
’abc’
3/30
nb lettres:
Archi
equ 26
4/30
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Sections de données - suite
SECTION .text
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) :
100
1
1
Exemple
commencer par déclarer global l’étiquette de début de
programme (main) pour qu’elle soit visible :
db 0
; 100 fois l’octet 0x00
dd 0xffffffff ; 28 fois le m^
eme mot
resb
resw
resd
Sous-programmes
B Corps du programme : SECTION .text
B Données non initialisées : SECTION .bss
input1:
input2:
input3:
Entrées/Sorties
Section de code
répéter une déclaration avec la directive : times
exemples :
p0: times 100
p1: times 28
Structure d’un programme
; réserve 100 octets
; réserve 2 octets
; réserve 1 mot (4 octets)
fin de fichier :
mov
mov
int
ebx, 0
eax, 1
0x80
; code de sortie, 0 = normal
; numéro de la commande exit
; interruption 80 hex, appel au noyau
! ! ! Étiquette = adresse de la donnée.
Archi
Structure d’un programme
Entrées/Sorties
Archi
5/30
Sous-programmes
Exemple
Fichier squelette
Structure d’un programme
Entrées/Sorties
6/30
Sous-programmes
Exemple
Assembler un programme
Assemblage : créer un fichier objet (transformer le programme
écrit en langage d’assemblage en instructions machine)
%include "asm_io.inc"
SECTION .data
; données initialisées
;
nasm -g -f <format> <fichier> [-o <sortie>]
Exemples :
SECTION .bss
; données non initialisées
;
nasm -g -f coff toto.asm
nasm -g -f elf toto.asm -o toto.o
Produire un listing des instructions machine :
SECTION .text
global main
; rend l’étiquette visible de l’extérieur
nasm -g -f elf toto.asm -l toto.lst
Édition de lien :
main:
; programmme
;
mov ebx,0
mov eax,1
int 0x80
ld -e main toto.o -o toto
En utilisant des bibliothèques C ou écrites en C (par exemple,
asm io de P. Carter, pour les E/S) :
; code de sortie, 0 = normal
; numéro de la commande exit
; interruption 80 hex, appel au noyau
Archi
nasm -g -f elf toto.asm
gcc toto.o asm_io.o -o toto
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
Structure d’un programme
Entrées/Sorties
9/30
Sous-programmes
Exemple
Entrées/sorties
Archi
Structure d’un programme
Entrées/Sorties
10/30
Sous-programmes
Exemple
Affichage par interruption
Entrées-sorties (I/O) : échanges d’informations entre le
processeur et les périphériques.
Entrées : données envoyées par un périphérique (disque, réseau,
clavier...) à destination de l’unité centrale.
Sorties : données émises par l’unité centrale à destination d’un
périphérique (disque, réseau, écran...).
Gestion par interruptions :
permet de réagir rapidement à un changement en entrée.
le périphérique prévient le processeur par une interruption,
le processeur interrompt la tâche en cours, effectue l’action
prévue pour cette interruption et reprend l’exécution du
programme principal là où il l’avait laissée.
SECTION .text
global main
main:
Gestion “haut-niveau” :
Bibliothèques standards en C pour les E/S (pas en assembleur).
MAIS, les conventions d’appels utilisées par C sont complexes...
Archi
SECTION .data
msg1:db "message 1",10
lg1: equ $-msg1
11/30
...
mov
mov
mov
mov
int
...
edx,
ecx,
ebx,
eax,
0x80
lg1
msg1
1
; stdout
4
; write
Archi
12/30
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Affichage en utilisant printf
Structure d’un programme
Entrées/Sorties
%include "asm_io.inc"
SECTION .data
msg2: db "msg 2", 10, 0
SECTION .data
msg3: db "msg 3", 10, 0
SECTION .text
global main
SECTION .text
global main
main:
main:
Sous-programmes
Exemple
...
mov eax, msg3
call print_string
...
msg2
printf
Archi
Structure d’un programme
Exemple
Affichage avec ams io.inc
extern printf
...
push
call
...
Sous-programmes
Entrées/Sorties
13/30
Sous-programmes
Exemple
Archi
Structure d’un programme
Entrées/Sorties
14/30
Routines d’E/S de P. Carter
print int
print char
print string
print nl
read int
read char
affiche à l’écran la valeur de l’entier stocké dans eax
affiche à l’écran le caractère dont le code ASCII est
stocké dans al
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)
affiche à l’écran un caractère de nouvelle ligne
lit un entier au clavier et le stocke dans le registre eax
lit un caractère au clavier et stocke son code ASCII
dans le registre eax
Sous-programmes
%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
Sous-programmes
Structure d’un programme
Entrées/Sorties
Exemple
Exemple, sans sous-programme
Les sous-programmes servent à mutualiser du code (éviter les
copier-coller)
%include "asm_io.inc"
Exemple : les fonctions des langages haut niveau.
cmp
jl
Le code appelant le sous-programme et le sous-programme
lui-même doivent se mettre d’accord sur la façon de se passer
les données (conventions d’appel).
SECTION .data
msg1: db "entier <10 ?",10,0
msg2: db "bravo",10,0
msg3: db "perdu",10,0
Un saut peut être utilisé pour appeler le sous-programme, mais
le retour pose problème.
Le sous-programme peut être utilisé par différentes parties du
programme B il doit revenir au point où il a été appelé !
Donc, le retour du sous-programme ne peut pas être codé “en
dur” par un saut vers une étiquette.
L’étiquette de retour doit être un paramètre du sous-programme.
Archi
Structure d’un programme
Sous-programmes
rate: mov
call
jmp
eax, msg3
print_string
fin
SECTION .text
global main
ok:
mov
call
eax, msg2
print_string
main: mov
call
fin:
mov
mov
int
ebx, 0
eax, 1
0x80
call
eax, msg1
print_string
read_int
Archi
17/30
Entrées/Sorties
Sous-programmes
Exemple
Sous-programme “à la main”
eax, 10
ok
Structure d’un programme
Entrées/Sorties
18/30
Sous-programmes
Exemple
Instructions call et ret
Problèmes :
%include "asm_io.inc"
SECTION .data
msg1: db "entier <10 ?",10,0
msg2: db "bravo",10,0
msg3: db "perdu",10,0
SECTION .text
global main
main: mov
call
eax, msg1
print_string
mov
jmp
ret_sb: call
read_int
Un peu compliqué
Besoin d’autant d’étiquettes que d’appels du sous-programme.
Solution : call et ret
fin:
mov
mov
int
ebx, 0
eax, 1
0x80
sb:
cmp
jl
mov
jmp
mov
jmp
eax, 10
ok
eax, msg3
ecx
eax, msg2
ecx
rate:
ok:
call
ecx, ret_sb
sb
print_string
L’instruction call effectue un saut inconditionnel vers un sousprogramme après avoir empilé l’adresse de l’instruction suivante
l1: call
fonction
push
l2
l2: ...
jmp
fonction
L’instruction ret dépile une adresse et saute à cette adresse :
ret
pop
reg.
jmp
reg.
Lors de l’utilisation de ces instructions, il est très important de
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
Sous-programme avec call et ret
%include "asm_io.inc"
SECTION .data
msg1: db "entier <10 ?",10,0
msg2: db "bravo",10,0
msg3: db "perdu",10,0
fin:
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Passage des paramètres
call
call
sb
print_string
mov
mov
int
ebx, 0
eax, 1
0x80
cmp
jl
mov
ret
mov
ret
eax, 10
ok
eax, msg3
! ! Il est très important de dépiler toute donnée qui a été
empilée dans le corps du sous-programme.
Exemple :
plus2:
add
push
ret
eax, 2
eax
; dépile la valeur de eax !!
Ce code ne reviendra pas correctement !
SECTION .text
global main
sb:
rate:
main: mov
call
call
eax, msg1
print_string
ok:
Autre problème : passage des paramètres par registres
limite le nombre de paramètres ;
eax, msg2
mobilise les registres pour les conserver.
read_int
Solution : passer les paramètres par la pile (convention de C).
Archi
Structure d’un programme
Entrées/Sorties
21/30
Sous-programmes
Exemple
Passer les paramètres par la pile
Entrées/Sorties
22/30
Sous-programmes
Exemple
Passer les paramètres par la pile - suite
Les paramètres passés par la pile sont empilés avant le call.
Si le paramètre doit être modifié par le sous-programme, c’est
son adresse qui doit être passée.
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 :
Sinon, comme ils sont empilés avant le call, l’adresse de retour
devrait être dépilée avant tout (puis ré-empilée ensuite).
Si les paramètres sont utilisés à plusieurs endroits :
B ça évite de les conserver dans un registre ;
B les laisser sur la pile permet de conserver une copie de la
donnée en mémoire accessible à n’importe quel moment.
Lors d’un appel de sous-programme : la pile ressemble à
...
esp
adresse de retour
esp+4
paramètre
Si la pile est également utilisée dans le sous-programme pour
stocker des données, le nombre à ajouter à esp change.
Par exemple, après un push la pile ressemble à :
...
esp
donnée du sous-programme
esp+4
adresse de retour
esp+8
paramètre
Maintenant, le paramètre est en esp+8, et non plus en esp+4.
esp pour faire référence aux paramètres ⇒ erreurs possibles.
Pour résoudre ce problème, utiliser ebp (base de la pile).
La convention de C est qu’un sous-programme commence par
empiler la valeur de ebp puis affecte à ebp la valeur de esp.
Permet à esp de changer sans modifier ebp.
A la fin du programme, la valeur originale de ebp est restaurée.
Accès au paramètre par adressage indirect : [esp+4]
Archi
Archi
Structure d’un programme
23/30
Archi
24/30
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Passer les paramètres par la pile - suite
etiquette sousprogramme:
push ebp
; empile la valeur originale de ebp
mov
ebp, esp
; ebp = esp
; code du sous-programme
pop
ebp
; restaure l’ancienne valeur de ebp
ret
Exemple
Archi
Une fois le sous-programme terminé, les paramètres qui ont
été empilés doivent être retirés.
Un sous-programme utilisant cette convention peut être
appelé comme suit :
Le paramètre est accessible avec [ebp+8] depuis n’importe quel
endroit du sous-programme.
push
call
add
param
fnc
esp, 4
Exemple
; passe un paramètre
; retire le paramètre de la pile
La 3ème ligne retire le paramètre de la pile en manipulant
directement l’adresse du sommet de la pile.
Une instruction pop pourrait également être utilisée, mais
le paramètre n’a pas besoin d’être stocké dans un registre.
25/30
Sous-programmes
Sous-programmes
La convention d’appel C spécifie que c’est au code appelant
de le faire (convention différente en Pascal, par exemple).
La pile au début du code du sous-programme ressemble à
...
...
esp
donnée
esp
ebp
ebp prec.
esp+4
ebp
ebp prec.
esp+4 ebp+4 adr. de retour
esp+8
ebp+4 adr. de retour
esp+8 ebp+8
paramètre
esp+12 ebp+8
paramètre
Entrées/Sorties
Entrées/Sorties
Passer les paramètres par la pile - fin
Forme générale d’un sous-programme qui suit ces conventions :
Structure d’un programme
Structure d’un programme
Archi
Structure d’un programme
Entrées/Sorties
26/30
Sous-programmes
Exemple
Exemple de passage de paramètre par la pile
%include "asm_io.inc"
SECTION .data
msg1: db "entier <10 ?",10,0
msg2: db "bravo",10,0
msg3: db "perdu",10,0
fin:
sb:
print_string
mov
mov
int
ebx,0
eax,1
0x80
push
mov
cmp
jl
rate: mov
pop
ret
ok:
mov
pop
ret
SECTION .text
global main
main: mov
eax,msg1
call print_string
call read_int
push
call
add
call
eax
sb
esp, 4
Archi
ebp
ebp, esp
dword [ebp+8], 10
ok
eax, msg3
ebp
Exemple complet
eax, msg2
ebp
27/30
Archi
28/30
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Afficher des rayures
Structure d’un programme
Entrées/Sorties
Sous-programmes
Exemple
Programme
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.
%include "asm_io.inc"
SECTION .data
msg1:db
msg2:db
msg3:db
blanc:
"nb bandes?",10,0
"nb lignes?",10,0
"caractere?",10,0
db "
",0
SECTION .bss
nbb: resd 1
nbl: resd 1
SECTION .text
global main
mov
call
call
mov
eax, msg2
print_string
read_int
[nbl], eax
mov
call
call
call
mov
eax,msg3
print_string
read_char
read_char
ecx, [nbl]
ligne:
push ebp
mov ebp, esp
push ecx
nxt:push
push
call
add
pop
eax
dword [nbb]
ligne
esp, 4
eax
mov
sv: mov
call
mov
call
loop
ecx, [ebp+8]
eax, [ebp+12]
print_char
eax, blanc
print_string
sv
call print_nl
pop ecx
main:
mov
call
call
mov
Archi
29/30
loop nxt
eax, msg1
print_string
read_int
[nbb], eax
fin:mov ebx, 0
mov eax, 1
int 0x80
Archi
pop
ret
ebp
30/30

Documents pareils