Transmission de paramètres sur la pile
Question
Lorsque vous passez des paramètres à une fonction sur la pile de cpu,
Vous mettez les paramètres sur puis JSR met l'adresse de retour sur la pile. Cela signifie donc que dans votre fonction, vous devez prendre l'élément supérieur de la pile (l'adresse de retour) avant de pouvoir prendre les autres off)
La valeur de retour est stockée par convention dans D0
de registre.
par exemple, est le suivant la bonne façon de s'y prendre:
...
|Let’s do some addition with a function,
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
|the result of the addition (4+5) is in D0 (9)
...
add:
MOVE.L (SP)+, A1 |store the return address
|in a register
MOVE.L (SP)+, D0 |get 1st parameter, put in D0
MOVE.L (SP)+, D2 |get 2nd parameter, put in D2
ADD.L D2, D0 |add them,
|storing the result in D0
MOVE.L A1, -(SP) |put the address back on the
|Stack
RTS |return
La solution
Non.
Le callee (la fonction cible) est généralement pas responsable de la suppression de ses propres arguments. L'appelant les a mis là, et est celui qui connaît le mieux la façon de les supprimer.
Et sur le 68000, il est facile à lire à l'aide d'un décalage relatif dans la pile, il n'y a pas besoin d'enlever physiquement (pop) les arguments de la pile. Cela va contourner le problème d'avoir à « double-tampon » l'adresse de retour tout à fait bien.
Alors, votre code doit lire quelque chose comme ceci:
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
ADDQ.L #8, SP |remove the arguments from the stack, both at once.
...
add:
MOVE.L 4(SP), D0 |get 1st parameter, put in D0
ADD.L 8(SP), D0 |add the 2nd parameter
RTS |return
Autres conseils
Vous ne « take off » paramètres de la pile, dans le sens où vous ne les pop pas. Vous attribuez généralement un registre de cadre pour pointer vers le haut de la pile au point d'entrée à la procédure, et d'accéder aux paramètres constants, à des décalages connus du pointeur de cadre. Ensuite, votre index juste « saute » l'adresse de retour, que vous connaissez est là.
par exemple. dans une assemblée hypothétique, quand vous êtes dans une procédure. pile Supposer de plus en plus bas:
...
argument2
argument1
ret addr <---- stack pointer
argument1
juste d'accès à sp+4
offset (en supposant 32 bits), argument2
à sp+8
offset, etc. Comme ces conventions d'appel sont connus, ces décalages sont codés en dur dans votre code et sont efficaces pour calculer.
Le pointeur de cadre est très utile puisque vous poussez également les variables locales à empiler, et vous ne voulez pas l'indexation des paramètres pour changer dans des endroits différents, de sorte que le pointeur de cadre fournit un point d'ancrage stable tout au long de l'exécution de la procédure.
Non, il n'y a pas besoin de pop paramètres de la pile à les regarder; la procédure habituelle consiste à utiliser un registre « pointeur de trame », comme dit @eli. En fait, le 68k a même une instruction (LINK
) qui est conçu pour faciliter ce que: il est une instruction unique qui (a) permet de sauvegarder le pointeur de la trame précédente, (b) copier le pointeur de pile courante du pointeur de trame, et (c) décréments le pointeur de pile d'une quantité spécifiée pour laisser place à des variables locales.
Voici un exemple de code C et l'assembleur 68000 correspondant.