Was genau ist der Basiszeiger und Stapelzeiger? Worauf weisen sie hin?

Lesezeit: 7 Minuten

Benutzeravatar von Elysium verschlungen
verschlungenes Elysium

Verwenden dieses Beispiel aus Wikipedia, in der DrawSquare() DrawLine() aufruft,

Alt-Text

(Beachten Sie, dass dieses Diagramm hohe Adressen unten und niedrige Adressen oben hat.)

Kann mir jemand erklären was ebp und esp stehen in diesem Zusammenhang?

Von dem, was ich sehe, würde ich sagen, dass der Stapelzeiger immer auf den Anfang des Stapels zeigt und der Basiszeiger auf den Anfang der aktuellen Funktion? Oder was?


edit: Ich meine das im Zusammenhang mit Windows-Programmen

edit2: Und wie funktioniert eip auch arbeiten?

edit3: Ich habe den folgenden Code von MSVC++:

var_C= dword ptr -0Ch
var_8= dword ptr -8
var_4= dword ptr -4
hInstance= dword ptr  8
hPrevInstance= dword ptr  0Ch
lpCmdLine= dword ptr  10h
nShowCmd= dword ptr  14h

Alle von ihnen scheinen Dwords zu sein und nehmen somit jeweils 4 Bytes ein. Ich kann also sehen, dass es eine Lücke von hInstance zu var_4 von 4 Bytes gibt. Was sind Sie? Ich nehme an, es ist die Absenderadresse, wie auf dem Bild von Wikipedia zu sehen ist?


(Anmerkung des Herausgebers: ein langes Zitat aus Michaels Antwort entfernt, das nicht in die Frage gehört, aber eine Folgefrage wurde bearbeitet):

Dies liegt daran, dass der Ablauf des Funktionsaufrufs ist:

* Push parameters (hInstance, etc.)
* Call function, which pushes return address
* Push ebp
* Allocate space for locals

Meine Frage (zuletzt, hoffe ich!) ist jetzt, was genau passiert von dem Moment an, in dem ich die Argumente der Funktion, die ich aufrufen möchte, bis zum Ende des Prologs platziere? Ich möchte wissen, wie sich ebp, esp in diesen Momenten entwickeln (ich habe bereits verstanden, wie der Prolog funktioniert, ich möchte nur wissen, was passiert, nachdem ich die Argumente auf den Stapel und vor den Prolog verschoben habe).

  • Eine wichtige Sache, die zu beachten ist, ist, dass der Stack im Speicher “nach unten” wächst. Das heißt, um den Stapelzeiger nach oben zu bewegen, verringern Sie seinen Wert.

    – BS

    8. September 2009 um 19:07 Uhr

  • Ein Hinweis, um zu unterscheiden, was EBP/ESP und EIP tun: EBP und ESP beschäftigen sich mit Daten, während sich EIP mit Code befasst.

    – mmmmmmmm

    8. September 2009 um 19:19 Uhr

  • In Ihrem Diagramm ist ebp (normalerweise) der “Frame-Zeiger”, insbesondere der “Stack-Zeiger”. Dies ermöglicht den Zugriff auf Einheimische über [ebp-x] und Stapelparameter über [ebp+x] konsistent, unabhängig vom Stapelzeiger (der sich innerhalb einer Funktion häufig ändert). Die Adressierung könnte über ESP erfolgen, wodurch EBP für andere Operationen freigegeben wird – aber auf diese Weise können Debugger den Aufrufstapel oder die Werte von Einheimischen nicht mitteilen.

    – Peterchen

    8. September 2009 um 19:31 Uhr

  • @ Ben. Nicht unbedingt. Einige Compiler legen Stack-Frames in den Heap. Das Konzept des Stack-Wachstums ist genau das, ein Konzept, das es leicht verständlich macht. Die Implementierung des Stapels kann beliebig sein (die Verwendung zufälliger Teile des Stapels macht Hacks, die Teile des Stapels überschreiben, viel schwieriger, da sie nicht so deterministisch sind).

    – Martin York

    8. September 2009 um 20:06 Uhr

  • In zwei Worten: Stapelzeiger ermöglichen Push/Pop-Operationen zu funktionieren (damit Push und Pop wissen, wo Daten abgelegt/abgeholt werden sollen). Der Basiszeiger ermöglicht es dem Code, unabhängig auf Daten zu verweisen, die zuvor auf dem Stapel abgelegt wurden.

    – tigrou

    4. September 2013 um 9:39 Uhr

  • Danke für die Erklärung! Aber ich bin jetzt etwas verwirrt. Nehmen wir an, ich rufe eine Funktion auf und befinde mich in der ersten Zeile ihres Prologs, ohne eine einzige Zeile davon ausgeführt zu haben. Was ist zu diesem Zeitpunkt der Wert von ebp? Hat der Stack zu diesem Zeitpunkt noch etwas außer den gepushten Argumenten? Vielen Dank!

    – verschlungenes Elysium

    9. September 2009 um 12:33 Uhr

  • EBP wird nicht auf magische Weise geändert. Bis Sie also ein neues EBP für Ihre Funktion eingerichtet haben, haben Sie immer noch den Wert des Anrufers. Und neben Argumenten enthält der Stack auch die alte EIP (Rücksendeadresse)

    – MSalter

    9. September 2009 um 13:34 Uhr

  • Gute Antwort. Obwohl es nicht vollständig sein kann, ohne zu erwähnen, was im Epilog steht: Anweisungen “verlassen” und “rettung”.

    – Kalmarius

    4. Juli 2013 um 7:01 Uhr

  • Ich denke, dieses Bild wird helfen, einige Dinge darüber zu verdeutlichen, was der Fluss ist. Denken Sie auch daran, dass der Stapel nach unten wächst. ocw.cs.pub.ro/courses/_media/so/laboratoare/call_stack.png

    – Andrei-Niculae Petre

    5. Oktober 2013 um 15:06 Uhr


  • Liegt es an mir, oder fehlen alle Minuszeichen im obigen Code-Snippet?

    – BarbaraKwarc

    20. Januar 2017 um 4:09 Uhr

  • Bisher die beste Erklärung, die ich über esp und ebp gelesen habe.

    – Chris Bao

    18. August 2020 um 0:04 Uhr

  • Eine Sache, die für Asm-Neulinge irreführend sein könnte, ist, dass die BP in EBP steht für Base Pointerwas nicht wirklich der Fall ist, da EBP zeigt in die Mitte des Stapelrahmens, NICHT nach unten. Das Frame Pointer scheint ein besserer Name für dieses Register zu sein.

    – Anis LOUNIS alias AnixPasBesoin

    20. Februar 2021 um 17:05 Uhr


  • Einige CPUs haben tatsächlich ein Register namens “Frame Pointer”, wie z. B. die Digital Alpha CPU.

    – David R. Tribble

    18. März 2021 um 20:47 Uhr

  • Ich dachte, das ESP ändert sich nicht und bleibt während der gesamten Lebensdauer des Programms konstant, da es einfach den Start des Stapels (oben) bedeutet?

    – Epischer Speedy

    22. September 2021 um 20:44 Uhr

  • @EpicSpeedy Nein, ESP zeigt auf das letzte Element, das Sie auf den Stapel geschoben haben (oder den freien Speicherplatz darüber, ich kann mich nicht erinnern, welcher). In jedem Fall ändert es sich, wenn Sie Register drücken / öffnen oder Funktionen aufrufen / von ihnen zurückkehren.

    – Welpentrommel64

    21. Juni um 15:56 Uhr

  • @Robert: Wenn Sie vor dem Aufruf der Funktion “vorher” oben auf dem Stapel sagen, ignorieren Sie sowohl die Parameter, die kurz vor dem Aufruf der Funktion auf den Stapel geschoben werden, als auch den Aufrufer-EIP. Dies könnte die Leser verwirren. Sagen wir einfach, dass in einem Standard-Stack-Frame EBP auf die gleiche Stelle zeigt, auf die ESP gerade zeigte nach Eingabe der Funktion.

    – Perücke

    9. September 2009 um 13:24 Uhr

  • Wenn Sie etwas auf den Stack schieben, wird der Stack-Zeiger dekrementiert, da die unterste Adresse des Stacks die höchste Adresse hat.

    – bwass31

    21. Februar um 20:25 Uhr

  • Nein, ESP weist das nicht auf Unterseite des Stapels. Das Speicheradressierungsschema hat damit nichts zu tun. Dabei spielt es keine Rolle, ob der Stack zu niedrigeren oder höheren Adressen anwächst. Die “Oberseite” des Stapels ist immer dort, wo der nächste Wert verschoben wird (auf die Spitze des Stapels gelegt wird) oder bei anderen Architekturen dort, wo der letzte verschobene Wert abgelegt wurde und wo er derzeit liegt. Daher zeigt ESP immer auf die oben des Stapels.

    – BarbaraKwarc

    20. Januar 2017 um 4:17 Uhr


  • Das Unterseite oder Base des Stacks hingegen ist dort, wo die Erste (oder älteste) Wert wurde gesetzt und dann durch neuere Werte abgedeckt. Daher kommt der Name “Basiszeiger” für EBP: Er sollte auf die Basis (oder das Ende) des aktuellen lokalen Stacks einer Subroutine zeigen.

    – BarbaraKwarc

    20. Januar 2017 um 4:22 Uhr

  • Barbara, beim Intel x86 ist der Stack AUF DEM KOPF. Die Oberseite des Stapels enthält das erste Element, das auf den Stapel geschoben wird, und jedes nachfolgende Element wird UNTER das oberste Element geschoben. Am unteren Ende des Stapels werden neue Gegenstände platziert. Programme werden im Speicher abgelegt, beginnend bei 1k und wachsen bis ins Unendliche. Der Stapel beginnt bei unendlich, realistischerweise maximaler Speicher minus ROMs, und wächst gegen 0. ESP zeigt auf eine Adresse, deren Wert kleiner als die erste Adresse ist, die verschoben wird.

    – Jmucchiello

    10. Oktober 2018 um 19:53 Uhr

  • Nein, ESP weist das nicht auf Unterseite des Stapels. Das Speicheradressierungsschema hat damit nichts zu tun. Dabei spielt es keine Rolle, ob der Stack zu niedrigeren oder höheren Adressen anwächst. Die “Oberseite” des Stapels ist immer dort, wo der nächste Wert verschoben wird (auf die Spitze des Stapels gelegt wird) oder bei anderen Architekturen dort, wo der letzte verschobene Wert abgelegt wurde und wo er derzeit liegt. Daher zeigt ESP immer auf die oben des Stapels.

    – BarbaraKwarc

    20. Januar 2017 um 4:17 Uhr


  • Das Unterseite oder Base des Stacks hingegen ist dort, wo die Erste (oder älteste) Wert wurde gesetzt und dann durch neuere Werte abgedeckt. Daher kommt der Name “Basiszeiger” für EBP: Er sollte auf die Basis (oder das Ende) des aktuellen lokalen Stacks einer Subroutine zeigen.

    – BarbaraKwarc

    20. Januar 2017 um 4:22 Uhr

  • Barbara, beim Intel x86 ist der Stack AUF DEM KOPF. Die Oberseite des Stapels enthält das erste Element, das auf den Stapel geschoben wird, und jedes nachfolgende Element wird UNTER das oberste Element geschoben. Am unteren Ende des Stapels werden neue Gegenstände platziert. Programme werden im Speicher abgelegt, beginnend bei 1k und wachsen bis ins Unendliche. Der Stapel beginnt bei unendlich, realistischerweise maximaler Speicher minus ROMs, und wächst gegen 0. ESP zeigt auf eine Adresse, deren Wert kleiner als die erste Adresse ist, die verschoben wird.

    – Jmucchiello

    10. Oktober 2018 um 19:53 Uhr

1426440cookie-checkWas genau ist der Basiszeiger und Stapelzeiger? Worauf weisen sie hin?

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

Privacy policy