Hallo Besucher, der Thread wurde 12k mal aufgerufen und enthält 63 Antworten

letzter Beitrag von Mac Bacon am

Neues ACME-Release

  • Nein. Das würde ich auch kaum versuchen wollen, da es prinzipiell nicht 100%ig sicher machbar ist.

    Eben. Sehe ich auch so. Machbar wäre wohl, dass der Programmeirer per "!native" oder "!emulation" dem Assembler mitteilt, unter welcher Umgebung der Code lt. Itention des Programmeirers ausgeführt werden soll.
    Wenn man sich entschließt, solche Befehle einzuführen, könnte man die Warnungen spezieller machen.

    Das ließe sich machen. Wenn die 65816-Coder diese Warnung als kontraproduktiv empfinden, baue ich das entsprechend um - ich selbst habe kaum praktische Erfahrung mit dem 65816 und würde mich da nach der Mehrheit richten.

    Ich habe mit 65816 auch keine Erfahrung - würde aber wollen, dass der Assembler mich nicht dazu überredet, etwas zu ändern, was ich auf einer gewissen Zielcpu gar nicht ändern müsste.


    PS: Beim 65802 (und ich vermute auch beim 65816) wollte man im Emulationsmodus auch die CPU-Zyklenanzahl zum 6502 beibehalten. Vermutlich deswegen hat man gewisse Bugs nicht korrigiert im Emulationsmodus - obwohl i. A. Bugs korrigiert worden sind.

  • Es gibt in ACME übrigens noch ein Feature, welches ich vermisse - ich versuche das mal an einen Anwendungsbeispiel zu erklären:


    Es sei ein !pseudopc-Block gegeben, der beispielsweise in der Floppy ausgeführt werden soll. Dann sind darin natürlich eine gewisse Anzahl Labels drin. Jetzt stelle man sich vor, dass der Teil vor der Übertragung zur Floppy noch gepatched werden soll - je nachdem, welche Floppy erkannt worden ist.
    Man fängt also an, wild mit den Labels zu rechnen, um die Speicheradresse zu bekommen, wo der Code im Programm ist:


    floppycode
    !pseudopc $0300 {
    nop
    nop
    nop


    floppylabel1 STX a1801 ;PA, port A
    }
    floppylabel1addr = floppylabel1 + 1 - $0300 + floppycode
    sample: lda #$1c
    sta floppylabel1addr


    Schön wäre es, wenn einfach schreiben könnte


    sample: lda #$1c
    sta &floppylabel1+1


    und er durch das Prefix "&" vor dem Label erkennt, dass er pro Prefix eine "pseudopc"-Ebene rausgehen soll und die Adresse, wo es dort dann (virtuell) steht nimmt.

  • Schön wäre es, wenn einfach schreiben könnte
    sample: lda #$1c
    sta &floppylabel1+1
    und er durch das Prefix "&" vor dem Label erkennt, dass er pro Prefix eine "pseudopc"-Ebene rausgehen soll und die Adresse, wo es dort dann (virtuell) steht nimmt.

    Ich habe zwar noch nicht ganz verstanden, wie das funktionieren soll, aber genau sowas bräuchte ich aktuell für die C64-Diag. Da ist ein Teil des RAM-Tests doppelt enthalten, einmal für die Ausführung im ROM und einmal für die Ausführung im RAM (wenn das ROM ausgeblendet ist).
    Ich wollte mir einen Relocator schreiben, der die Routinen beim Kopieren ins RAM patcht. Das würde einigen Programmspeicher sparen.

  • Also, die technische Implementierung von Acme kenne ich auch nicht :-)


    Jedenfalls könnte man konzeptionell an den Symboltabelleneinträgen jeweils eine Liste dranhängen, um wieviel Bytes die !PSEUDOPC verschoben sind (vorzeichenbehaftet). Dann kann der Assembler das bei einem Label zurückrechnen (auf dem PC ist ja Arbeitsspeicher da, da stört so eine Liste pro Label nicht).


    Im Minimalbeispiel wäre das dann aus Benutzersicht:


    * = $c000
    !pseudopc 1000 {
    !pseudopc 2000 {
    !pseudopc 3000 {
    !pseudopc 4000 {
    demolabel nop
    }
    }
    }
    }



    demolabel -> 4000
    &demolabel -> 3000
    &&demolabel -> 2000
    &&&demolabel -> 1000
    &&&&demolabel -> c000


    Ja, zugegeben: Verschachtelt und dann auch noch die verschiedenen Adressen braucht man nicht so oft - aber wenn schon, dann sollte ein Vorschlag universell sein.
    Um "&" als Zeichen sich wirklich eignet: Keine Ahnung, es erinnert nur in angenehmer Weise an den Adress-Operator von C.

  • Je länger ich jetzt darüber nachdenke, desto mehr halte ich das Verhalten der 65816-CPU in dieser Hinsicht für inkonsequent:
    Der 6502 bleibt mit Zeropage-Zeigern immer in der Zeropage. Das kann man als Feature oder als Bug betrachten, aber der Grund für dieses Design leuchtet ein, nämlich die einfachere Implementierung.
    Eine Nachfolge-CPU könnte nun dieses Limit aufheben, so dass ($ff),y das Highbyte von $0100 holt.
    Eine Nachfolge-CPU könnte auch die Zeropage frei im Speicher verschiebbar machen.
    Aber beides zugleich? Semantisch gesehen verschiebt man dann einen direkt adressierbaren Block von 256 Adressen beliebig im Adressraum, aber für bestimmte Adressierungsarten ist dieser logische Block dann 257 oder 258 Bytes groß - d.h. es gibt Zeiger "in der Zeropage", deren zweites und/oder drittes Byte man nicht mit Zeropage-Adressierung setzen kann.

    Die Adressierungsarten des 65816 muss man auf sich einwirken lassen, dann erscheint einem nach und nach logischer. Das Problem ist, man darf sich hier nicht von der Stardard-6502-Seite her nähern, sondern muss immer die die (optionale) 16-bittigkeit der Register in Betracht ziehen.
    $ff von ($ff),y ist dann nicht ein Zeropage-Register, sondern lediglich ein 8-Bit-Offset innerhalb eines 16-Bit-Raums in der Bank 0 bezogen auf die Direct-Page-Basis. Hier tritt das nicht so in Erscheinung, weil ja nur der implizite High-Byte (bei Long auch der Bank-Byte) Zugriff den 256er-Bereich verlassen kann. Aber bei ($nn,X) wird es offensichtlich, da ja X auch 16-bittig sein kann. Da ist $nn einfach ein 8-bit-Offset und X ein 16-bit-Wert im Raum der Bank 0. So gesehen ist die Direct Page eigentlich immer 64 K groß, beginnt beim Offset gemäß DPR (Direct Page Register) und man navigiert mit Offset und Index-Register dort umher. Bei den Adressierungsarten ($nn) und ($nn),y geht es naturgemäß nicht wesentlich darüber hinaus, weil halt nur die "high" Bytes davon betroffen sind.
    Das Denkmodell "Zero-Page" sollte man im Native-Modus nicht so übernehmen und "erweitern", sondern von Grund auf in der Direct-Page-Bedeutung des Native-Modes "leben". Sonst stolpert man mehr durch und empfindet es dann umso mehr als "inkonsequent".


    Im Emulation-Mode gibt es dann auch noch so Stolpersteine wie, dass das Wrapping vom Low-Byte des DPR abhängt. Ist es 0 -> Wrapping, sonst aber nicht!


    Nein. Das würde ich auch kaum versuchen wollen, da es prinzipiell nicht 100%ig sicher machbar ist.

    Fände ich auch haarig und zudem nicht 100%ig sicher. Ich hab es nur erwähnt, weil es ja auch Assembler gibt, die ein SEP/REP-Tracking machen und implizit Long/Short-Modi der Register erkennen, was natürlich auch zu Problemen führt, wenn irgendwie wild herumgesprungen wird (zur Laufzeit), was ein Assembler dann nicht mehr so ohne weiteres mehr mitbekommt.



    Der ist tatsächlich schon lange implementiert, danke. Ich muss den Status des Bugs mal auf "Closed" setzen. Immer dieses Neuland...

    Super, danke!


    Das ließe sich machen. Wenn die 65816-Coder diese Warnung als kontraproduktiv empfinden, baue ich das entsprechend um - ich selbst habe kaum praktische Erfahrung mit dem 65816 und würde mich da nach der Mehrheit richten.

    Ich bin auf jeden Fall dafür das von der CPU-Klassifikation abhängig zu machen.



    Wer so eine hat, möge sie mir schicken, dann baue ich die Informationen in trunk/docs/cputypes.txt mit ein.

    Progamming the 65C816 von WDC (PDF), da gibt's an mehreren Stellen Hinweise auf Bugs & Quirks und wie diese unterschiedlich gehandhabt werden, ab Page 40, 42, weiter bis 62. Table 4-6 zeigt eine grobe Gegenüberstellung.


    Dazu allerdings auch gleich die Korrektur des ziemlich vor Fehlern strotzenden Dokuments von WDC (für den genannten Bereich):


    p. 52


    In the 6502/65C02, the effective address formed using zero
    page indexed addressing from a zero page base address of $F0 and an
    index of $20 is $10; that is, zero page indexed effective addresses wrap
    around to always remain in the zero page. In the emulation mode this is
    < also true. But in native mode, there is no page wraparound: a direct
    page starting at $2000 combined with a direct page base of $20 and a
    sixteen-bit index holding $300 results in an effective address of $2320.



    In the 6502/65C02, the effective address formed using zero
    page indexed addressing from a zero page base address of $F0 and an
    index of $20 is $10; that is, zero page indexed effective addresses wrap
    around to always remain in the zero page. In the emulation mode this is
    > also true except for 65802/65816 only opcodes or the direct page
    > low byte is not equal zero. But in native mode, there is no page wraparound: a direct
    page starting at $2000 combined with a direct page base of $20 and a
    sixteen-bit index holding $300 results in an effective address of $2320.
    > Note that a direct page access is always limited to bank 0 (wrapping
    > around at $FFFF)..


    -------------------------


    p. 59, Table 4-6 Major Dofferences Between Processors and Modes



    6502 65C02 65802 Native Emul. 65816 Native Emul.
    < direct page indexed wraps wraps crosses page wraps crosses page wraps
    > direct page indexed wraps wraps crosses page*2 wraps*1 crosses page*2 wraps*1



    > Notes:
    > *1 only for 6502/65C02 opcodes and if direct page register low byte = 0, *2
    > *2 only in bank 0, wrapping around

  • Windows Update ist bei sf.net https://sourceforge.net/projec…cme0.96.3win.zip/download .


    Und später auch mit Assembler-Beispielen und den alten Relaunch-Binäries bei
    Thorsten unter
    www.emu64-projekt.de/acme
    zu finden.

  • Schön wäre es, wenn einfach schreiben könnte


    sample: lda #$1c
    sta &floppylabel1+1


    und er durch das Prefix "&" vor dem Label erkennt, dass er pro Prefix eine "pseudopc"-Ebene rausgehen soll und die Adresse, wo es dort dann (virtuell) steht nimmt.

    Das hätt ich auch gerne!

    Nach ein paar Tagen unbewusst-drüber-nachdenken wollte ich gerade vorsichtig grünes Licht geben, aber jetzt ist mir doch noch ein (kleines) Problem eingefallen. Bei sowas wie arg_hi = floppylabel1 + 2müsste das neue Symbol die Offsetliste des alten Symbols erben, damit dann auch &arg_hi funktioniert. Je nach Komplexität des mathematischen Ausdrucks wird das aber beliebig kompliziert. Eine mögliche Lösung wäre, sowas einfach zu verbieten: Der &-Operator darf also nur auf Labels und nicht auf beliebige davon abgeleitete Symbole angewandt werden. Ich denk mal weiter drüber nach...

    genau sowas bräuchte ich aktuell für die C64-Diag

    Ich bin nicht überzeugt, dass der &-Operator Dein Problem löst: Der &-Operator würde es erlauben, einfach auf den Original-Speicherbereich einer für "anderswo" assemblierten Routine zuzugreifen, um diese vorher zu patchen. Du willst aber die Konvertierung für "anderswo" zur Laufzeit machen, weil die Routine ja auch im Originalbereich lauffähig sein soll. Es scheint mir einfacher, die Routine einfach an der gleichen Adresse, nur eben mit ausgeschalteten ROMs laufen zu lassen.

    Das Denkmodell "Zero-Page" sollte man im Native-Modus nicht so übernehmen und "erweitern", sondern von Grund auf in der Direct-Page-Bedeutung des Native-Modes "leben". Sonst stolpert man mehr durch und empfindet es dann umso mehr als "inkonsequent".

    Dann ist "Direct Page" aber auch ein blöder Name. :P
    Aber gut, sehen wir es als "base pointer", "context register", "object ref" oder dergleichen; das erlaubt in der Tat eine andere Herangehensweise.

    Progamming the 65C816 von WDC (PDF)

    Der Link ist leider tot, auch Wayback hat nicht geholfen.

  • Da hast Du natürlich Recht. Erst mal würde das auch für reine Labels reichen. Dennoch lohnt es sich natürlich, darüber nachzudenken, um das Mögliche herauszufinden.


    Das PDF "Programming the 65816, Including the 6502, 65C02 and 65802" von "The Western Design Center Inc." habe ich hier. Ist lediglich zu groß, um es hier anzuhängen.


    Nachtrag: Exakten Titel bei Google suchen hilft.


    Nchtrag 2: In dem Zusammhang ggf. auch &* unterstützen. Für so etwas wie
    FOO = &* + 1


    Meistens weiß man ja, ob man vor oder nach dem Kopieren patchen will, so dass Labels innerhalb einer Instruktion schon für den passenden Adressbereich gemacht werden können.

  • Nachtrag: Exakten Titel bei Google suchen hilft.

    Hier mal eine Zwischenkopie

    Vielen Dank.


    spider-j hat vorhin ein Ticket auf Sourceforge angelegt, weil "!scrxor" den XOR-Wert nur auf die Strings anwendet und nicht auf Symbole. Das mag unschön sein, aber da das schon ewig so ist und auch so in den Docs steht, will ich das nicht mehr ändern. Als alternative Lösungsmöglichkeit schwebt mir ein neuer Pseudo Opcode vor wie z.B.:

    Code
    1. !xor $a3 {
    2. ; ALLE in diesem Block erzeugten Ausgabebytes werden exklusiv-geodert
    3. }

    Hat jemand eine bessere Idee?

  • Was macht !scrxor denn bei Symbolen? Einfach den Original-Wert belassen [...]?

    Genau. Bei allem, was nicht mit Doublequotes anfängt, wird die Formelauswertung angeworfen. Deren Ergebnis wird dann nicht mehr weiter verändert, das ist bei "!raw", "!pet", "!scr" und "!scrxor" immer gleich. Nullterminatoren, Steuerzeichen oder Escape-Codes will man ja normalerweise nicht durch eine Textkodierungs-Konvertierungstabelle schleusen.

  • Ich könnte mir vorstellen, dass man auf solche Blöcke auch kompliziertere Umsetzungen als ein einfaches XOR machen will, z.B: einen Packer aufrufen.

    Verallgemeinern kann man natürlich immer, aber ab einem gewissen Punkt sind dann wieder externe Tools das Mittel der Wahl. Im Augenblick ist das Problem:

    Code
    1. ; scroll text with 1x2 charset:
    2. !scr "Hi everyone, this is ", CRYPTIC_CHAR, " by ", GROUP_LOGO_CHAR
    3. !scrxor $80, "Hi everyone, this is ", CRYPTIC_CHAR, " by ", GROUP_LOGO_CHAR

    Damit das wie gewünscht funktioniert, müsste man im Augenblick in der letzten Zeile bei jedem Symbol noch manuell ein "XOR $80" dazu schreiben.


    EDIT: Nach erneutem Durchlesen kommt mir meine Antwort zu sehr wie ein Abbügeln vor, daher hier noch ein Disclaimer: Ich mag allgemeine Lösungen und würde in der Tat auch eher etwas bevorzugen, was universeller verwendbar ist als ein simples Output-XOR. Aber da der einfache Fall vermutlich häufiger gebraucht wird als der komplizierte, würde ich auch bei Vorhandensein einer universelleren Lösung eine Art "Shortcut" haben wollen, um ein simples Output-XOR schnell und einfach erreichen zu können. Insofern würde ich lieber jetzt die einfache Möglichkeit einbauen wollen und sie später(tm) zum Spezialfall eines universelleren Systems erklären, als erst viel Gehirnschmalz in ein universelles System zu stecken, das dann so gut wie nie gebraucht wird.
    Wäre der schon seit ewigen Zeiten geplante String-Support endlich mal fertig, könnte man sich die XOR-Funktionalität evtl. auch schon auf Makro-Basis selber basteln, das fände ich sogar noch besser...

  • Hi!


    ACME hat jetzt die Versionsnummer 0.96.4, für den Link zum Source siehe meine Signatur.
    Die Änderungen sind:

    • Die letztens eingeführte Warnung wegen Zeropage-Wraparound kommt jetzt nicht mehr für die 24-Bit-Pointer des 65816, denn in diesem Fall findet gar kein Wraparound statt (Pseudo Opcodes zur Unterscheidung zwischen Native und Emulation Mode stehen auf der TODO-Liste).
    • Neuer Pseudo Opcode "!xor" (wie oben bereits angekündigt), der alle Ausgabebytes beeinflusst.
    • Neuer CLI-Switch "-I" für Suchpfade, wie kürzlich von peiselulli angeregt.

    Der hier angeregte "Referenzierungs-Operator" steht ebenfalls auf der TODO-Liste, ich wollte nur erstmal diverse Änderungen aus meinem lokalen Repository loswerden, weil es sonst zu unübersichtlich wird. Wird Zeit, von Subversion zu git zu wechseln...

  • Wird Zeit, von Subversion zu git zu wechseln..

    Dann interessiert es Dich vielleicht, dass ich eine per subgit nach git gewandelte Version Deines Subversion-Repositories hier habe. Da sind sogar die Subversionsrevisionsvummern als Notes im git eingetragen.