Allg. Verständnisfrage - Der Stack (push, pop, ebp, esp)
-
Hi,
also ich hab mit folgenden noch große Schwierigkeiten sie zu verstehen:
1. Wofür ist der esp (Stackpointer) gut? Was passiert z.b. beimov eax, esp
?
2. Wofür ist der ebp (Basepointer) gut? Über ihn soll man an (bei Funktionen) seine Argumente kommen? Warum nicht direkt über den esp (Stackpointer)?
3. Bei push/pop, inwiefern wird dort der esp (Stackpointer) und der ebp (Basepointer) verändert? Werden sie überhaupt verändernt? (Ich nehme an der ebp, aber der esp nicht, warum?)
Ja, ich hoffe auf schnelle Antwort, da dies Fragen sind die mich eigentlich schon lange quälen.
P.S. Könnte mir mal jemand von euch folgenden Code erklären?
push offset Error_ExecuteHost push dword ptr fs:[0] mov fs:[0], esp
Hier soll anstatt der internen Windows-Fehlermeldung an die Adresse Error_ExecuteHost gesprungen werden, um diese selbst zu handeln. Aber wie funktioniert das? (Schwerpunkt Verständnis von esp)
-
HAR schrieb:
Hi,
1. Wofür ist der esp (Stackpointer) gut? Was passiert z.b. beimov eax, esp
?
Der ESP beinhaltet die Speicheradresse, an der das letzte ("oberste") Element des Stacks rumliegt.
2. Wofür ist der ebp (Basepointer) gut? Über ihn soll man an (bei Funktionen) seine Argumente kommen? Warum nicht direkt über den esp (Stackpointer)?
Joah, den EBP benutzt man i.A. dafür. Das Problem mitm ESP ist, dass der Stack innerhalb einer Funktion sich verändern kann und man so evtl. nicht immer vernünftig üebr den ESP drauf zugreifen kann.
3. Bei push/pop, inwiefern wird dort der esp (Stackpointer) und der ebp (Basepointer) verändert? Werden sie überhaupt verändernt? (Ich nehme an der ebp, aber der esp nicht, warum?)
Der EBP bleibt konstant, der ESP evrände sich (schließlich zeigt er aufs oberste Element des Stacks, muss sich also verändern, wenn ein neues Element dazukommt). push blabla entspricht ESP = ESP - 4; Speicher[ESP] = blabla. pop blabla dementsprechend blabla = Speicher[ESP]; ESP = ESP + 4.
P.S. Könnte mir mal jemand von euch folgenden Code erklären?
push offset Error_ExecuteHost push dword ptr fs:[0] mov fs:[0], esp
Hier soll anstatt der internen Windows-Fehlermeldung an die Adresse Error_ExecuteHost gesprungen werden, um diese selbst zu handeln. Aber wie funktioniert das? (Schwerpunkt Verständnis von esp)
Also was man heir sehen kann ist, ist dass Error_ExecuteHost aufn Stack kommt und dann das was an FS:0 steht. Danach wird der Stackpointer in FS:0 kopiert. Mehr tut der Code nicht, alles weitere hat mit dne internen Funktionalitäten udn der bedeutung von Speicherstellen der Sorte FS:xxx zu tun.
-
Ok, aber bei
mov fs:[0], esp
wird der Stackpointer ins fs-Segment geschrieben. Aber müsste jetzt fs nicht auf sich selbst zeigen, anstatt auf Error_ExecuteHost?
-
HAR schrieb:
Ok, aber bei
mov fs:[0], esp
wird der Stackpointer ins fs-Segment geschrieben. Aber müsste jetzt fs nicht auf sich selbst zeigen, anstatt auf Error_ExecuteHost?
In FS:0 steht jetzt eine Adresse, an der der alte Wert von FS:0 ist, ja. Könnte was mit den Exception-Handlern von Windows zu tun haben, wobei ein Exception-Handler eine Fehlerbehandlungsroutine beinhaltet (die 4 Bytes weiter steht) und einen Zeiger auf die nächste Routine. Wenn man eine neue Einträgt, muss man also die alte Adresse und die Behandluingsroutine eintragen.
-
Hat nichts mit dem Thema zu tuhen, aber lohnt sich nicht dafür ein neues Topic aufzumachen, deswegen:
hInstance dd 0 .code _start: push 0 call GetModuleHandleA mov [hInstance], eax
Zum Verständnis: Die [] geben an, dass in den Speicherbereich geschrieben werden soll, ohne [] zeigt an, dass in die Variable geschrieben werden soll. Aber irgendwie fehlt mir hier das Verständnis, nehmt Rücksicht, bin n alter C'ler und da isses nunmal einfacher :p
-
HAR schrieb:
Die [] geben an, dass in den Speicherbereich geschrieben werden soll, ohne [] zeigt an, dass in die Variable geschrieben werden soll.
Das waer ein bissel das gleiche, da Variablen normalerweise im Speicher liegen, doer?
Noe, "[]" zeigt wie du schon sagtest einen Speicherzugriff (=Zugriff auf eine Variable) an.
Ohne die eckigen Klammern waere das eine Konstante/fixer Zahlenwert im Programm.
Somit waere dein Codeschnippsel nicht assemblierbar, da sich schlecht ein Wert in eine konstante kopieren laesst. (zum Vergleich: mov 1234h,ax geht eben so wenig)
Nun kommt aber eine Fiesigkeit: Manche komischen Hochsprachencompiler, wie zB.TurboPascal (weiss nicht wie das bei C-Compilern ist...), ignorieren in bestimmten Faellen die eckigen Klammern um Variablennamen. Dh. da kannst du auch ohne eckige Klammern Werte in oder aus einer Variable verschieben.