Hello, Guest the thread was called2.1k times and contains 24 replays

last post from dg5kr at the

Hilfe bei BASIC Erweiterung: FIND [BEFEHL|TEXT]

  • Ich würde gerne für meine neue BASIC Erweiterung den Befehl

    FIND "TEXT" bzw. FIND "BEFEHL" verwirklichen.

    Der Befehl FIND soll aus dem BASIC Listing gefundene Texte oder Textteile oder Befele mit Zeilennummer auflisten.

    Ich finde aber so rechte keinen Ansatz wie ich das hin kriege.


    Hat jemand eine Idee oder ein Programm Beispiel??

  • dg5kr

    Changed the title of the thread from “Hilefe bei BASIC Erweiterung: FIND [BEFEHL|TEXT]” to “Hilfe bei BASIC Erweiterung: FIND [BEFEHL|TEXT]”.
  • Moin,


    letztlich weißt Du ja über die Zeropage den Bereich des Basiclisting, sprich den Teil den Du durchsuchen musst.

    Endweder nach dem Basic-Token oder dem Text den du suchst.


    Der schwierige Teil dürfte wohl die Analyze des Suchstrings sein - sprich wird jetzt ein Befehl gesucht oder nur Text, oder sogar beides.


    Da die Basiczeile im Speicher nach diesem Format aufgebaut ist, bekommst Du auch die Zeilennummer raus:

    ($0801 mal als Basic-Start gesetzt)



    Ein .byte $00, $00 bedeutet dass das Basiclisting dort zu Ende ist.


    Schau auch hier:

    https://www.c64-wiki.de/wiki/Speicherbelegung_(BASIC)

    http://www.retrointernals.org/basic/basic.html


    Gruß

    Thomas

  • Hallo, grundsätzlich müßte der FIND-Befehl so ähnlich arbeiten, wie der READ-DATA Befehl.

    Außer daß kein DATA-Befehl gesucht wird, sondern eben der gesuchte String.

    Ich hatte da ja mal ein GOTO-LABEL/DATA gepostet, daß darauf basierte erst einen DATA Zeichenkette zu suchen und dann an die gefundene Adresse zu verzweigen.

    Schönen Gruß.

  • In Simons' Basic gibt es genau einen solchen "FIND"-Befehl... Vielleicht kann man analysieren, wie das gemacht worden ist.


    Edit Demnach müsste das ja auch in dem Simons' Basic Nachbau TSB zu finden sein: https://github.com/godot64/TSB - und davon gibt es Quelltext.

  • Das Help Plus Modul von Print-Technik hat auch das Kommando #F mit einer Find-Funktion. Es wird dabei alles was nach #F kommt wie eine Eingabezeile umgesetzt (da läuft ja der Tokenizer drüber) und das Fragment wird dann in allen Zeilen gesucht - also ein PRINT sucht nach dem Token für PRINT, aber an PRIN nur nach einer Variablen namens PRIN. Es wird aber nicht innerhalb von String-Konstanten gesucht. Dafür muss man explizit den Suchausdruck mit " beginnen lassen, dann passiert eine Teilstringsuche nur in String-Konstanten.

    Hab ein bisschen über den Code drüber geschaut, schaut mir nicht spektakulär aus. Siehe $833a falls du die Erweiterung bei der Hand hast, sonst einfach eine PM.

  • Zu aller erst: Vielen Dank an die helfenden Hände. Das sind mehr Ideen als ich auf einmal verarbeiten kann. Aber alle hören sich gut an.


    Ich habe mir bereits ein paar Vorgedanken zum Thema Befehl vs. Stringtext gemacht. Um beispielsweise nach dem String PRINT zu suchen nutze ich die " Zeichen, also FIND "PRINT". Damit würde ich den Befehl veranlassen die alle HEX Zeichen (also BASIC Token) als STRING zu betrachten.

    Mit FIND PRINT würden dann alle HEX Zeichen als Token angesehen, ABER: Nur der HEX Code NACH einer Zeilennummer oder nach einem : wird betrachtet. Alle anderen Hex Code würden ignoriert.


    Soweit die Vorgedanken. Daraus ergeben sich dann konkrete Fragen.

    1. Wenn ich den BASIC Speicher abscanne, wie erkenne ich das es sich um eine 16Bit Zeilennummer handelt?

    2. Wie erkenne ich das Ende der BASIC Zeile?

    3. Wenn ich einen String/Token gefunden habe, wie hole ich mir die Zeilennummer dazu? (Zeilennummer bei Beginn erfassen und speichern?)

    4. Wenn ich das Token gefunden habe, wie nutze ich den "Klartexter" um daraus einen befehl zu machen.


    Wenn ich auf den richtigen Holzweg bin, dann ist ein BASIC Programm so aufgebaut:

    $0801 Lo Hi (Adresse der nächsten Zeile, verweist hier auf Adresse $080x+1)

    $0803 Lo Hi (16 Bit Zeilenummer)

    $0805 Token + Text oder Parameter

    $080x byte $00 (Abschluss der BASIC Zeile)

    $080x+1 nächste Zeile nach dem gleichen Schema


    Ist das richtig so?

  • Demnach müsste das ja auch in dem Simons' Basic Nachbau TSB zu finden sein: https://github.com/godot64/TSB

    Ganz recht und zwar in Part 4 an Adresse $a594 (Einsprung), fängt aber schon an $a553 (label TOFIND) an (Finden des Gesuchten und Ausgabe der Zeilennummern). Der Code ist an dieser Stelle leider nicht besonders kommentiert, da ich das SB-Original hier nicht groß verändert habe. Der Code für FIND geht von $a553 bis $a5f8.


    Arndt

  • Demnach müsste das ja auch in dem Simons' Basic Nachbau TSB zu finden sein: https://github.com/godot64/TSB

    Ganz recht und zwar in Part 4 an Adresse $a594 (Einsprung), fängt aber schon an $a553 (label TOFIND) an (Finden des Gesuchten und Ausgabe der Zeilennummern). Der Code ist an dieser Stelle leider nicht besonders kommentiert, da ich das SB-Original hier nicht groß verändert habe. Der Code für FIND geht von $a553 bis $a5f8.


    Arndt

    Oh, das ist aber schon mehr als ich erwartet habe. Ich werde mir den Code mal genauer ansehen. Vielen Dank!

  • Soweit die Vorgedanken. Daraus ergeben sich dann konkrete Fragen.

    1. Wenn ich den BASIC Speicher abscanne, wie erkenne ich das es sich um eine 16Bit Zeilennummer handelt?

    2. Wie erkenne ich das Ende der BASIC Zeile?

    3. Wenn ich einen String/Token gefunden habe, wie hole ich mir die Zeilennummer dazu? (Zeilennummer bei Beginn erfassen und speichern?)

    Lass einen ZP-Zeiger auf das erste Byte der Zeile zeigen, also auf das Lowbyte des Links. Dieser Zeiger wandert dann von Zeile zu Zeile, zeigt dort aber immer auf den Anfang. Dann findet man mit Y=0/1 immer den Link auf die nächste Zeile und mit Y=2/3 immer die Zeilennummer.

    Gescannt wird die Zeile dann durch Hochzählen von Y, das Ende der Zeile erkennt man am Wert Null.

    Sicherheitshalber sollte man auch auf einen Überlauf von Y prüfen, falls das Programm extern erstellt wurde und überlange Zeilen hat...

  • Du schreibst von Hexzahlen (was sich etwas verwirrend liest), die da gelesen werden sollen usw., aber meinst die gelesenen Bytes des Programmtextes. Ein Hexzahl hat an sich keinen Bezug auf eine Speicherstelle, sondern sagt nur über die Zahlendarstellung einer Zahl aus (welchen Werteumfang die damit hat, ist nicht gesagt). Dass solche eine Darstellung in einem Monitor als Hexzahl aufscheint, dient da einfach nur der einfacheren/übersichtlicheren Darstellung eines Speicherinhalts. Es kann ja parallel auch als Character dargestellt sein (wenn es etwas Anzeigbares ist). Also ich würde diese Begrifflichkeiten nicht so vermischen. ;)


    Wenn ich den BASIC Speicher abscanne, wie erkenne ich das es sich um eine 16Bit Zeilennummer handelt?

    Das hat MacBacon ja bereits abgehandelt, vielleicht nur noch ein paar Details ergänzt:

    Wie erkenne ich das Ende der BASIC Zeile?

    An einer 0. Wenn danach der Link 0/0 hat ist auch das Programm zu Ende.

    Wenn ich einen String/Token gefunden habe, wie hole ich mir die Zeilennummer dazu? (Zeilennummer bei Beginn erfassen und speichern?)

    Wie MacBacon schrieb, mit Index 2/3 in Y. Die Zahl dann einfach mit der Interpreterroutine 16-Bit-Zahl ausgeben mit $BDDD (eine der wenigen Adressen die mir wirklich auswendig merke). ;)

    Ist das richtig so?

    Auf den ersten Blick ja.

  • Hallo Johann (Jeek), danke für die erklärenden Worte. Ja du hast recht.“HEXZAHL“ war was blöd ausgedrückt. Natürlich weiß was das das eine der das Andere ist. Ob du es glaubst oder nicht, ich habe im Studium nicht nur Zahlen Basen umgewandelt, nee ich durfte dort auch die Rechengesetze wie Binome anwenden :thumbsup:.

    Es waren für mich die passenden Worte, weil ich das Programm „BASIC 3,5“ von Michael Schimek nicht im Sourcecode habe. Also habe ich mir das Programm erstmal als

    !byte Zeilen in ACME kompatiblen Assembler code umgewandelt. Somit war ich schon mal in der Lage die !byte Zeilen (das sind meine „HEXZAHLEN“) zu kompilieren. Dann habe ich mir wichtige Stellen für Vectoren, F-Tasten Vorbelegung usw. durch Disassemblierung raus gesucht und habe dann einen Memnonischen Assebler Code daraus gemacht.


    Alles klar soweit??( Oder hab ich wieder Unsinn gefaselt:P...

  • Nun aber zu meinem „FIND“ Befehl. Aus dem TSB (Tuned Simons Basic) habe ich mir den Source raus gefummelt und es lief. Aber um ehrlich zu sein hats mich nicht so richtig befriedigt. Also habe ich mein FIND.ASM wieder geleert und habe angefangen mir doch sleber Gedanken zu machen. Ich bin zu, sagen wir mal 60% damit fertig. Aber dafür ist es ne Eigenleistung. Trotzdem schaue ich immer wieder mal nach Rechts und nach Links wie es andere gemacht haben.

    Wie heißt es so schon: To be continue....

  • Aber um ehrlich zu sein hats mich nicht so richtig befriedigt.

    Hehe… mich auch nicht. FIND zeigt immerhin die Zeilennummern (aber nicht die Zeile selbst), in denen der Suchbegriff zu finden ist. Da der Begriff direkt an das Befehlswort FIND angeheftet werden muss und dabei die Tokenisierung zuschlägt, muss man sich genau überlegen, was man für die Suche eingibt, um auch wirklich fündig zu werden. Und Großbuchstaben in Strings sind das zweite Problem, die werden nur erkannt, wenn du das Anführungszeichen als erstes setzt, wobei dann aber alle Zeichen bis zum Großbuchstaben ebenfalls gesetzt werden müssen. Es müsste so eine Art Schalter für den Befehl geben, der sagt, dass man jetzt in Strings suchen will.


    Arndt

  • Hi Arndt, im TSB Code habe ich zumindest in der Tokenerkennung ein SPACE reingemacht. Also die saubere Trennung zwischen Befehl und Parameter.

    Trotzdem fand ich es "moderner" alles ohne " als Befehl zu suchen (also Token) und alles in " " wird als String gesucht. Deshalb meine "eigene" Suche.

  • :gluck H I L F E


    So und nun haben wir den Mist. Ich habe einen Fehler den ich nicht finden kann. Liebe "Supercode" bitte helft mir.
    Ich habe irgendwo was "eingebaut" was zum Absturz führt, also der absolute GAU.

    Der Fehler ist 100% reproduzierbar:

    Ladet und startet das im Anhang gelegte BASIC45.PRG. gebt einen zwei Zeiler ein:

    10 REM

    20 ? "GAU"

    startet das Ganze und prima, läuft. Nun editiert ihr z.B. Zeile 10 und ersetzt REM durch irgend einen anderen Befehl, z.B. SCNCLR

    und Bumm, das wars.

    HHHHIILLLFFFEEEE !!!!! :cry:


    Ich vermute das Problem i meinen modifizieren RUN-Befehl. Aber wo ???

  • startet das Ganze und prima, läuft. Nun editiert ihr z.B. Zeile 10 und ersetzt REM durch irgend einen anderen Befehl, z.B. SCNCLR

    und Bumm, das wars.

    Ok, konnte ich nachvollziehen. Ich hab ein anderes Programm probiert. Dabei ist mir schon mal komisch vorgekommen, dass I=I+1 so ein Fehler entsteht und bei der Ausgabe die Zahlen invers dargestellt werden?


    Dann wollte ich das Programm erweitern und es kam zu besagten Crash. Der Schirm wird wirr mit Zeichen vollgeschrieben:

    Kann es sein, dass beim Einfügen der Programmzeile und dem entsprechenden Blockverschieben, das Ende nicht richtig gesetzt ist (Zeiger vertauscht, Rollover, ...), also irgendwie der Code der BASIC Erweiterung überschrieben wird. Schau mal im VICE monitor, ob beim Crash noch alles an den Adressen steht, wo es sein soll.


    Im VICE zeigt mir der Monitor folgenden crash-after-do-loop.txt: Schaut mir sehr nach einem Stack-Überlauf aus, als würde hier nicht aufgeräumt werden ... für ein Einfügen einer Zeile ist mir da zu viel von der Formelauswertung am Stack. =O




    Hast du Revisionen angelegt, damit man die Unterschiede nachvollziehen kann bzw. zu einer Version zurück gehen kann, wo das Problem noch nicht da war?

  • und alles in " " wird als String gesucht

    Dann kannst du natürlich nicht die Anführungszeichen selbst suchen (also Stellen, bei denen das Anführungszeichen - vorne oder hinten - eine Rolle spielt).


    Arndt

    Man könnte ja die Logik einbauen, dass ein doppeltes Anführungszeichen das Anführungszeichen selbst als Suchbegriff bedeutet. Zum Beispiel also

    FIND"" "" sucht nach " "

    oder wenn das " innnerhalb des Strings sein soll:

    FIND "="" "" sucht nach =" ", wobei das ein schließendes " hier einfach weggelassen wird.

    Ich hätte da 2 Ansätze:

    Konzeptuell könnte man sagen, dass ein Doppel-" immer ein " im Suchstring repräsentiert und mit einem beginnenden " (egal ob einzeln - dann ist es ein Delemiter, doppelt ein " im Suchstring selbt) die Klartext-String-Suche gemeint ist. Wenn man strikt ist, müsste man dann die obigen Beispiele dann vielleicht so schreiben:

    FIND """ """

    oder

    FIND "="" """

    Der andere Ansatz wäre, ein Initiales " nur als Einstieg in die Klartextsuche zu nehmen, das verwirft man und alles was dann kommt wird 1:1 als Suchtext genommen, auch wenn noch weitere " angeben sind. Die Zeile kann dann einfach enden. Nur wenn am Zeilenende ein " ist, dann wird dieses als schließende Klammer für den Suchstring angesehen und nicht als Such-String-Bestandteil gesehen. Dann sieht das so aus:

    FIND "" " bzw. FIND "" ""

    oder

    FIND "=" " bzw. FIND "=" ""

    Wenn man die Sequenz =" ": sucht, dann FIND "=" ":"

  • Kann es sein, dass beim Einfügen der Programmzeile und dem entsprechenden Blockverschieben, das Ende nicht richtig gesetzt ist (Zeiger vertauscht, Rollover, ...), also irgendwie der Code der BASIC Erweiterung überschrieben wird. Schau mal im VICE monitor, ob beim Crash noch alles an den Adressen steht, wo es sein soll.

    Ich hab einen Breakpoint bei $caea gesetzt, so ich die Eingabe der neu einzufügenden Zeile zeichenweise durchgehe, dann zum Kopieren in den Eingabepuffer $0200 komme und schließlich über die Restore-Routine dann auch hier her:

    (C:$a667) z

    .C:a669 84 34 STY $34 - A:FF X:03 Y:7F SP:f8 ..-....C 134066643

    (C:$a669) z

    .C:a66b A5 2D LDA $2D - A:FF X:03 Y:7F SP:f8 ..-....C 134066646

    (C:$a66b) z

    .C:a66d A4 2E LDY $2E - A:C7 X:03 Y:7F SP:f8 N.-....C 134066649

    (C:$a66d) z

    .C:a66f 85 2F STA $2F - A:C7 X:03 Y:00 SP:f8 ..-...ZC 134066652

    (C:$a66f) z

    .C:a671 84 30 STY $30 - A:C7 X:03 Y:00 SP:f8 ..-...ZC 134066655

    (C:$a671) z

    .C:a673 85 31 STA $31 - A:C7 X:03 Y:00 SP:f8 ..-...ZC 134066658

    (C:$a673) z

    .C:a675 84 32 STY $32 - A:C7 X:03 Y:00 SP:f8 ..-...ZC 134066661

    (C:$a675) z

    .C:a677 20 1D A8 JSR $A81D - A:C7 X:03 Y:00 SP:f8 ..-...ZC 134066664

    (C:$a677) m 2b 2f

    >C:002b 01 10 c7 00 c7 .....

    (C:$0030)

    Das Ende des Basic-Programmtextes ist bei $00C7 ... das nimmt dann glaub ich kein gutes Ende ... :/