​Was macht der BASIC-Interpreter, wenn man RUN eingibt?

Es gibt 22 Antworten in diesem Thema, welches 1.913 mal aufgerufen wurde. Der letzte Beitrag (12. Oktober 2024 um 00:38) ist von 1570.

  • Ich möchte aus GUI64 heraus auch Dateien starten können. Dafür möchte ich gerne das Programm in den Speicher bei $0801 laden und dann das machen, was BASIC macht, wenn RUN eingegeben wird. Die Routine ist ja schon da im BASIC-ROM - ich bräuchte also lediglich die Adresse im ROM, welche bei der Eingabe von RUN aufgerufen wird. Kennt sich da jemand aus?

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Im C64: $A871. Beachte aber, dass es testet, ob danach noch eine Zeilennummer kommt. Daher sollte das Z-Flag beim Einsprung gelöscht sein, weil er sonst die Zeilennummer lesen will (mittels CHRGET)

  • strik Alles klar, vielen Dank.

    Beachte aber, dass es testet, ob danach noch eine Zeilennummer kommt. Daher sollte das Z-Flag beim Einsprung gelöscht sein

    Jo, hab nachgeschaut. Sonst springt er nach $A87D. Es ginge also sowas wie

    Code
    lda #1 ; lösche zero flag
    jmp $a871
    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Die kanonische Vorgehensweise in dem Fall ist, daß man zunächst den TXTPTR in der CHRGET-Routine auf den Start des BASIC-Programms zurücksetzt, CLR ausführt und dann in die Interpreterschleife direkt einspringt. Das machen die zwei Aufrufe:

    Code
     JSR $A659 ; CLR, TXTPTR zurücksetzen
     JMP $A7AE ; Eintritt in Interpreterschleife

    Voraussetzung für eine einwandfreie Funktion ist natürlich, daß die Link-Pointer im BASIC-Text richtig sind (das ist relevant wenn das Programm an eine andere Position geladen wurde als von wo es abgespeichert wurde) und selbstredend muß der Zeiger in 45/46 auf das erste Byte nach dem BASIC-Text zeigen.

    Wenn also z.B. das BASIC-Programm mit der KERNAL-LOAD-Routine geladen wurde, sieht das insgesamt so aus:

    Code
    [... Vorbereitung für KERNAL-LOAD ...]
     JSR $FFD5
    [... hier ggfs. Fehlerbehandlung ...]
     STX $2D   ; Zeiger auf Start der Variablen
     STY $2E   ; (a.k.a. "Ende des Programms") setzen
     JSR $A533 ; Programm re-linken
     JSR $A659 ; CLR, TXTPTR zurücksetzen
     JMP $A7AE ; Eintritt in Interpreterschleife
  • Mike VIelen Dank! Ok, du schlägst also etwas anderes vor als strik . Wenn ich beide Vorschläge vergleiche, fällt mir auf, dass $A659 in striks Methode mit JMP angesprungen wird (nämlich bei $A87A), bei dir jedoch mit JSR. Was hat es denn damit auf sich?

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Je nachdem, was Du genau vorhast, auch dran denken, vorher alle üblichen Pointer richtig zu setzen. Z.B. erwartet der Loader von Action Replay-Freezes einen korrekt gesetzten Dateinamen aus dem letzten LOAD, weil er daraus den Dateinamen der nachzuladenden Datei ableitet; eine Menge anderer Programme machen das auch.

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • $A659 [wird] in striks Methode mit JMP angesprungen

    Um das zu verstehen, muß man wissen wie der Aufruf von $A659 den Stack behandelt. Er nimmt die obersten zwei Bytes runter (bei einem JSR $A659 ist das genau die Rücksprungadresse hinter den JSR-Befehl!), stellt den Stackpointer zurück und legt dann die Rücksprungadresse wieder drauf.

    Wenn (aber auch nur wenn!) $A871 aus dem Kontext des BASIC-Interpreters aufgerufen wird, dann steht auf dem Stack bei $A87A die Rücksprungadresse $A7EA (minus 1, von $A7E7 JSR $A7ED), JMP $A659 hebt diese zwei Bytes ab, setzt den Stack zurück und legt $A7EA minus 1 wieder drauf, springt dann zu $A7EA - und $A7EA führt den gewünschten JMP $A7AE aus, der an den Start der Interpreterschleife springt.

    Du hast aber keine Garantie, daß die obersten zwei Bytes auf dem Stack genau die Rücksprungadresse $A7EA - 1 darstellen, wenn Du sozusagen von außerhalb des BASIC-Interpreters den Befehl JMP $A871 ausführst. Und steht da eben was anderes, dann crasht's.

    Die Abfolge JSR $A659/JMP $A7AE in Beitrag Bitte melde dich an, um diesen Link zu sehen. führt nun genau die Routinen im Interpreter aus, die RUN ohne Parameter auch ausführen würde, ist aber nicht darauf angewiesen, daß der Stack wie gerade beschrieben präpariert ist. Heißt also: Geht. Tut. Funktioniert. :)

  • Mike Ich danke dir für deine ausführlichen Erklärungen.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • der Loader von Action Replay-Freezes [erwartet] einen korrekt gesetzten Dateinamen aus dem letzten LOAD, weil er daraus den Dateinamen der nachzuladenden Datei ableitet; eine Menge anderer Programme machen das auch.

    Das ist interessant, klingt aber einigermaßen nach "mit heißer Nadel gestrickt" (also, was die Programme da machen).

    Der LOAD-Befehl im Direktmodus legt den Dateinamen als temporären String am oberen Ende des BASIC-Speichers ab. Lädt man ein überlanges Programm, das schon teilweise unter das BASIC-ROM "ragt", dann wird genau dieser Dateiname überschrieben. Ebenso wenig haben Programme, die derartig auf den Dateinamen angewiesen sind eine Garantie, daß der User den Dateinamen brav ausgeschrieben hat. Er könnte genauso gut den Dateinamen mit "*" abgekürzt haben, oder gar gleich "*" verwendet haben.

    Insgesamt heißt das, daß die fortgesetzte Existenz des Dateinamens (mit Längenangabe und Zeiger darauf, etc.) nach dem LOAD-Aufruf eben keine Bedingung mehr für aufgerufene Programme darstellen sollte. Programme, die das tun, sind eigentlich "kaputt bei Design".

    Interessanterweise sollte ein Programm-Browser/Lader die Situation sogar eher entschärfen. Damit der Ladevorgang an sich nicht mit dem geladenem Programm kollidiert, steht die LOAD+RUN-Routine (hoffentlich) irgendwo versteckt im Speicher (z.B. im Stack ab $0140), zusammen mit dem (unverkürzten!) Dateinamen, und macht da eben SETNAM+SETLFS+LOAD+RUN, womit auch der Dateiname im Nachgang eher noch verfügbar ist.

  • Lädt man ein überlanges Programm, das schon teilweise unter das BASIC-ROM "ragt", dann wird genau dieser Dateiname überschrieben.

    Der Action Replay-Freeze-Loader ist allerdings kein überlanges Programm.


    Er könnte genauso gut den Dateinamen mit "*" abgekürzt haben, oder gar gleich "*" verwendet haben.

    Wenn ich mich recht entsinne wird der Dateiname der Datei vom Loader konstruiert, indem am Anfang was ergänzt wird. Das funktioniert also immerhin mit * am Ende, wobei noch zu klären wäre ob der Code dabei auch mit : getrennte Präfixe im Namen korrekt behandelt.

    10 x=rnd(-1963):fori=1to81:y=rnd(1):next
    20 forj=1to5:printchr$(rnd(1)*16+70);:next
    30 printint(rnd(1)*328)-217

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Geht auch wie gesagt nicht nur um AR-Freezes, etliche andere Programme machen das auch, und wenn's nur ist, um anscheinend zu prüfen, dass auch ja niemand sie umbenannt hat.

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • [...] etliche andere Programme machen das auch, und wenn's nur ist, um anscheinend zu prüfen, dass auch ja niemand sie umbenannt hat.

    Sollte mir so ein Programm unterkommen, dann baue ich diesen Test aus. :D

  • Mag ja sein, aber hier geht's ja anscheinend um einen allgemeinen Launcher für "Endbenutzer", für die gibt's diese Option nicht bzw. wenn das Symptom lediglich ist, dass das jeweilige Programm nicht startet oder hängt, ist es erstmal gar nicht klar, dass der Launcher mit das Problem ist.

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Also, ich als Noob kann euch nicht folgen. Ist der Code oben von Mike jetzt in Ordnung? Ich hatte es so verstanden. Und da GUI64 schlussendlich auf ein Modul soll, hat ein Action Replay sowieso keinen Platz mehr im Modulschacht.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • Die Abfolge JSR $A659/JMP $A7AE in Beitrag Bitte melde dich an, um diesen Link zu sehen. führt nun genau die Routinen im Interpreter aus, die RUN ohne Parameter auch ausführen würde, ist aber nicht darauf angewiesen, daß der Stack wie gerade beschrieben präpariert ist. Heißt also: Geht. Tut. Funktioniert. :)

    Du hast recht, ich hatte mir RUN nicht genau genug angeschaut. Irgendwo im Hinterkopf hatte ich noch, dass es etwas anders macht, ich hatte es bloß nicht mehr im Kopf.

    Ich habe aber auch nicht behauptet, dass ein JSR die Lösung ist. 8) Ich habe nur behauptet, dass dort die Routine steht. :thumbsup:

    Dein Ansatz hat aber noch eine Schwäche: Es vergisst, das Programm-Modus Flag zu setzen, welches in $A871 als erstes gemacht wird. (LDA #0, JSR $FF90). Je nachdem, in welchem Modus man vorher war (wie also das Maschinenspracheprogramm aufgerufen wurde), kann das überflüssig sein oder nicht.

    Und je nachdem, was das Programm macht, kann es zumindest die Ausgabe zerhauen, wenn es falsch steht.

  • Und da GUI64 schlussendlich auf ein Modul soll, hat ein Action Replay sowieso keinen Platz mehr im Modulschacht.

    Es geht um das LADEN von Freezes, die mit dem AR erstellt wurden. Dafür muss das AR nicht eingesteckt sein.

    Und wie gesagt fallen auch etliche andere Programme ohne sauber gesetzten Dateinamen auf die Nase.

    Aber mach sonst ruhig die gleichen Fehler wie dutzende andere Launcher-Autoren vor Dir (z.B. FB64 bekomnt's auch nicht hin). ;)

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • 1570 Ich lerne ja gerne dazu. Was ist "ein Freeze"? Ich hätte gedacht, sowas ist eine Datei, in die das AR den Zustand des gesamten C64 gespeichert hat. Aber sowas wäre ja keine Programmdatei, die man nach dem Laden mit RUN starten kann. Oder bereitet das AR die Datei so auf, dass sie standalone nach einem RUN tatsächlich "gestartet" wird und das Spiel ab dem Zeitpunkt des Freezes beginnt?

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • [...] das Programm-Modus Flag [...]

    Das ist ein guter Hinweis, danke. In Beitrag Bitte melde dich an, um diesen Link zu sehen. hatte ich das jetzt ausgelassen, es ist aber auf jeden Fall richtig, daß die Systemmeldungen ("FOUND ...", "SEARCHING FOR ...") im Programmmodus ausgeschaltet sein sollen.

    Übrigens, nur als kleiner Hinweis, das ist übrigens auch ein Bug in CONT. CONT vergißt nämlich, den Programmmodus (wieder) einzuschalten. :whistling:

    Ist der Code oben [...] jetzt in Ordnung?

    Ja, auf jeden Fall. Der Einwand von 1570 betrifft Programme, die eine Sache machen ("Abfrage des Dateinamens unter dem das Programm geladen wurde"), welche vom KERNAL so *nicht* vorgesehen ist, nur rein zufällig funktioniert aber prinzipbedingt eben nicht 100%ig zuverlässig funktionieren kann.

    Wenn Du den kritischen Teil deines Ladeprogramms so wie von mir in Beitrag Bitte melde dich an, um diesen Link zu sehen. kurz angedeutet so schreibst, daß der Dateiname, die Länge desselben und der Zeiger darauf in $B7/$BB/$BC und idealerweise auch das zuletzt genutzte Device (in $BA) noch vorhanden sind wenn Du das Programm startest, dann paßt alles.

  • Ok, ich schau mal und würde mich wieder melden, wenn es Probleme gibt.

    Bitte melde dich an, um diesen Link zu sehen. (Bitte melde dich an, um diesen Link zu sehen.)Bitte melde dich an, um diesen Link zu sehen.Bitte melde dich an, um diesen Link zu sehen.
  • es ist aber auf jeden Fall richtig, daß die Systemmeldungen ("FOUND ...", "SEARCHING FOR ...") im Programmmodus ausgeschaltet sein sollen.

    Nicht zu vergessen der "I/O ERROR #" Fehler, den die meisten gar nicht kennen oder je gesehen haben...