Hallo Besucher, der Thread wurde 3,1k mal aufgerufen und enthält 29 Antworten

letzter Beitrag von mc71 am

anfänger: lda ($0300,$0301),x oder wie?!

  • ähm also ich habe in:


    $008b $77 $66 $55 $44 $33 $22 ;werte stehen
    $c000 $69 $69 $69 $69 $69 $69 ;und



    <low & >high dieser werte stehen immer in:
    $0300 $00 ;c0
    $0301 $8b ;00


    jetzt möchte ich:
    ldx #0
    lda ($0300, $0301), x
    machen, 6 mal, um meine werte bearbeiten zu können, aber
    wie bekomme ich die beiden zeiger (0300 + 0301) zusammen zu einem wert?


    ich hab das hier Adressierung schon gesehen, aber irgendwie kann ich seit meinem letzten -ähm- "stunt" (mit der schulter und dem auge) nicht mehr so richtig gut gucken ;-)
    1. hab ich etwas übersehen, oder
    2. geht das nur über mit 2 zeropage-adressen? (komme ich dann überhaupt über die zeropage hinaus?)


    kann mir mal kurz sagen wie das geht?
    super riesen vielen herzlich grossen tausen dank!

  • Ich vermute mal, Du möchtest so etwas wie

    Code
    1. lda $300 ; hole unteres Byte des Zeigers
    2. sta zeropage
    3. lda $301 ; hole oberes Byte des Zeigers
    4. sta zeropage + 1
    5. ldy #0
    6. lda (zeropage), y ; Achtung! Y und nicht X!

    "zeropage" ist hierbei eine beliebige freie Stelle auf der Zeropage in der Größe von 2 Bytes für den Zeiger, den man bei der indirekten Adressierung benötigt. Wichtig: Willst Du ein Register zum Zeiger addieren, geht nur die Adressierung "(zp), y". "(zp, x)" macht etwas anderes, was Du wahrscheinlich nie benötigen wirst mit einer Ausnahme: Wenn X = 0 ist, verhält sich "(zp, x)" identisch zu "(zp), y" (für Y=0) und kann daher zum Einsatz kommen, wenn man das Y-Register bereits für andere Dinge verwendet.

  • ...oder statt $0300/$0301 einfach von vorn herein eine ZP-Speicherstelle nehmen.


    EDIT: Außerhalb der Zeropage gibt es indirekte Adressierung nur beim JMP-Befehl, daher müssen Zeiger immer in der Zeropage abgelegt werden. Alternativ benutzt man selbstmodifizierenden Code, aber damit sollte man erst anfangen, wenn man die Grundlagen drauf hat.

  • @ Mac Bacon
    ja gut, das fiel mir dann auch ein, einfach gleich zeropage addressen nehmen...
    und -äh- ich werd nachher mal gucken, aber ich glaub' mein Code modifiziert sich nicht selbst. ich denke das ist ein zeichen von gesundheit. =]
    (nach dem anderen werd ich gleich mal hier suchen...)


    @ Zaadii
    die stellen der daten variieren, die adressen/zeigen dorthin werden aber immer in 0300 + 0301 aktualisiert...
    aber danke! ich wer's so machen wie michael jackson es mir erklärt hat:


    @ M. J.
    DANKE! weil es das, was ich suchte anscheinend nicht gibt, ist deine antwort wahrscheinlich für mich) die beste (einzige?) lösung...



    <EDIT Syshack> Fäkalien korrigiert zum 'Code' ;-)

  • weil es das, was ich suchte anscheinend nicht gibt, ist deine antwort wahrscheinlich für mich) die beste (einzige?) lösung...

    Schwebt Dir vielleicht sowas vor wie auf dem i80386 und späteren Intel-Prozessoren:


    MOV EAX, dword ptr [EBX + offset + index]
    ?


    Edit:
    bei der Ausgangsfrage bin ich über folgende "Kleinigkeit" gestolpert:


    Zitat von ..

    <low & >high dieser werte stehen immer in:
    $0300 $00 ;c0
    $0301 $8b ;00

    Vielleicht ist es auch ein Verständnisproblem, weil es auf dem 6502 ungewöhnlich scheint, dass das High-Byte in 0300 und das Low-Byte in 0301 stehen soll (Big endian vs. little endian),
    Ist das in der Aufgabenstellung so vorgegeben dass zuerst das Highbyte kommen muss?
    unklar ist mir auch ob der ; hier eine "Alternative Belegung" meint also als Kommentar, oder die Auflistung 16-Bit-Werte bezeichnet?
    (Falls letzteres, würde es in 0301 aber eine Überlappung geben)

  • Schwebt Dir vielleicht sowas vor wie auf dem i80386 und späteren Intel-Prozessoren:


    MOV EAX, dword ptr [EBX + offset + index]

    Wenn wir schon beim fabulieren sind und Anfänger weiter abschrecken:
    So etwas geht auch mit dem 65816 nicht so schön aus dem Stand heraus. Da geht das auch wie oben gehabt über die Direct-Page. Aber im Native-Mode hätte man hingeben 16-Bit-Index-Register und könnte gleich so machen:


    (vorausgesetzt sei:)

    Code
    1. rep #$10 ; X/Y 16-Bit-Modus
    2. sep #$20 ; Akku/Memory 8-Bit-Modus

    Beliebig im Speicher oder optional in Bank 0

    Code
    1. ldx $0300
    2. ldy #6 ; 6 mal
    3. loop:
    4. lda >0,x ; absolute,x, geht in jeder Bank
    5. ;lda <0,x ; mit directpage,x geht's nur in Bank 0
    6. ...
    7. inx
    8. dey
    9. bne loop

    Man legt die Direct-Page vorübergehend auf $0300 (sofern möglich):

    Code
    1. pea $0300
    2. pld ; Direct-Page-Register laden
    3. ldy #0
    4. loop:
    5. lda (0),y ; $0300(=DPR) + 0 -> Adresse, Inhalt von (Adresse+y)
    6. ...
    7. iny
    8. cpy #6
    9. bne loop

    Über Stack kann auch gearbeitet werden:

    Code
    1. ldx $0300 ; Inhalt von $0300 als 16-Bit-Adresse, z.B. $c000 auf Stack = 1,s
    2. ldy #0
    3. loop:
    4. lda (1,s),y ; indirekt via Stack, Inhalt von z.B. ($c000+y)
    5. ...
    6. iny
    7. cpy #6
    8. bne loop
    9. pla ; stack aufräumen
    10. pla

    Je nach Rahmenbedingungen hat man da einige Spielarten, um das zu realisieren.
    (ich weiß, ist eher akademisch, da die wenigsten eine SuperCPU oder andere 16-bit-Karte ihr Eigen nennen können, aber einen Vergleich ist es ja wert) :D

  • @ Stephan
    danke für deinen genauen blick und deinen gedankengang - *aber* ich hatte einfach nur mal wieder low und high byte verwechselt; ich kann mir diese low/high byte sache irgendwie einfach nicht merken... wie machst du das? ich weiss mttlerweile wieder das c64 "big startian" (=little endian) ist, (also zum beispiel: $c000 für 49152 und nicht $00c0) und/aber geschrieben wird: <low zuerst $00 und dann >high $c0, richtig? ich bekomme das immer durcheinander weil es little endian (klein-ender) heisst, aber addressen (hoch-bytig) mit high-byte-wert endet (vielleicht kann ich mir das endich so merken :-))


    @ JeeK
    gut!, aber ich könnte diese arte der addressierung für den 6502/6510 gebrauchen:
    * sta (#$0400+x), y ; x=(dez) 0 bis 1000
    oder/und
    * sta (#$0400+$c000),y ;wobei in $c000 der wert (dez) 0 bis 1000 liegt
    oder
    * sta #$0400, (y*8) ; wobei: y*8 = 0-1000
    oder
    * sta #$0400 + (x*8),y
    oder ähnliches...
    ich kam darauf, weil ich in turbo macro pro ohne probleme schreiben & compilieren kann:
    * sta $0400 + (dez) 1000, y
    aber diese '1000' dann nicht mehr variabel verändern kann - aber genau das bräuchte ich - wie geht sowas?
    selfmodifing code und dann dadurch diese '1000' (in zb 777 oder in den wert, der in $c000 steht) verändern?


    @ Mike
    ähm - kann sein :-) eines schönen tages werde auch ich das verstehen :-)
    aber zur zeit wundere ich mich wie man 16 bit zähler und 16 bit adressierung kombinieren könnte - also (wie oben bereits beschrieben z.B.):
    wenn ich einen zähler in $c000 liegen habe (mit dem wert dez 1000) wie bekomme ich den in meinen befehl:
    sta (#$0400 + $c000), x oder y?


    darüber zerbreche ich mir gerade den kopf - wie macht ihr das?

  • ähm - kann sein eines schönen tages werde auch ich das verstehen

    Also - es nutzt recht wenig, wenn Du dir Befehle zusammenfantasierst, die der 65xx nicht hat.


    Was der 65xx an Befehlen hat, steht in genügend erhältlichen Dokus im Internet. Diese Befehle wirken auf die Register, die Flags und den Speicher so wie dort beschrieben. Aus den gegebenen Befehlen mußt Du dir ggfs. mit kleinen Unterroutinen das zusammenbauen, was Du machen willst.


    Nur als Beispiel: "sta #$0400 + (x*8),y"


    Erstens: das Zeichen "#" wird hier üblicherweise nur im Zusammenhang mit Direkt-Operanden (engl. Immediate) benutzt, und sagt dann, daß die 8-Bit-Zahl "xx" im Operanden direkt als Wert hergenommen werden soll. Was *nicht* getan werden soll: an Adresse "xx" nachschauen und den Wert da holen.


    Der "Befehl" soll also das X-Register hernehmen, dessen Wert mit 8 multiplizieren, dann noch Y als Offset hinzuaddieren, den ganzen Wert als Offset zu $0400 hinzuaddieren, den resultierenden Wert als effektive Adresse verwenden und den Akku da speichern. Schön. Man merkt, daß Du vom 68K kommst.


    Das geht auf dem 65xx z.B. so - "tmp" und "tmp+1" sind zwei aufeinanderfolgende Adressen in der Zeropage:

    Noch Fragen?


    Und ja. So ein Code ist auf dem 65xx ganz normal, sobald man mit 16-Bit-Werten arbeitet.

  • danke mike für deine antwort!


    "#" ja, ich wollte damit auch sagen: den wert $0400 benutzen, nicht die speicherstellen - wäre aber 16bit...


    "Befehl" ja, du hast meine (an)frage ganz genau richtig gelesen.


    besten dank! für den code, scheint alles richtig zu machen - damit muss ich jetzt erstmal herumspielen um herauszufinden ob/wie ich das nutzen kann - oder irgendwie anders gehen muss... danke erstmal!

  • ich hatte einfach nur mal wieder low und high byte verwechselt; ich kann mir diese low/high byte sache irgendwie einfach nicht merken... wie machst du das? ich weiss mttlerweile wieder das c64 "big startian" (=little endian) ist, (also zum beispiel: $c000 für 49152 und nicht $00c0)

    WTF?!

    und/aber geschrieben wird: <low zuerst $00 und dann >high $c0, richtig? ich bekomme das immer durcheinander weil es little endian (klein-ender) heisst, aber addressen (hoch-bytig) mit high-byte-wert endet

    Du denkst viel zu kompliziert.
    Jede Wurst hat zwei Enden, welches Ende wird zuerst in den Senf getunkt und gegessen?
    Das Ende mit den niederwertigen Bits: Die Architektur ist little-endian.
    Das Ende mit den höherwertigen Bits: Die Architektur ist big-endian.


    Dass die Dezimalzahl 49152 in Hexadezimaldarstellung dann $c000 geschrieben wird, hat damit genau gar nichts zu tun. Es geht nur darum, welche Bytes zuerst im Speicher stehen.

  • Ich hatte grade weisswurst mit suessem senf .... irritiert mich bei dem Thema.


    0 | 0 | 00000000
    1 | 1 | 00000001
    2 | 2 | 00000010
    3 | 3 | 00000011
    ...
    9 | 9 | 00001001
    10 | a | 00001010
    11 | b | 00001011
    bis f
    usw.


    P.S.: e2020, Du bringst das nicht durcheinander. Genau der Sinn von little und big endian ist die Unterscheidung dieser willkürlich gesetzten Nomenklatur. Wenns eine dritte möglichkeit gibt, dann erfinde ich sie;) Hoer auf Mac;)

  • Ich hatte grade weisswurst mit suessem senf .... irritiert mich bei dem Thema.

    Da hast Du dich bei der Uhrzeit aber streng daran gehalten, daß die das Mittagsgeläut nicht hören darf... 8|


    Genau der Sinn von little und big endian ist die Unterscheidung dieser willkürlich gesetzten Nomenklatur. Wenns eine dritte möglichkeit gibt, dann erfinde ich sie;)

    Mid-Endian gibt's schon. Prost! :D

  • das Mittagsgeläut nicht hören darf

    Dafür war wohl der Senf schon ein paar Tage übers Datum... ;-)

    Mid-Endian gibt's schon.

    Big Fish- Little Fish- Card Board Box...


    'little endian' sind die, die das kleine Ende zuerst haben wollen, 'big endian' die, die das große Ende zuerst haben wollen... was machen 'middle endian' denn dann mit den Endstücken?


    Und wo tun wir 'post-segmented big endian' hin? oder den TMS 9900, bei dem A1 das höchstwertige Adreßbit ist und A15 das niedrigste, während die Datenbits normal sortiert sind?


    (Falls die Ursprungsfrage noch nicht beantwortet sein sollte: Ich habe keine Ahnung, was die Schreibweise darstellen soll; sofern ich richtig rate, geht 'lda (0300),x' gleich zweimal nicht- es muß deine Zeropage-Adresse sein, und es geht nur mit dem Y-Register.)

  • 'little endian' sind die, die das kleine Ende zuerst haben wollen, 'big endian' die, die das große Ende zuerst haben wollen... was machen 'middle endian' denn dann mit den Endstücken?

    Mid endian ist für 32-Bit Werte und stammt von DEC PDP Rechnern.
    Die 16-Bit Worte des 32-Bit Wertes sind big endian angeordnet. Die Bytes der 16-Bit Worte sind little endian angeordnet. Der 32-Bit Wert 0xA0B0C0D0 würde so im Speicher stehen, wenn die Adressen von links nach rechts ansteigen:
    0B 0A 0D 0C


    Ich durfte mal als Student ein Programm schreiben, dass irgendein ein obskures CAD-Format lesen sollte. Manche Werte in diesem CAD-File waren auch mid endian codiert.

  • flowerking hat ja schon was zu Mid-Endian geschrieben. :)


    Und wo tun wir 'post-segmented big endian' hin? oder den TMS 9900, bei dem A1 das höchstwertige Adreßbit ist und A15 das niedrigste, während die Datenbits normal sortiert sind?

    Dann stellt sich halt die Frage, ob bei einer Architektur die Endianess von Wortebene bis auf Bitebene durchgehend beibehalten worden ist.


    Selbst beim C64 und VC-20 ist das im Zusammenhang mit dem Videochip nicht durchgehend einheitlich umgesetzt: während die CPU ihre Bytes in Little-Endian anordnet, werden die Pixel aus einem Byte vom Videochip in Big-Endian dargestellt! 8|


    Nicht lachen - genau das hat bei mir für einige Verwirrung gesorgt, als ich meine ersten Gehversuche in Grafikprogrammierung auf ARM+VIDC am Archimedes gemacht hab - der VIDC zeigt die (Hires-1 bpp) Pixel nämlich in Little-Endian an. Und das beißt sich wiederum mit den Richtungen, die der im ARM integrierte Barrelshifter nutzt. Der geht nämlich wiederum von einer Big-Endian Anordnung der Bits im CPU-Register aus. Richtig übel wird's dort dann bei den Fließkommaformaten. Bei Double und Extended sind die 32-Bit-Worte jeweils für sich in Little-Endian gehalten, werden aber mit dem höherwertigen Wort zuerst geschrieben. :drunk:


    Wer räumt das Durcheinander mal bitte auf? :gahh:


    Zitat

    Falls die Ursprungsfrage noch nicht beantwortet sein sollte:

    e2020 wurde schon geholfen: falls die CPU den Befehl nicht hat, basteln wir ihn uns selbst. :D

  • also wenn ich mal n ender/ending erfinden müsste, dann würde ich den neuen "sta" ausrufen - den "Big staEnder" (auch 'h0m0 erec1us' genannt) - der wird immer dann sofort zum standard wenn frauen binär zählen :-)
    der ist ganz einfach und komplett aufgeräumt: es gibt unendlich viele nullen und/aber nur eine 1.
    und -äh- die muss irgendwie in irgendeine null... quasi sowas wie: 'das eckige muss ins runde' - aber binär...


    :roll2:



    ähm - mein lda($ll +1),y funktioniert (noch) nicht - werd morgen früh solange debuggen bis ich weiss woran es liegt...