PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verständnisfrage: cpi vs. andi



Kesandal
04.07.2011, 20:23
Hallo,

beschäftige mich erst neuerdings (gezwungenermaßen :D) mit Assembler.

Habe leider ein Verständnisproblem mit den Befehlen cpi und andi

Ich war bis jetzt der Meinung, dass ich mit cpi einen Vergleich mache.

Also:



cpi var_x, 0


if(x==0)



breq jp_true


wenn gleich: springe zu jp_true







soweit so gut.

Nun bin ich auf ein Problem gestoßen wenn ich PINA (an dem Port hängen Switches) abfragen möchte.

in C würde meine Abfrage lauten:



if ( PINA & _BV(1) != 0 ){
// Taste gedrückt
}


Nun der Assembler teil


in tmp, PINA





cpi tmp, 1


if(tmp==1)



breq jp_true


wenn gleich: springe zu jp_true







Das klappt so aber leider nicht :(

Statdessen klappt es wenn ich den Befehl andi nehme.
Kann mir bitte jemand sagen warum das so ist?

Muss ich bei PINx immer andi nehmen oder verwechsel ich die Bedeutung von cpi und mein "if(x==xyz)" muss ich mit andi realisieren.


Danke
Kesandal

Besserwessi
04.07.2011, 21:04
Der CPI Befehl (und die anderen ähnliche Formen wie CMP, CPC usw. ) dienen dazu Zahlenwerte zu vergleichen. Also ganze Bytes, oder zusammengesetzt auch 16 Bit Zahlen. Befehle wie ANDI und ähnliche sind Bitoperationen, da werden also die Bits verknüpft. Damit kann man dann einzelne Bits überprüfen.

Es gibt auch noch extra Befehle um direkt ein Bit abzufragen und dann ggf. einen Befehl zu überspringen. Das sind die Befehle SBRS, SBRC, SBIS und SBIC. Um entweder ein Bit im CPU Register (R0...R31) oder in einem der ersten 32 IO-Register zu testen.
Als andere Alternative um einzelne Bits zu testen gibt es noch den Befehl BST und dann als Sprung BRTC oder BRTS.

Die Bits vom IO Port haben eher selten die Bedeutung als Zahl - meist fragt man da die Bits einzeln ab.

Kesandal
04.07.2011, 22:01
Vielen Dank für Deine ausführliche Antwort. Diese hat Licht ins Dunkle gebracht :)

Eine Frage habe ich noch:

Warum funktioniert folgender Code




mainloop:
in tmp,PINA
mov save,tmp

mov tmp,save
andi tmp,2
breq taste1

mov tmp,save
andi tmp,1
breq taste0

rjmp mainloop


anstatt


mainloop:

in tmp,PINA
mov save,tmp

andi tmp,2
breq taste1

andi tmp,1
breq taste0

rjmp mainloop



Wieso muss ich erst tmp in ein weiteres Register kopieren um es anschließend wieder zurück zu kopieren?



Gruß und danke

PICture
04.07.2011, 22:56
Hallo!

... weil "andi" verändert den Inhalt vom "tmp". ;)

Kesandal
04.07.2011, 23:03
Hallo!

... weil "andi" verändert den Inhalt vom "tmp". ;)


oh.
Dann ist es klar :)

Vielen Dank für Deine Antwort!

Besserwessi
04.07.2011, 23:14
Wenn man die Abfrage mit dem Befehl BST und dem T Flag macht, kann man es auch ohne die extra Kopie machen.
Mit BST wird einfach das eine Bit direkt ins T Flag kopiert und kann dann für Sprünge benutzt werden. Also etwa so:

mainloop:

in tmp,PINA

BST tmp,1 ; Bit-Nummer, nicht bitwert !
brtc taste1

BST tmp,0
brtc taste0
...
rjmp mainloop