1 CHAPITRE 10 Les sous-programmes 2 Sous-programme • Suite d’instructions appelée de manière répétitive • Par un programme • Par plusieurs programmes distincts • Une seule façon de faire l’appel • Sauvegarde de la valeur courante du PC • Effectuer un branchement à l’adresse du sous-programme • Une seule façon de faire le retour • Effectuer un branchement à l’ancienne valeur du PC, à une constante près. 3 Sous-programme • Un sous-programme se compose généralement de: • Récupération des paramètres (inverse du passage de paramètres) • Sauvegarde de l’environnement de l’appelant • Traitement • Retour des résultats, s’il y a lieu • Rétablissement de l’environnement de l’appelant • Retour vers l’appelant (inverse de l’appel) 4 Passage de paramètres • Sur le SPARC • On utilise l’instruction save pour sauvegarder l’environnement • On peut utiliser six registres O pour le passage de paramètres. • Que faire si on doit passer plus de six paramètres? • Que faire si l’architecture n’offre pas de fenêtres de registres? 5 Passage de paramètres • Il existe différentes façons d’effectuer le passage des paramètres • Utilisation d’une fenêtre de registre (comme le SPARC) • Utilisation directe des registres • Utilisation de l’adresse de retour ou du registre de lien • Utilisation d’une table • Utilisation d’une pile 6 Fenêtre de registres • Peut être utilisé lorsque l’architecture supporte le concept de fenêtre de registres Pgm: mov 10, %o0 mov 25, %o1 call Somme mov 32, %o2 mov %o0, %l6 … Somme: save %sp, -208, %sp add %i0, %i1, %i0 add %i0, %i2, %i0 ret restore 7 Registres • Similaire à la technique précédente • Ne fonctionne pas si le nombre de paramètres est plus grand que le nombre de registres. Pgm: mov 10, %l0 mov 25, %l1 call Somme mov 32, %l2 mov %l0, %l6 … Somme: add %l0, %l1, %l0 add %l0, %l2, %l0 retl nop 8 Adresse de retour • On met les paramètres directement dans le code • Juste après l’appel du sous-programme • Sur le SPARC, l’adresse de retour est dans le registre %o7 • On peut donc indexer, à partir de cette adresse, le bon paramètre • On doit modifier la valeur de %o7 pour que le retour soir à la suite des paramètres • %𝑜7 + 8 + 𝑛 × 4 donne l’adresse de retour du sous- programme, avec n paramètres. 9 Adresse de retour Pgm: call Somme nop .word 10 .word 25 .word 32 mov %l0, %l6 … Somme: ldsw [%o7+8], %l0 ldsw [%o7+12], %l1 ldsw [%o7+16], %l2 add %o7, 12, %o7 add %l0, %l1, %l0 add %l0, %l2, %l0 retl nop 3 × 4 = 12 octets %o7 + 8 10 Table • On met les paramètres dans une table en mémoire • On passe l’adresse de la table comme paramètre du sous- programme • On peut donc indexé à partir de cette adresse pour obtenir chacun des paramètres • Comme avec la méthode précédente, on peut passer un nombre arbitraire de paramètres. 11 Table Pgm: setx Table, %l7, %l0 call Somme nop mov %l0, %l6 … Somme: ldsw [%l0], %l1 ldsw [%l0+4], %l2 ldsw [%l0+8], %l3 add %l1, %l2, %l0 add %l0, %l3, %l0 retl nop Table: .section ".rodata" .align 4 .word 10, 25, 32 12 Pile • On met les paramètres au sommet d’une pile • C’est le programme appelant qui s’occupe d’empiler • Le programme appelant et le sous-programme ont accès à un registre qui contient l’adresse du sommet de la pile. • Le sous-programme dépile les paramètres • Empile le résultat sur la pile • En SPARC, le registre %sp contient l’adresse du sommet de la pile • C’est une pile biaisée (2047) et il faut ajouter 128 (on va voir plus tard) 13 Pile Pgm: mov 10, %l0 dec 8, %sp stx %l0, [%sp+2047+128] mov 25, %l0 dec 8, %sp stx %l0, [%sp+2047+128] mov %sp-24 32 32, %l0 %sp-16 25 dec 8, %sp %sp-8 10 stx %l0, [%sp+2047+128] call Somme nop ldx … [%sp+2047+128], %l6 %sp 14 Pile Somme: ldx [%sp+2047+128], %l3 inc 8, %sp ldx [%sp+2047+128], %l2 inc 8, %sp ldx [%sp+2047+128], %l1 inc 8, %sp add %sp 32 %l1, %l2, %l0 %sp+8 25 add %l0, %l3, %l0 %sp+16 10 dec 8, %sp %sp+24 stx %l0, [%sp+2047+128] 67 retl nop 15 Récursivité • Il faut habituellement sauvegarder l’environnement de l’appelant lors de l’exécution d’un sous-programme • On utilise généralement une pile • C’est d’autant plus vrai pour les sous-programmes récursifs • Si l’architecture ne fournit qu’une seule fenêtre de registres • Il faut sauvegarder tous les registres que le sous-programme modifie • L’endroit le plus adapté est la pile • Sur le SPARC, le changement de fenêtre de registres règle le problème 16 Récursivité Factoriel: dec 8, %sp stx %o7, [%sp+2047+128] dec 8, %sp stx %o1, [%sp+2047+128] dec 8, %sp stx %l0, [%sp+2047+128] dec 8, %sp stx %l1, [%sp+2047+128] %sp-32 %l1 %sp-24 %l0 %sp-16 %o1 %sp-8 %o7 %sp brz,a %o1, fact05 mov 1, %o0 mov %o1, %l0 sub %o1, 1, %o1 call Factoriel nop 17 Récursivité brz,a %o0, fact05 nop mulx %l0, %o0, %l1 srlx %l1, 32, %l0 brnz,a %l0, fact05 clr %sp-32 %l1 %o0 %sp-24 %l0 mov %l1, %o0 %sp-16 %o1 %sp-8 ldx [%sp+2047+128], %l1 %o7 inc 8, %sp ldx [%sp+2047+128], %l0 inc 8, %sp ldx [%sp+2047+128], %o1 inc 8, %sp ldx [%sp+2047+128], %o7 inc 8, %sp fact05: retl nop %sp 18 La pile sous Solaris • Espace d’adressage d’un processus Système 0xFFFFFFFFFFFFFFFF Pile Pile %sp+0x7FF Librairies partagées Biais %sp Système Tas (heap) Données Instructions Système 2047 section .data, .rodata, .bss section .text 0x0000000000000000 19 La pile sous Solaris • Le contenu de la pile varie selon l’utilisation que le programmeur veut en faire • Si le programmeur utilise l’instruction save • Le système d’exploitation utilise aussi la pile • Si un sous-programme en assembleur est appelé par un programme en langage évolué (par exemple C) • Le code généré par le compilateur modifie le contenu de la pile • Il faut donc respecter certaines règles d’utilisation 20 La pile sous Solaris • Pour résoudre le manque de fenêtres de registres, le programme et les sous-programmes s’allouent un espace sur la pile • Appelé « bloc » • C’est le système d’exploitation qui s’occupe de sauvegarder dans un bloc l’image de tous les registres de la fenêtre utilisée 21 La pile sous Solaris • Allocation d’un bloc %sp %fp %sp %fp %sp save %sp, -nn, %sp save %sp, -mm, %sp restore restore 22 La pile sous Solaris • Composition d’un bloc %fp %sp Données locales -m octets Données dynamiques -n octets Espace de travail -p octets Paramètres additionnels -q octets • • • Registres %o0 à %o5 -48 octets Registres %i0 à %i7 %l0 à %l7 -128 octets Tout programme a accès aux données de son bloc • Grâce au registre %sp, avec des déplacements positifs • Grâce au registre %fp, avec des déplacements négatifs Tout programme a accès aux données du bloc de l’appelant • Grâce au registre %fp avec des déplacements positifs Tout bloc doit être aligné sur une frontière de double mot Le 128 ajouté à la valeur du %sp dans les exemples précédents