Hello, Guest the thread was called428 times and contains 14 replays

last post from dg5kr at the

Wie kann ich aus Assembler heraus eine BASIC Variable mit Inhalt erzeugen?

Heute 13.11.2019 ca. 11:30 Uhr Serverreboot wegen Systemupdates. Danke für Euer Verständnis. Team Forum64.de

  • Wie kann ich aus Assembler heraus eine BASIC Variable mit Inhalt erzeugen und diese anschliessend auch in BASIC nutzen?

    Fiktives Beispiel: sys49152,"CBA",A$ -> Das Ergebnis dieser Sortier Routine soll in der Variable A$ abgelegt werden.

    Oder als fiktive BASIC Erweiterung: SORT "CBA",A$ -> Das Ergebnis dieser Sortier Routine soll in der Variable A$ abgelegt werden.


    Danke an die Spezialisten.

  • Eine Möglichkeit ist es im Basic beim Programmstart eine Variable zu definieren . (zb: '0 A$="xxxx":A$=A$+"xxxx")

    Diese bleibt dann an einer festen Position im Speicher am oberen Ende vom Basic-Ram. Auch eine GarbadgeCollection verschiebt die nicht. Die kannst du dann 'hart' per ASM beschreiben.

    Wichtig: per Basic nur auslesen, wenn du die im Basic beschreibst dann verschiebt sich die Position.


    Gruß, Gerd

  • Ist das nicht genau der Anwendungsfall für USR()?

    ────────────────────────────────────────────────────────────
    Time of Silence - Time of Silence 2 Development Blog
    ────────────────────────────────────────────────────────────

  • Da steht aber doch "Der Rückgabewert wird im Fließkomma-Akkumulator #1 beginnend bei der Speicheradresse 97 ($61) erwartet, welcher vom BASIC-Programm als Funktionswert weiter verarbeitet werden kann. Dieser kann numerisch als Fließkommazahl vorliegen oder aber auch eine Zeichenkette sein..."

    ────────────────────────────────────────────────────────────
    Time of Silence - Time of Silence 2 Development Blog
    ────────────────────────────────────────────────────────────

  • Ja, verdammt. Ich sollte mal richtig lesen. Du hast natürlich recht. :platsch:
    Dann könnte ich das damit machen. Werds direkt mal testen.


    Vielen Dank :respect:

    Dann aber auch richtig den String-Heap-Speicher nicht nur anfordern, sondern auch dann belegen, wie in Assembler: VAR$=MEINE_FUNC$(INTEGER) in BASIC Erweiterung. Aber wie? erläutert. Bei USR muss dann im FAC der Descriptor (der am String-Descriptor-Stack liegt) liegen, der auf den Hex-String zeigt und so in der Ausdrucksauswertung weiter verarbeitet werden kann.

    Dazu muss man mit JSR $B47D (in A die Länge), den Platz anfordern und dann mit TXA; JSR $B487 (mit Stringadresse des angeforderten Strings in A/Y) den Descriptor am String-Descriptor-Stack aufbauen und der Ausdrucksauswertung rückmelden, dass das Ergebnis (das in $61/$62/$63 steht) ein String ist, der am Top of SDS bereit liegt.

  • Dann aber auch richtig den String-Heap-Speicher nicht nur anfordern, sondern auch dann belegen, wie in Assembler: VAR$=MEINE_FUNC$(INTEGER) in BASIC Erweiterung. Aber wie? erläutert. Bei USR muss dann im FAC der Descriptor (der am String-Descriptor-Stack liegt) liegen, der auf den Hex-String zeigt und so in der Ausdrucksauswertung weiter verarbeitet werden kann.

    Dazu muss man mit JSR $B47D (in A die Länge), den Platz anfordern und dann mit TXA; JSR $B487 (mit Stringadresse des angeforderten Strings in A/Y) den Descriptor am String-Descriptor-Stack aufbauen und der Ausdrucksauswertung rückmelden, dass das Ergebnis (das in $61/$62/$63 steht) ein String ist, der am Top of SDS bereit liegt.

    Ich muss gestehen, dass ich USR noch nie verwendet habe, aber kann der String-Descriptor und der zugehörige String nicht einfach irgendwo im Speicher stehen? Ich hätte gedacht, dass man da nicht groß mit Heap und Stack rumfuhrwerkt, sondern einfach einen Puffer im Assemblerprogramm vorhält (z.B. irgendwo ab $C000). Bei der Zuweisung A$=USR(1234) wird dann doch A$ ordnungsgemäß im Heap angelegt und die Stringdaten dorthin kopiert, oder?

    ────────────────────────────────────────────────────────────
    Time of Silence - Time of Silence 2 Development Blog
    ────────────────────────────────────────────────────────────

  • Ich muss gestehen, dass ich USR noch nie verwendet habe, aber kann der String-Descriptor und der zugehörige String nicht einfach irgendwo im Speicher stehen? Ich hätte gedacht, dass man da nicht groß mit Heap und Stack rumfuhrwerkt, sondern einfach einen Puffer im Assemblerprogramm vorhält (z.B. irgendwo ab $C000). Bei der Zuweisung A$=USR(1234) wird dann doch A$ ordnungsgemäß im Heap angelegt und die Stringdaten dorthin kopiert, oder?

    Die String-Adresse kann auch irgendwo im Speicher stehen, wenn oberhalb des String-Heaps liegend (z. B. ab $c000), dann wird der String auch von der GC in Ruhe gelassen. Nur der Descriptor kann nur in einer Variablen (bzw. einem Array-Element) oder eben am temporären String-Descriptor-Stack liegen. Dafür ist der ja da, sonst funktioniert eine Ausdrucksauswertung nicht mehr, wie etwa H$="$"+USR(X) oder B$ = LEFT$(USR(X),2) ...


    Nein, bei der Zusweisung A$=USR(1234) wird der Descriptor(!) vom Descriptor-Stack in die Variable A$ kopiert und dann entfernt, siehe ROM (LET-Befehl).

    Wo der String im Descriptor hinzeigt ist dann eigentlich egal. Man muss immer unterscheiden zwischen dem Descriptor, der nur auf die String-Daten zeigt und dem String selbst. Man kann nicht sagen "A$ ordnungsgemäß im Heap angelegt", denn genau genommen ist nur der String am Heap und der Descriptor am temporären String-Descriptor-Stack oder in einer Variable (Array-Element).


    Man muss nicht "groß herumfuhrwerken", es sind ja alle Routinen im ROM, man muss sie nur (zugegebenermaßen) richtig aufrufen. Die zwei JSRs mit einem TXA halte ich für zumutbar ... ;)

  • Dann aber auch richtig den String-Heap-Speicher nicht nur anfordern, sondern auch dann belegen, wie in Assembler: VAR$=MEINE_FUNC$(INTEGER) in BASIC Erweiterung. Aber wie? erläutert. Bei USR muss dann im FAC der Descriptor (der am String-Descriptor-Stack liegt) liegen, der auf den Hex-String zeigt und so in der Ausdrucksauswertung weiter verarbeitet werden kann.

    Dazu muss man mit JSR $B47D (in A die Länge), den Platz anfordern und dann mit TXA; JSR $B487 (mit Stringadresse des angeforderten Strings in A/Y) den Descriptor am String-Descriptor-Stack aufbauen und der Ausdrucksauswertung rückmelden, dass das Ergebnis (das in $61/$62/$63 steht) ein String ist, der am Top of SDS bereit liegt.

    Das ist jetzt etwas knapp angeführt. Ich hab jetzt meine Routinen heraus gekramt, und da bieten sich 2 Möglichkeiten an. Die STR$()-Methode und die CHR$()-Methode.

    Bei STR$() wird der String im Input-Puffer aufgebaut, ab $00FF und der muss 0-terminiert sein. Dabei wird der String automatisch am String-Heap angelegt und rüberkopiert.

    Beim Ansatz wie bei CHR$() wird der String am Heap selbst angelegt und dann nur noch der Descriptor am SDS gelegt.

    Hier ist die STR$()-Variante (Label STR) die Vorgabe. Wahlweise mit JMP CHR die andere Variante wählen.

    Wie auch im ROM wird mit dem Trick gearbeitet, dass die beiden PLA den Aufrufer (der einen nummerischen Wert erwartet!) entfernt wird. Dann ist der Weg frei für einen String als Rückgabewert.


    Ein BASIC-Test-Programm könnte dann so aussehen:

    Code
    1. 10 f=f+1:if f=1 then load "usr-string",8,1
    2. 20 poke785,0:poke786,192
    3. 30 def fn f(x)=40960-peek(51)-peek(52)*256
    4. 100 print fnf(.)
    5. 110 for i=0to100:print usr(i);:next
    6. 200 print fnf(.)

    Das Image mit den Programmen: usr.zip :)

  • Ah, verstehe! Dann finde ich den C64-Wiki-Artikel ein wenig zu vereinfacht formuliert, denn das hört sich so an als ob USR quasi out-of-the-box String-Unterstützung hätte. Aber der Artikel hat eh so einige Schwächen, vielleicht fixe ich zumindest mal die wirklich offensichtlichen...

    ────────────────────────────────────────────────────────────
    Time of Silence - Time of Silence 2 Development Blog
    ────────────────────────────────────────────────────────────

  • Ah, verstehe! Dann finde ich den C64-Wiki-Artikel ein wenig zu vereinfacht formuliert, denn das hört sich so an als ob USR quasi out-of-the-box String-Unterstützung hätte. Aber der Artikel hat eh so einige Schwächen, vielleicht fixe ich zumindest mal die wirklich offensichtlichen...

    Die "out--of-the-box"-Unterstützung passt so nicht ganz. Die USR-Funktion ist so ja nicht vorhanden und besteht nur aus einem JMP über die Vektoradresse. Die kann so gesehen nichs vorbereiten oder im Nachgang etwas tun. Den Umgang mit Strings als Rückgabewert machen auch Funktionen wie CHR$ oder STR$, die dabei den Aufrufkontext explizit festlegen (eher als eine Art "Override-Mechanismus" zu verstehen). Wenn USR sich ebenso verhalten soll, dann muss sie sich auch an dieselben Hausregeln des Interpreters halten.


    Ich hab den C64-Wiki-Artikel dahingehend angepasst und erweitert. Ist das so besser bzw. hilfreicher?

  • Sehr viel besser und das Beispiel für Stringverarbeitung ist super! Ich habe noch ein paar winzige Typos korrigiert. Vielen Dank (im Namen aller Basicprogrammierer :thumbup:)!

    ────────────────────────────────────────────────────────────
    Time of Silence - Time of Silence 2 Development Blog
    ────────────────────────────────────────────────────────────

  • Sehr viel besser und das Beispiel für Stringverarbeitung ist super! Ich habe noch ein paar winzige Typos korrigiert. Vielen Dank (im Namen aller Basicprogrammierer :thumbup:)!

    Freut mich und danke auch für den Feinschliff. Ich schaff es einfach nicht auch nur die kleinsten Passagen zu erstellen, ohne dass mir da irgendwelche Flüchtigkeitsfehler unterlaufen. :S Da bin ich wirklich froh, dass immer viele andere Augenpaare im Wiki "mitschauen".