Forum: PC-Programmierung Schleife ASM 6502 : 300x256 durchführen


von Peter B. (funkheld)


Lesenswert?

Hallo, guten Tag.
Ich brauche bitte eine Schleife für 76800 Byte.

Das ist mein Anfang. Ich habe 256x256 schleifendurchgänge. Es fehlen 
noch 34 Schleifen. Wie kann man die bitte dort zwischen den 2x loop mit 
unterbringen oder muss ich am ende eine schleife mit 34x256 dranhängen?

------------------------------
   ldx #$00
 loop1:
    ldy #$00
  loop:
    lda #45
    sta $9f23
    iny
  bne loop
    inx
    bne loop1

   oder eine Schleife von 34x256 dranhängen?
-------------------------------

Danke.

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Nö, da fehlen dir noch 44.

Da aber nur ein fester Wert (45) an eine absolute Adresse (0x9f23) 
geschrieben wird:
1
    lda #45
2
    ldx #0
3
loop1:
4
    ldy #150
5
loop:
6
    sta $9f23
7
    sta $9f23
8
    dey
9
    bne loop
10
    dex
11
    bne loop1

von Ozvald K. (Firma: Privat) (ozvaldk)


Lesenswert?

Du könntest auch Bytes auf zero page verwenden, z.B. $10 und $11
    lda #44
    sta $10
    lda #01
    sta $11
    ldy #$00
  loop:
    lda #45
    sta $9f23
    iny
  bne loop
    dec $10
    bne loop
    dec $11
    bpl loop

von Kurt (sommerwin)


Lesenswert?

Welchen Sinn macht es 76800 (vermutl. verschiedene) Werte an eine 
einzige Adresse zu schreiben?

von Wastl (hartundweichware)


Lesenswert?

Kurt schrieb:
> Welchen Sinn macht es 76800 (vermutl. verschiedene) Werte an eine
> einzige Adresse zu schreiben?

320 * 240 = 76800

Klingelts?

von Wastl (hartundweichware)


Lesenswert?

Peter B. schrieb:
> Ich brauche bitte eine Schleife für 76800 Byte.

Wie wär's denn mit zweimal 38400?

von Norbert (der_norbert)


Lesenswert?

Kurt schrieb:
> Welchen Sinn macht es 76800 (vermutl. verschiedene) Werte an eine
> einzige Adresse zu schreiben?

Wenn es eine Peripherie-Adresse ist (VIA,RIOT), könnte zB. jedes mal ein 
Strobe erzeugt werden.

von Wastl (hartundweichware)


Lesenswert?

Norbert schrieb:
> könnte zB. jedes mal ein Strobe erzeugt werden.

Das hilft überhaupt nichts da es nicht das Problem löst über
die 16-Bit Grenze von 65535 hinaus zählen zu müssen.

von Norbert (der_norbert)


Lesenswert?

Wastl schrieb:
> Das hilft überhaupt nichts da es nicht das Problem löst über
> die 16-Bit Grenze von 65535 hinaus zählen zu müssen.

Wer soll denn da außer der CPU noch zählen? Einfach einen Sack voller 
gleicher Werte zB. an ein Display senden um es mit einer Farbe oder 
einem Muster zu initialisieren. Das Display wird dafür sorgen die 
eingehenden Daten angemessen zu verarbeiten.

von Wastl (hartundweichware)


Lesenswert?

Norbert schrieb:
> ...............

Ich sehe schon, du bist in der Assembler-Programmierung von
8-Bit Prozessoren voll fit.

von Norbert (der_norbert)


Lesenswert?

Wastl schrieb:
> Norbert schrieb:
>> ...............
>
> Ich sehe schon, du bist in der Assembler-Programmierung von
> 8-Bit Prozessoren voll fit.

Sag mal, hast du getrunken?
Schau dir mal meinen Code oben an.
Und dann versuche einfach mal 150 × 2 × 256 zu rechnen!

von Mario M. (thelonging)


Lesenswert?

Was Peter macht, ist wie immer voll geheim. Ich glaube, es geht darum:
https://www.8bitcoding.com/p/vera-overview.html?m=1

: Bearbeitet durch User
von Kurt (sommerwin)


Lesenswert?

Wastl schrieb:
> Das hilft überhaupt nichts da es nicht das Problem löst über
> die 16-Bit Grenze von 65535 hinaus zählen zu müssen.

Das ist korrekt, mit x und y lassen sich 256*256 = 65536 Werte zählen. 
Um bis 76800 zu zählen kommt man also um eine zweite Schleife nicht 
herum. Verstehe nur den Sinn des ganzen nicht...

von Norbert (der_norbert)


Lesenswert?

Kurt schrieb:
> Verstehe nur den Sinn des ganzen nicht...

Du musst dich nur ein wenig mit der Ansteuerung von Hardware 
beschäftigen, dann wird das…

von Mario M. (thelonging)


Lesenswert?

Das ist eine Grafikkarte, siehe Link weiter oben. Man könnte auch 
einfach mehrfach schreiben und entsprechend weniger wiederholen.

von Kurt (sommerwin)


Lesenswert?

Meine C-128 Zeiten sind lang vorbei...

von Peter D. (peda)


Lesenswert?

Man darf auch in Assembler weiter rechnen als nur bis 255. Dazu werden 
mehrere 8Bit Variablen zusammen gefaßt.
Im einfachsten Fall nimmst Du ein C-Programm, legst eine Schleife mit 
32Bit Variable an und läßt es nach Assembler übersetzen.

von Kurt (sommerwin)


Lesenswert?

Peter D. schrieb:
> Man darf auch in Assembler weiter rechnen als nur bis 255. Dazu werden
> mehrere 8Bit Variablen zusammen gefaßt.
> Im einfachsten Fall nimmst Du ein C-Programm, legst eine Schleife mit
> 32Bit Variable an und läßt es nach Assembler übersetzen.

Recht und schön, funktioniert aber nicht mit beim 6502. Der hat nur 
einen 8 Bit Datenbus und 16 Bit breiten Adressbus. Der 6502 kann auch 
Arrays grösser 256 nur blockweise ansprechen.

von Norbert (der_norbert)


Lesenswert?

Kurt schrieb:
> Recht und schön, funktioniert aber nicht mit beim 6502.

Wäre schön wenn hier nur Leute schrieben, die sich zumindest mal auf 
weniger als 500m einem Assembler genähert hätten. Über handgedengelten 
Maschinencode will ich schon gar nicht schreiben.

Aber – dies ist ja mittlerweile das Arduino Forum - was will man 
erwarten…

PS: Es gab auch mal einen 4004 Prozessor. Der konnte dann wohl nur bis 
fünfzehn zählen…

: Bearbeitet durch User
von Mario M. (thelonging)


Lesenswert?

Kurt schrieb:
> Der 6502 kann auch Arrays grösser 256 nur blockweise ansprechen.

Es geht hier nicht um Arrays, sondern um Wiederholungen. Und Zähler kann 
man so breit aufbauen, wie man Speicher hat.

von Norbert (der_norbert)


Lesenswert?

Mario M. schrieb:
> Es geht hier nicht um Arrays,

…und selbst wenn es um Arrays ginge, selbst dann wäre seine Aussage 
falsch.
Und zwar so falsch das noch nicht einmal das Gegenteil richtig wäre.

Der 6502 kannte natürlich auch indirect,indexed und ebenso 
indexed,indirect.
Und damit konnte man den kompletten Adressbereich ohne – wie war das, 
"Blöcke" – abarbeiten.

von Peter D. (peda)


Lesenswert?

Kurt schrieb:
> Recht und schön, funktioniert aber nicht mit beim 6502. Der hat nur
> einen 8 Bit Datenbus und 16 Bit breiten Adressbus.

Hat der 8051 auch nur. Trotzdem benutze ich dort problemlos 32Bit long 
und 32Bit float Variablen. Der Compiler bastelt sich das automatisch aus 
4 Byte im RAM oder in Registern zusammen, in Assembler muß man das eben 
händisch machen.

: Bearbeitet durch User
von Martin H. (horo)


Lesenswert?

Peter D. schrieb:
> in Assembler muß man das eben händisch machen.

Schön ist das nicht, aber „wat mutt, dat mutt“.
Um eine weitere 8-Bit-Familie ins Spiel zu bringen, ein beispielhaftes 
32-Bit-Macro für PIC (wie ich die Syntax hasse, einfach nur hässlich, 
wie schön war doch Z80):
1
;--------------------------------------------------------------------------
2
; MACRO to perform 32-bit addition - adds the four bytes at src
3
; to the four bytes at dst (most significant bytes first), returns the
4
; result in dst with src unchanged and the carry flag set if overflow
5
;--------------------------------------------------------------------------
6
7
ADDx32  MACRO   src, dst          ;dst := dst + src
8
9
        bcf     STATUS, C
10
        movf    src+3, w
11
        btfsc   STATUS, C
12
        incfsz  src+3, w
13
        addwf   dst+3, f
14
        movf    src+2, w
15
        btfsc   STATUS, C
16
        incfsz  src+2, w
17
        addwf   dst+2, f
18
        movf    src+1, w
19
        btfsc   STATUS, C
20
        incfsz  src+1, w
21
        addwf   dst+1, f
22
        movf    src+0, w
23
        btfsc   STATUS, C
24
        incfsz  src+0, w
25
        addwf   dst+0, f
26
27
        ENDM

: Bearbeitet durch User
von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Peter D. schrieb:

> Der Compiler bastelt sich das automatisch aus
> 4 Byte im RAM oder in Registern zusammen, in Assembler muß man das eben
> händisch machen.

Genau. Und der funkheld wird das wohl nie wirklich lernen. Der versucht 
sich mit unzähligen Architekturen, begreift aber offensichtlich bei 
keiner davon auch nur irgendetwas.

Crackhead oder Troll? Ich bin mir trotz der langen Historie seiner 
Bemühungen immer noch nicht sicher.

von Kurt (sommerwin)


Lesenswert?

Norbert schrieb:
> und selbst wenn es um Arrays ginge, selbst dann wäre seine Aussage
> falsch.
> Und zwar so falsch das noch nicht einmal das Gegenteil richtig wäre.
> Der 6502 kannte natürlich auch indirect,indexed und ebenso
> indexed,indirect.
> Und damit konnte man den kompletten Adressbereich ohne – wie war das,
> "Blöcke" – abarbeiten.

Achso, das stimmt also nicht?

Wie gross ist denn das x und y Register vom 6502?

Und wenn ich jetzt einen Speicherblock (Array) ansprechen will, geht das 
dann auf einen Rutsch oder blockweise?

Und wenn ich jetzt indirekt adressiere z.B mit <lda ($45),y  inc y...> 
kann er dann weiter zählen als bis zum Maximum des y Wertes?

Spätestens dann muss der Wert von im Beispiel $45 geändert werden um den 
restlichen Speicher zu adressieren.

von Norbert (der_norbert)


Lesenswert?

Ich sehe schon, du hast dein Wissen nun um eine Seite erweitert.

Zumindest hast du erkannt, das man die Basisadresse auf die in der ZP 
verwiesen wird, beliebig ändern (zB. inkrementieren) kann. Das ist sogar 
der tiefer liegende Sinn des ›indirect‹

Man kann diese auch 2^16-1 × inkrementieren (oder ein Gemisch aus Basis 
und Index). Das hatte MOS (der Hersteller) schon Mitte der Siebziger 
erkannt und in ihrem ›Programming Manual‹ freundlicherweise sehr sauber 
dokumentiert.

Du jedoch schriebst:
Kurt schrieb:
> Der 6502 kann auch
> Arrays grösser 256 nur blockweise ansprechen.

MOS ist da eben anderer Meinung. Wenn man sich allerdings explizit nur 
auf Änderung der X/Y Register versteifen möchte, dann bleibt man in 
seinem 8Bit Denken verfangen…

Du denkst offensichtlich an ›absolute indexed addressing‹ und ja, damit 
kann man nur 256 Bytes mittels X oder Y Register ansprechen. Es gibt 
aber mehr…

Fakt bleibt, Arrays (egal welcher Größe bis zum maximalen Adressraum) 
können Byte-weise angesprochen werden. Sowohl ›indirect‹ als auch 
›indirect indexed‹. Der Programmierer hat da freie Wahl. Einfach indem 
er den ›indirect‹ Part und vielleicht auch noch den ›indexed‹ Part 
ändert.

Nu wird's aber langweilig…

von Re (r42)


Lesenswert?

Kurt schrieb:
> Und wenn ich jetzt indirekt adressiere z.B mit <lda ($45),y  inc y...>
> kann er dann weiter zählen als bis zum Maximum des y Wertes?

Wenn man nicht darauf besteht, Y hochzählen zu lassen, sondern das 
Bytepaar {$45/$46} hochzählen lässt, dann geht das durchaus. Nicht nur 
blockweise.

Die Zero-Page des 6205 kann man dabei als erweiterte Registerbank 
betrachten, ähnlich wie beim AVR der Speicherbereich 0x00-0x1f, der dort 
explizit auf die Register r0..r31 gemapt ist.



Kurt schrieb:
> Welchen Sinn macht es 76800 (vermutl. verschiedene) Werte an eine
> einzige Adresse zu schreiben?

Zugriff auf Speicher, die größer als die 16-Bit des Adressbusses des 
6502 sind. Hat man auch bei Z80 oder 8051  schon so gemacht. 
Grafikkarten, Massenspeicher, Peripherie, ...



Drittens: Zählen (um das ging es dem TO) kann der 6502 so weit, wie man 
Speicherstellen benutzt, also auch 32-Bit oder 64-Bit oder noch 
längeres, so weit der Speicher reicht.


Man muss sich nur davon lösen, das alles ausschließlich mit A oder Y 
oder X machen zu wollen, sondern die Mittel nutzen, die der Prozessor 
sonst noch zur Verfügung stellt.


HTH, (re)

von Kurt (sommerwin)


Lesenswert?

Re schrieb:
> Wenn man nicht darauf besteht, Y hochzählen zu lassen, sondern das
> Bytepaar {$45/$46} hochzählen lässt, dann geht das durchaus. Nicht nur
> blockweise.

Klar kann man damit eine 16 bit Zahl darstellen, aber wie gross kann 
denn der Wert von $45 oder $46 werden? Spätestens bei $00 oder $ff muss 
einer der beiden Zeiger geändert werden wenn weiter gezählt werden soll.

von Re (r42)


Lesenswert?

Kurt schrieb:
> Spätestens bei $00 oder $ff muss
> einer der beiden Zeiger geändert werden wenn weiter gezählt werden soll.

Das ist ein 16-Bit-Zeiger, der da in %45/$46 abgelegt ist:

https://web.archive.org/web/20221112220344if_/http://archive.6502.org/datasheets/synertek_programming_manual.pdf 
[Seite 87]


(re)

von Norbert (der_norbert)


Lesenswert?

Es ist EIN Zeiger (wie von Re schon geschrieben wurde)!
1
version1:
2
    ldx     #10
3
    stx     ARRPTR+1    ; high array beginnt bei $1000
4
    ldx     #0
5
    stx     ARRPTR      ; low
6
loop1:                  ; 61440×, bis Adresse $FFFF
7
    lda     (ARRPTR,X)  ; Array byteweise lesen
8
    eor     #$ff        ; und bits invertieren
9
    sta     (ARRPTR,X)  ; Array byteweise schreiben
10
    inc     ARRPTR      ; nächste Adresse im Array
11
    bne     loop1
12
    inc     ARRPTR+1
13
    bne     loop1
14
15
version2:
16
    ldx     #10
17
    stx     ARRPTR+1    ; high array beginnt bei $1000
18
    ldx     #0
19
    stx     ARRPTR      ; low
20
loop2:                  ; 61440×, bis Adresse $FFFF
21
    lda     (ARRPTR,X)  ; Array byteweise lesen
22
    eor     #$ff        ; und bits invertieren
23
    sta     (ARRPTR,X)  ; Array byteweise schreiben
24
    inx                 ; nächste Adresse im Array
25
    bne     loop2
26
    inc     ARRPTR+1
27
    bne     loop2

Entweder nur über ARRPTR oder über Kombination mit X (spart 3 cycles pro 
Schleife)

: Bearbeitet durch User
von Kurt (sommerwin)


Lesenswert?

Natürlich ist das ein Zeiger, wo hasst in dein Beispiel die beiden 
Pointer definiert?

Und dein Pogramm macht genau das, was ich die ganze Zeit hier schreibe. 
Du lädst in dem ersten Beispiel x mit 00 und zählst bis ff hoch. 
Anschliessend erhöhst du das Highbyte deines Pointers. Und weil das 
Highbyte des Pointers nicht ausgewertet wird, haben wir jetzt eine 
Enlosschleife.

von Norbert (der_norbert)


Lesenswert?

Kurt schrieb:
> wo hasst(sic) in dein Beispiel die beiden
> Pointer definiert?

Oh ja, das ist natürlich ein schwieriger Code-Komplex. Das liefere ich 
nach.
1
ARRPTR = $40
oder auch gerne irgendwo sonst in der ZP. Und es hat auf die Diskussion 
keinerlei Einfluß. Lenkt aber vielleicht etwas ab.

Und es ist immer noch EIN Zeiger. Nur EINER! Und der ist 16Bit breit.

Kurt schrieb:
> Und weil das
> Highbyte des Pointers nicht ausgewertet wird, haben wir jetzt eine
> Enlosschleife.

Das ist natürlich auch schwierig.
1
    inc     ARRPTR+1
2
    bne     loop1

Ich hoffe jetzt inständig das ich das Z-Flag nicht erklären muss.

Zum Rest deiner Ausführungen:
Kurt schrieb:
> macht genau das, was ich die ganze Zeit hier schreibe.

Nein, das hast du nicht geschrieben!
Ich habe aber jetzt wirklich keine Lust mehr auf dein ständiges 
Herauswinden.

von Kurt (sommerwin)


Lesenswert?

Norbert schrieb:
> Ich hoffe jetzt inständig das ich das Z-Flag nicht erklären muss.

Sorry, da hast du recht, ist ein Fehler von mir.

Norbert schrieb:
> ARRPTR = $40

ARRPTR = $40, das ist eine 8 bit Adresse -- ARRPTR+1 = $41, ebenso 8 
bit, beide zusammen 16 bit und nicht einer allein. Wenn du mit 16 bit 
rechnen willst, brauchst du Low und High Byte

Man könnts auch direkt schreiben: lda $40 - eor #$ff - sta $40 und 
später inc $41


Schreib jetz auch nix mehr, iss mir einfach zu dumm...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.