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
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
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
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
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
@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.
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
@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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.