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

letzter Beitrag von Mnemonic am

Speicheradresse in Variable (?) übertragen... wie?

  • Hallo zusammen,


    wohl mal wieder eine meiner üblichen "sieht den Wald vor lauter Bäumen nicht"-Fragen.


    Wie kann ich denn eine Adresse (z.B. $0380) in eine Variable (z.B. "Tabelle") übertragen?


    Hintergrund ist, dass ich bei mehrmaligem Aufruf einer Subroutine gerne die im Sourcecode verwendete Variable "Tabelle" jedesmal mit einer neuen Adressen füllen will.


    Ich stehe da grade mal total auf dem Schlauch; meine Idee bisher war, die Lo- und Hi-Bytes der Adressen einfach hintereinander irgendwo im Speicher abzulegen, diese (je nachdem, wann ich meine Subroutine aufrufe) dort auslese und und die irgendwie in die Variable der Subroutine übertrage.


    Und genau beim letzten Schritt komme ich irgendwie net weiter...


    Schematisch soll folgendes ablaufen...


    Tabelle mit Bytes meiner Adressen -> Adresse in Variable -> ab in die Subroutine -> über die aktuelle Adresse in der Variable Daten aus dem Speicher lesen und damit rumrechnen...


    Ich hab' so die Befürchtung, dass das wohl ohne selbstmodifizierenden Code net zu machen geht, also meine Subroutine z.B. ab $1000 assemblieren und die Bytes für die Adresse, die ich im jeweiligen Durchlauf verwenden will, direkt in die Speicherstelle schreiben, an der dann z.B. mein LDA $xxxx kommt.


    Wie würdet ihr das lösen?


    Gruß und Danke,


    Mnemonic

  • Wie wäre es mit Indexed Indirect Addressing ?
    Beispiel:


    Code
    1. LDX #00
    2. LDA ($FC,X)



    Akku wird mit dem Inhalt der Adresse geladen die in den Bytes $FC und $FD steht.
    Wenn in $FC z.B 00 und in $FD eine 01 stehen würden, dann hast du zum schluß
    den Wert von $0001 im Akku.


    hoffe es hilft..


    Grüße
    Björn

  • Ah, o.k.!


    Wenn ich's richtig verstehe, verwende ich dann halt zwei Register statt einer Variablen, kann dann aber nur momentan die Adresse "erzeugen" und hab' die nicht dauerhaft.


    Da ist dann noch das Problem, dass ich in meiner Subroutine ja auch einiges berechnen will, das wird dann wohl sehr knifflig.


    Ich will ja die erzeugte Adresse mehrmals in meiner Subroutine verwenden, da ich ab dieser (mit ggf. noch entsprechendem Offset) Daten aus dem Speicher holen will.


    So müsste ich die ja dann vor jedem Auslesen meiner Daten erst wieder neu erzeugen, oder?


    Gruß,


    Mnemonic

  • Solange Du an den Inhalten von $FC/$FD nichts änderst wird immer die gleiche Adresse genommen.
    Offset ist X, wenn du X um 1 erhöhst werden $FD/$FE zugrundegelegt.


    Oder Du legst im Speicher eine Tabelle ab und benutzt Indirect Indexed Addressing


    Mal angenommen du legst ab §1000 eine Tabelle der Adressen ab.


    dann geht das so:


    LDX #00
    LDA ($FC),X


    X ist hier der Offset und in $FC/$FD liegt der Start deiner Tabelle
    Es wird also nachgeschaut was in $FC/$FD steht und die dort stehende Adresse + X
    in den Akku geladen.
    Jetzt musst Du einfach X um jeweils 2 erhöhen um die nächste Adresse der Tabelle zu bekommen.


    und falls Du X gerade für was anderes brauchst dann gibt es ja noch den Stack (TXS, TSX)


    Grüße
    Björn

  • moooment... da stimmt jetzt aber mal so einiges nicht mehr ;)
    1.) TSX bzw. TXS beeinflussen den Stackpointer. Mit auf den Stack retten hat das nichts zu tun, du müsstest schon TXA und PHA bzw. PLA und TAX machen um das X Regsiter zu retten/ weiderherzustellen. (Natürlich würde eine TXS/ TSX Kombo das X register schon retten aber danach wäre der Stack mit 99% Wahrscheinlichkeit "zuerschossen", da ja der Stackpointer nicht mehr stimmt, da er ja mit dem Inhalt des X Regitsters überschrieben wurde)


    2.) Wenn die Addresstabelle bei $1000 liegt (also nicht in der Zeropage) ist obiges Beispiel schlicht falsch.
    Am besten du nimmst die indirekt indizierte Addressierung, ist erstens geeigneter und zweitens auch leichter zu verstehen, obwohl sehr ähnlich:


    Code
    1. lda #<addressen
    2. sta $fa
    3. lda #>addressen
    4. sta $fb
    5. ldy #0
    6. lda ($fa),y ; hole Lobyte der 1. Addresse in der TAbelle
    7. ...
    8. iny
    9. lda ($fa),y ; hole hi byte...


    ist so ähnlich wie die inidiziert indirekte aber eben abdersrum: also, der tatsächliche Wert der in den Akku geladen wird ist der der an der Addresse steht, auf die $fa/ $fb (im Beispiel) zeigt.
    Deshalb lädst du eben die anfangsaddresse der Tabelle in $fa (lobyte) und $fb (hibyte). Mit dem .Y Regsiter indizierst du dann, also da es sich ja um 16-bit Daten (Addressen) handelt, wäre eben mit .Y = 0 das Lobyte der 1. Addresse indiziert, mit Y=1 das Hibyte der 1. Addresse, mit Y=2 das Lobyte der 2. Addresse usw.

  • Die vorindizierte indirekte X-Adressierung dient dazu, vorgefertigte Zieltabellen zu verwenden. Du hast z.B. ab $1000 eine Tabelle mit Adressen irgendwo im VIC. Mit dem X-Register wählst du dann bequem eine bestimmte dieser Zieladressen aus. Der Ass-Befehl (STA oder LDA) beeinflusst den Wert an der Zieladresse (holt oder schreibt ihn). Hier findest du ein Schaubild zu dem Prozess: C64-Wiki.


    Arndt

  • moooment... da stimmt jetzt aber mal so einiges nicht mehr ;)
    1.) TSX bzw. TXS beeinflussen den Stackpointer. Mit auf den Stack retten hat das nichts zu tun, du müsstest schon TXA und PHA bzw. PLA und TAX machen um das X Regsiter zu retten/ weiderherzustellen. (Natürlich würde eine TXS/ TSX Kombo das X register schon retten aber danach wäre der Stack mit 99% Wahrscheinlichkeit "zuerschossen", da ja der Stackpointer nicht mehr stimmt, da er ja mit dem Inhalt des X Regitsters überschrieben wurde)

    Hast Du natürlich recht ;)


    Ich bin wohl gerade etwas durcheinandergekommen zwischen dem 6502 und dem ATMEGA


    Grüße
    Björn

  • Hallo nochmal! :winke:


    @hannenz: Supi, ich habe das mal so ausprobiert wie von Dir beschrieben, und es macht genau das, was ich gesucht habe! Hab's nach dem ausprobieren auch endlich begriffen und mir in meinen Source schön kommentiert.


    Danke auch an den Rest von Euch!


    Gutes Nächtle,


    Mnemonic