it-swarm.com.de

Grundlegendes zum Stapelrahmen des Funktionsaufrufs in C / C ++?

Ich versuche zu verstehen, wie Stapelrahmen erstellt werden und welche Variablen (Parameter) in welcher Reihenfolge zum Stapeln verschoben werden. Einige Suchergebnisse zeigten, dass der C/C++ - Compiler basierend auf Operationen entscheidet, die innerhalb einer Funktion ausgeführt werden. Wenn die Funktion beispielsweise nur einen übergebenen int-Wert um 1 erhöhen sollte (ähnlich dem ++ - Operator) und ihn zurückgeben soll, werden alle Parameter der Funktion und der lokalen Variablen in Register eingetragen.

Ich frage mich, welche Register für zurückgegebene oder übergebene Werteparameter verwendet werden. Wie werden Referenzen zurückgegeben? Wie wählt der Compiler zwischen eax, ebx, ecx und edx?

Was muss ich wissen, um zu verstehen, wie Register, Stapel- und Heap-Referenzen bei Funktionsaufrufen verwendet, erstellt und zerstört werden?

19
Gana

Zusätzlich zu dem, was Dirk gesagt hat, besteht eine wichtige Verwendung von Stapelrahmen darin, vorherige Werte von Registern zu speichern, damit sie nach einem Funktionsaufruf wiederhergestellt werden können. Selbst auf Prozessoren, auf denen Register zum Übergeben von Parametern, zum Zurückgeben eines Werts und zum Speichern der Rücksprungadresse verwendet werden, werden die Werte dieser Register vor einem Funktionsaufruf auf dem Stapel gespeichert, damit sie nach dem Aufruf wiederhergestellt werden können. Dadurch kann eine Funktion eine andere aufrufen, ohne ihre eigenen Parameter zu überschreiben oder ihre eigene Absenderadresse zu vergessen.

Das Aufrufen einer Funktion B von Funktion A auf einem typischen "generischen" System kann daher die folgenden Schritte umfassen:

  • Funktion A :
    • Drücken Sie das Leerzeichen für den Rückgabewert
    • Parameter drücken
    • Drücken Sie die Absenderadresse
  • springe zur Funktion B
  • Funktion B :
    • Drücken Sie die Adresse des vorherigen Stapelrahmens
    • Push-Werte von Registern, die diese Funktion verwendet (damit sie wiederhergestellt werden können)
    • Platz für lokale Variablen verschieben
    • führen Sie die erforderlichen Berechnungen durch
    • stellen Sie die Register wieder her
    • stellen Sie den vorherigen Stapelrahmen wieder her
    • speichern Sie das Funktionsergebnis
    • zur Absenderadresse springen
  • Funktion A :
    • pop die Parameter
    • pop den Rückgabewert

Dies ist keineswegs die einzige Möglichkeit, wie Funktionsaufrufe funktionieren können (und ich habe möglicherweise ein oder zwei Schritte außer Betrieb), aber es sollte Ihnen eine Vorstellung davon geben, wie der Stapel verwendet wird, damit der Prozessor verschachtelte Funktionsaufrufe verarbeiten kann.

11
Caleb

Dies hängt von der verwendeten Aufrufkonvention ab. Wer die Aufrufkonvention definiert, kann diese Entscheidung treffen, wie er will.

In der gängigsten Aufrufkonvention unter x86 werden Register nicht zum Übergeben von Parametern verwendet. Die Parameter werden beginnend mit dem Parameter ganz rechts auf den Stapel übertragen. Der Rückgabewert wird in eax platziert und kann edx verwenden, wenn zusätzlicher Speicherplatz benötigt wird. Referenzen und Zeiger werden beide in Form einer Adresse in eax zurückgegeben.

11
Dirk Holsopple

Wenn Sie Stack sehr gut verstehen, werden Sie verstehen, wie Speicher im Programm funktioniert, und wenn Sie verstehen, wie Speicher im Programm funktioniert, werden Sie verstehen, wie Funktionsspeicher im Programm gespeichert sind, und wenn Sie verstehen, wie Funktionsspeicher im Programm funktionieren, werden Sie verstehen, wie rekursive Funktionen funktionieren und wenn Sie verstehen, wie die rekursive Funktion funktioniert. Sie werden verstehen, wie der Compiler funktioniert. Wenn Sie verstehen, wie der Compiler funktioniert, funktioniert Ihr Verstand als Compiler und Sie können jedes Programm sehr einfach debuggen

Lassen Sie mich erklären, wie Stack funktioniert:

Zuerst müssen Sie wissen, wie Funktionen im Stapel gespeichert werden:

Heap speichert dynamische Speicherzuordnungswerte. Automatische Zuordnungs- und Löschwerte für Stapelspeicher.

(enter image description here

Lassen Sie uns mit Beispiel verstehen:

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)

Verstehen Sie nun Teile dieses Programms:

(enter image description here

Nun wollen wir sehen, was Stapel ist und was Stapelteile sind:

(enter image description here

Zuordnung des Stapels:

Denken Sie an eine Sache, wenn eine Funktion "return" erhält, unabhängig davon, ob sie alle ihre lokalen Variablen geladen hat oder irgendetwas, das sie sofort vom Stapel zurückgibt, wird sein Stapelrahmen. Dies bedeutet, wenn eine rekursive Funktion eine Basisbedingung erhält und wir eine Rückgabe nach der Basisbedingung setzen, damit die Basisbedingung nicht darauf wartet, lokale Variablen zu laden, die sich im Programmteil "else" befinden, wird sofort der aktuelle Frame vom Stapel zurückgegeben, und jetzt, wenn ein Frame vorhanden ist Der nächste Frame befindet sich im Aktivierungsdatensatz. Sehen Sie dies in der Praxis:

(enter image description here

Freigabe des Blocks:

Immer wenn eine Funktion eine return-Anweisung gefunden hat, wird der aktuelle Frame vom Stapel gelöscht.

bei der Rückkehr vom Stapelwert wird in umgekehrter Reihenfolge zurückgegeben, in der sie im Stapel zugewiesen wurden.

(enter image description here

Dies ist eine sehr kurze Beschreibung. Wenn Sie mehr über Stapel- und Doppelrekursion erfahren möchten, lesen Sie zwei Beiträge in diesem Blog:

Mehr über Stack Schritt für Schritt

Weitere Informationen zur doppelten Rekursion Schritt für Schritt mit dem Stapel

5
user5904928

Was Sie suchen, heißt Application Binary Interface - ABI.

Für jeden Compiler gibt es eine Spezifikation, in der der ABI angegeben ist.

Jede Plattform gibt normalerweise ABI an, um die Interoperabilität zwischen Compilern zu unterstützen. Beispiel: x86-Aufrufkonventionen beschreibt die typischen Aufrufkonventionen für x86 und x86-64. Ich würde jedoch ein offizielleres Dokument als Wikipedia erwarten.

3
Bill Door