2012-06-24 15 views
8

Ich spiele mit gcc -S herum, um zu verstehen, wie Speicher und Stapel funktioniert. Während dieser Stücke fand ich einige Dinge unklar. Könnten Sie mir bitte helfen, die Gründe zu verstehen?Warum gcc beim Erstellen von Assemblercode?

  1. Wenn Aufruf der Funktion setzt Argumente für eine nannte man es mov zu esp statt push verwendet. Was ist der Vorteil, push nicht zu verwenden?

  2. Funktion, die mit seinem Stapel arbeitet, zeigt Argumente auf sie als ebp + (N + offset) (wobei N eine Größe ist, die für Rücksendeadresse reserviert ist). Ich erwarte esp - offset, was verständlicher ist. Was ist der Grund dafür, ebp als grundlegenden Punkt überall zu verwenden? Ich weiß, dass diese gleich sind, aber trotzdem?

  3. Was ist das für Magie am Anfang von main? Warum muss esp nur auf diese Weise initialisiert werden?

    and esp,0xfffffff0 
    

Danke,

+3

Dies könnte 3 separate Fragen sein. Wie auch immer, die Antwort auf den 3. Punkt ist die Stapelausrichtung. – Mysticial

Antwort

7

Ich werde annehmen, dass Sie da in einer 64-Bit-Umgebung Argumente übergeben werden in den Registern unter einer 32-Bit-Umgebung arbeiten.

Frage 1

Vielleicht sind vorbei Sie ein Floating-Point-Argument hier. Sie können diese nicht direkt drücken, da die Anweisung push in einer 32-Bit-Laufzeit 4 Bytes gleichzeitig verschiebt, sodass Sie den Wert aufteilen müssen. Es ist manchmal einfacher, 8 von esp zu subtrahieren und sie bewegen das 8-Byte-Vierwort in [esp].

Frage 2

ebp ist, um die Parameter und einheimischen zum Indizieren in Stapelrahmen in 32-Bit-Code, häufig verwendet. Dadurch können die Offsets innerhalb von Frames auch dann fixiert werden, wenn sich der Stapelzeiger bewegt. Zum Beispiel

void f(int x) { 
    int a; 
    g(x, 5); 
} 

Betrachten wir nun, wenn Sie nur die Stack-Frame Inhalt mit esp zugegriffen wird, dann a bei [esp] ist, würde die Absenderadresse bei [esp+4] und x bei [esp+8] wäre. Jetzt generieren wir Code zum Aufruf g. Wir müssen zuerst 5 drücken und dann x drücken. Aber nach dem Drücken von 5 hat sich der Offset von x von esp geändert! Deshalb wird ebp verwendet. Normalerweise drücken wir bei der Eingabe von Funktionen den alten Wert von ebp, um ihn zu speichern, und kopieren dann esp in ebp. Jetzt kann ebp verwendet werden, um auf Stapelrahmeninhalte zuzugreifen. Es wird sich nicht bewegen, wenn wir uns in der Mitte der Argumente befinden.

Frage 3

Diese Anweisung and Nullen, die die letzten 4 Bits esp geführt, um es zu einer 16-Byte-Grenze auszurichten. Da der Stapel nach unten wächst, ist dies schön und sicher.

+1

Q3: Es nullen die letzten 4 Bits – hirschhornsalz

+0

Oh mein, danke, @drhirsch. Tippen ohne nachzudenken. Furchtbar. Vielen Dank! Bearbeitet. –

Verwandte Themen