2015-11-23 10 views
9

Im Prolog der main-Funktion (eines einfachen Spielzeugprogramms), die mit gcc -g -o program -m32 program.c auf einer 64-Bit-Maschine kompiliert wurde (läuft ubuntu 14.04) bekomme ich die folgende Zerlegung:Was ist der Zweck der Stapelzeigerausrichtung im Prolog von main()

dump of assembler code for function main: 
    0x08048e24 <+0>: push %ebp 
    0x08048e25 <+1>: mov %esp,%ebp 
    0x08048e27 <+3>: and $0xfffffff0,%esp 
    ... 

Was ist der Zweck der Anweisung in < 3>? Das heißt, warum sollte der $esp auf eine 16-ausgerichtete Adresse zeigen?

Antwort

9

Das System V AMD64 ABI (x86-64 ABI) erfordert eine 16-Byte-Stapelausrichtung. double erfordert 8-Byte-Ausrichtung und SSE-Erweiterungen erfordern 16-Byte-Ausrichtung.

gccdocumentation Punkte es in seiner Dokumentation für -mpreferred-stack-boundary Option:

-mpreferred-stack-Grenze = num

Versuch, die Stapelgrenze zu einem 2 ausgerichtet zu halten, um num Byte-Grenze angehoben . Wenn -mpreferred-stack-boundary nicht angegeben ist, ist der Standardwert 4 (16 Byte oder 128 Bit).

Warnung: Beim Generieren von Code für die x86-64-Architektur mit deaktivierten SSE-Erweiterungen kann -mpreferred-stack-boundary = 3 verwendet werden, um die Stack-Grenze auf 8-Byte-Grenze auszurichten. Da x86-64 ABI eine 16-Byte-Stapelausrichtung erfordert, ist dies ABI-inkompatibel und dazu gedacht, in einer kontrollierten Umgebung verwendet zu werden, in der der Stapelraum eine wichtige Einschränkung darstellt. Diese Option führt zu falschem Code, wenn Funktionen, die mit 16-Byte-Stapelausrichtung kompiliert wurden (z. B. Funktionen aus einer Standardbibliothek), mit falsch ausgerichtetem Stapel aufgerufen werden. In diesem Fall können SSE-Anweisungen zu fehlausgerichteten Speicherzugriffs-Traps führen. Außerdem werden variable Argumente für 16 Byte ausgerichtete Objekte (einschließlich x87 long double und __int128) falsch behandelt, was zu falschen Ergebnissen führt. Sie müssen alle Module mit -mpreferred-stack-boundary = 3 einschließlich aller Bibliotheken erstellen. Dies umfasst die Systembibliotheken und Startmodule.

+1

Es hält immer noch, wenn ich mit -m32 Flag kompilieren? – Bush

+0

@Bush Ich denke, sie verwenden 16-Byte mit "-m32" auch wegen SSE. – ouah

+0

Nun, nicht jeder x86-64 ABI tut das, deshalb bin ich immer etwas irritiert, wenn Leute vorgeben, dass es nur einen einzigen x86-64 ABI gibt. In diesem Fall ist im Kontext von Ubuntu klar, welche ABI gemeint ist, aber das ist nicht immer der Fall. –