Hello, Guest the thread was called2k times and contains 50 replays

last post from JeeK at the

Variablenwert aus Basic durch Poke verändern

  • Wird sie nicht, sondern nur die Adresse der Variable a$ (Name inkl. Typ, Länge, Textzeiger), nicht ihres Inhalts.

    Ja, jetzt hab' ich das auch begriffen.


    Danach kommt der Text-Zeiger, der auf den Text zeigt, der am Ende des BASIC-Speichers liegt. Diesen Zeiger, den man nach Gebrauch der Variablen auch in der Zeropage findet, muss man wiederum für die Manipulation des Strings selbst benutzen.

    Das kann ich dann theoretisch nutzen - hab eben mal durchprobiert.

    Ob das am Ende noch Sinn macht...

    Diesen Zeiger, den man nach Gebrauch der Variablen auch in der Zeropage findet, muss man wiederum für die Manipulation des Strings selbst benutzen.

    Direkt? Hab' ich nicht gefunden.


    Print ist trotzdem nötig, klar. Aber die Änderung des Strings erfolgt bei Änderung einer Einstellung, d. h. ich muss das nicht bei jedem Print prüfen und zusammensetzen - so die Idee dahinter.


    Das macht man normalerweise eigentlich so:

    z.B.

    a$="test test test":
    print"[weiß]"a$"[rot]"a$

    Schon klar. Und wenn jetzt der zweite Buchstabe vom zweiten Test rot gefärbt wird und das dritte test von normal auf revers wechselt und das erste in Hintergrundfarbe (gar nicht) angezeigt wird, dann steht da sowas wie print"[hintergrundfarbe]";left$(a$,5);mid$(a$,6,1);"[rot]";mid$(a$,7,1);"[normalfarbe]";mid$(8,3);"[rvson]";right$(4)...

    Wenn der eigentliche String aber z.B. so aussieht:


    a$="[RVSOFF][standardfarbe]test[RVSOFF][standardfarbe] [RVSOFF][standardfarbe]t[standardfarbe]e[standardfarbe]st[RVSOFF][standardfarbe] [RVSOFF][standardfarbe]test[RVSOFF][standardfarbe]"

    dann schreibt man eben an die Stelle des erstendes Standardfarbe die Hintergrundfarbe, anstelle des dritten [standardfarbe] ein 28 für rot und an stelle des 5. RVSOFF ein RVSON.

    Und das macht man dann, wenn die Änderung stattfindet und gibt es nur noch aus.


    So der Gedanke dahinter.


    (Nagelt mich jetzt nicht auf die korrekte Syntax fest)

  • Frage am Rande:
    Wenn die Strings selber im Bereich ab $c000 liegen und dann eine GC passiert, wie verhält die sich dann? Ignoriert sie Strings außerhalb des Stringspeichers auch, wenn sie oberhalb liegen?

    Muss sie das nicht schon deshalb tun, damit der Normalfall funktioniert? Es wird doch immer der String mit der höchsten Adresse im unaufgeräumten Bereich gesucht, dieser dann nach ganz oben verschoben, und dann das Ende des unaufgeräumten Bereichs heruntergesetzt. Strings über $c000 sehen bei der GC dann also schon von Anfang an so aus, als seien sie schon aufgeräumt.

  • Mit der String-Adressformel kann man natürlilch alles ausprobieren.


    Die String-Programmierung erschließt natürlich ein weites Feld für fortgeschrittene Programmierer.

    Wie z.B. die Vermeidung der GBC durch speicheroptimierte Programmierung.

    z.B. durch Lesen von Eingabepuffer und Ausgabepuffer.

    Ist aber natürlich auch für Maschinensprache interessant, da man nun mit Strings Maschinencode lesen, zusammensetzen und ausführen kann.


    z.B. :a$=chr$(96):sys s:


    Schönen Gruß.

  • Naja und wie gesagt macht das auch den Weg zu unwartbarem unflexiblem nicht mehr kompilierbarem Code frei - aber ist natürlich schöne Spielerei/Hackerei, gar keine Frage.


    Garbage Collection würde ich durch Einbinden einer besseren GC-Routine beheben (da gibt's ja nun genug Auswahl) oder durch Kompilieren mit Basic Boss oder MOSpeed oder schlicht durch Vermeidung von übermäßig String-Frickelei (speziell dieses "ich habe Angst vor Arrays und nutze stattdessen Unmengen von MID$"-Verhalten). Ist IMHO alles besser als POKE/PEEK-Tricks.

  • ...Es wird doch immer der String mit der höchsten Adresse im unaufgeräumten Bereich gesucht, dieser dann nach ganz oben verschoben, und dann das Ende des unaufgeräumten Bereichs heruntergesetzt. Strings über $c000 sehen bei der GC dann also schon von Anfang an so aus, als seien sie schon aufgeräumt.

    Sieht nach einer sinnvollen Umsetzung aus, wird dann wohl so sein. Hätte aber auch was von "Suche den höchsten String und schiebe ihn ans Ende" drin sein können. Ich hab mich jedenfalls daran erinnert, dass Strings innerhalb des Programms ein extra abgefragter Sonderfall sind,

  • Stringpointer auf Daten innerhalb des Programmcodes werden auch ignoriert, klar, schließlich liegen alle String-Konstanten (A$="BLA") dort und sogar auch alle per READ gelesenen Konstanten (READ A$:DATA"BLA"). Bei letzterem war ich ja etwas baff, bei MS wäre ich davon ausgegangen, dass dabei stumpf eine Kopie im Speicher angelegt wird. ;)

  • Die Screen-Texte mit den unterschiedlichen Farben sind ja auch Konstanten. Das hieße doch, dass man deren Adressen gar nicht erst umständlich ermitteln müsste, sondern einfach bei der Initialisierung die gewünschten Stellen im Programmtext bePOKEn könnte, also eine Selbstmodifikation durchführt. Dann bräuchte man nicht einmal Variablen dafür, sondern könnte das direkt in dem PRINT-Text machen.


    Nachteil: Bei jeder Programmänderung vor dem PRINT-Text verschiebt sich das. Man könnte den Text aber in einer Subroutine ganz ans Ende des Programms legen, wo er (im Programm) eh am besten aufgehoben ist. Dann die Adresse des Programm-Endes aus der ZP auslesen und die Länge der Ausgaberoutine subtrahieren, um ihre Basisadresse zu erhalten; die Offsets für die POKEs bleiben gleich.


    Oder, man legt den Text nach $C000-$D000 und gibt den mit etwas Asm-Code aus. Das nähme nichts vom BASIC-Speicher.

  • Sieht nach einer sinnvollen Umsetzung aus, wird dann wohl so sein. Hätte aber auch was von "Suche den höchsten String und schiebe ihn ans Ende" drin sein können. Ich hab mich jedenfalls daran erinnert, dass Strings innerhalb des Programms ein extra abgefragter Sonderfall sind,

    Das ist genau genommen kein Sonderfall, sondern es werden einfach nur jene Strings am (unaufgeräumten) String-Heap betrachtet und dieser zusammenhängender Bereich beginnt unmittelbar nach den Arrays bis zum nach unten wandernden Heap-Pointer (der währende der GC die Grenze darstellt, bei der die "unaufgeräumten darunter, die aufgeräumten darüber liegen). Alles was außerhalb liegt, wird nicht berücksichtigt. Die Print-String-Routine im Interpreter, generiert auch einen String-Descriptor, dessen String ins ROM zeigt und die bleiben auch unangetastet (da der String-Descriptor-Stack) natürlich bei der GC (also einer korrekt funktionierenden Implementierung) auch berücksichtigt wird.
    Will nur damit sagen, dass das kein Zufall ist, sondern "by-design" so ist.