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

letzter Beitrag von atomcode am

Definitionen und Standards zu ASM Adressierungen, Syntax und Mnemonics [OT aus 'Assembler Tricks']

  • ASL A :gruebel Der CBM 8032 hat doch einen 6502 verbaut. Demnach ist die Mnemonik hier nicht richtig. Implizite Adressierung wird benötigt, aber eine absolute mit unbekanntem Label A ist angegeben.
    Ansonsten ja, es ist kürzer als die Anwendung einer Tabelle, die mit Auslesecode fast doppelt so viele Bytes brauchen würde.


    Dieser Thread ist auf jeden Fall sinnvoll. Vllt. sammle ich die Einzelergebnisse auf meiner Internetseite zum schnelleren Nachschlagen, denn kaum einer wird sich später noch den kompletten Thread hier durchlesen, glaube ich.


    Die Verteilung der Priorität von Zeit und Raum innerhalb eines Systems, in dem beides sehr begrenzt zur Verfügung steht, ist genau das Yin und Yang, warum für mich bei diesem Hobby bereits der Weg ein Ziel ist.
    Hätte Konfuzius jetzt nicht besser sagen können. ;)

  • ASL A :gruebel Der CBM 8032 hat doch einen 6502 verbaut. Demnach ist die Mnemonik hier nicht richtig. Implizite Adressierung wird benötigt, aber eine absolute mit unbekanntem Label A ist angegeben.

    "A" ist kein Label sondern ist der reservierte Oprand für die Adressierungsart "Accumulator".
    Es ist keine "implizite" Adressierung.
    Der ASL Befehl kennt fünf Adressierungsmodi:

    Code
    1. ASL A
    2. ASL ZeroPage
    3. ASL ZeroPage,X
    4. ASL Absolute
    5. ASL Absolute,X

    Wenn die Adressierungsart Accumulator gewählt wird, muss deshalb "ASL A" geschrieben werden.
    Es git zwar Assembler, die den Code "ASL" ohne Operanden akzeptieren und ohne Fehlermeldung den Code für "ASL A" erzeugen,
    dies verletzt allerdings den 6502 Standard.

  • Bit Shifter: Zum Glück hat sich die ursprüngliche Schreibweise, mit an den Mnemonic angehängter Adressierungsart (z.B. LDAIM $02 statt LDA #$02) nicht durchgesetzt.


    Wenn die Adressierungsart Accumulator gewählt wird, muss deshalb "ASL A" geschrieben werden. Es gi_b_t zwar Assembler, die den Code "ASL" ohne Operanden akzeptieren und ohne Fehlermeldung den Code für "ASL A" erzeugen, dies verletzt allerdings den 6502 Standard.

    Ob bei implizierter bzw. Akkumulator-Adressierung von Shift-Befehlen A als Operand angegeben werden soll und ob A beim disassemblieren ausgegeben wird, hängt exakt *nur* vom verwendeten Werkzeug ab. Nix "Standard", beide Schreibweisen sind gängig. *)


    Gegebenenfalls empfehle ich einen scharfen Blick in das Dr. Dobbs Journal, Ausgabe 9/1976: "A 6502 Disassembler From Apple - Steve Wozniak & Allen Baum" auf Seite 22. Da steht drin, wie man die Tabellen ändern kann um zwischen beiden Darstellungen zu wechseln. :)



    *) auch ob z.B. ">" das High- oder das Low-Byte bereitstellt hängt ebenso vom Assembler ab. Einmal meint ">" eben den "größeren" Teil der Adresse, im anderen Fall zeigt es auf den "rechten" Teil. Tja.

  • Hier muss ich leider gleich mehrfach widersprechen:


    1) Es gibt sehr wohl einen Standard: "http://bytecollector.com/archive/misc/6500-50A_MCS6500pgmManJan76.pdf"
    Dieses Programming Manual wurde von MOS, den Entwicklern des 6502 herausgegeben.
    Auf der Seite B-4 wird der Befehl ASL A beschrieben.


    2) Implizite und Akkumulator Adressierung sind zwei verschiedene Adressierungsarten!
    Befehler mit impliziter Adressierung haben NIE einen Operanden, wie z.B. PHA, TXA, DEY usw.
    Die Akkumulator Adressierung kommt bei Befehlen vor, die IMMER einen Operanden haben, wie ASL Adresse,X oder ASL A.


    3) Wenn Disassembler beim Befehl ASL A das "A" weglassen, so geschieht dies aus Schlampigkeit oder um Code Bytes zu sparen.


    Der 6502 Standard Befehlssatz ist so schön strukturiert und beschrieben, dass es keinen Grund gibt, davon abzuweichen.


    Nicht standardisiert sind die Pseudo-Ops wie .BYTE .WORD usw., was durch den Punkt am Anfang deutlich gemacht wird.

  • Eins vorweg: in meiner Toolchain hab' ich auch einen Assembler am Start, der bei Shift-Befehlen das "A" verlangt. Brauchst dich also nicht auf den Schlips getreten fühlen. Deswegen sage ich ad 1) nichts weiter. Allerdings führt eben diese Notation zu Mehrdeutigkeiten (nicht beim Assembler selbst, sondern beim Leser!) sofern es sich um einen symbolischen Assembler handelt. Ist nun das Symbol A definiert, dann ist eben - für den Leser! - nicht mehr eindeutig, was jetzt gemeint ist!


    ad 2) Befehle mit impliziter Adressierung haben *sehr wohl* einen Operanden, der ist eben durch den Mnemonic impliziert, bei PHA eben der Akku (nicht das Statusregister!) und noch weiter implizit die Adresse "$0100,S", bei TXA Akku und X-Register, bei DEY das Y-Register. Die Transportbefehle könnte man anders schreiben (etwa MOV x,y - fehlen halt leider TXY und TYX beim NMOS) - also ist das ebenfalls Interpretationssache. Genauso wie zwar Intel beim 8080 Mnemonics vorgegeben hat, das hat Zilog aber nicht davon abgehalten, eine andere Schreibweise beim Z80 zu etablieren.


    3) deine Meinung. Zur potentiellen Mehrdeutigkeit habe ich zuvor schon was geschrieben.

    Der 6502 Standard Befehlssatz ist so schön strukturiert und beschrieben, dass es keinen Grund gibt, davon abzuweichen.

    Nochmal: beim NMOS 6502 entstehen durch Hinzunahme oder Weglassen der A-Adressierung keinerlei Gewinne oder Verluste. Genau wie bei den Assembler-Direktiven hängt das einfach vom Werkzeug ab.


    Ab dem CMOS 65xx kommen dann z.B. noch die Befehle INC A und DEC A dazu. *Dann* kann man schon eher in Richtung deiner Lieblingsschreibweise tendieren - mit (auch nochmal) der Fußfalle, daß A als Symbol jetzt zu Mehrdeutigkeiten führt.

  • Hehe, gut, dass Ihr euch um die Adressierung kabbelt.


    Ich wollte nur auf deine Frage zum ASL A antworten, dass MOS Technologies in ihrem Programming Manual zum 6502 festgelegt haben,
    dass A, X und Y reservierte Symbole für die entsprechenden Register sind und A den Operanden zum Befehl ASL darstellt.
    Die Grundsatzdiskussion von Mike ist komplett überflüssig, da MOS genauso wie Intel, AMD und IBM zu ihren CPU's die Assembler Syntax festgelegt haben.
    Das erinnert mich an den Straßenverkehr. Da gibt es auch feste Regeln, aber manche halten sich trotzdem nicht dran.

  • Die Grundsatzdiskussion von Mike ist komplett überflüssig, da MOS genauso wie Intel, AMD und IBM zu ihren CPU's die Assembler Syntax festgelegt haben.

    Genauso ist dieser Thread hier überflüssig. Spezielle "Lieblingsalgorithmen" werden hier gezielt in enger thematisch gefaßten Threads besprochen. Was Du hier machst, ist Fischen im Trüben.

  • dann z.B. noch die Befehle INC A und DEC A dazu.

    Ich hab mir immer ein INA und DEA gewünscht. :)


    5 FORT=1TO49:IFB(X)=1THENPRINTT
    ...
    ?LOGIC ERROR IN 5
    AUTO RECOMMENDATION: USE B(T)


    Hab meine ROMs etwas weiterentwickelt. ;)


    Die Aufgabe in einer Zeitschrift war damals, das als Assemblerprogramm zu machen und zwar möglichst kurz, deswegen auch keine zwei LSR dazu.
    Päckchen-Darstellung wie auf dem Schein, Titel, Einkreisungen und (TASTE) gehören auch dazu. Würde mich aber interessieren, ob das in BASIC V2 in 1:1 auch mit 224 Bytes machbar wäre.


    @Bit Shifter
    >"dass MOS Technologies in ihrem Programming Manual zum 6502 festgelegt haben"


    Das glaube ich dir unbesehen. Aber vor wie vielen Jahrhunderten war das? Kannten die da schon moderne Assembler wie ACME, sodass sie die spätere Handhabung bereits zur Entwicklungszeit der CPU absahen und berücksichtigen konnten? Wohl eher nicht. Ich glaube sogar, dass das relativ früh wieder verworfen wurde, wenn auch inoffiziell, denn auch im Studium wird das so nicht gelehrt, und da sind Standards das A und O.


    Ich hatte es von Anfang an, als mein "Speichermedium" noch aus Papier bestand und noch bevor ich meinen ersten Maschinensprache-Monitor aus einer Zeitschrift abgetippt hatte, um ihn auf Kassette speichern und nutzen zu können, so gelernt, dass die Adressierungsarten eine Eigenschaft der CPU sind. Demnach ist die implizite Adressierung genau deswegen eine solche, weil sie eben KEINE Angabe eines Operanden braucht und die Adressierung etwaiger Register bereits impliziert.


    Das sollte also auch genau so in der Mnemonik dargestellt werden, also nichts Doppeltgemoppeltes. Dass das vor Urzeiten mal anders war, mag sein, aber alles hat eben irgendwie angefangen. Die Darstellung mit der Angabe eines Operanden, den es in Wirklichkeit gar nicht gibt, halte auch ich für grundverkehrt, unlogisch und irreführend. Diese veraltete Schreibweise funktionierte noch bei der Benutzung von MS-Monitoren, wo man ohnehin daneben die Bytes sieht, aber mit heutigen Assemblern muss man das unbedingt verwerfen. In 35 Jahren sehe ich das zum ersten Mal, dass das noch jemand so schreibt. Manchmal ist der Standard eben einfach das, was sich aus praktischen Gründen durchsetzt und nicht, was irgendwer vorgeben möchte.


    >"Straßenverkehr. Da gibt es auch feste Regeln"
    Wenn ich einen Schwerverletzten transportieren würde, würde ich mich nicht an die Geschwindigkeitsbegrenzungen halten. Regeln sind notwendig, aber manchmal ist es auch notwendig und sinnvoll, sie zu überschreiben.


    Nach der Vorschrift-Logik müsstest du dann ja auch konsequent diese bescheuerten Gibi-, Tebi- und Tinkiwinki-Bytes benutzen, ein Standard, den sich praxisferne Sesselpuper der IEC ausgedacht haben.


    Also, der Code, der bei "ASL" (implizit), ROR, INX, etc. nur aus einem Byte besteht, hat bereits durch Konvention und "Verdrahtung" impliziert, welche Register adressiert sind bzw. behandelt werden. Die flächendeckende Vereinbarung ist darum die, dass immer, wenn nichts weiteres innerhalb der dreistelligen Mnemonik angegeben ist, der Akkumulator gemeint ist. Eine zusätzliche Angabe von A wäre faktisch eine unnötige Redundanz, zumal die 6502-Mnemonik für das Code-Byte generell eben 3 Buchstaben vorsieht.


    Last but not least müssen wir hier ja auch miteinander klarkommen, und auch hier ist der Standard eben die konsequent dreistellige Darstellung des Befehls, sofern es sich nicht um andere CPUs dreht. Und das sage ich, der ich mich als wenig teamfähig einschätze. Weil früher jeder sein eigenes Süppchen kochte, wird diese Anfangszeit Softwarekrise genannt. Deswegen sollten wir uns wenigstens jetzt und hier auf die wichtigsten Standards einigen, und da zeichnet sich eben ACME ab, wo diese alte ASL-A-Darstellung nicht mehr funktioniert, und in den Köpfen der allermeisten 6502-Programmierer eben auch nicht.

  • Dass MOS die "ASL A"-Notation benutzt hat, dürfte mit dem 6800 von Motorola zusammenhängen. Diese CPU war ja quasi die Vorlage für den 6502, hat aber zwei Akkumulatoren, genannt A und B. Die Befehle "ASL A" und "ASL B" ergaben dementsprechend zwei unterschiedliche Opcodes.
    Auf Opcode-Ebene würde ich das dann aber immer noch als implizite Adressierung bezeichnen, einfach weil keine Argumentbytes geholt werden. Aber aus Marketingsicht ist es natürlich gut, wenn im Datenblatt eine möglichst hohe Anzahl von Adressierungsarten genannt werden kann... :anonym

  • Die Grundsatzdiskussion von Mike ist komplett überflüssig, da MOS genauso wie Intel, AMD und IBM zu ihren CPU's die Assembler Syntax festgelegt haben.
    Das erinnert mich an den Straßenverkehr. Da gibt es auch feste Regeln, aber manche halten sich trotzdem nicht dran.


    Sich nicht an überflüssige Regeln zu halten, kann auch gute Gründe haben. Die Intel-Syntax für den 8080 zum Beispiel ist ja auch sehr aufgebauscht im Vergleich zu der durchdachteren Z-80-Syntax von Zilog.

  • Kannten die da schon moderne Assembler wie ACME, sodass sie die spätere Handhabung bereits zur Entwicklungszeit der CPU absahen und berücksichtigen konnten?
    [...]
    Deswegen sollten wir uns wenigstens jetzt und hier auf die wichtigsten Standards einigen, und da zeichnet sich eben ACME ab, wo diese alte ASL-A-Darstellung nicht mehr funktioniert, und in den Köpfen der allermeisten 6502-Programmierer eben auch nicht.

    Auf meiner TODO-Liste für ACME steht irgendwo im "kann-man-mal-machen-wenn-ganz-viel-Zeit-ist"-Kapitel auch noch was von "baue Kommandozeilenoption ein, um Akkumulator-Adressierung aktivieren zu können" - und sei es nur, um entsprechende Sourcecodes ohne vorherige Konvertierung verarbeiten zu können.


    Über die "richtige" Schreibweise habe ich mir damals aber keine großen Gedanken gemacht; für "ASL statt ASL A" gibt es genau zwei Gründe:


    1. Ich habe Assembler mit dem Sonderheft 35 gelernt, dort wurde diese Notation benutzt. Als Tools wurden dort Hypra-Ass und SMON benutzt/vorgeschlagen, die habe ich aber nicht verwendet, denn:


    2. Ich habe den im 128er-ROM vorhandenen TedMON verwendet. Dieser assembliert "ASL" zu $0a und disassembliert $0a zu "ASL". Gibt man "ASL A" ein, erhält man $06 $0a (ASL $0a). Die Version im C16/+4 akzeptiert "ASL A" überhaupt nicht.


    ...so gesehen schiebe ich die Verantwortung mal auf Commodore bzw. auf Stephen Wozniak oder wer auch immer den Monitorcode ursprünglich mal geschrieben hat (auch wenn ich heute der Meinung bin, dass dieser Code es "richtig" macht).


    Ach ja, im Alchemiekurs heißt es übrigens:

    Zitat von Heimo Ponnath

    Bevor wir die Adressierung zu den Akten legen, sei noch erwähnt, daß manche Lehrbücher noch eine weitere Art, die Akkumulator-Adressierung, unterscheiden. Betroffen sind davon vier 1-Byte-Befehle, die wir noch kennenlernen werden und die man ebensogut als implizit adressiert ansehen kann.

    Im weiteren Verlauf des Kurses und in den Opcode-Tabellen wurde die Akkumulator-Adressierung immer in Anführungszeichen oder Klammern gesetzt. Man wollte sie also nicht unter den Tisch fallen lassen, aber wohl auch nicht "vollwertig" mitzählen.

  • ...so gesehen schiebe ich die Verantwortung mal auf Commodore bzw. auf Stephen Wozniak oder wer auch immer den Monitorcode ursprünglich mal geschrieben hat.

    Volltreffer!


    Die Disassemble-Routine im TEDMON und auch in anderen Monitoren von CBM ist "geklaut" vom Apple-II-Monitor. Woz hat diese Routine dann im DDJ publiziert. Der Gegenpart ist von CBM selbst gebaut worden, die Assemble-Routine ist von Bill Seiler. Sowohl der "Mini-Assembler" von Apple als auch Bill Seilers Variante fahren quasi das Disassemblen rückwärts: es werden alle 256 Opcodes ausprobiert, ob ein disassemblierter Befehl zur Eingabe paßt (mit Platzhalter-Bytes für die Operanden-Ziffern). :drunk:


    "ASL A" "klappt" nur deshalb im C128er-TEDMON, weil die Adreßparser-Routine etwas flexibler ist (kann mit Hex-, Dezimal-, Oktal- und Binärzahlen umgehen) und per default Hex auch ohne "$" erkennt. Ob das dann Zeropage ist, wird anhand der Größe festgelegt: <256 => Zeropage, >=256 => Absolute. Will man Absolute-Adressierung mit Operanden <256 haben, muß man das "sauber" in Hex anschreiben: $00xx.

  • Dieses Programming Manual wurde von MOS, den Entwicklern des 6502 herausgegeben.
    Auf der Seite B-4 wird der Befehl ASL A beschrieben.

    Ja und? Dewegen ist das jetzt die Bibel? Standards werden nicht nur einmalig vom Hersteller ganz zu Beginn bei Veröffentlichung einer bestimmten Hardware gesetzt, sondern auch von den Benutzern einer solchen. Der Merlin-Assembler auf dem AppleII war damals[tm] der Standard bei der Assemblerprogrammierung und verwendete ganz selbstverständlich "LSL" und nicht "LSL A".
    "LSL A" ist
    a) redundant,
    b) schwerer für Menschen zu lesen,
    c) doppeldeutig,
    d) schwerer zu parsen für den Assembler.
    Es gibt keinen Grund, diese unnütze Schreibung zu verwenden, nur weil irgendsoein Typ in grauer Vorzeit am grünen Tisch aus Marketinggründen das so hingekritzelt hat.
    Und natürlich ist "LSL" eine implizite Adressierung. Ansonsten müßte man auch "INC X" schreiben anstelle von "INX" etc. Bei Einführung des 65c02 hat man den neuen Befehl auch "INA" genannt und nicht "INC A" und noch später beim 65ce02 "INZ" und nicht "INC Z". Da hatte der Hersteller selbst schon längst mit der unsinnigen Notation gebrochen.
    Persönlich habe ich noch nie "LSL A" irgendwo in einem Programm geschrieben, weder damals noch heute. Und besonders für heute gilt, daß der ACME-Assembler der jetzige Standard ist. Daran sollte man sich orientieren.

  • DU LIEBE ZEIT! ...


    Ja, wenn es wirklich nur ein mögliches Register gibt, auf das sich die Instruktion bei impliziter Adressierung (und, abermals ja, es ist immer implizite Adressierung wenn im Maschinencode kein "Operand" folgt, es aber einen durch den Opcode implizierten gibt) bezieht, dann ist die Angabe natürlich redundant. Sie zu fordern könnte höchstens noch den Sinn haben, dass es dann auffällt, wenn man mal einfach nur den Operanden vergessen hat. Nunja, mein bevorzugter Assembler unterstützt beide Schreibweisen (ich schreibe trotzdem asl a), also ist dieser Vorteil dahin.


    Aber alles in allem, daraus eine solch ausufernde Diskussion zu machen, meint ihr das wirklich ernst? Ist doch völlig schnuppe ...

  • Dieser Thread ist in eine unglückliche Richtung abgedriftet, aber ich möchte doch noch einen letzten Versuch machen, hier die Fakten zur 6502 Syntax zusammenzufassen.


    - Die ältesten Manuals zur 6502 Programmierung, darunter das von MOS Technologies, listen für die Shift Befehle 5 Addressierungsarten auf, Accumulator, Zeropage, Absolute, Zeropage,X und Absolute X.
    - Es folgte eine Vielzahl von Assemblern, Disassemblern und Maschinensprache-Monitoren von unterschiedlicher Komplexität und Qualität.
    - Diese wurden teils von Informatikern aber auch von Hobbyisten erstellt, die sich mehr oder weniger an die durch MOS definierten Vorgaben hielten.
    - Teilweise wurden dort die Adressierungen "implicit" und "accumulator" in einen Topf geworfen, weil sie die gleiche Eigenschaft haben eine Befehlslänge von ein Byte zu haben.
    - Sieht man sich aber die Befehlsgruppen an, so bilden die Bitschiebe Befehle ganz klar eine eigene Gruppe, die die oben beschriebenen 5 Adressierungsarten haben.
    - Implizite Befehle kennen nur genau eine einzige Adressierungsart.
    - Die 5 Adressierungsarten der Shift-Befehle sind, wie Intel es bezeichnet vom type (r/m) = register or memory.
    - Deshalb wird bei diesen entweder die Adresse als Operand angegeben, oder das Register, wobei hier der Akkumulator A das einzig mögliche ist.
    - Dies ist auch für den Parser praktisch, weil der Programmierer beim Fehlen des Operanden auf einen Fehler (vielleicht ein Vergessen des Operanden) hingewiesen werden kann.
    - Die Tatsache, dass nur A bei der Akkumulator-Adressierung als Register in Frage kommt, wurde allerdings von vielen Assembler-Implementatoren benutzt, um eine laxe Abkürzung zuzulassen.
    - Es wurde praktisch eine neue Regel zur Syntax hinzuerfunden, die besagt: Wenn ich keinen Operanden hinschreibe, meine ich A.
    - Das ist auch ohne Einfluss auf den erzeugten Code, kann aber zu Inkompatibilitäten führen, falls der eine Assembler nur die Schreibweise mit A und ein anderer nur ohne A toleriert.


    Dieses Problem von Sprachdefinition und Implementation gibt es übrigens nicht nur bei Assemblersprachen sondern in viel größerem Ausmaß bei Hochsprachen.
    Besonders arg war es mit FORTRAN. Hier gab es immer einen Standard, der aber immer Jahre hinter der Hardware-Entwicklung zurücklag.
    Das führte dazu, dass jeder größere Hardware-Hersteller, wie CRAY, CDC, IBM, DEC und viele andere eigene FORTRAN Dialekte entwickelten die untereinander inkompatibel waren.


    Zurück zum konkreten Fall: Ich habe absolut nichts dagegen, wenn Leute den "abgekürzten" ASL Befehl benutzen, wenn sie einen Assembler verwenden, der dies unterstützt oder sogar verlangt.
    Genauso wünsche ich mir aber auch Toleranz gegenüber meinem Code, wenn ich mich an die von MOS Technologies definierte Syntax halte.
    Wenn wir uns also darauf einigen können wäre es möglich wieder zum eigentlichen Zweck dieses Threads zurückzukehren.

  • Akkumulator-Adressierung ist und bleibt eine Nebelkerze. Ansonsten wäre inx dann X-Adressierung. Man hätte den Mnemonic ja auch als inc x festlegen können. Wenn eine Instruktion einen Operanden hat, der im Opcode impliziert wird, ist das ganz einfach implizite Adressierung.


    Macht aber nichts, wie bereits erwähnt schreibe ich auch immer asl a, ist ja nichts falsch daran, sich an die Assembler-Syntax des Herstellers zu halten. Dass die aber auch nicht unbedingt frei von logischen Widersprüchen sein muss versteht sich doch wohl von selbst ;) Ja, zurück zur Programmierung bitte!

  • Akkumulator-Adressierung ist und bleibt eine Nebelkerze. Ansonsten wäre inx dann X-Adressierung. Man hätte den Mnemonic ja auch als inc x festlegen können. Wenn eine Instruktion einen Operanden hat, der im Opcode impliziert wird, ist das ganz einfach implizite Adressierung.

    Wir drehen uns im (Argumentations)-Kreis ;)
    ASL impliziert KEINE Adressierungsart. Je nach Operand (oder fehlendem Operand) wird ja aus 5 verschiedene Befehlscodes einer gewählt.
    Bei Menemonics mit impliziter Adressierung existiert eine eindeutige Zuordnung von einem Menmonic zu einem Code, z.B. INX -> $E8.
    Aus ASL wird einer der Codes $0A, $06, $16, $0E, $1E - damit ist die Zurodnung NICHT implizit.