PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Inline Assembler: gezielt auf Array-Felder zugreifen



malthy
08.06.2012, 13:48
Moin!

Ich möchte in einer Assembler ISR-Routine auf die Felder eines vorher definierten Byte Arrays zugreifen. Mein (soweit funktionierender) Ansatz sieht jetzt wie folgt aus (wobei das natürlich nur ein Testcode ist um erstmal das Prinzip zu erarbeiten). Ich habe aber ein Verständnisproblem mit dem add (s.u.).



$asm
Loadadr A(1) , X
ldi r23, 4
add r26, r23
ld R22, X
STS {I}, R22
$end Asm


Zur Erläuterung: das Array heißt A und sei <255 Felder (= Bytes) groß. Ich lade die Adresse vom ersten Feld nach X, also in das Registerpaar R26:R27. in R23 steht der (nullbasierte) Index des Feldes (im Bsp 4) auf das ich zugreifen möchte. Ich addiere dann einfach R23 auf R26 (was ja das Lowbyte von X ist), also den gewünschten Index. Dann lade ich den Inhalt der Adresse X, was nun dem gewünschten Index entspricht nach R22 um von dann damit weiterzuarbeiten (hier einfach in das Byte I übertragen). Was ist aber mit dem Übertrag bei der Addition? also angenommen das Lowbyte der Adresse ist schon 253 und würde darauf 6 addieren? Passiert der Übertrag ins R27 automatisch? Oder geht das Ganze sowieso anders eleganter :-)?

Danke für alle Hinweise!

Gruß
Malte

MagicWSmoke
08.06.2012, 18:06
Was ist aber mit dem Übertrag bei der Addition?
Der landet im Carry.

Passiert der Übertrag ins R27 automatisch?
Nein da geht nix automatisch, Du musst mit ADC eine 0 zu R27 addieren, dabei wird das Carry berücksichtigt.

Oder geht das Ganze sowieso anders eleganter ?
Nein, das ist der übliche Weg um in einem AVR absolut ein Array zu adressieren.
Will man ab dieser Stelle auf-/absteigend weiterlesen, so verwendet man LD rxx, X+ und LD rxx, -X

malthy
08.06.2012, 19:13
Hallo,

danke für die Unterstützung! Bei Verwendung von ADC muss der abzuziehende Wert ja per Register übergeben werden, erfordert also einen zusätzlichen Befehl. Gibt es einen "add immediate with carry", sodass ich die 0 direkt übergeben kann? Ich habe nur einen SBCI (Subtract Immediate with Carry) gefunden...

Gruß
Malte

MagicWSmoke
08.06.2012, 21:01
Hallo malthy,

Bei Verwendung von ADC muss der abzuziehende Wert ja per Register übergeben werden, erfordert also einen zusätzlichen Befehl.
"abzuziehende" ? Aber ansonsten, ja, so ist es.

Gibt es einen "add immediate with carry", sodass ich die 0 direkt übergeben kann?
Nein, gibt's nicht, da musst Du ein Hilfsregister für ADC nehmen. Was aber nicht weiter tragisch ist, denn braucht man mehrmals eine 0, dann reserviert man sich ein Register extra dafür. In C ist das von Haus aus z.B. R1.

Ich habe nur einen SBCI (Subtract Immediate with Carry) gefunden...
Das hilft Dir nix, da das Carry dabei subtrahiert würde.
Du kannst den Bascom Simulator für Testcode benutzen, lass Dir das Register-Fenster anzeigen und wähle in den Tabs links oben "uP" aus, da siehst Du das SREG und dort die einzelnen Flags.

malthy
08.06.2012, 21:14
Hallo nochmal,


Zitat (http://www.atmel.com/Images/doc0937.pdf)

As the AVR has no add immediate or add immediate with carry ... .

ja, habe mitlerweile auch von dieser "Asymmetrie" der AVRs gelesen :-). Aber im Prinzip müsste doch auch ein SBCI den Zweck erfüllen, ob ich 0 abziehe oder draufaddiere macht ja keinen großen Unterschied. Oder übersehe ich da was?

EDIT: sorry, war blöd ein add immediate ohne carry (fürs lowbyte) gibt' ja auch nicht. Ich komme um die Register also nicht drumrum...

Was ich oben übrigens mit "abzuziehender Wert" meinte, wäre eben die 0, die ich extra in ein Register legen müsste...

Danke!
Malte

MagicWSmoke
08.06.2012, 21:31
Aber im Prinzip müsste doch auch ein SBCI den Zweck erfüllen, ob ich 0 abziehe oder draufaddiere macht ja keinen großen Unterschied. Oder übersehe ich da was?
Für diesen Zweck riet ich Dir den Simulator zu benutzen, dann kannst Du Versuche anstellen und sehen was dabei raus kommt.

EDIT: sorry, war blöd ein add immediate ohne carry (fürs lowbyte) gibt' ja auch nicht. Ich komme um die Register also nicht drumrum...
Als Index auf ein Array hast Du meist eine Variable, das ergibt sich quasi von selbst, dass Du dafür ein Register brauchst.
Wenn Du einen konstanten Offset willst, ohne dass das Register erhöht wird, dann kannst Du LD rxx, Z+x schreiben, geht aber nur für das Y und Z Register.

Was ich oben übrigens mit "abzuziehender Wert" meinte, wäre eben die 0, die ich extra in ein Register legen müsste...
Du willst einen Index auf den Start des Arrays addieren, Du willst nix abziehen :D

malthy
08.06.2012, 21:37
Du willst nix abziehen :D

Ach, sorry, hast natürlich Recht. Mit schwirrt gleichzeitig ein anderes Problem im Kopf rum, da will ich abziehen. Etwas zerstreut heute... :-)

Alles in allem: ja, mit den Infos komme ich erstmal weiter. Mir geht's schon auch darum einigermaßen "optimal" zu proggen. Deswegen feilsche ich um jeden Prozessortakt - aber primär aus sportlichem Ehrgeiz. Schaden kann's ja nicht viel...

Dank Dir!
Malte