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
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top