Beiträge von JeeK im Thema „Parameterübergabe über die Zeropage“

    Die Superkraft des 6502-Stacks ist, dass man in gerade 3 Zyklen Werte raufschieben kann (günstig wie Zeropage-Zugriff) und dank Auto-Dekrement die Indexregister frei bleiben.

    Aber dafür 4 Takte für runterziehen braucht, was ein Takt mehr ist als ein ZP-Restore. Das PLA setzt aber nebenbei auch gleich die Flags N, Z, was viele andere CPUs (vorwiegend aus dem Zilog- und Intel-Lager) bei Stack-Operationen nicht machen und eventuell einen gesonderte Test-Instruktion notwendig macht (sofern halt dann notwendig).

    Ja, aber eine technisch begründete Einordnung nach Bitbreiten ist nicht so trivial (gewesen).

    Da braucht man gar nicht herumstreiten. Das ist alles nur Defintiionssache. Man muss halt fairerweise immer dazu sagen, nach welcher Definitiion man geht, wenn man von einer z. B. 8-Bit-CPU spricht. Dann kann man noch die gemeinhin akzeptierte Einordnung voraussetzen, was natürlich immer die Leute auf den Plan ruft, die eine dazu andere Auffassung haben (und die Diskussion anzetteln).

    ... Anzahl der Adressleitungen?

    Ist kein wirklich brauchbares Kriterium, da es mit der Leistungsfähigkeit nicht wirklich gut korreliert bzw. kein aussagekräftige Einteilung ergibt.

    16 Adressleitungen haben nahezu alle unzweifelhaft als 8-Bit geltende CPUs (unabhängig davon, ob die am Gehäuse herausgeführt sind oder nicht, oder gar irgendwie multiplexed sind) und mir ist nicht bekannt, dass es eine Diskussion gegeben hätte, die solche als "16-Bit-CPUs" betrachten. ;)

    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.

    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 ... ;)

    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.