Metadiskussion Gosub, Goto, Stackpointer

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Metadiskussion Gosub, Goto, Stackpointer

      Michael schrieb:

      Wenn du Unterprogramme nicht mit Return abschließt, läuft dein Stack über.
      So ist es.

      Bin auch darüber gestolpert, ist aber in Bascom so, wenn Stackspeicher zu klein dann kann es basieren du überschreibst den Dim Bereich. Die Folgen sind verheerend da es ein nicht nachvollziehbar Fehler wird.
      Also wenn du eine Sub vor Return verlässt wird Stackbereich nicht für eine neue Subadresse freigegeben sondern ein neurer Platz wird reserviert.
      Somit sollte dieser Bereiche optimal eingestellt werden.

      Nun kommt gleich noch ein Tipp warum ich Bascom mag. Ist nicht so starr wie andere Hochsprachen.
      Du schreibst ja nicht Return bla, sondern nur Return, somit ist Befehl allgemein gültig.
      Könnte also auch so aussehen.

      main:

      Return
      do
      bla bla
      debounce taster,0,sub
      loop
      Return

      sub:
      bla
      bla
      gosub bla
      Return

      bla:
      do
      if bla > bla then
      gosub main
      end if
      loop
      Return

      Nun sollte der Speicherplatz immer zurückgesetzt sein.(ist ein Return zu viel wird gemeckert)

      Aber warum so umständlich wenn ich mit bedacht Goto anwende.
      Ja Goto- Befehl ist hier verhöhnt. Warum ist mir immer noch ein Rätsel, obwohl ein uralter und sicherer Befehl.
      Mit Befehl kannst du knallhart von jedem Ort in ein Lable springen ohne was zwischen zu speichern oder hoch zu zählen. Aber wie gesagt „mit bedacht“ da Du genau wissen musst wo hin und her gesprungen wird. Compiler nimmt Dich dies nicht mehr ab.
      Dies könnte der einzige Grund sein warum GOTO , obwohl selbst in Bascom-AVR es ein wichtiger Bestandteil des Programms ist, belächelt wird.
      Bevor ich ein HW- Reset erzwinge bevorzuge ich immer eine SW –Lösung um nicht die Hauptschleife zu verlassen und alle den „Kram“ wieder neu zu laden.

      Mal so auf der Schnelle.

      main:
      Losgehts: ‘Bitte nicht “Start” als Name nutzen. Ist eine Systemvariable. Gleich noch Startbedingungen generieren.
      Osterei kaput = 0
      Ei = Gelb usw.
      Return

      ‘ nun wird Hauptschleife wieder gestarten.

      Do
      bla bla
      debounce taster,0,sub ‘Taster ist der Hammer
      If Osterei kaput Then Goto Losgehts ‘beginnt wieder bei „main“ nicht ganz oben.
      Else Gosub Sub
      Loop

      Sub:
      If Ei blau Then Goto Losgehts ‘Neustart
      Else Gosub Nachricht
      Return

      Nachricht:
      Print „FrohesOsterfest“
      Wait 60
      Return ‚Spring nach Sub und bekommt je nach Eierfarbe ein Return und Stack ist wieder „Sauber“

      Sehr grob und schelmisch beschrieben.
      Mit freundlichen Grüßen

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von fredred ()

    • fredred schrieb:

      Bin auch darüber gestolpert, ist aber in Bascom so, wenn Stackspeicher zu klein dann kann es basieren du überschreibst den Dim Bereich.
      Ja klar und woher kommt es? Weil "wild" aus Schleifen gesprungen wird; z.B. mit GOTO oder syntaktische Fehler vorliegen.
      Außerdem hat dies nichts mit Bascom zu tun, sondern ist generell so.
      Code first, think later - Natural programmer :D
    • @fredred was du da schreibst, ist ein einziger Graus, brutal, aber ich steh dazu

      fredred schrieb:

      main:

      Return
      do
      bla bla
      debounce taster,0,sub
      loop
      Return
      Was soll das? Ein return holt sich vom stack eine Sprungadresse und springt dahin. Was liegt am Anfang auf dem stack? Na, was? Hast du da was hingelegt? Und wenn du zufällig mit dem Befehl gosub main an dem return vorbei kommst, welche Adresse steht jetzt zum Springen drin? Die, woher du gerade zur main gesprungen bist.

      fredred schrieb:

      Sub:
      If Ei blau Then Goto Losgehts ‘Neustart
      Else Gosub Nachricht
      Return

      Nachricht:
      Print „FrohesOsterfest“
      Wait 60
      Return ‚Spring nach Sub und bekommt je nach Eierfarbe ein Return und Stack ist wieder „Sauber“
      Was soll das? Die Mühe, die du dir machen musst, dass auf dem stack wirklich noch die Adresse von 'sub' steht ist doch in keinem Verhältnis zu der bisschen Mühe konsequent zu programmieren.

      Also Fred, du hast schon mal was besseres, brauchbareres abgesondert. :thumbdown:
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      Was soll das? Ein return holt sich vom stack eine Sprungadresse und springt dahin. Was liegt am Anfang auf dem stack? Na, was? Hast du da was hingelegt?
      Nun zeig mal wie und wo eine Sprungadresse ohne Sub angelegt wird. Möchte und muss noch viel lernen wie so ein Controller im CPU- Bereich funktioniert.
    • fredred schrieb:

      Nun zeig mal wie und wo eine Sprungadresse ohne Sub angelegt wird.
      kann ich nicht, aber das ist ja das Problem. Ein return nimmt sich halt 2 bytes vom stack als Rücksprungadresse. Das wird auch gehen, nur ist das noch der stack, der vorher noch nie benutzt wurde? In welchem Speicherbereich ist jetzt der stackpointer (den Begriff wirst du kennen)?

      ichbinsmoin schrieb:

      gibt es einen Bascom Befehl, der den Stack löscht/ neutralisiert?
      Damit könnte ich mein vermurkstes Programm reparieren, ohne es völlig neu schreiben zu müssen.
      das geht nur, wenn du aus dem chip den stackbereich mit einem feinen Bohrer heraus bohrst. Ich geb's zu, ist schwierig a_15_a5ddcf85
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      aus dem chip den stackbereich mit einem feinen Bohrer heraus bohrst. Ich geb's zu, ist schwierig
      ungefähr hier
      stack.jpg
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • hasta schrieb:

      ich dachte immer "Auferstehung" ist erst an Himmelfahrt.
      ne, ist Ostern.

      tschoeatsch schrieb:

      das geht nur, wenn du aus dem chip den stackbereich mit einem feinen Bohrer heraus bohrst.
      .. muss aber 3-schneidig , Hartmetall und titanbeschichtet sein. rolling:

      Können wir wieder zum eigentlichen Thema kommen? Ich denke ,das Thema Goto versus Gosub ist
      hier schon mehrmals breit diskutiert worden. Es werden sich da keine neuen Erkenntnisse ergeben.
      Es ging ja wohl ursprünglich um das "komische" Verhalten einer Random Variablen.

      Detlef
      Leichtsinn ist kein Mut, Vorsicht keine Feigheit.
    • tschoeatsch schrieb:

      In welchem Speicherbereich ist jetzt der stackpointer (den Begriff wirst du kennen)?
      @hasta hat es noch mal bestätigt.
      Aber bitte erlaub mir noch die Frage „ wer startet die einzelnen Stackpointer“ . Nagut den Begriff kenne ich nicht in meiner Heimatsprache aber es könnte verdeutscht ein Zähler sein.
      Sollte ich dich nun richtig verstanden haben werden dieser einfach mal so gestartet. (Auch ohne Subaufruf)
      Der interne CPU ist eben nicht so ein Troll wie ich. Er macht alles so wie es mal so beschrieben wurde.
      Mal ein Register anders zu beschreiben oder abzufragen, dass nicht so im Datenblatt steht, ist hier Trollerei. Mal ein praktischen Versuch zu wagen wird schon im Ansatz verspottet.
      Ja @hasta ist schon schlimm für Dich meine Kommentare zu lesen, aber hast du nicht mal selber geschrieben, muss man nicht lesen?
    • fredred schrieb:

      Nagut den Begriff kenne ich nicht in meiner Heimatsprache aber es könnte verdeutscht ein Zähler sein.
      ich dachte, du kannst/kennst Assembler!? Der stackpointer ist ein Zeiger (Register), der auf den ersten freien Platz im stack zeigt. Ein gosub schreibt an der Stelle den 'programcounter' hin (Zeilennummer oder Adresse des Maschinen-Programmbefehls) und erhöht den stackpointer um 2. Jetzt zeigt der wieder auf den nächsten freien Platz im stack. Ein return liest den Stackpointer und weiß dadurch, die 2 bytes oberhalb diesen stackpointerwertes sind die Adresse des programmcounters, wo das letzte gosub stand. Auf diese Adresse wird jetzt der programmcounter gesetzt (jetzt steht er wieder auf dem gosub) und erhöht, damit der nächste Befehl nach dem gosub ausgeführt wird.
      Cable hat je eine deutsche Übersetzung des atmega hier gepostet, da wird der stackpointer mit Stapelzeiger übersetzt.

      7.5 Stapelzeiger
      Der Stapel (Stack) wird hauptsächlich benutzt, um temporäre oder lokale Daten zu speichern und um Rücksprungadressen bei der Ausführung von Interruptrouinen und Unterprogrammen zu sichern. Der Stapelzeiger zeigt immer auf die nächste freie Speicherstelle im Stapel. Der Stapel ist so aufgebaut, dass der von hohen Speicheradressen hin zu niedrigen wächst. Das bedeutet, dass beim Sichern eines Datenbytes in den Stapel (PUSH-Befehl) der Stapelzeiger dekrementiert wird.

      Der Stapelzeiger zeigt auf eine Speicherstelle im SRAM, diese muss durch das Programm zunächst bestimmt werden, bevor ein erstes Unterprogramm ausgeführt wird oder die Interrupts freigegeben werden. Der Initialisierunswert des Stapelzeigers entspricht der letzten RAM-Adresse. Der Zeiger muss stets größer als der RAM-Anfang sein, siehe Tabelle 8-3.
      Siehe folgende Tabelle für Details.

      Tabelle 7-1: Befehle mit Stapelzeiger

      BefehlStapelzeigerBeschreibung
      PUSHVermindert um 1Daten werden im Stapel abgelegt
      CALL
      ICALL
      RCALL
      Vermindert um 2Rückkehradresse wird bei Unterprogrammaufruf oder Interrupt im Stapel abgelegt
      POPErhöht um 1Daten werden vom Stapel abgeholt
      RET

      RETI
      Erhöht um 2Rückkehradresse wird vom Stapel abgeholt

      Der Stapelzeiger besteht aus zwei 8-Bit-Registern im I/O-Adressraum. Die Anzahl der Bits, die wirklich für die Adressierung verwendet werden, hängt von der Größe des zu adressierenden Speicherbereiches ab. In einigen AVR-Controllern ist der Speicherbereich so klein, dass nur das Low-Byte des Stapelzeigers verwendet wird. In diesen Fällen ist das High-Byte gar nicht implementiert.
      7.5.1 SPH und SPL
      SP15SP14SP13SP12SP11SP10SP9SP8SP7SP6SP5SP4SP3SP2SP1SP0
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      ich dachte, du kannst/kennst Assembler!?
      Ja das scheint mein Denkfehler zu sein.
      ASM ist doch ein direkter Zugriff auf Speicherzellen, dachte ich mal.
      Obwohl dein Hinweis es nun nochmals bestätigt.

      tschoeatsch schrieb:

      Der Stapel (Stack) wird hauptsächlich benutzt, um temporäre oder lokale Daten zu speichern und um Rücksprungadressen bei der Ausführung von Interruptrouinen und Unterprogrammen zu sichern.
      Na was passiert wenn ich keine Interruptrouinen oder Unterprogrammen sichern möchte?
      Muss ich zwingend Speicher für Stack reservieren?
      Muss ich ein nicht angelegten Stackbereich verwalten?
      Naja gebe hier auf. Wer am Boden liegt verschwendet noch mehr Energie beim strampeln.
    • fredred schrieb:

      Muss ich zwingend Speicher für Stack reservieren?
      Nö, nur wenn du ihn brauchst. Ein Blinkprogramm kann ohne ihn auskommen. (glaub' ich)
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Übrigens kann man den Stack auch sehr gut mit Büroarbeit vergleichen.
      Auf dem Schreibtisch liegt ein Stapel Papier der abgearbeitet werden muss. Man ist an irgend einer Stelle im Stapel angekommen und plötzlich kommt der Chef und legt einen neuen Stapel auf den in Bearbeitung befindlichen Stapel (ein Gosub). Wenn der neue Stapel dann abgearbeitet ist kommt man wieder zum alten (ein Return) zurück.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.