Forum: Mikrocontroller und Digitale Elektronik Datenüberlauf im Stack


von Martin (Gast)


Lesenswert?

Hallo Leute!

Ich beschäftige mich gerade mit dem LPC2138 von ARM und hatte gerade
ein kleines Problem mit der Stackgröße.
Der Kontroller stürzte ab oder Variablen änderten plötzlich aus
heiterem Himmel ihre Größe.

Jedenfalls nach der Umstellung: Der Fast-IRQ-Stack wurde von mir von 4
Byte auf 0x20 Bytes angehoben.
Nun funktioniert alles einwandfrei.

Ich habe in meiner Ausbildung gelernt, dass der Stack-Speicher nur
Rücksprungadressen sichert, damit der PC-Counter weiß, an welcher
Stelle er im Hauptprogramm z.B. nach einer IRQ-Routine oder nach der
Ausführung einer Funktion, weitermachen muss.

Nun hörte ich aber, dass der Stack des CARM-Keil-Compilers nicht nur
Rücksprungadressen enthalten soll, sondern auch lokale Variablen.
Wie soll dass denn gehen? Ist das ein Gerücht oder stimmt das?

Meiner Meinung nach ist ein Stack nur ein Stapelspeicher
(FIRST-IN-LAST-OUT), wie soll man auf eine Variable oder auf ein
Variablen-Feld, welche sich im Stack befinden zugreifen, man hat doch
hier keinen direkten Zugriff?!?

Was haltet ihr von der Sache?

Ich freue mich schon auf eure Antworten.

Danke im Voraus.

Tschüss, Martin

von Rainer S. (Gast)


Lesenswert?

Hallo Martin,

Dein Wissen über einen Stack ist nicht vollständig. Es ist richtig,
dass er neben den Rücksprungadressen auch lokale Variablen aber auch
Parameter enthalten kann. So ist es z.B. üblich, dass die
Interrupt-Routine Register, die innerhalb der Interrupt-Routine
verändert werden, sichert und am Ende wiederherstellt. Damit erklärt
sich auch die Auswirkung der Vergrößerung von 4 auf 32 Byte.

Die Bezeichnung für einen Stack alias Stapelspeicher ist eher LIFO
(Last In First Out). Deine Bezeichnung ist allerdings semantisch
korrekt, auch wenn die Bezeichnung nicht üblich ist.

Gruß,
Rainer

von Uwe Große-Wortmann (Gast)


Lesenswert?

Es ist üblich, einem Unterprogramm über den Stack die Variablen zu
übermittelt, mit denen dieses arbeiten muss. Vor jedem Aufruf werden
also die Daten gemeinsam mit der Rücksprungadresse auf den Stack
gepackt, das Unterprogramm holt sich den ganzen Krempel wieder, macht
seinen Job damit, packt die Ergebnisse wieder auf den Stack und springt
zurück. Dann kann das Hauptprogramm die Ergebnisse auf dem Stack
abholen.

von johnny.m (Gast)


Lesenswert?

Schau Dir mal das Assembler-Listing von Deinem Programm an. Du wirst
Dich wundern, wie viele push- und pop-Befehle da auftauchen... Und
genau mit diesen Befehlen hat man nämlich direkten Zugriff auf den
Stack.

von Läubi (Gast)


Lesenswert?

direkten zugriff auf den Stack hat man über den Stackpointer... mit push
und pop nur auf das oberste Element...

von Stephan H. (stephan-)


Lesenswert?

@Uwe
> Es ist üblich, einem Unterprogramm über den Stack die Variablen zu
übermittelt,

und was wenn beim Einsprung in´s Unterprogramm nen Interrupt auftritt
??
halte ich für keine gute Idee.
Es gibt eeir Leute die vergeben dafür ne rote Karte ..... ;-)

Das sollte man dann doch lieber in den Registern tun. Auf den SP
gehören nur die Returns und die Regitser die im Interrupt geändert
werden.
Mehr nicht.

von Rainer S. (Gast)


Lesenswert?

@Stephan: Wieso sollte es mit der Übergabe von Parametern auf dem Stack
in Verbindung mit einem Interrupt Probleme geben? Es spielt keine
Rolle, ob eben eine z.B. eine arithmetische Operation abgearbeitet wird
oder ein Datum auf den Stack gelegt wird. Es ist für die Interrupt
Routine völlig egal, was das Programm macht, das unterbrochen wird.

Gruß,
Rainer

von mh789 (Gast)


Lesenswert?

Auf die Schnelle hab ich mal das ergoogelt:
<http://www.cs.umbc.edu/~chang/cs313.s02/stack.shtml>;. Ich hoffe, das
hilft Martin und Stephan.

von Karl H. (kbuchegg)


Lesenswert?

> und was wenn beim Einsprung in´s Unterprogramm nen Interrupt
> auftritt ??

Was soll dann sein?
Dann wird, wie sonst auch, dass pushen auf den Stack durch
den Interrupt unterbrochen, der Interrupt abgearbeitet
(der hoffentlich den Stack so hinterlässt wie er ihn vorgefunden
hat), und dort weiter gemacht wo der Interrupt unterbrochen hat:
Beim pushen der Argumente auf den Stack.

> Das sollte man dann doch lieber in den Registern tun.
Geb ich dir grundsätzlich recht. Geht auch schneller.
Nur was hilfts, wenn der Compiler das ganz anders implementiert.

von Stephan H. (stephan-)


Lesenswert?

@Rainer,
halte ich für keine gute Idee..... schrieb ich. Nicht Probleme.
Die Rede war ja von "Es ist üblich ".

Es ist aber nicht üblich sondern ehr unüblich.
Wer am SP fummelt, sollte schon sehr genau wissen was er da tut.
Und wenn Martin, was ich vermut, noch nicht lange programmiert, dann
sollte man ihm sowas auch nicht noch nahe legen. Er hats ja schließlich
richtig gelernt. Da er warscheinlich kein Assembler macht, hat er
natürlich kaum einen Überblick über die Menge der verwendeten Push´s
und Pop´s.
Schwach das Keil sowas beim Copilieren offensichlich nicht bemerkt

.........oder Martin hat die Meldung ignoriert.

Du kannst ja mit Deinem SP machen was Du willst, ich bleibe bei R0-R7,A
und B und frage ruhig andere Assembler Programmierer, die meisten werden
Dir das gleiche sagen.

von peter dannegger (Gast)


Lesenswert?

Also Leute haut euch.

Die Parameterübergabe über den Stack ist auch sicher, wenn man
Disziplin hält, d.h. genau genau so viel popt, wie gepusht wurde. Ein
C-Compiler hat damit keinerlei Probleme.


Aber in Assembler schludert man gerne mal und dann ist es viel
gefahrloser, wenn man Register nimmt. Es schadet dann überhaupt nichts,
wenn man mehr Werte übergibt, als abgeholt werden.


Und wenn man mehrere Register hat, dann ist natürlich die
Parameterübergabe über Register schneller und Code sparender.
Deshalb pushen Compiler für Registerarchitekturen (AVR, 8051) eher
selten.


Peter

von Stephan H. (stephan-)


Lesenswert?

HIER wird nicht gehaun !!!
Bin sehr sensibel...... war 45 verschüttet...... :-)

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.