web-dev-qa-db-fra.com

Comprendre le cadre de pile de l'appel de fonction en C / C ++?

J'essaie de comprendre comment les cadres de pile sont construits et quelles variables (paramètres) sont poussées pour s'empiler dans quel ordre? Certains résultats de recherche ont montré que le compilateur C/C++ décide en fonction des opérations effectuées dans une fonction. Par exemple, si la fonction était censée simplement incrémenter une valeur int transmise de 1 (similaire à l'opérateur ++) et la renvoyer, elle placerait tous les paramètres de la fonction et les variables locales dans des registres.

Je me demande quels registres sont utilisés pour les paramètres renvoyés ou passés par valeur. Comment les références sont-elles retournées? Comment le compilateur choisit-il entre eax, ebx, ecx et edx?

Que dois-je savoir pour comprendre comment les registres, les références de pile et de tas sont utilisés, créés et détruits lors des appels de fonction?

19
Gana

En plus de ce que Dirk a dit, une utilisation importante des trames de pile est de sauvegarder les valeurs précédentes des registres afin qu'ils puissent être restaurés après un appel de fonction. Ainsi, même sur les processeurs où des registres sont utilisés pour transmettre des paramètres, renvoyer une valeur et enregistrer l'adresse de retour, les valeurs de ces registres sont enregistrées sur la pile avant un appel de fonction afin de pouvoir être restaurées après l'appel. Cela permet à une fonction d'en appeler une autre sans écraser ses propres paramètres ni oublier sa propre adresse de retour.

Ainsi, appeler une fonction B à partir de la fonction A sur un système "générique" typique peut impliquer les étapes suivantes:

  • fonction A:
    • Poussez l'espace pour la valeur de retour
    • Paramètres push
    • Appuyez sur l'adresse de retour
  • passez à la fonction B
  • fonction B:
    • Poussez l'adresse du cadre de pile précédent
    • Valeurs push des registres que cette fonction utilise (pour pouvoir les restaurer)
    • Espace push pour les variables locales
    • faire le calcul nécessaire
    • restaurer les registres
    • restaurer le cadre de pile précédent
    • stocker le résultat de la fonction
    • sauter à l'adresse de retour
  • fonction A:
    • pop les paramètres
    • pop la valeur de retour

Ce n'est en aucun cas la seule façon dont les appels de fonction peuvent fonctionner (et j'ai peut-être une étape ou deux en panne), mais cela devrait vous donner une idée de la façon dont la pile est utilisée pour permettre au processeur de gérer les appels de fonction imbriqués.

11
Caleb

Cela dépend de la convention d'appel utilisée. Celui qui définit la convention d'appel peut prendre cette décision comme bon lui semble.

Dans la convention d'appel la plus courante sur x86, les registres ne sont pas utilisés pour transmettre des paramètres; les paramètres sont poussés sur la pile en commençant par le paramètre le plus à droite. La valeur de retour est placée dans eax et peut utiliser edx si elle a besoin de l'espace supplémentaire. Les références et les pointeurs sont tous deux retournés sous la forme d'une adresse en eax.

11
Dirk Holsopple

Si vous comprenez très bien la pile, vous comprendrez comment fonctionne la mémoire dans le programme et si vous comprenez comment la mémoire fonctionne dans le programme, vous comprendrez comment le magasin de fonctions dans le programme et si vous comprenez comment le magasin de fonctions dans le programme, vous comprendrez comment fonctionne la fonction récursive et si vous comprenez comment fonctionne la fonction récursive vous comprendrez comment fonctionne le compilateur et si vous comprenez comment fonctionne le compilateur votre esprit fonctionnera comme compilateur et vous déboguerez n'importe quel programme très facilement

Permettez-moi d'expliquer comment fonctionne la pile:

Vous devez d'abord savoir comment stocker les fonctions dans la pile:

Stockage dynamique des valeurs d'allocation de mémoire dynamique. Stockez les valeurs d'allocation et de suppression automatiques.

enter image description here

Comprenons par exemple:

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

Comprenez maintenant certaines parties de ce programme:

enter image description here

Voyons maintenant ce qu'est la pile et quelles sont les pièces de la pile:

enter image description here

Attribution de la pile:

Souvenez-vous d'une chose si une fonction obtient un "retour", qu'elle ait chargé toutes ses variables locales ou quoi qu'elle revienne immédiatement de la pile dans son cadre de pile. Cela signifie que lorsqu'une fonction récursive obtient la condition de base et que nous mettons return après la condition de base pour que la condition de base n'attende pas pour charger les variables locales qui sont situées dans la partie "else" du programme, elle retournera immédiatement l'image actuelle de la pile et maintenant si une image retourner l'image suivante est dans le dossier d'activation. Voir ceci en pratique:

enter image description here

Désallocation du bloc:

Alors maintenant, chaque fois qu'une fonction trouve l'instruction return, elle supprime l'image courante de la pile.

en revenant de la valeur de pile retournera dans l'ordre inverse de l'ordre dans lequel ils ont alloué dans la pile.

enter image description here

Ce sont des descriptions très courtes et si vous voulez en savoir plus sur la pile et la double récursivité, lisez deux articles de ce blog:

Plus d'informations sur la pile étape par étape

En savoir plus sur la récursivité double étape par étape avec la pile

5
user5904928

Ce que vous recherchez s'appelle Application Binary Interface - ABI.

Il existe une spécification pour chaque compilateur qui définit l'ABI.

Chaque plate-forme spécifie généralement et ABI afin de prendre en charge l'interopérabilité entre les compilateurs. Par exemple, Conventions d'appel x86 définit les conventions d'appel typiques pour x86 et x86-64. Je m'attendrais à un document plus officiel que wikipedia cependant.

3
Bill Door