Hello, Guest the thread was called3.5k times and contains 109 replays

last post from Endurion at the

Vorherige BASIC Zeile finden

  • Hallo, nach langer Zeit habe ich weiter an BASIC 4.5 gearbeitet und an meiner "Hassliebe" den BASIC Zeilen Scrolleditor.
    Ich suche nach einer Routine, wie ich ausgehend von einer aktuellen BASIC Zeile ($14/$15) die vorhergehende Zeile finde.

    Die nächste Zeile zu finden ist recht simpel, steht ja jeweils in der Zeile drin. Aber leider nicht die vorhergehende Zeile.


    Zum Beispiel:

    1090 REM MEIN PROG

    2010 PRINT "HALLO"

    3900 PRINT "DU DA."

    4000 END


    Aktuell steht der Pointer auf Zeile 3900. In $14/$15 steht also 0F3C. Jetzt muss ich aber $14/$15 mit der Zeile 2010 bestücken. Wie zum Teufel finde ich die Zeilennummer heraus. Die kann ja alles mögliche sein.

    Ich habe da voll den Blackout und brauche ein paar ideen. Wer kann mir weiterhelfen?


    Danke, Danke, Danke!

  • Die langsame (aber sichere) Variante wäre, dass du an den BASIC Anfang gehst und die Pointer durchläufst, bis du den findest der auf deine gewünschte Zeile zeigt.

    Theoretisch könntest du auch rückwärts suchen, aber ich denke es könnte passieren dass zufällige Werte dann vorhanden sein könnten die so aussehen als wenn sie auf die Zeile zeigen würden obwohl sie vielleicht nur Teil eines BASIC Befehls sind.

  • Die langsame (aber sichere) Variante wäre, dass du an den BASIC Anfang gehst und die Pointer durchläufst, bis du den findest der auf deine gewünschte Zeile zeigt.

    Theoretisch könntest du auch rückwärts suchen, aber ich denke es könnte passieren dass zufällige Werte dann vorhanden sein könnten die so aussehen als wenn sie auf die Zeile zeigen würden obwohl sie vielleicht nur Teil eines BASIC Befehls sind.

    Das ist nicht wirklich ein Problem. Das der Interpreter bei Rückwärtsverweisen von Vorne beginnt, liegt nur daran, da dass die Suche schneller geht, weil ja mit dem Linkzeiger auf die nächste Zeile springen kann, was das sequenzielle Suche des gesamten BASIC-Textes erspart.
    Wenn man aber genau die vorige Zeile braucht, dann orientiert man sich einfach an 0, die jede Zeile abschließt. Eine 0 darf nicht in einer Zeile sonst wie vorkommen (könnte schon vorkommen, aber dann ist es keine legale BASIC-Syntax).
    Von der aktuellen Zeile -1 Byte zurück sollte die abschließende 0 der vorigen Zeile stehen, dann hantelt man sich zur nächsten davor liegenden 0, 1+ und man hat den Anfang der vorigen Zeile. ;)

  • dann hantelt man sich zur nächsten davor liegenden 0, 1+

    Klingt gefährlich. 0 ist zwar in der Zeile verboten, aber als Zeilennummer oder Linkpointer kann die vorkommen.

    Richtig, kriegt man aber aus dem Kontext raus. Wenn man annimmt, das es die Ende-0 ist, dann hat man die 2 Bytes danach den Link-Pointer und vergleicht, ob das auf den Anfang der Folgezeile zeigt, wenn nicht geht man 1 Byte zurück (dann war man am Low-Byte des Link-Pointers, das High-Byte kann eigentlich nicht 0 sein).

  • Ich glaub, das ist noch komplizierter. Die erste Null, die man findet, kann eines von 2 Bytes der Zeilennummer, das Low-Byte des Linkpointers oder das gesuchte Nullbyte sein.

    Ich bin nicht sicher, ob man das nicht aufs Kreuz legen kann:


    00 <== das Gesuchte

    a <== Lo-Byte des Pointers

    b <== Hi-Byte des Pointers

    c <== Lo-Byte der Zeilennummer

    d <== Hi-Byte der Zeilennummer

    ee <== erste Befehle


    a, c und d können 0 sein.

    a=0: Könnten bc zufälligerweise dem Pointer entsprechen?

    c=0: ...de...

    d=0: ...ee...


    Ich denke, das könnte in die Hose gehen.

  • JeeK so was ähnliches schrub ich vor 2 Monaten ..

    Man könnte rückwärts bis zum vorletzten Zeilenterminator parsen und den darauffolgenden Adresseintrag anhand der gegebenen Adresse überprüfen.; muss man aber selbst coden.

    Hab aber auch noch mal überlegt, und es sind Konstellationen denkbar, wo es nicht funktioniert. Bsp.:


    [...] 00

    $207a: 86 20 fa 00 86 20 41 28 32 30 29 00

    $2086: [...]


    Die gesuchte Zeilennummer ist 250 [$00fa]. Die Zeile, von der aus wir suchen, beginnt bei $2086. In Zeile 250 steht DIM A(20) [86 20 41 28 32 30 29].


    ---

    Es wäre wohl wirklich das sicherste, von oben bis zur aktuellen Zeile zu hangeln und unterwegs die jeweils letzte Zeilenadresse zu merken.

  • Hab aber auch noch mal überlegt, und es sind Konstellationen denkbar, wo es nicht funktioniert.

    Man könnte es vielleicht retten, indem man die Zeile nur akzeptiert, wenn man noch eine Zeile "davor" mit einer Referenz auf diese findet (oder es die erste Zeile ist).

    Natürlich kann man auch da noch Fälle konstruieren, wo es schiefgehen könnte, aber das wäre schon eine recht ordentliche Heuristik, denke ich.


    Falls es nicht reicht, kann man ja auch 2 oder 3 Zeilen davor fordern...

  • Gutes Beispiel. Vielleicht bleibt es eine Heuristik, aber mit weiteren Tests könnte man das sicherer (wenn auch nicht absolut sicher - ich bin mal vorsichtig in den Voraussagen) gestalten.


    1. Wenn man einen Kandidaten hat, wo auch die Link-Adresse passt, dann die Zeilennummer kontrollieren. Wenn sie >= der aktuellen ist, dann verwerfen und weiter zurück gehen. Also hier müsste Zeile $2841 kleiner sein.

    2. Generell auf die weitest zurückliegende Sequenz <00> <link-low> <link-high> gehen. Es reicht wenn man hier max 256 Byte zurückgeht oder max. 4 Nuller (ab der ersten gefundenen 0) betrachtet, je nach dem was früher eintritt.


    Während 1) nur ein Verwerfungskriterium ist, könnte 2) schon ziemlich sicher sein (also mit einer sehr hohen Wahrscheinlichkeit einen Irrtum ausschließen). Da kann ich mir vorstellen, dass selbst das Konstruieren eines Gegenbeispiels schon schwierig wird und selbst wenn, wird es wohl eher unwahrscheinlich in der Wildnis zu finden sein.

  • Ich weiß ja, wo die nächste Zeile anfängt. Also suche ich von dort rückwärts, bis ich auf die Bytefolge "0", "LOW-nächste-Zeile", "HIGH-nächste-Zeile" treffe. Die Speicheradresse "LOW-nächste-Zeile" ist der Anfang der aktuellen Zeile - also suche ich von dort rückwärts, bis ich "0", "LOW-aktuelle-Zeile", "HIGH-aktuelle-Zeile" finde.

    Die Speicherstelle von "LOW-aktuelle-Zeile" ist dann der Anfang der vorherigen Zeile.


    Edit: Sorry, zu früh abgeschickt - das Spielchen muss man natürlich noch eine Iteration weiter machen: um sicherzustellen, dass auf den gerade gefunden Anfang der vorherigen Zeile eine andere Zeile verlinkt (oder dass wir bereits den Basic-Anfang erreicht haben)

  • Kann man sich nicht die Eigenschaft zunutze machen, dass jede Basic-Zeile entweder mit einem Basic-Befehl (Token > $80) oder einem Doppelpunkt anfängt?


    Arndt

    Da LET obligatorisch ist, kann eine Zeile auch mit A-Z beginnen (Variablenname erstes Zeichen).
    Im Prinzip ja, aber das würde voraussetzen, dass die Syntax des Programms korrekt ist.

  • Ich weiß ja, wo die nächste Zeile anfängt. Also suche ich von dort rückwärts, bis ich auf die Bytefolge "0", "LOW-nächste-Zeile", "HIGH-nächste-Zeile" treffe. Die Speicheradresse "LOW-nächste-Zeile" ist der Anfang der aktuellen Zeile - also suche ich von dort rückwärts, bis ich "0", "LOW-aktuelle-Zeile", "HIGH-aktuelle-Zeile" finde.

    Die Speicherstelle von "LOW-aktuelle-Zeile" ist dann der Anfang der vorherigen Zeile.

    Tja, bitte die Postings davor genauer durchlesen. Da waren wir schon. ;)

  • Tja, bitte die Postings davor genauer durchlesen. Da waren wir schon. ;)

    Naja, nicht wirklich. Wenn du jedes Mal auf "NULL" + zwei Link Bytes testest, wie groß ist die Wahrscheinlichkeit dass das zwei Mal hintereinander einen False Positive ergibt?


    Edit, ah sorry - ist schon spät... Einfach noch eine Zeile weiter testen, dann hat man die Doppelprüfung, auf die ich raus wollte.

  • Kann man sich nicht die Eigenschaft zunutze machen, dass jede Basic-Zeile entweder mit einem Basic-Befehl (Token > $80) oder einem Doppelpunkt anfängt?

    Variablen sind auch noch drin, und natürlich Quatsch-Programme.

    Ich weiß ja, wo die nächste Zeile anfängt. Also suche ich von dort rückwärts, bis ich auf die Bytefolge "0", "LOW-nächste-Zeile", "HIGH-nächste-Zeile" treffe.

    Ja, praktisch sucht man eine Folge dieser 3 Bytes in den 256(?) Bytes vor der aktuellen Zeile. Aber es ist halt nicht 100%ig ausgeschlossen, dass man die 2mal findet, das Beispiel von Atomcode. Dann müsste man das Spielchen mit beiden Treffern wiederholen, wobei die gleiche Situation wieder auftreten kann usw.


    Klingt zwar praktisch enorm unwahrscheinlich, aber irgendwann kommt es zum Bug, und wenn es über 20 Jahre dauert.

  • Da LET obligatorisch ist, kann eine Zeile auch mit A-Z beginnen

    Ah ja, stimmt ja. :platsch: (du meintest aber "obsolet", oder?)


    Und wenn man nicht $00, sondern den Vektor auf die aktuelle Zeile sucht? Also, die aktuelle Zeile fängt zum Beispiel an $08ef an, dann rückwärts nach $ef $08 suchen? Dann zur Sicherheit die $00 mitchecken?


    Arndt

  • Ja, praktisch sucht man eine Folge dieser 3 Bytes in den 256(?) Bytes vor der aktuellen Zeile. Aber es ist halt nicht 100%ig ausgeschlossen, dass man die 2mal findet, das Beispiel von Atomcode. Dann müsste man das Spielchen mit beiden Treffern wiederholen, wobei die gleiche Situation wieder auftreten kann usw.

    Nein, deswegen schrieb ich ja, dass man nach 3 maximal gefundenen Nullen aufhören könnte. Es können vor dem echten Zeilenende nur höchstens 3 Nullen existieren (Fall 7).

    Das wären meiner Meinung nach die möglichen Konstellationen, wie die Nullen auftreten können. Die erste Null ist das wirkliche Zeilenende der vorvorigen Zeile.

    Fall 1: 0 <link-low> <link-high> <line-low> 0 <basic code> 0

    Fall 2: 0 <link-low> <link-high> 0 <line-high> <basic code> 0

    Fall 3: 0 <link-low> <link-high> 0 0 <basic code> 0

    Fall 4: 0 0 <link-high> <line-low> <line-high> <basic code> 0

    Fall 5: 0 0 <link-high> <line-low> 0 <basic code> 0

    Fall 6: 0 0 <link-high> 0 <line-high> <basic code> 0

    Fall 7: 0 0 <link-high> 0 0 <basic code> 0


    Wenn man also von <basic code> kommend rückwärts auf die erste 0 stößt, betrachtet man weitere Nullen, braucht aber ab dann nur maximal 4 Bytes weiter zurück gehen. Wenn dann spätestens dort nicht 0 + Link-Adresse zu finden ist, dann muss der zuletzt gefundene Kandidat der echte Zeilenanfang sein. Andernfalls stimmt der Zeilenaufbau an sich nicht.
    In diesen Konstellationen kann es auch keine davor liegende Zeile mit korrektem Aufbau sein.


    Vielleicht hab ich ja was übersehen, was meint ihr?