PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Adressierung mit Displacment



gulliver
26.06.2007, 16:07
Hallo

Wie kann ich eine Adressierung mit Offset bewerkstelligen?
Optimal und kurz wäre eine Adressierung mit Displacment. Was ist das Displacment eigentlich? Kann ich dafür nur eine Zahl einsetzen oder geht es auch über eine Variable? Eine Zahl ist etwas festes und für meinen Zweck nicht brauchbar.
Letztendlich sind es doch alles nur Zahlen für den Prozessor.

Mein Problem:
.dseg
Modulblock:
Prog1: .byte 4 ;jeweils 4 Byte reservieren
Prog2: .byte 4
Prog3: .byte 4
...

Nachdem die Werte eingetragen wurden, sieht es im Speicher dann z.B. so aus:
ab Adr. Prog1: 0 1 2 255 (entsprechend r,g,b,255)
ab Adr. Prog2: 1 2 0 255
ab Adr. Prog3: 2 1 0 255
...

Auf den Blockanfang möchte ich einen festen Zeiger haben (Modulblock). Dies ist kein Thema.
Nun habe ich einen Zeilen- und einen Spaltenoffset. Diese werden addiert und sollten in ldd R,Z+q als Displacment q dienen.
Bei allen anderen Ladebefehlen würde sich die Adresse jedesmal ändern, da ich den Offset jedesmal hinzuaddieren müßte. Dagegen ändert sich die Adresse bei dem Displacmentbefehl nicht, es wird nur mit Offset zugegriffen. Darum erscheint mir dieser am geeignetsten.

Nun hatte ich schon verschiedene Möglichkeiten probiert und komme auf keine kurze Lösung. Der einzig gangbare Weg war bisher die Offsets zu addieren und diese Summe anschließend zur Grundadresse hinzuaddieren. Dazu mußte diese vorher immer ge'push't und nach dem Zugriff wieder ge'pop't werden.
Gibt es nur diesen Weg oder kann man dies noch anders hinkriegen?

mfg Roger

wkrug
26.06.2007, 18:09
Mit

LDS r16,(Prog1)
LDS r17,(Prog1+1)
LDS r18,(Prog1+3)
...

gehs nicht ?

Bei den Klammern bin ich mir jetzt nicht ganz sicher ob die stimmen, ne # reinkommt, oder gar nichts, aber ansonsten...

JanB
26.06.2007, 19:28
Hallo,

Der Offset q beim LDD Rd,Y+q Befehl kann max. +-32 groß sein.
Er ist fest in dem OPcode eingebaut, kann also leider
nicht aus einem Register kommen.
Mein Vorschlag wäre den LD Rd,Z zu benutzen.
"Push" und "Pop" würde ich dabei aber lassen, das kostet zuviel Zeit.
Stattdessen die Grundadresse lieber in einem Registerpaar halten
und von dort mit MOVW Rd,Rd holen.

z.B.
;Einmal bei Programmstart:
CLR R2 ;null nach Register 2
LDI R4,low(Grundaddr<<1)
LDI R5,high(Grundaddr<<1)

;Jetzt der Zugriff später im Prog:
MOVW Z,R4 ;R4 und R5 halten die Grundadresse
ADD ZL,R6 ;R6 enthält Offset1
ADC ZH,R2 ;R2 enthält 0
ADD ZL,R7 ;R7 enthält Offset2
ADC ZH,R2
LD R8,Z ;Lesen aus der Grundadresse+Offset1+Offset2

Das Berechnen des Offset inkl. Holen der Grundadresse dauert so 5 Taktzyklen

Gruß Jan

gulliver
26.06.2007, 21:08
Danke erst mal für den Feedback.
Im ersten Beitrag ist ja der klassische Weg, den ich so nicht wollte. Ich suche nach einer Möglichkeit wie:

.dseg
index: .byte

.cseg
loop:
...
ldd temp1,Z+index
...
Die Adresse von index steht in Y
...
ld temp2,Y
inc temp2
st Y,temp2
...
rjmp loop
...

Wenn das Displacment fest im Opcode eingebaut ist, hat sich der Fall für mich erledigt und ich muß den Umweg über Registeraddition zur Adresse machen. Da ich alle Adreßregister verplant habe, muß ich mich mit einer Doppelnutzung begnügen, wo ich dann kurz zwischensichern muß.

Die Zeit spielt keine allzu große Rolle. In einem 5ms-Abstand bei 8MHz hat man reichlich Takte zur Verfügung. Die Hauptarbeit wird über PWM gemacht und den Timer habe ich nur zum Aufwachen genommen. Dann springt das Programm wieder in die Bearbeitungsroutine damit die Leistung der Led's wieder einen Tick mehr nach oben oder unten geregelt wird und danach pennt er weiter. Hätte auch den Wachhund nehmen können, aber bei dem weiß ich im Fehlerfall unter Umständen nicht so genau woher der Sprung zu Reset kommen könnte, vom Watch Dog oder Programmfehler. Darum nehme ich ihn nicht so gern.

Jan, danke für den Tip mit dem Opcode. Auf die Idee bin ich noch garnicht gekommen, mir diesen mal genauer anzusehen. Ich habe mich bisher immer nur für die Schreibweise der Befehle und die Parameter interessiert.

mfg Roger