Forum: PC-Programmierung Wie wird der Zugriff auf lokale Variablen umgesetzt?


von Meow (Gast)


Lesenswert?

wenn ich innerhalb einer C-Funktion drei Variablen
deklariere:
int a,b,c

dann kann ich ja mit denen machen, was ich will.
ob ich nun sage:

c++;a++; b++;
oder
b++;a++;c++
ist egal.

Ich habe also wärend des Programmierens quasi wahlfreien Zugriff auf die 
Variablen innherhalb der Funktion.

Automatische Variablen werden ja auf dem Stack abgelegt. Wenn nun im 
Programm kommt:
c++;
und c ist nicht ganz oben auf dem Stack, wie wird dann auf c 
zugegriffen?

Macht der Herr Compiler das in Maschinensprache etwa so:

"Der Will c ändern.
Hmm, c ist auf dem Stack an der 3. Position.
Da nehm ich erstmal zwei runter und speicher die, hmm, keine Ahnung, 
inne Ecke?
Gut, nun liegt c oben. Les ich aus in ein Register R für späteres 
bearbeiten des Wertes. Nun pack ich den gelesenen Wert wieder auf den 
Stack.
Noch den Kram aus der Ecke rauf."
c ist noch nicht geändert.
Nun stelle ich eine berechnung an mit R (das für den Wert von C steht).
Das Ergebnis in R wird mit ähnlicher Methodik von vorhin in c 
geschrieben.


Wobei die "ECKE" ein vom Compiler reservierter Speicherbereich ist?
Wie groß wird denn so eine "ECKE" wenn man den Speicherbedarf für 
Controller abschätzen muss?
Theoretisch müsste die ECKE ja genauso groß sein wie die (Anzahl lokaler 
variablen)-1, damit genug Platz zum rumpacken ist. Wird die ECKE 
dynamisch verwaltet? (Auf nem 8-Bitter wohl eher nicht?).

von Frank G. (pancho)


Lesenswert?

Du hast den Stack nicht ganz verstanden. Der Stackpointer zeigt zwar 
immer auf das "oberste" Datum, so dass neue Daten "oben drauf" 
gespeichert werden können, trotzdem kann auf alle Daten "darunter" 
zugegriffen werden.
Der Compiler weiß, dass c über [Stackpointer + 8] erreichbar ist, weil 
davor noch 2 * 4 Byte für a und b reserviert sind. (Ich gehe davon aus, 
dass ein Integer 32 Bit hat und der SP nach unten wächst)

von Ronny (Gast)


Lesenswert?

Die Sache mit der Ecke ist reichlich ineffektiv.Wie genau es gemacht 
wird,hängt sicher auch vom Compiler und den Optimierungsgraden ab.Es wär 
sicherlich vorstellbar,das in einigen Fällen der Speicherzugriff ganz 
wegoptimiert und ein Register verwendet wird.

Ansonsten wird ein Zeiger relativ zum Stackpointer benutzt.Dazu wird der 
Stackpointer zu Beginn der Funktion gesichert und alle lokalen Variablen 
sind dann Offsets zu diesem Wert.Damit können dann auch push/pop zum 
sichern von Daten oder weitere Funktionsaufrufe genutzt werden,ohne das 
etwas verloren geht.Dadurch ist es beispielsweise möglich,das eine 
Funktion sich selbst aufruft.

Beim x86 (PC) gibt es sogar ein extra Register um den Stackpointer für 
lokale Variablen zu sichern (BP Base Pointer)

von Meow (Gast)


Lesenswert?

Super erklärung, Danke euch!
Den Stack hatte ich also nicht verstanden, weil ich vom unflexiblen 
stack in nem 8-Bitter auch auf den PC geschlossen hatte.

von Ronny (Gast)


Lesenswert?

Das Grundprinzip des Stacks ist immer das selbe,ein Zeiger-Register wird 
intern benutzt um nach dem FIFO-Prinzip (First In-First Out) Daten 
temporär zu sichern.Mir fällt jetzt auf Anhieb keine Architektur ein,wo 
der Stack nicht nach unten (von höheren zu niederen Adressen hin) 
wächst.

Ob die Architektur nun noch ein zusätzliches Register bereitstellt,um 
den Stack indirekt zu adressieren hängt davon ab,wie gut sie auf 
Hochsprachen optimiert ist.Aber meistens spricht nix dagegen,sich 
einfach auf ein Register zu einigen und diese selbst erstellte 
Konvention dann konsequent durchzuziehen.Einen Stackpointer der von der 
Hardware verwaltet wird,gibt es eigentlich immer,schliesslich müssen ja 
bei Interrupts und Funktionsaufrufen auch Sachen auf dem Stack gesichert 
werden.

von Frank (Gast)


Lesenswert?

Ein FIFO ist der Stack gerade nicht, LIFO wäre passender.

von Karl H. (kbuchegg)


Lesenswert?

> Den Stack hatte ich also nicht verstanden, weil ich vom unflexiblen
> stack in nem 8-Bitter auch auf den PC geschlossen hatte.

Der Stack ist auch auf einem 8-Bitter nicht unflexibel.
Was du die ganze Zeit ausser acht lässt ist, dass der
Stack in ganz gewöhnlichem Ram residiert. Der Stack ist
also eine Datenstruktur, die logisch gesehen etwas
höher anzusiedeln ist als reine Speicherzugriffe. Aber
da der Stack im RAM realisiert wird, ist es selbstverständlich
möglich mittels ganz normaler Speicherzugriffe auf das
RAM und damit auf den Stack zuzugreifen (*). Alles was man
dazu braucht ist die aktuelle Position des obersten
Elements im Stack. Das ist die Basisadresse von der
weg gerechnet wird. Wenn ich die habe, kann ich immer
mittels gewöhnlicher Speicherzugriffe auf den Stack
zugreifen. Das unterscheidet sich konzeptionell in nichts
von zb. einem Zugriff auf ein bestimmtes Element eines
Arrays. Auch dort kenne ich nur die erste Adresse des
Arrayelementes und kann daraus berechnen, wo das Element
mit dem Index i im Speicher liegt. Es läuft immer auf
dasselbe hinaus: Wenn ich eine Adresse im Speicher kenne,
und weis wo in Relation dazu die gesuchten Daten gespeichert
sind, kann ich deren Speicheradresse ausrechnen und den
Speicherzugriff machen. Manche Prozessoren haben halt dafür
noch spezielle Befehle bzw. spezielle Register. Das kann
so sein, muss aber nicht. Durch das Vorhandensein dieser
Spezialitäten wird nichts an Funktionsumfang gewonnen.
Einzig die Art und Weise wie der Zugriff gemacht werden kann,
bzw. wie schnell er gemacht werden kann ist anders. Aber
Möglichkeiten hab ich deswegen auch nicht mehr.

(*) Von Assembler aus. Der Compiler darf das. Als Hochsprachen-
programmierer wird dir einiges von den Möglichkeiten genommen
um zu verhindern, dass du gegen den Compiler programmierst.

von Ronny (Gast)


Lesenswert?

@Frank:

Natürlich hast du Recht.Das letzte Element was "oben auf" gelegt 
wird,ist zugleich das erste,was wieder abgenommen wird.Ab einer gewissen 
Zeit sollte man einfach schlafen ;)

von X. H. (shadow0815)


Lesenswert?

Okay, dann habe ich es jetzt verstanden :)
In nem PIC war der Stack ne eigene Hardware und nicht im Ram.
Hab mir jetzt aber auch lieber nen Mega8 geholt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.