Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Wie werden Fkt. auf Stack gelegt? -> Mini Prog.

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
03.01.2006, 16:59 Uhr
~bdfbdfbfb
Gast


Hallo,
ich hätte eine Verständnisfrage zu folgendem Code (Google und sufu sind zu ungenau):


Code:
#include <stdlib.h>
#include <stdio.h>

long *p2;
int j;

int main(int argc, char** argv);

void test(int i) {
         char buffer[16];

         p2 = (long*)&buffer;
         for (j=0;j<16;j++) buffer[j]= j;
         printf("\nbuffer: %10.8p\n", &buffer);
         printf("i: %d %10.8p\n", i, &i);
         printf("Test: %10.8p\n", test);
         printf("main: %10.8p\n", main);
         printf("Stack:\n");
         for (j=8;j>=0;j--)
                 printf("%10.8p: %10.8p\n",(long*)(p2+j),(long*)(*(p2+j)));
}

int main(int argc, char** argv) {
         test(16);
}



Ich habe ein Programm gefunden welches mdie jeweiligen StackAdressen von sich selbst ausgibt.
Es dient dazu zu verstehen wie Programme auf dem Stack abgelegt werden....
Mir ist erstens unklar warum p2 vom Typ long ist?
Zusätzlich ist mir die zweite for-schleife in der methode test unklar?
irgendwie wird hier der stack ausgegeben...?!?

Könnte mir jemand vielleicht helfen wie genau dieses oder eben andere Programme auf den Stack gelegt werden?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
03.01.2006, 18:15 Uhr
virtual
Sexiest Bit alive
(Operator)


Erstmal ist p2 ein long* und kein long. Aus reiner C Lehre ist das aber nicht zwingend der richtige Typ. Letztlich geht es darum: Das Programm nimmt an, daß ein ein Feld auf dem Stack immer zu einem long aufgerufet wird, jedenfalls was den Platz angeht. Für Demozwecke eine Annahme, die okay ist.
Die schleife gibt den Stackframe aus. p2 Zeigt dabei auf den Buffer. In der Schleife werden nun 8 Longs ausgegeben, incl. der Adressen. Die Ausgabe kann man wie folgt interpretieren:

C++:
buffer: 0xbffff41c   # Hier zeigt auch p2 hin, zeiger auf dem Stack
i: 16 0xbffff434      # Parameter i, der hat eine höhere Adresse als buffer, weils Stacks hin zu kleineren Adreseen wachsen
Test: 0x08048410  # Programmcode adresse
main: 0x08048520  # Programmcode adresse
Stack:
0xbffff43c: 0x400583c8  
0xbffff438: 0xbffff458
0xbffff434: 0x00000010 # Parameter i
0xbffff430: 0x08048530 # Rücksprungadr. in main
0xbffff42c: 0xbffff44c   # Gerettetes epb Regiuster
0xbffff428: 0x0f0e0d0c  # buffer[12-15], inhalt zufällig
0xbffff424: 0x0b0a0908 # buffer[8-11], inhalt zufällig
0xbffff420: 0x07060504 # buffer[4-7], inhalt zufällig
0xbffff41c: 0x03020100 # buffer[0-3], inhalt zufällig


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
03.01.2006, 22:27 Uhr
(un)wissender
Niveauwart


Also bei mir sieht das etwas anderes aus, i liegt hier vor buffer, d.h. hat die kleinere Adresse.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
04.01.2006, 02:59 Uhr
~guigui
Gast


vielen dank für eure Antworten.
ich konnte unter google leider nichts genaues finden bezüglich stack.
Habe ich das richtige verstanden dass bei einem unterprogramm aufruf zuerst in umgekehrter Reihenfolge die parameter auf den stack gelegt werden
und dann die adresse des unterporgamms
und dann der base pointer ?
und dann der stack pointer ?

Ich komme da total durcheinander. Wozu dient genau der Instruction pointer.....? oder der base pointer?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
04.01.2006, 08:04 Uhr
virtual
Sexiest Bit alive
(Operator)


Der Instructionpointer (IP) ist ein Register, welches immer auf den als nächstes auszuführenden Befehl zeigt. Wenn Du einen Befehl ausführst, wird der IP automatisch vom Prozessor hochgezählt. Eigentlich gibt es nur vier möglichkeiten, den IP zu verändern:
1. Wie angesprochen durch die Ausführung eines Befehls
2. Durch ausführung eines Sprungbefehls. Die Zieladresse des Sprungbefehls beeinflußt den IP
3. Aufruf einer Unterroutine
4. Modifikation einer auf dem Stack abgelegten Rücksprungadresse (wird eigentlich nur dann genutzt, wenn man das Programm was anderes tun lassen will, als es soll insbes. beim Cracken/Hacken von Programmen)

Analog zeigt der Stackpointer (SP) auf den ersten freien SPeicherplatz auf dem Stack., In welche richtung der Stack wächst, hängt vom System ab. Hier gibt es ebenfalls vier Möglichkeiten, den SP zu verändern:
1. Durch pushen oder poppen von Werten auf den Stack
2. Aufrug einer Unterroutine
3. Explizites addieren/subrahieren eines Wertes von SP
4. Explizites Setzen eines neuen Wertes für SP. Diese letzte Möglichkeit finde man eher selten (zB in Bootloadern oder im Systemkern, wenn ein Prozess gestartet wird)

Der Basepointer dient im wesentlichen zum Referenzieren von lokalen Variablen von Funktionen. Im Unterschied zum IP und SP gibt es hier allerdings keinen Automatismus, welche den BP neu setzt, wenn eine Unterroutine aufgerufen wird, dies geschieht meist durch ein explizites kopieren von SP nach BP und aufaddieren eines Konstante, die angibt, wie viel Platz die Lokalen Variablen benötigen. Die lokalen Variablen werden relativ zum BP adressiert.

Beim Aufruf der Fkt. test passiert also folgendes:
1. Zunächst werden die Parameter auf den Stack abgelegt. Da es in C /C++ möglich ist, variable Parameterlisten zu haben ist - anders als etwa Pascal - der Aufrufer dafür verantwortlich, nach Funktionsaufruf die Parameter wieder vom Stack zu entfernen. Ausserdem werden in C die Parameter in umgekehrter Reihenfolge auf dem Stack abgelegt, eben aus dem Grund, weil die Parameterliste variabel sein kann (denke an printf) und daher die Aufgerufene Routine vor allem wissen muß, wo die ersten Parameter liegen.
Das "Parameter auf den Stack legen" verändert eigentlich nur den SP.

2. Jetzt wird die Funktion Aufgerufen. Dazu wird ein Assemblerbefehl namens "call" o.ä. ausgeführt. Dieser macht zweierlei: zunächst pusht er auf den Stack, wo denn nach dem Abarbeiten der Funktion in main weiter gemacht werden soll. Dh er schreibt den zukünftigen wert vom IP auf den Stack. Anschließend schreibt er nach IP die Anfangsadresse der Routine. Somit werden sowohl IP alsauch SP verändert.

3. Beim Eintritt in die Funktion liegn also erstmal die Rücksprungadresse und die Parameter auf dem Stack. Um die Parameter aber auch noch anzulegende lokale Variablen ansprechen zukönnen, muß man also Element auf dem Stack ansprechen. Die Routine geht also hin und kiopiert in den BP den Wert vom SP. Dies wird genau einmal am Anfang gemacht, so daß man im folgenden über den BP die Variablen/Parameter referenziert und frei ist, weitere Routinen aufzurufen, welche ja den SP verändern könnte. Da das aber alle so machen, ist es notwendig, den alten Wert vom BP zuvor zu speichern. Er wird daher auf dem stack abgelegt. Danach wird BP = SP gesetzt.

4. Nun werden die lokalen Variablen angelegt. Dies geschied einfach dadurch, indem man zu SP den Platzbedarf für die Lokalen Variablen addiert/subtrahiert. In unserem Ursprungsbepiel war SP=0xbffff42c: Da buffer 16 Byte benötigt, wurden 16 Byte abgezogen und man erhält 0xbffff41c

5. Die Routine wird nun abgearbeitet. Für in der Routine abgearbeitete Funktionen wiederholen sich die hier dargestellten Schritte.

6. Am Ende wird im Wesentlichen BP zurück nach SP kopiert, was die lokalen Variablen löscht. Anschließend wird der alte Wert von BP restauiert, indem man ihn vom Stack popt. Dann wird ein ret -Assembler befehl aufgerufen, welcher den im 2. Schritt auf den Stack gespeicherten IP popt und setzt. dadurch ist der Fkt.aufruf fast beendet:

7. Es werden die in 1 auf den Stack plazierten Elemente vom Stack genommen.

Je nach Betriebssystem und Rechnerarchitektur gibt es hier auch noch abweichungen, aber das Grundmodell ist in etwa so wie hier beschrieben.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
04.01.2006, 08:08 Uhr
(un)wissender
Niveauwart


Also gerade bei google bekomme ich für stack Millionen Treffer (112 M.). Gleich auf der ersten Seite findet sich was du suchst.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
04.01.2006, 14:46 Uhr
~guigui
Gast


ÖHA!!!
An virtual erstmal vielen lieben Dank!!! So ne BombenAntwort hätte ich jetzt nicht erwartet. Danke.

Gegoogelt habe ich schon wie blöd. Aber nur sporadisch konnte ich auf meine Fragen Antwort bekommen sorry. Zumeist wurde dann auf Assembler eingegangen....

Hier im Forum sah ich dann die Möglichkeit gezielt die Frage zu stellen. Sorry wenn es belästigend wirkte.

Danke für eure Hilfe!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
07.01.2006, 00:32 Uhr
Hans
Library Walker
(Operator)



Zitat von (un)wissender:
Also gerade bei google bekomme ich für stack Millionen Treffer (112 M.). Gleich auf der ersten Seite findet sich was du suchst.

Hi,

also den millionen Treffern stimme ich zu:
Zitat:
Ergebnisse 1 - 10 von ungefähr 54.000.000 für stack

Aber mit den Ergebnissen gleich auf der ersten Seite... - naja. Wenn man weis, was man sucht, bzw. wonach man gucken muss, dann ja. Aber sonst eher nicht.


Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
07.01.2006, 09:53 Uhr
(un)wissender
Niveauwart


Ha, mein google findet mehr als deins!


Bearbeitung:

Ok, wenn man nicht weiß, wonach man sucht ist das Finden eigentlich immer schwer.


--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 07.01.2006 um 09:54 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
07.01.2006, 17:48 Uhr
Hans
Library Walker
(Operator)



Zitat von (un)wissender:
Ha, mein google findet mehr als deins!


Sehr witzig!!!

In Anlehnung an einen alten Werbeslogan für Deospray: Mein google. - Dein google. - Google ist für alle da!

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 07.01.2006 um 17:58 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: