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 ausesp
.– 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