Hallo ! Ich habe begriffen, was ein Stack-Overflow ist, aber was passiert dann mit dem Stack-Pointer? Läuft er wieder von oben ins SRAM? Oder bewegt er sich durch den I/O-Bereich, das heißt, schreibt er dann bei "call" oder "push" Daten in diese Register? Oder läuft er durch die "normalen" 32 Register? Im Datenblatt finde ich nichts dazu. :-(
Wasserlaeufer schrieb: > Im Datenblatt finde ich nichts dazu. :-( Und was dein Simulator, wenn du fleißig Bytes vom Stack holst?
Wenn die CPU einen Hardware-Stack hat, dürfte ein Reset kommen, wenn der Stackpointer aus den zulässigen Adressen rauskommt. Genaues sagt das DaBLa des betreffenden Kerns. Beim Software-Stack (Stack im RAM) bekommt die CPU von allein nicht mit, dass der Stack überläuft. Die Adesse wird also beim push einfach weitergesetzt, und die CPU versucht die Adressen zu beschreiben. Beim pop analog wird normal ausgelesen und der Stackpointer zurückgezählt. Solange der Pointer nicht eine Adresse erreicht, die beim Schreiben einen NMI auslöst, passiert (ausser sehr seltsamen Programmfehlern) nix weiter... Besonders eklig wirds, wenn der Stack-Pointer Bereiche erreicht, in denen die Variablen stehen. Die werden dann nämlich überschrieben...
siehe Bild - Frage beantwortet. Dein Programm wird aber i.a. eher abstürzen, ehe der SP in den I/O-Bereich kommt :-)
PS: Welche Adressen/Register beim Überlauf überschrieben werden, siehst du an der Memory-map im DaBla deines Prozessors, und dem Wissen, wo du den Stack im RAM anlegst...
Danke euch für die vielen nützlichen Hinweise! Verwendet habe ich einen ATmega328 mit Assembler. Abgestürzt ist bis jetzt nichts. Das hat mich verwirrt.... Deswegen war ich mir nicht sicher, ob bei einem Push wirklich in Register geschrieben wird.
Wasserlaeufer schrieb: > Abgestürzt ist bis jetzt nichts. Das hat mich verwirrt.... > Deswegen war ich mir nicht sicher, ob bei einem Push wirklich in > Register geschrieben wird. Nach weiteren Experimenten: Weder push noch call oder rcall schreiben in Speicherbereiche, die außerhalb des SRAM liegen. Ich habe bis jetzt nirgends eine Dokumentation für dieses Verhalten finden können. In meinem Fall ist es praktisch, dass beim Stacküberlauf nichts passieren kann. :-) Andere wird es vielleicht enttäuschen, weil dadurch keine Register hilfsweise als Stack verwendet werden können. Weitere Infos oder Doku jederzeit willkommen!
Ich würde Deine Ergebnisse, wohl aber nicht Dein Bemühen, eher mit einer gewissen Skepsis sehen. Zumindest bedürfen sie meiner Ansicht nach der weiteren Erläuterung. Soweit ich weiss sind z.B. die Register, sowohl die Arbeitsregister als auch die Register der Peripherieeinheiten durchaus auch auf Speicherbereichen erreichbar; wenn auch je nach Atmel-Typ in verschiedenem Umfang und an anderen Adressen. Deine Äusserung: >Nach weiteren Experimenten: >Weder push noch call oder rcall schreiben in Speicherbereiche, die >außerhalb des SRAM liegen. Ich habe bis jetzt nirgends eine >Dokumentation für dieses Verhalten finden können. widerspricht dem nicht. Andererseits wäre es wissenswert ob Register verändert werden. Auch ist mir an dieser Erklärung nicht klar, ob Du "Experimente" tatsächlich an der realen CPU durchgeführt hast und auf welche Weise. Das in der Dokumentation pathologische Fälle eher selten wenn überhaupt geschildert werden überrascht mich nicht. Auch bei anderen Herstellern geschieht dies eher dann wenn tatsächlich eine Beschädigung auftreten könnte. Ein Fehlen der Beschreibung dieses Falles überzeugt mich nicht. Warum ich so lange rede. Ich bin überzeugt davon das die Zugriffe via Stackpointer bei den AVRs mit Stack im RAM nicht überprüft werden und das jeder Zugriff tatsächlich ausgeführt wird egal ob da nun RAM oder ein memory-mapped Register dahinter liegt oder eben das "Nichts".
Hallo Hmm! Hmm schrieb: > Soweit ich weiss sind z.B. die Register, sowohl die Arbeitsregister als > auch die Register der Peripherieeinheiten durchaus auch auf > Speicherbereichen erreichbar; wenn auch je nach Atmel-Typ in > verschiedenem Umfang und an anderen Adressen. Richtig! Deswegen dachte ich ursprünglich mal, ein überlaufender Stack würde für Chaos sorgen. > Deine Äusserung: (...) > widerspricht dem nicht. Andererseits wäre es wissenswert ob Register > verändert werden. Sie wurden nicht verändert. > Auch ist mir an dieser Erklärung nicht klar, ob Du "Experimente" > tatsächlich an der realen CPU durchgeführt hast und auf welche Weise. An einem echten ATmega328. Dessen SRAM beginnt bei 0x0100. Der Stackpointer läuft locker nach unten raus, also 0x00ff, 0x00fe usw., aber es wird in Adressen unter 0x100 per push nichts geschrieben. Ich habe das mit IO-Registern probiert und auch mit GP-Registern (r0 bis r31). > Warum ich so lange rede. Ich bin überzeugt davon das die Zugriffe via > Stackpointer bei den AVRs mit Stack im RAM nicht überprüft werden und > das jeder Zugriff tatsächlich ausgeführt wird egal ob da nun RAM oder > ein memory-mapped Register dahinter liegt oder eben das "Nichts". Ja, diese Vermutung ist naheliegend, aber anscheinend ist es in der Praxis anders. So wie es aussieht, kann zwar z.B. sts in den gesamten Adressbereich schreiben, nicht aber push, call, rcall, also anscheinend alles was mit indirekter Adressierung über SP zu tun hat.
Tut mir leid wenn ich nachbohre. Du glaubst nicht was man hier so an Textverständnis erlebt: >> Auch ist mir an dieser Erklärung nicht klar, ob Du "Experimente" >> tatsächlich an der realen CPU durchgeführt hast und auf welche Weise. >An einem echten ATmega328. Was heisst "echt"? Ich habe gefragt "real"! Im Simulator? Oder physisch vorhanden?
Hmm schrieb: > Tut mir leid wenn ich nachbohre. Du glaubst nicht was man hier so an > Textverständnis erlebt: Voll ok. :-) Ich lese hier auch oft mit und erlebe immer wieder, dass Leute aneinander vorbeireden. >>An einem echten ATmega328. > > Was heisst "echt"? Ich habe gefragt "real"! Im Simulator? Oder physisch > vorhanden? Mit "echt" meinte ich "physisch". Versuchsaufbau: ATmega328-PU auf Breadboard, Angeschlossen über USBasp, der fürs Programmieren da ist und danach auch für die Stromversorgung sorgt. Als weitere Bauteile hatte ich nur eine Leuchtdiode und einen Vorwiderstand. Jetzt kommt wahrscheinlich die berechtigte Frage, woher ich dann weiß, was nach den jeweiligen Versuchen in den Registern steht: ich habs einfach über die LED rausgemorst. Das mache ich öfter so, bin nämlich zu faul, viele Bauteile aufzustecken. :-)
Interessant, wenn mir auch gerade keine nützliche Anwendung dafür einfällt. Hast Du das mal bei AVRFreaks gepostet?
Hmm schrieb: > Interessant, wenn mir auch gerade keine nützliche Anwendung dafür > einfällt. Hast Du das mal bei AVRFreaks gepostet? Nein, bei denen war ich noch nie. Wozu man das braucht? Auch eine gute Frage... Wenn man Interrupts nutzt, aber keinen Rücksprung braucht oder kein SRAM nutzen will, weil man es für andere Zwecke verwendet. Alles in allem irgendwelche seltenen Spezialfälle.
Werde ich morgen mal ausprobieren. Definitiv war es früher so, dass der SP bei gewissenloser Nutzung alles platt gemacht hat :-) Einen Unterschied sieht man aber schon im Datenblatt: die neueren Typen (wie 48/88/168/328) haben SP-init-Werte nach reset ramend. Die früheren Typen (z.B. Mega32) haben 0 im SP stehen. Offensichtlich hat Atmel die SP-Logik zumindest angefasst. Vielleicht auch einen (minimalen) Speicherschutz?? Aber einen wirklichen Nutzen hat es in der Tat nicht, zumindest sehe ich keinen.
H.joachim Seifert schrieb: > Werde ich morgen mal ausprobieren. Bin gespannt! > Definitiv war es früher so, dass der SP bei gewissenloser Nutzung alles > platt gemacht hat :-) Meinst du mit "alles" das komplette SRAM oder auch alle anderen Register? Das SRAM wird immer noch überschrieben, daran hat sich nichts geändert. Wenn du also ein Programm hast, das das SRAM verwendet, um dort Variablen abzulegen (wie z.B. bei C üblich), musst du aufpassen. > Typen (z.B. Mega32) haben 0 im SP stehen. Offensichtlich hat Atmel die > SP-Logik zumindest angefasst. Vielleicht auch einen (minimalen) > Speicherschutz?? Ich hab den Verdacht, die früher fehlende automatische Initialisierung hat damit nichts zu tun.
>Ich hab den Verdacht, die früher fehlende automatische Initialisierung hat damit nichts zu tun. Ich denke das hat er damit auch nicht sagen wollen. Aber diese Aussage >Meinst du mit "alles" das komplette SRAM oder auch alle anderen >Register? Das SRAM wird immer noch überschrieben, daran hat sich nichts >geändert. >Wenn du also ein Programm hast, das das SRAM verwendet, um dort >Variablen abzulegen (wie z.B. bei C üblich), musst du aufpassen. weckt leider doch wieder meine Skepsis. Denn die Register sind (wie oben geschrieben in je nach Typ unterschiedlicher Weise und Umfang) auch in den Speicher abgebildet. Du kannst z.B. R1 bis R31 durch schreiben ins RAM ändern. Zumindest solte noch ein Zweiter mal Deine Tests nachvollziehen. Magst Du mal Deinen Testcode posten?
test: #asm ldi r16, 0 out SPH, r16 ldi r16, 0xff out SPL, r16 ldi r16, 0xaa loop: push r16 rjmp loop #endasm Mal kurz einen Mega16 auf das STK500 gesteckt und mit JTAG MKII und AVR-Studio laufen lassen (ich hoffe, das JTAG wirklich ein exaktes Prozessorbild liefert??) - der SP überschreibt weder I/O noch Register. Zählt aber brav bis 0 runter. Danach springt er übrigens auf 0x0fff... Jetzt bin ich etwas ratlos.
>(ich hoffe, das JTAG wirklich ein exaktes Prozessorbild liefert??) Ich gehe davon aus, aber... >Jetzt bin ich etwas ratlos. ...ich erwäge gerade meinen Glauben an den Weihnachtsmann wieder zu beleben. :-) Witzig! Haben die Ings. bei Atmel das tatsächlich abgefangen.
Es wäre auch mal interessant, was herauskommt, wenn man bei einem SP, der in die Register zeigt, einen Wert poppt. Der Wert des Registers, 0 oder gar ff?
H.joachim Seifert schrieb: > Zählt aber brav bis 0 runter. Danach springt er übrigens auf 0x0fff... Ah, interessant! Aber irgendwie logisch, denn der SP besitzt wahrscheinlich einen eigenen Hardware-Inkrementierer/Dekrementierer, da hat man sich ein paar Transistoren gespart, weil die High-Bits sowieso nicht verwendet werden. Irgendwo im Datenblatt steht sogar, dass die unbenutzten Bits des SP "don't care" sind, man sich deswegen auf deren Inhalt nicht verlassen darf und gut daran tut, sie auszumaskieren. Zumindest dieses Mysterium ist gelöst. ;-) Ob der AVR-Simulator das alles auch berücksichtigt? Ich hab leider keinen.
H.joachim Seifert schrieb: > pop mit SP <0x60 liefert 0x00, zumindest laut JTAG. Wenn das auch für RET/RETI gilt, landet das Programm sowieso irgendwann im Reset Vector.
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.