Stapelzuweisung, Polsterung und Ausrichtung

Lesezeit: 4 Minuten

Davids Benutzeravatar
David

Ich habe versucht, ein tieferes Verständnis dafür zu erlangen, wie Compiler Maschinencode generieren und insbesondere, wie GCC mit dem Stack umgeht. Dabei habe ich einfache C-Programme geschrieben, sie in Assembler kompiliert und mein Bestes gegeben, um das Ergebnis zu verstehen. Hier ist ein einfaches Programm und die Ausgabe, die es generiert:

asmtest.c:

void main() {
    char buffer[5];
}

asmtest.s:

pushl   %ebp
movl    %esp, %ebp
subl    $24, %esp
leave
ret

Was mir rätselhaft ist, ist, warum 24 Bytes für den Stapel zugewiesen werden. Ich weiß, dass der Stack aufgrund der Art und Weise, wie der Prozessor den Speicher adressiert, in 4er-Schritten zugewiesen werden muss, aber wenn dies der Fall wäre, sollten wir den Stack-Zeiger nur um 8 Bytes verschieben, nicht um 24. Als Referenz ein Puffer von 17 Bytes erzeugt einen um 40 Bytes verschobenen Stapelzeiger, und überhaupt kein Puffer bewegt den Stapelzeiger um 8. Ein Puffer zwischen 1 und 16 Bytes einschließlich bewegt sich ESP 24 Bytes.

Angenommen, die 8 Bytes sind eine notwendige Konstante (wofür wird sie benötigt?), bedeutet dies, dass wir in Blöcken von 16 Bytes zuweisen. Warum sollte der Compiler so ausgerichtet werden? Ich verwende einen x86_64-Prozessor, aber selbst ein 64-Bit-Wort sollte nur eine 8-Byte-Ausrichtung erfordern. Warum die Diskrepanz?

Als Referenz kompiliere ich dies auf einem Mac mit 10.5 mit gcc 4.0.1 und ohne aktivierte Optimierungen.

  • Verwandte: Warum schreibt System V / AMD64 ABI eine 16-Byte-Stack-Ausrichtung vor? Die Argumentation gilt auch für die i386 SysV ABI und gcc’s -mprefered-stack-boundary Standardeinstellung, die 16 Bytes für 32-Bit-Code war, noch bevor die i386-SysV-ABI offiziell geändert wurde, um dies zu verlangen / zu garantieren.

    – Peter Cordes

    11. April 2018 um 2:51 Uhr

  • Seltsam, ich habe den gleichen Code ausprobiert, mit -mpreferred-stack-boundary=4 aber es gibt nur einen Abzug von 16 aus esp.

    – Ta Thanh Dinh

    13. Juni 2018 um 9:44 Uhr

  • Verwandte: Warum weist GCC mehr Speicherplatz als nötig auf dem Stapel zu, über das hinaus, was für die Ausrichtung erforderlich ist? – sub $8, %esp sollte den Stapel neu ausrichten und diese 8 Bytes für das Array nutzbar machen. Die zusätzlichen 16 sind eine gcc-verpasste Optimierung.

    – Peter Cordes

    25. Juli 2020 um 5:29 Uhr

  • hat “push %ebp” esp um 8 byte verringert? plus ret’s 8 bytes, da sollten schon 16-byte ausgerichtet sein. Warum benötigt der Dosis-Compiler diese zusätzlichen 8 Bytes?

    – Joe.Z

    12. Juli 2013 um 7:52 Uhr

  • Oh, ich habe es. Dies ist eine 32-Bit-Maschine. Es tut uns leid. Es sollte ret 4 Byte + ebp 4 Byte + aligned 8 Byte + Buffer 16 sein

    – Joe.Z

    12. Juli 2013 um 13:05 Uhr

  • Die aktuellen Versionen der i386- und x86-64-System-V-ABIs erfordern eine 16B-Stack-Ausrichtung (vor a call Anweisung), also dürfen Funktionen davon ausgehen. In der Vergangenheit war für den i386 ABI nur eine 4B-Ausrichtung erforderlich. (Links zu ABI-Dokumenten finden Sie unter stackoverflow.com/tags/x86/info). GCC hält auch %esp sogar in Blattfunktionen ausgerichtet (die keine anderen Funktionen aufrufen), wenn es Platz reservieren muss, und darum geht es hier.

    – Peter Cordes

    7. September 2017 um 19:31 Uhr


  • Ich habe möglicherweise zu wenig Erfahrung mit der Angelegenheit, um zu behaupten, dass Ihre Antwort falsch ist. Aber verwendest du nicht movupd und ähnliches ugenau auf diesen Zweck ausgerichtete Anweisungen (Laden/Speichern nicht ausgerichtet gepackte Daten)? Soweit ich weiß, du kann bekommen fehlerhaftes Verhalten beim Versuch zu verwenden movapd und ähnliche Anweisungen zu nicht ausgerichteten Daten, aber Daten, die nicht ausgerichtet sind, sollten im Allgemeinen kein Problem darstellen.

    – andree

    15. Dezember 2015 um 20:53 Uhr


  • @andreee: movups ist auf Core2 und früher langsamer, selbst wenn die Daten ausgerichtet sind. Die ABI wurde damals entwickelt, als alle CPUs so waren. Und außerdem erlaubt Ihnen ausgerichtet paddd xmm0, [rsp] anstatt eine separate zu benötigen movdqu Anweisung. Siehe Warum schreibt System V / AMD64 ABI eine 16-Byte-Stack-Ausrichtung vor?

    – Peter Cordes

    11. April 2018 um 2:41 Uhr


  • Die tatsächliche ABI-Anforderung besteht darin, dass der Stapel auf 16 Byte ausgerichtet ist an Funktionsaufrufgrenzen.

    – Stefan Kanon

    24. November 2009 um 2:18 Uhr

  • Das stimmt, aber da Funktionsprologe/-epiloge ungefähr die einzigen Stellen sind, an denen der Stapelzeiger geändert wird, ist dies fast dasselbe, als würde man sagen, dass er jederzeit ausgerichtet werden muss.

    – Klingeln

    30. November 2009 um 18:08 Uhr

  • Die tatsächliche ABI-Anforderung besteht darin, dass der Stapel auf 16 Byte ausgerichtet ist an Funktionsaufrufgrenzen.

    – Stefan Kanon

    24. November 2009 um 2:18 Uhr

  • Das stimmt, aber da Funktionsprologe/-epiloge ungefähr die einzigen Stellen sind, an denen der Stapelzeiger geändert wird, ist dies fast dasselbe, als würde man sagen, dass er jederzeit ausgerichtet werden muss.

    – Klingeln

    30. November 2009 um 18:08 Uhr

1409380cookie-checkStapelzuweisung, Polsterung und Ausrichtung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy