La gestion des procédures Laboratoire de Systèmes Logiques
Appel de procédure En langage de haut niveau: procedure toto; begin end; toto; toto; En langage machine: toto: rts jsr toto jsr toto Page 2
L instruction jsr toto a deux effets: sauver l adresse de retour (c est-à-dire l adresse de l instruction qui suit l instruction jsr) dans la pile du système (stack): SP SP - 4 stack PC sauter à l instruction placée à l adresse toto: PC toto 1A04 1A05 1A06 1A07 adresse de retour stack pointer (SP) Page 3
Passage de paramètres Afin de généraliser l appel, il faut une convention unique, standard, de passage de paramètres pour toutes les procédures, même si elle est inefficace pour certaines La procédure doit trouver les paramètres toujours au même endroit, pour les accéder pendant l exécution. Il existe deux possibilités: la pile les registres Ce qu on met dans la pile dépend du type de passage: par valeur: on met la valeur du paramètre (sauf si le paramètre est un non scalaire très complexe: dans ce cas on met l adresse du paramètre, pour éviter un gaspillage d espace dans la copie) par référence: on met l adresse du paramètre Page 4
Exemple: procedure toto (var a: xarray; b: integer; var c: integer); begin end; toto(fa, i+1, j); pea fa move.w i,d0 add.w #1,d0 move.w d0,-(a7) pea j jsr toto adresse de retour ^j i+1 ^fa a7 (SP) Page 5
Pour autant que le SP ne change pas de position pendant l exécution de la procédure, un paramètre peut être accédé simplement avec un adressage relatif au SP Il y a deux problèmes: on ne peut pas garantir que le SP ne change pas de valeur pendant l exécution de la procédure cette méthode permet l accès aux paramètres de la procédure active, mais pas à des variables appartenant à d autres procédures extérieures Page 6
Gestion des blocs d activation Une solution au problème précédent est donnée par les blocs d activation A chaque appel de procédure, un bloc est réservé dans la pile, pour stocker: l adresse de retour les variables locales de la procédure appelée un pointeur au bloc précédent: le lien dynamique, ou lien avec le bloc de la procédure appelante Un nouveau registre est nécessaire: le frame pointer (FP), qui pointe au début du bloc de la procédure active Toute référence à une variable locale de la procédure active est faite par rapport au FP Page 7
Exemple: program toto; procedure A; procedure B; procedure C; begin call B; end; begin call C; end; begin call B; end; begin call A; end. En supposant la séquence d appels toto, A, B, C, B la configuration de la pile sera: B C B A toto variables locales lien dynamique adresse de retour variables locales lien dynamique adresse de retour variables locales lien dynamique adresse de retour variables locales lien dynamique adresse de retour variables locales lien dynamique adresse de retour SP FP nil Page 8
A la fin de la procédure, le SP prendra la valeur du FP, et celui-ci celle du lien statique Toutefois, il est toujours impossible d accéder une variable d une autre procédure que l active. Pour cela, nous devons ajouter un autre lien, pointant au bloc de la procédure mère: c est le lien statique L adresse d une variable est donnée maintenant par deux paramètres: X, Y distance statique: nombre de liens statiques à parcourir pour arriver au bloc de la variable cherchée déplacement à l intérieur du bloc Page 9
L organisation de la pile dans notre exemple sera maintenant: B C B A toto variables locales lien dynamique adresse de retour lien statique variables locales lien dynamique adresse de retour lien statique variables locales lien dynamique adresse de retour lien statique variables locales lien dynamique adresse de retour lien statique variables locales lien dynamique adresse de retour lien statique SP FP nil nil Page 10
Instructions spécialisées du 68000 Le processeur 68000 possède un SP, le registre a7, mais pas de FP. Toutefois, par convention, le registre a6 fait fonction de FP lors de la compilation Le processeur 68000 dispose de deux instructions pour la gestion des blocs d activation: LINK et UNLK LINK An,#constante (An est le FP et constante est la taille du bloc) Cette instruction, première de la procédure, réalise les fonctions suivantes: création du lien dynamique du nouveau bloc: SP SP - 4 M[SP] An mise à jour du FP: An SP la place pour le nouveau bloc est allouée: SP SP + constante Page 11
UNLK An Cette instruction défait l action de l instruction LINK: la place allouée au bloc est libérée: SP An le FP est mis à jour: An M[SP] SP SP + 4 Page 12
Exemple: program exemple; var a,b,c: integer; procedure proc1; var ap1: integer; procedure proc2; begin b := 4; ap1 := b end; procedure proc3(par3: integer); var ap3: integer; begin ap3 := c; ap3 := ap3 + par3; proc2; a := b + ap3 end; begin ap1 := 1; proc3(ap1) end; begin a := 1; b := 2; c := 3; proc1 end. Page 13
proc2: link a6,#0 move.w #4,-$102(a5) movea.l $8(a6),a0 move.w -$102(a5),-$12(a0) unlk a6 move.l (a7)+,(a7) rts proc3: link a6,#-$12 move.l d7,-(a7) move.w -$104(a5),d7 add.w $c(a6),d7 move.l $8(a6),-(a7) jsr proc2 move.w -$102(a5),d0 add.w d7,d0 move.w d0,-$100(a5) move.l (a7)+,d7 unlk a6 movea.l (a7)+,a0 addq.w #6,a7 jmp (a0) proc1: link a6,#-$12 move.w #1,-$12(a6) move.w -$12(a6),-(a7) move.l a6,-(a7) jsr proc3 unlk a6 rts move.w #1,-$100(a5) move.w #2,-$102(a5) move.w #3,-$104(a5) jsr proc1 unlk a6 jsr system Page 14
Instructions spécialisées du MIPS MIPS, comme tous les processeurs RISC, donne un très faible support aux procédures L'appel de procédure est fait par l'instruction jump and link: jal adresse Cette instruction ne garde pas l'adresse de retour dans une pile mais dans le registre $ra Il n'y a pas d'instruction spécialisée pour le retour de procédure. On peut employer l'instruction jump register: jr $ra Pour des appels imbriqués, le programmeur doit gérer lui-même la pile. Un registre est réservé pour faire office de stack pointer: $sp Un registre est réservé pour faire office de frame pointer: $fp Page 15
Quatre registres sont réservés pour le passage de paramètres: $a0-$a3 Deux registres sont réservés pour rendre des valeurs: $v0-$v1 Huit registres doivent rester inchangés entre l'appel et le retour de la procédure: $s0-$s7. Si la procédure appelée doit les modifier, elle doit les sauver dans la pile avant de les utiliser, et les restaurer à la fin de la procédure Les registres temporaires $t0-$t9 peuvent être modifés à volonté Page 16
Exemple 1: Supposez la procédure suivante, écrite en langage C: int leaf_example (int g, int h, int i, int j) { int f; } f = (g + h) - (i + j); return f; Le code machine correspondant est: Page 17
leaf_example: sub $sp,$sp,12 sw $t1,8($sp) sw $t0,4($sp) sw $s0,0($sp) add $t0,$a0,$a1 add $t1,$a2,$a3 sub $s0,$t0,$t1 add $v0,$s0,$zero lw $s0,0($sp) lw $t0,4($sp) lw $t1,8($sp) add $sp,$sp,12 jr $ra # réservation de place dans la pile # sauvegarde des registres # $t0 = g + h # $t1 = i + j # $s0 = f # $v0 = f # restauration des registres # mise à jour de la pile # retour de procédure Page 18
Exemple 2: Supposez la procédure suivante, écrite en langage C: int fact (int n) { if (n < 1) return (1); else return (n * fact(n-1)); } Le code machine correspondant est: Page 19
fact: sub $sp,$sp,8 # réservation de place dans la pile sw $ra,4($sp) # sauver l'adresse de retour sw $a0,0($sp) # sauver le paramètre n slt $t0,$a0,1 # n >= 1 beq $t0,$zero,l1 # alors sauter à L1 add $v0,$zero,1 # rendre 1 add $sp,$sp,8 # remettre à jour la pile jr $ra # retour de procédure L1: sub $a0,$a0,1 # n = n - 1 jal fact # appel récursif de la procédure lw $a0,0($sp) # restaurer le paramètre n lw $ra,4($sp) # restaurer l'adresse de retour add $sp,$sp,8 # remettre ã jour la pile mult $v0,$a0,$v0 # rendre n*fact(n-1) jr $ra # retour de procédure Page 20