Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage: Stack/RAM (Assembler)


von Andy K. (sokar)


Lesenswert?

Hallo alle zusammen, arbeite mich gerade in Assembler ein. Mir ist es 
relativ wichtig auch die Architektur und den inneren Ablauf zu verstehen 
und bin da mal auf eine Frage gestoßen:

Also den Stack initialisiere ich, d.h. im Z Register wird die "oberste" 
SRAM Adresse gespeichert. Wenn sich der STACK nun langsam füllt schreibt 
er ja nach "unten". Natürlich muss ich evtl. aber auch andere Daten, 
z.B. berechnete Variablen im SRAM speichern. So wie ich mir das denke 
werde ich das dann wohl am besten von "unten" im SRAM machen oder?
Kann es jetzt nicht irgendwann mal dazukommen, wenn der STACK recht voll 
wird. Das der STACK mir quasi meine Daten die ich "unten" im SRAM 
gespeichert habe von "oben" her überschreibt?

Bin ich da vom Verständis her richtig?
Das müsste ich dann bei der Programmierung auch beachten oder?

Danke euch für Antworten

von Sebastian (Gast)


Lesenswert?

Genau richtig
Die Userdaten schiebt man entweder auch auf den Stack (manchmal die 
bessere Lösung, manchmal sinnlos), oder fängt am anderen Ende des 
Speichers an.

Ein Überschreiben von Daten muss man selbst verhindern. Entweder du 
achtest bei der Programmierung gleich darauf, dass sich die Speicher NIE 
in die Quere kommen, oder du musst in deinem Programm vor jedem 
Speichervorgang prüfen, wie viel Platz denn noch ist.

Sebastian

von Wolfgang Weinmann (Gast)


Lesenswert?

Hallo,

es ist relativ einfach: Der frei verfügbare RAM muß mindestens so groß 
sein, daß bei maximal verschachtelten Subroutinencalls mit 
PUSH-Operationen nie die statischen Variablen überschrieben werden.
Viel zu tricksen gibts da nicht - man braucht einfach einen genügend 
großen Speicher. Alles andere ist "Herummurckserei".

Wenn doch mal ganz eng wird und es gar nicht anders geht, dann muß man 
die PUSH/POP Operationen für Parameterübergabe reduzieren oder entfallen 
lassen, und das Programm so gestalten, daß es trotz zerstörter Register 
korrekt läuft. Das ist halt mit deutlich mehr manueller Kontrolle 
verbunden.

Wenn man viel Daten bei einem Subroutinencall übergeben will, dann kann 
man zum Beispiel nur die Anfangsadresse auf den Stack pushen und nicht 
das ganze Array. So machen das normalerweise auch Compiler.

Gruß

Wolfgang Weinmnann
www.ibweinmann.de - Brushless Development Kit

von rene (Gast)


Lesenswert?

Der stack fuellt sich nicht langsam und auch nicht von selbst. Ein Wert 
wird manuell auf dem stack plaziert mit push, und geholt mit pop. Die 
Reihenfolge ist wichtig. Dann wird der Stack noch gebraucht mit call - 
subroutine, die endet mit einem ret. Das ist es. Dazu kommt noch die 
Interrupt behandlung, die wird beendet mit iret oder so. Danach ist der 
stack wieder gleich gross.

rene

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

welcher stack wächst denn von oben nach unten?

von Wolfgang Weinmann (Gast)


Lesenswert?

Hallo,

"welcher stack wächst denn von oben nach unten?"

der Stack wächst immer in die Richtung, wie der Prozessor das macht bei 
POP Befehlen - normalerweise in Richtung kleinerer Adressen. Also muß 
der Stackpointer ans RAM-Ende initialisiert werden.

Bei Compilern mir dynamischen Variablen gibts dann noch den Heap - der 
wächst von unten nach oben.

Gruß

Wolfgang Weinmnann
www.ibweinmann.de - Brushless Development Kit

von SiO2 (Gast)


Lesenswert?

@wolfgang: beim 8051 wächst er aber vonunten nach oben afaik 
(klugscheiss ;) )

von crazy horse (Gast)


Lesenswert?

@Andy:
"Also den Stack initialisiere ich, d.h. im Z Register wird die "oberste"
SRAM Adresse gespeichert."
Das ist zumindest beim AVR falsch, er hat einen eigenen stackpointer 
(SPH, SPL).
Man kann allerdings z.B. mit dem Z-Register (oder x,y) einen eigenen 
stack aufbauen, macht manchmal Sinn.
Wie schon gesagt, gibt es keinerlei Speicherschutz-Mechanismen, der 
Stack läuft auch in den Variablen, I/O-Bereich und sogar in den 
Registerbereich, wenn man nicht selbst aufpasst. Einfache Fehler wie 
nicht zusammenpassende push/pop oder verlassen von mit call aufgerufenen 
Funktionen mit jmp erkennt man normalerweise sehr schnell.
Eine ganz böse Falle können rekursive Funktionen sein, wenn die 
Rekursionstiefe variabel ist, da hilft nur eine worst-case-Betrachtung.
Bei komplexeren Programmen ist es manchmal gar nicht so einfach, die 
max. Verschachtelungstiefe zu erkennen. Disziplin bei der Programmierung 
und stack-end-marker bei der Simulation helfen da weiter.

von Andy K. (sokar)


Lesenswert?

crazy horse wrote:
> @Andy:
> "Also den Stack initialisiere ich, d.h. im Z Register wird die "oberste"
> SRAM Adresse gespeichert."
> Das ist zumindest beim AVR falsch, er hat einen eigenen stackpointer
> (SPH, SPL).



Öh ja klar - weiß ich. Da hab ich mich wohl beim schreiben vertan :)

PS: Danke an alle für die zahlreichen Antworten

von Wegstabenverbuchsler (Gast)


Lesenswert?

@Wolfgang

Ein POP entfernt Daten vom Stack, welceh zuvor per PUSH "draufgelegt" 
wurden.

deine Aussage "der Stack wächst immer in die Richtung, wie der Prozessor 
das macht bei POP Befehlen" ist demzufolge widersprüchlich.

Der Stack schrumpft also bei POP Befehlen (in Richung kleinerer 
Speicheradresse) --> demzufolge wächst er bei PUSH in Richtung größerer 
Speicheradressen

von Andy K. (sokar)


Lesenswert?

Der Stack beginnt bei der obersten Speicheradresse im RAM (RAMEND). Beim 
ATmega 16 z.B. RAMEND  = 0x045f --> Wenn du jetzt auf dem Stack was 
ablegst, dann wird die Adresse im Stackpointer um eins reduiziert. Wenn 
du wieder etwas ablegst reduziert sie sich wieder --> Der Stack wächst 
im RAM (beim AVR) von der der obersten Adresse nach "unten".

Also die größe des STACK schrumpft schon bei POP Befehlen. Allerdings 
erhöht sich die Speicheradresse dabei - so sollte es sein. Andere 
Meinungen/Anregungen?


RAM:
0x045f <-- hier zeigt der Stackpointer nacht init hin
0x045e <-- wenn du was auf dem Stack ablegst reduziert sich die Adresse
0x045d <-- "wächst nach unten"
...
...
0x0060 <-- Beginn des RAMs
"darunter" liegen die Register









von Andy K. (sokar)


Lesenswert?

PS: Klar gibt es natürlich auch STACKs die von unten nach oben 
wachsen... ich beziehe mich auf dem ATmega 16 - hätte ich vielleicht 
erwähnen sollen









von Eckhard (Gast)


Lesenswert?

Hallo,

normalerweise kann man den Stackpinter setzen,
dann an man oberhalb des Stacks noch Platz lassen der vom Stack nicht 
überschrieben werden kann. b der restliche Platz dann für den Stack 
reicht ist allerdings von der Anwendung abhängig. Manche Cmiler mahn das 
auch automatisch so.


Eckhard

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.