Warum macht gcc das beim Erstellen von Assembler-Code?

8

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

  1. Beim Aufruf von function sets Argumente für einen aufgerufenen verwendet es mov bis esp anstatt push . Was ist der Vorteil, wenn Sie push nicht verwenden?

  2. Die Funktion, die mit ihren Stack-basierten Argumenten arbeitet, zeigt auf sie als ebp + (N + offset) (wobei N eine für die Rückgabeadresse reservierte Größe ist). Ich erwarte esp - offset , was verständlicher ist. Was ist der Grund dafür, ebp als fundamentalen Punkt überall zu verwenden? Ich weiß, dass diese gleich sind, aber trotzdem?

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

    %Vor%

Danke,

    
zweibaranov 24.06.2012, 06:46
quelle

1 Antwort

7

Ich nehme an, dass Sie in einer 32-Bit-Umgebung arbeiten, da in einer 64-Bit-Umgebung Argumente in Registern übergeben werden.

Frage 1

Vielleicht übergeben Sie hier ein Gleitkomma Argument. Sie können diese nicht direkt drücken, da die Anweisung push in einer 32-Bit-Laufzeit 4 Bytes gleichzeitig verschiebt, so dass 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 wird häufig zum Indizieren der Parameter und Locals in Stack-Frames in 32-Bit-Code verwendet. Dadurch können die Offsets innerhalb von Frames auch dann fixiert werden, wenn sich der Stapelzeiger bewegt. Betrachten Sie zum Beispiel

%Vor%

Wenn Sie jetzt nur auf den Stapelrahmeninhalt mit esp zugreifen, dann ist a auf [esp] , die Rückgabeadresse wäre [esp+4] und x wäre [esp+8] . Jetzt generieren wir Code zum Aufruf von 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 schieben 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 and Anweisung löscht die letzten 4 Bits von esp und richtet sie auf eine 16-Byte Grenze aus. Da der Stack nach unten wächst, ist das schön und sicher.

    
Ray Toal 24.06.2012, 07:24
quelle

Tags und Links