C Stack
-
Hallo Leute,
wir nehmen im Studium gerade Stacks und deren Eigenschaften durch. Bisher haben wir alles in Assembler geschrieben und soweit hab ich das auch verstanden. Nur habe ich nun folgenden C Code:
int main() { double a, b, c; a = 10; b = 10; F1(a, b); return (a); } int F1(double x, double y) { int i[3]; double n; //hier adresse von SBP und SP angeben n = 6.04 * x - 8.5; return (n); }
Wir sollen nun den Stackframe nach Aufruf der Funktion F1 zeichnen und Adressen des SBP und des SP wie gefordert angeben.
Zum SBP:
die Adresse des PC wird beim Funktionsaufruf in den Stack gespeichert.
Somit müsste doch auch die Adresse immer noch die gleiche sein wie beim Aufruf oder?SP:
diese müsste eig auf die call adresse bzw Ret Adresse zeigen da Int i[3] und double n keine Werte am Stack speichern odeR?Stackframe:
habe ich absolut keine Ahnung^^ Kann mir nur vorstellen das hier die Rückgabewerte der aufgerufenen Funktion stehen F1+ (x,y)Entschuldigt falls ich hier einiges durcheinander bringe. In Assembler war es iwie kla ersichtlicher was gerade auf dem Stack liegt bzw wo der SP gerade hinzeigt.
Könnte mir jemand weiterhelfen?
Danke !
VG
Daniel
-
nehmen wir an die argumente werden auch über den stack übergeben, dann kommen zuerst rücksprungadresse, x und y auf den stack, bevor die funktion aufgerufen wird. in der funktion kommen noch einmal 3 integer und 1 double auf den stack. der compiler merkt sich das und bevor die funktion verlassen wird, wird der stack wieder bereinigt.
nachtrag: da i[3] nicht benutzt wird, werden warscheinlich die integer nicht auf dem stack landen. n könnte auch in registern berechnet werden. eventuell kommen nur die return-adresse und die argumente x und y auf den stack.
-
@Bushmaster sagte in C Stack:
bevor die funktion verlassen wird, wird der stack wieder bereinigt.
Das mag für Pascal gelten, aber nicht für C.
In C räumt der Caller den Stack auf, da die Funktion nicht weiß, mit wieviel Parametern sie aufgerufen wurde.
-
@Bushmaster sagte in C Stack:
bevor die funktion verlassen wird, wird der stack wieder bereinigt.
Das mag für Pascal gelten, aber nicht für C.
In C räumt der Caller den Stack auf, da die Funktion nicht weiß, mit wieviel Parametern sie aufgerufen wurde.
danke für die berichtigung. die funktion wird aber wohl ihre lokalen variablen von stack nehmen. denn damit hat der caller ja nichts zu tun.
-
@Bushmaster sagte in C Stack:
die funktion wird aber wohl ihre lokalen variablen von stack nehmen.
Wie soll sie das denn machen?
Gelöscht (überschrieben) wird nicht.Die Funktion ruft die Rücksprungadresse auf und der Caller setzt den Stack so, wie vor dem Aufruf. Somit sind auch die lokalen Variablen der Funktion ungültig. Die Daten sind aber noch da.
-
Wie soll sie das denn machen?
sie setzt den stackpointer wieder auf den wert, wie er beim eintritt in die funktion war. damit sind die lokalen variablen nicht mehr existent.
-
#include <stdio.h> int F1(double x, double y) { int i[3]; double n; /*hier adresse von SBP und SP angeben*/ unsigned ebp,esp; asm volatile ("movl %%ebp,%0" : "=r" (ebp)); asm volatile ("movl %%esp,%0" : "=r" (esp)); printf("%lX\n%lX",ebp,esp); n = 6.04 * x - 8.5; return (n); } int main() { double a, b, c; a = 10; b = 10; F1(a, b); return 0; }
FF9C28D8
FF9C28A0
-
@Bushmaster sagte in C Stack:
sie setzt den stackpointer wieder auf den wert, wie er beim eintritt in die funktion war. damit sind die lokalen variablen nicht mehr existent.
Das ist überflüssig, da das der Caller gleich nochmal macht - für die Funktionsparameter, zudem sind die Daten immer noch da.
-
Das ist überflüssig, da das der Caller gleich nochmal macht - für die Funktionsparameter, zudem sind die Daten immer noch da.
ich hab den aufruf mal disassemblen lassen
F1(a, b); 00152072 sub esp,8 00152075 movsd xmm0,mmword ptr [b] 0015207A movsd mmword ptr [esp],xmm0 0015207F sub esp,8 00152082 movsd xmm0,mmword ptr [a] 00152087 movsd mmword ptr [esp],xmm0 0015208C call F1 (015103Ch) 00152091 add esp,10h
die main-funktion tut die beiden doubles auf den stack und, dann die return-adresse (durch den call) und räumt den stack danach mit add esp, 16 wieder auf. falls die andere funktion den esp verändert hat, würde das schief gehen. also geht main davon aus, dass die andere funktion ihren dreck auch wieder weg macht.
-
@Bushmaster sagte in C Stack:
also geht main davon aus, dass die andere funktion ihren dreck auch wieder weg macht.
Danke für die Klarstellung.
-
x86 Calling Conventions dub di dub
-
Hallo zusammen,
erstmal danke für die Antworten! Hat mich sehr gefreut.
Zusammengefasst müsste also der Stack nach dem Funktionsaufruf leer sein?
Danke an @Wutz habe einfach ein paar mehr Ausgaben hinzugefügt:
http://codepad.org/wmJ3CxxI
BP und SP zeigen auf die gleichen Adressen wie am Anfang von main.BP:
Zeigt in der geforderten Zeile auf die Return AdresseSP:
Adresse ergibt sich aus den Werten der beiden Double Variablen und dem Call ?Sehe ich das so richtig?
-
Zusammengefasst müsste also der Stack nach dem Funktionsaufruf leer sein?
Zusammengefasst ist der Stack Pointer nachher wo er vorher war. Wo genau "vorher" und "nachher" ist halt abhängig von der Calling Convention.