Frage

Wie wird ein Programm (z. B. C oder C ++) im Computerspeicher angeordnet? Ich weiß ein wenig über Segmente, Variablen usw., aber im Grunde habe ich kein solides Verständnis der gesamte Struktur.

Da sich die In-Memory-Struktur unterscheiden kann, nehmen wir eine C ++-Konsolenanwendung unter Windows an.

Einige Zeiger auf das, was ich speziell bin:

  • Umriss einer Funktion, und wie heißt sie?
  • Jede Funktion hat einen Stapelrahmen, was enthält das und wie ist sie im Speicher angeordnet?
  • Funktionsargumente und Rückgabewerte
  • Globale und lokale Variablen?
  • Const statische Variablen?
  • Lokaler Speicher aus Lokalspeicher ..

Links zu tutorialähnlichem Material und dergleichen sind willkommen, aber bitte kein Material im Referenzstil unter der Annahme von Kenntnissen des Assemblers usw.

War es hilfreich?

Lösung

Könnte dies das sein, wonach Sie suchen:

http://en.wikipedia.org/wiki/portable_exexecable

Das PE -Dateiformat ist die Binärdateistruktur von Windows -Binärdateien (.exe, .dll usw.). Grundsätzlich werden sie so in Erinnerung geraten. Weitere Details werden hier mit einer Erklärung beschrieben, wie Sie sich selbst die binäre Darstellung von geladenen DLLs im Speicher ansehen können:

http://msdn.microsoft.com/en-us/magazine/cc301805.aspx

Bearbeiten:

Jetzt verstehe ich, dass Sie erfahren möchten, wie sich Quellcode auf den Binärcode in der PE -Datei bezieht. Das ist ein riesiges Feld.

Zunächst müssen Sie die Grundlagen zur Computerarchitektur verstehen, die das Erlernen der allgemeinen Grundlagen des Assembly -Codes beinhalten. Jede "Einführung in die Computerarchitektur" College -Kurs wird erledigen. Die Literatur umfasst z.

Nachdem Sie dies gelesen haben, sollten Sie verstehen, was ein Stapel ist und wie er den Unterschied zum Haufen ist. Was der Stack-Zeiger und der Basizeiger sind und wie viele Register es gibt, wie viele Register usw.

Sobald Sie dies verstanden haben, ist es relativ einfach, die Teile zusammenzustellen:

Ein C ++ - Objekt enthält Code und Daten, dh Mitgliedvariablen. Eine Klasse

class SimpleClass {
     int m_nInteger;
     double m_fDouble;

     double SomeFunction() { return m_nInteger + m_fDouble; }
}

wird 4 + 8 Konsekutive Bytes im Speicher sein. Was passiert, wenn Sie dies tun:

SimpleClass c1;
c1.m_nInteger = 1;
c1.m_fDouble = 5.0;
c1.SomeFunction();

Zunächst wird das Objekt C1 auf dem Stapel erstellt, dh der Stapelzeiger ESP wird um 12 Bytes verringert, um Platz zu schaffen. Dann wird konstant "1" in die Speicheradresse ESP-12 geschrieben und konstant "5.0" wird in ESP-8 geschrieben.

Dann nennen wir eine Funktion, die zwei Dinge bedeutet.

  1. Der Computer muss den Teil der Binär -PE -Datei in Speicher laden, der Funktions -Einfunktion () enthält. Einige Funktionen befinden sich nur einmal im Speicher, egal wie viele Fälle von SimpleClass Sie erstellen.

  2. Der Computer muss die Funktion einige Funktionen () ausführen. Das bedeutet mehrere Dinge:

    1. Das Aufrufen der Funktion impliziert auch, dass alle Parameter übergeben werden. Oft erfolgt dies am Stapel. Einige Funktionen haben einen (!) Parameter, den Zeiger, dh den Zeiger auf die Speicheradresse auf dem Stapel, wo wir gerade die Werte "1" und "5.0" geschrieben haben
    2. Speichern Sie den aktuellen Programmstatus, dh die aktuelle Anweisungsadresse, die die Codeadresse ist, die ausgeführt wird, wenn einige Funktionen zurückgegeben werden. Wenn Sie eine Funktion aufrufen, müssen Sie die Absenderadresse auf den Stapel drücken und den Befehlszeiger (EIP) auf die Adresse der Funktion einfügen.
    3. Der alte Stapel wird in der Funktion in der Funktion gespeichert, indem der alte Basiszeiger (EBP) auf dem Stapel gespeichert wird (EBP drücken) und den Stapelzeiger zum neuen Basiszeiger (MOV EBP, ESP).
    4. Der tatsächliche Binärcode für einige Funktionen wird ausgeführt, wodurch die Maschinenanweisung aufgerufen wird, die m_ninteger in ein Doppel umwandelt und ihn zu M_FDUBLE hinzufügt. M_ninteger und m_fdouble finden sich auf dem Stapel bei EBP - x Bytes.
    5. Das Ergebnis der Zugabe wird in einem Register gespeichert und die Funktion kehrt zurück. Das bedeutet, dass der Stapel weggeworfen wird, was bedeutet, dass der Stapelzeiger auf den Basizeiger zurückgesetzt wird. Der Basiszeiger ist zurückgesetzt (nächster Wert im Stapel) und dann der Befehlszeiger auf die Absenderadresse festgelegt (erneut als nächster Wert im Stapel). Jetzt sind wir wieder im ursprünglichen Zustand, aber in einigen Registern lauert das Ergebnis der ArtfUction ().

Ich schlage vor, Sie bauen sich ein so einfaches Beispiel auf und treten durch die Demontage. Im Debug -Build ist der Code leicht zu verstehen, und Visual Studio zeigt in der Demontage -Ansicht variable Namen an. Sehen Sie, was die Register ESP, EBP und EIP tun, wo Ihr Objekt im Speicher zugewiesen wird, wo der Code usw. ist.

Andere Tipps

Was für eine große Frage!

Zuerst möchten Sie etwas lernen virtueller Speicher. Ohne das wird nichts anderes sinnvoll sein. Kurz gesagt, C/C ++ - Zeiger sind keine physischen Speicheradressen. Zeiger sind virtuelle Adressen. Es gibt eine spezielle CPU -Funktion (die MMU, Speicherverwaltungseinheit), die sie transparent dem physischen Speicher ordnet. Nur das Betriebssystem darf die MMU konfigurieren.

Dies bietet Sicherheit (es gibt keinen C/C ++ - Zeigerwert. Sie können diese Punkte möglicherweise in den virtuellen Adressraum eines anderen Prozesses erreichen, es sei denn (Tauschen Sie wie transparent einen Teil des Speicheres eines Prozesses auf die Festplatte aus und laden Sie ihn dann transparent zurück, wenn der Prozess versucht, ihn zu verwenden).

Der Adressraum eines Prozesses (auch bekannt als virtueller Adressraum, auch bekannt als adressierbares Speicher) enthält:

  • Eine riesige Speicherregion, die dem Windows -Kernel reserviert ist, den der Prozess nicht berühren darf;

  • Regionen des virtuellen Gedächtnisses, die "unmordend" sind, dh nichts wird dort geladen, es gibt keinen physischen Speicher, der diesen Adressen zugewiesen wird, und der Prozess stürzt ab, wenn es versucht, darauf zuzugreifen.

  • Teile die verschiedenen Module (EXE- und DLL -Dateien), die geladen wurden (jeweils enthält Maschinencode, Stringkonstanten und andere Daten); und

  • Was auch immer der andere Speicher der Prozess aus dem System zugewiesen hat.

In der Regel können die C-Laufzeitbibliothek oder die Win32-Bibliotheken in einem Prozess den größten Teil der Speicherverwaltung auf Super-Low-Ebene durchführen, einschließlich der Einrichtung:

  • Ein Stapel (für jeden Thread), in dem lokale Variablen und Funktionsargumente und Rückgabeteile gespeichert werden; und

  • ein Heap, wo der Speicher zugewiesen wird, wenn der Prozess aufruft malloc oder tut new X.

Für mehr über den Stack ist strukturiert, lesen Sie darüber Konventionen anrufen. Weitere Informationen darüber, wie der Haufen strukturiert ist, lesen Sie darüber Malloc -Implementierungen. Im Allgemeinen ist der Stack wirklich ein Stapel, eine letzte Datenstruktur, die Argumente, lokale Variablen und gelegentlich vorübergehende Ergebnisse enthält, und nicht viel mehr. Da es für ein Programm einfach ist, direkt über das Ende des Stapels hinauszuschreiben (der übliche C/C ++ - Fehler, nach dem diese Site benannt ist), stellen die Systembibliotheken in der Regel sicher, dass sich eine nicht kartierte Seite neben dem Stapel befindet. Dies macht den Prozess sofort zum Absturz, wenn ein solcher Fehler auftritt. Es ist also viel einfacher zu debuggen (und der Prozess wird getötet, bevor er mehr Schaden anrichten kann).

Der Haufen ist nicht wirklich ein Haufen im Sinne der Datenstruktur. Es handelt sich um eine Datenstruktur, die von der CRT- oder Win32 -Bibliothek aufrechterhalten wird, die Seiten des Speichers aus dem Betriebssystem entnimmt und sie überpaket malloc und Freunde. (Beachten Sie, dass das Betriebssystem dies nicht Mikromanage macht. Ein Prozess kann seinen Adressraum jedoch in großem Maße verwalten, wenn es nicht gefällt, wenn es die Art und Weise, wie die CRT es tut, nicht gefällt.)

Ein Prozess kann auch Seiten direkt aus dem Betriebssystem anfordern, indem Sie eine API -ähnlich verwenden VirtualAlloc oder MapViewOfFile.

Es gibt noch mehr, aber ich würde besser aufhören!

Zum Verständnis der Stapelrahmenstruktur können Sie sich beziehenhttp://en.wikipedia.org/wiki/call_stack

Es gibt Ihnen Informationen über die Struktur des Anrufstapels, wie Einheimische, Globale und Rückgabedressanadungen auf dem Call Stack gespeichert werden

Es ist vielleicht nicht die genaueste Informationen, aber MS Press bietet einige Beispielkapitel des Buches Inside Microsoft® Windows® 2000, dritte Ausgabe, Informationen zu Prozessen und deren Erstellung sowie Bilder einiger wichtiger Datenstrukturen.

Ich stolperte auch auf Dieser PDF Das fasst einige der oben genannten Informationen in einem schönen Diagramm zusammen.

Alle bereitgestellten Informationen sind jedoch mehr aus Sicht der Betriebssicht und nicht bis zu viel detailliert zu den Anwendungsaspekten.

Eigentlich werden Sie mit mindestens ein wenig Wissen in Assembler nicht weit in diese Angelegenheit kommen. Ich würde einen Umkehrort (Tutorial), z. B. Openrce.org, wiederherstellen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top