STA ($ll), Y

Aus C64-Wiki
Zur Navigation springenZur Suche springen
Mnemonic: STA ($ll), Y
Opcode: $91
Operand(en): $ll
Anzahl der Bytes: 2
Befehlsgruppe: Transfer-Befehl
Adressierung: indirekt Y-nachindiziert
Beeinflusste Flags im Statusregister:
keine
Taktzyklen: 6
1 PC Lese Opcode,
inkrementiere PC
2 PC Lese Zeigeradresse,
inkrementiere PC
3 Pointer R lese effektive Adresse Low
4 Pointer R lese effektive Adresse High,
addiere Y zum Lowbyte der
effektiven Adresse
5 Adresse + Y* R lese von effektiver Adresse,
korrigiere Highbyte der
effektiven Adresse
6 Adresse + Y W schreiben auf effektive Adresse
Anmerkung: Die effektive Adresse wird immer aus der Zeropage gelesen
Anmerkung: * das Highbyte der effektiven Adresse
könnte zu diesem Zeitpunkt ungültig sein


Der Assembler-Befehl STA ($ll),Y speichert den Wert des Akkumulators in die Speicherzelle jener Adresse, die sich aus der Zeigeradresse (LSB=$ll ; MSB=$ll+1) plus dem Y-Register zusammen setzt.

Man beachte, dass die Adresse selbst in einem Zwei-Byte-Block (Word) innerhalb der Zeropage liegt!

Funktionsprinzip

Bedeutung der Buchstaben im Befehl

STA STore Accumulator
Speichere Akkumulator

Beispiel

; Dieses Programm füllt den gesamten Bildschirm mit Leerzeichen.
; Programmstart mit SYS 49152
; Hinweis: Der Bildschirmspeicher ist nur 1000 Bytes groß. Im Beispiel
; wird der Einfachheit halber ein Bereich von 1024 Bytes überschrieben.
; Dies hat zur Folge, dass auch die Sprite-Pointer verändert werden.
 
*=$c000         ; Startadresse des Programms
 
SCREENMEM  = $fb
BLOECKE    = $04
ZEICHEN    = " "

start      lda #$00             ; $fc/$fb = $0400 = Bildschirmspeicher
           sta SCREENMEM
           lda #$04
           sta SCREENMEM+1

           ldx #BLOECKE         ; 4 Blöcke (4*256 Byte)

           ldy #$00
           lda #ZEICHEN         ; Füllzeichen = Leerzeichen
schleife   sta (SCREENMEM),Y    ; in den Bildschirm schreiben
           iny                  ; y um 1 erhöhen
           bne schleife         ; wiederhole bis y=0 (256 Durchläufe) 

           inc SCREENMEM+1      ; nächster Block des Bildschirmspeichers
           dex                  ; Blockschleifenzähler um 1 vermindern
           bne schleife         ; wiederhole bis Blockschleifenzähler=0

           rts                  ; Rücksprung zu BASIC

Speicherauszug:

.c000  a9 00  lda #$00
.c002  85 fb  sta $fb
.c004  a9 04  lda #$04
.c006  85 fc  sta $fc
.c008  a2 04  ldx #$04
.c00a  a0 00  ldy #$00									 
.c00c  a9 20  lda #$20
.c00e  91 fb  sta ($fb),y
.c010  c8     iny
.c011  d0 fb  bne $c00e
.c013  e6 fc  inc $fc
.c015  ca     dex
.c016  d0 f6  bne $c00e
.c018  60     rts

Alternative Implementierung

; Wenn man den Speicherbereich umgekehrt, also von oben nach
; unten, befüllt, kann das Y-Register auch als Low-Byte eines
; Zählers verwendet werden. Dadurch ist mit wenig Zusatzaufwand 
; ein byte-genaues Befüllen möglich.

*=$c000         ; Startadresse des Programms

SCRNPNTR = $fb          ; Zeropage-Pointer
STARTSCREEN = $0400     ; Beginn Bildschirmspeicher
LEN = 1000              ; Länge des Bildschirmspeichers
ZEICHEN = " "           ; Füllzeichen

start:  lda #<STARTSCREEN       ; Low-Byte der Bildschirmspeicheradresse
        sta SCRNPNTR            ; in Pointer schreiben
        clc                     ; Addition vorbereiten
        lda #>STARTSCREEN       ; auf High-Byte der Bildschirmspeicheradresse
        adc #>(LEN-1)           ; das High-Byte der Bereichsgröße - 1 addieren
        sta SCRNPNTR+1          ; und in das High-Byte des Pointers schreiben
        ldy #<(LEN-1)           ; das Low-Byte der Bereichgröße - 1 in das Y-Register laden
        ldx #(>(LEN-1))+1       ; das High-Byte der Bereichsgröße - 1 um 1 erhöht laden
        lda #ZEICHEN            ; Füllzeichen in den Akkumulator
       
-       sta (SCRNPNTR),y        ; Zeichen in den Bildschirm schreiben
        dey                     ; y um 1 dekrementieren
        bne -                   ; wiederhole bis y=0
        sta (SCRNPNTR),y        ; Zeichen für Index=0 schreiben
        dey                     ; y durch dekrementieren auf $FF (255) setzen
        dec SCRNPNTR+1          ; High-Byte des Pointers dekrementieren
        dex                     ; High-Byte des Zählers dekrementieren
        bne -                   ; wiederhole bis x=0
       
        rts                     ; Rücksprung

Speicherauszug:

.c000  A9 00       LDA #$00
.c002  85 FB       STA $FB
.c004  18          CLC
.c005  A9 04       LDA #$04
.c007  69 03       ADC #$03
.c009  85 FC       STA $FC
.c00b  A0 E7       LDY #$E7
.c00d  A2 04       LDX #$04
.c00f  A9 20       LDA #$20
.c011  91 FB       STA ($FB),Y
.c013  88          DEY
.c014  D0 FB       BNE $C011
.c016  91 FB       STA ($FB),Y
.c018  88          DEY
.c019  C6 FC       DEC $FC
.c01b  CA          DEX
.c01c  D0 F3       BNE $C011
.c01e  60          RTS

Beispielprogramme