Parameterübergabe über die Zeropage

Es gibt 55 Antworten in diesem Thema, welches 5.415 mal aufgerufen wurde. Der letzte Beitrag (7. März 2024 um 19:13) ist von JeeK.

  • Das besondere am C64 ist ja, dass man alles im RAM hat.

    Ich haette keine Skrupel, Parameter IN das Unterprogramm zu schreiben.

    Caller:

    .(

    sta parameter1
    stx parameter2
    ...

    .)

    function:
    .(

    &paramter1=*+1
    lda Bitte melde dich an, um diesen Link zu sehen.

    . ..
    &paramter2=*+1
    lda 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.

  • Aber genau das ist oft gar nicht gewollt, weil man dann z.B. Übergangsbilder beim Laden nicht zu sehen bekommt, wenn der VIC abgeschaltet wird.

    Aus dem Grund nimmt man auch Magic Formel :smile: Aber der Speeder ist nicht sooo kompatibel, das ist der Nachteil.

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".

  • Ich haette keine Skrupel, Parameter IN das Unterprogramm zu schreiben.

    Das ist natürlich auch eine Option, zumindest, wenn man den Parameter nicht an mehreren Stellen in der Routine laden muss.

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

  • Scheint mir hier beim schnellen Überfliegen nocht nicht genannt worden zu sein, aber...

    ... was ist mit der guten alten Übergabe eines Pointers auf eine beliebig große/komplexe Parameter-Struktur? =)

  • Man muss es ja nicht herausziehen. Der Freezeknopf funktioniert auch bei deaktiviertem Modul.

    Auch das kommt aufs Modul an. Es ist jedenfalls nervig, wenn man es erst abschalten muss.

    Was genau ist da jetzt nervig, wenn das Modul mit einem Switch abgeschaltet ist, um das laufende Programm zu freezen? Das ist ja die Definition von einem Freezer-Modul. Es muss inaktiv sein, damit es alles original belässt und auch einem Programm nicht die Möglichkeit gibt, das Modul zu erkennen. Das hängt mit der jeweiligen Aufgabe des Moduls zusammen. Ein Schnelllader hat ja eine andere Aufgabe.

  • wenn man die Parameter runter-popped, muss man sie ja meist auch wieder irgendwo zwischenspeichern

    Das funktioniert am PC aber problemlos und ist dort gängige Technik. Warum sollte das hier problematischer sein?

    Wenn ich slebst jetzt mal kein Interruptprogramm schreibe, dann sollte ich selbst über die Register quasi die Kontrolle haben, d.h. vom Programmablauf selbst wissen, was, wann, in welchem Register steht. Wenn ich nun Werte auf den Stack schiebe, kann ich sie im Unterprogramm wieder runter holen und sollte auch in keinen Konflikt rein laufen. Wird ein Interrupt ausgelöst, sollte das Programm dort eh alle Register auf den Stack schieben und vor Beenden wieder runter holen, d.h. bei der Rückkehr aus dem Interruptprogramm sollte eh der vorherige Zustand wieder hergestellt sein. Ich muss mir halt nur vorher schon überlegen, in welcher Reihenfolge ich die Werte auf den Stack schiebe, bzw. in welcher Reihenfolge ich diese brauche.

    Stell dir den 6502 als CPU vor, der 256 byte oder 128 16-bit "general purpose" Register hat. In einer CPU mit großem Registersätzen muss man auch mit den Registern haushalten und Konventionen einführen. Solche gibt es eben auch für den Gebrauch von ZP-Speicherstellen.

    Je nachdem, in welchem Umfeld man seine Routine nutzt. Wenn man typischerweise ein Erweiterung zum BASIC hat, das etwa via SYS aufgerufen wird, dann wird man die typischen Floating-Point-Register und alles war mit der Ausdrucksauswertung zu tun hat, nicht anrühren. Gewisse ZP-Register werden aber auch sonst nur temporär genutzt, können damit verwendet und quasi zerstört werden, ohne dass es den Interpreter stört.
    Auch bieten sich die ZP-Stellen an, die etwa für Band-IO oder RS-232 verwendet werden, wenn diese zur Laufzeit der eigenen Routine nicht verwendet werden.

    Man sollte explizit die Finger von solchen Stellen lassen, die mit Interrupts zu tun haben (Timer, Tastaturabfrage) oder solchen, die einen fest vorgegebenen Wert enthalten müssen (z. B. $55 muss immer eine 3 enthalten, sonst haut die Garbage Collection nicht mehr hin), die nur beim Systemstart gesetzt wurden.

    Zur Not, wenn man wirklich viel ZP-Raum braucht, sichert man diese an einen anderen Ort aus und restauriert die dann am Ende des Programms wieder. Wenn das umfangreichere Routinen sind, fällt der Aufwand dann auch nicht mehr so ins Gewicht (Druckertreiber, Garbage-Collection, Grafikroutinen).

    Das mit dem Stack ist wie schon öfter erwähnt wurde gerade beim 6502 nicht gerade der netteste Ort, um mit Daten zu hantieren. Das ist von der Architektur so vorgegeben und Möglichkeiten seitens der Adressierung gibt das vor. Da ist es müßig darüber zu sinnieren, wie man das bei x86 oder anderen CPUs macht - jede hat so ihre eigene Welt des Umgangs, der man sich aus Effizienzgründen anpasst. The Art of Assembler Programming ist eben, sich dahingehend anzupassen und nicht zu versuchen Hochsprachen- und sonstige allgemein gültige Paradigmen abzubilden. Dafür haben wir ja Compiler ... ;)

  • Freezen geht eigtl. immer.

    Wie, ohne Modul?

    Einfach in die Tiefkühltruhe legen ... wenn Du schnell genug bist, bleiben die Bits erhalten :lol27:

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".

  • Einfach in die Tiefkühltruhe legen ... wenn Du schnell genug bist, bleiben die Bits erhalten :lol27:

    Vorsicht, das Programm breitet sich beim Einfrieren aus. Deswegen immer etwa 2 KByte Speicher freilassen!

    Bitte melde dich an, um diesen Link zu sehen. - Ratespiel • Bitte melde dich an, um diesen Link zu sehen. - BASIC-Erweiterung • Bitte melde dich an, um diesen Link zu sehen. - Sprite-Editor • Bitte melde dich an, um diesen Link zu sehen. - Zeichensatz-Editor Bitte melde dich an, um diesen Link zu sehen. - 2048 Blöcke

  • Ich haette keine Skrupel, Parameter IN das Unterprogramm zu schreiben.

    Aber in den Programmcode zu schreiben ist doch böse ...

    ... was ist mit der guten alten Übergabe eines Pointers auf eine beliebig große/komplexe Parameter-Struktur? =)

    Diese Methode wird neben anderen in dem Video vorgestellt:

    Bitte melde dich an, um dieses Medienelement zu sehen.

  • wenn man die Parameter runter-popped, muss man sie ja meist auch wieder irgendwo zwischenspeichern

    Das funktioniert am PC aber problemlos und ist dort gängige Technik. Warum sollte das hier problematischer sein?

    Weil ...

    1. ... der C64 einen sehr winzigen Stack hat.

    und

    2. ... die neueren CPUs darauf auch optimiert wurden dass man den Stack als bequemen Zwischenspeicher nutzt.

    Beim C64 hast du kaum Befehle um mit dem Stack vernünftig arbeiten zu können. Es geht zwar, und ich habe das auch schon gemacht, aber es istnicht sonderlich komfortabel. Bei anderen CPUs z.B. 68k oder Intel, hast du diverse Register und Stackbefehle um Framepointer zu setzen und dann darüber auf deinen Variablenbereich zugreifen zu können.

  • Die (C64-)Stackfunktionen nutze ich hauptsächlich zum Retten bzw. Zwischenspeichern von Registerinhalten. Vorteil dabei: Braucht gegenüber ZP-Befehlen nur den halben Speicherplatz für Befehle und quasi keinen Platz für die Daten. Parameterübergabe kann man machen, ist aber mit Vorsicht zu genießen.

    ZP-Register haben gegenüber dem Stack den Vorteil, dass sie zu jedem Zeitpunkt gelesen werden können, also auch bedingt; dass das Laden ein TZ schneller ist; dass sie beliebig oft gelesen werden können und nicht nur einmal; dass sie direkt in X und Y geladen werden können und nicht nur direkt in A; und auch die Indizierungsarten sind nützlich, zumal es für die ZP die Indexregister-Befehle auch x- und y-indiziert gibt, nicht aber für 16Bit-Adressen.

    Zu der Sache mit den Modulen und veränderten ROMs verweise ich noch mal auf die PLA, die es erlaubt, alles auszublenden und das ganze RAM zu nutzen, mit oder ohne IO-Layer.

    Bitte melde dich an, um diesen Link zu sehen.

    Man kann ein Programm auch mit aktiviertem Modul einladen; das Programm muss dann nur selbst dafür sorgen, dass es die Kontrolle übernimmt und sich nicht durch das Modul stören lässt. Wenn man z.B. die Multi-Disk-Demo "Uncensored" mit aktivierter AR6 startet, dann wird ein 1,5 kB großer Loader mit AR6-Fastload geladen, und nach dessen Start hat das AR6-Fastload nichts mehr zu melden.

    Was ich aber nervig finde, ist, dass man ein Freezer-Modul nicht mehr verwenden kann, z.B. den Monitor davon, wenn man ein anderes Modul eingelegt hat. Aber ok, hat jetzt nichts mit dem Thema ZP zu tun.

  • Beim C64 hast du kaum Befehle um mit dem Stack vernünftig arbeiten zu können.

    Gibt es denn 8-Bit-CPUs, die eine Stackpointer-relative o.ä. Adressieung anbieten?

    Der 65ce02 und seine Nachfolger (im C65) haben sowas, und der 65816 auch.

    Nein, ich diskutier jetzt nicht darüber, ob man den 65816 nicht vielleicht doch als 16-Bitter zählen müsste. :D

    Yes, I'm the guy responsible for the Bitte melde dich an, um diesen Link zu sehen. cross assembler. And some Bitte melde dich an, um diesen Link zu sehen..

  • Beim C64 hast du kaum Befehle um mit dem Stack vernünftig arbeiten zu können.

    Gibt es denn 8-Bit-CPUs, die eine Stackpointer-relative o.ä. Adressieung anbieten?

    Gute Frage. Der 8080 hat zumindest einige mehr Möglichkeiten, um auf seinen 16-Bit Stack zuzugreifen. Ich hab den noch nie programmiert, aber es sieht so aus, als ob man da zumindest weniger rumwurschteln müsste.

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

  • Nein, ich diskutier jetzt nicht darüber, ob man den 65816 nicht vielleicht doch als 16-Bitter zählen müsste. :D

    Muss man gar nicht. Wenn der 65C816 oder 65C802 im Emulationmodus betrieben wird, ist er ähnlich wie ein 65C02, allerdings sind auch immer die Adressierungsarten (neuen Opcodes) auch aktiv und können verwendet werden, sofern diese eben einen Sinn ergeben.

    So gäbe es etwa

    LDA offset,S

    LDA (offset,S),Y

    "offset" ist ein vorzeichenbehafter 8-Bit-Wert.

    Gibt es denn 8-Bit-CPUs, die eine Stackpointer-relative o.ä. Adressieung anbieten?

    Legendär ist der 6809. Dessen Grundkonzeption unterstützt Stacks massiv. Hat sogar 2 16-Bit-Stackpointer (S, U) die völlig gleichwertig genutzt werden können. Lediglich die Instruktionen, die implizit den "Stack" verwenden, beziehen sich auf S (JSR, RTS, BSR, LBSR, Interrupt-Handling etc.).

    Mit dem Stackpointer kann man dann - am Beispiel S, U gleichwertig)

    LDA ,S (ohne Offset)

    LDA offset,S (5, 8 oder 16 Bit Offset als Konstante)

    LDA A,S (8-Bit Offset aus Akku A)

    LDA B,S (8-Bit Offset aus Akku B)

    LDA D,S (16-Bit Offset aus Register B/A=D)

    All diese Formen gehen dann noch noch mal mit einer weiteren Indirektion indem das Argument in eckige Klammern gesetzt wird. Also z.B.

    LDA [D,S] -> Die Speicherstelle D+S und D+S+1 enthalten eine Adresse, die dann ausgelesen und nach Akku A transferiert wird.