www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega asm - schon mal CPSE benutzt?


Autor: Alexander v. Grafenstein (avogra)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,

ich bin grad schon wieder zum X-ten mal über den Befehl CPSE gestolpert. 
Ich hab mich riesig gefreut, was der alles auf einmal macht - um dann 
festzustellen, dass er für mich genau falsch rum ist.

CPSE vergleicht zwei Register und überspringt den nächsten Befehl, wenn 
beide Register gleich sind.

ich hätt schon oft ein CPSN oder noch besser: CPISN gebraucht. Also dass 
der nächste Befehl übersprungen wird, wenn die beiden Register NICHT 
gleich sind bzw. wenn ein Register und eine Konstante ungleich sind. 
Auch ein TSTSN würd ich oft hernehmen, also Befehl überspringen, wenn 
ein Register nicht 0 ist.

Tragisch ist es natürlich nicht, dann muss ich eben 2 Befehle benutzen.

Aber irgendwie wundert mich, dass Atmel genau den Befehl implementiert 
hat, der zumindest meiner Meinung nach der nutzloseste der genannten 
Varianten ist.

Nimmt den von euch wer her und ich bin einfach noch nicht drauf 
gekommen, wie ich ihn richtig einsetz?

Grüße, Alex

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ist möglicherweise speziell für Funktionen wie strncpy/memchr... 
vorgesehen, die sowohl einen Zähler als auch einen Wert als 
Abbruchbedingung haben. Läuft dann raus auf sowas wie:

l1: ld   r1,x+
    dec  r2
    cpse r1,r0
    brne l1

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Alexander v. Grafenstein schrieb:
> Hey,
>
> ich bin grad schon wieder zum X-ten mal über den Befehl CPSE gestolpert.
> Ich hab mich riesig gefreut, was der alles auf einmal macht - um dann
> festzustellen, dass er für mich genau falsch rum ist.
>
> CPSE vergleicht zwei Register und überspringt den nächsten Befehl, wenn
> beide Register gleich sind.

komisch, geht mir genauso, ich ignoriere ihn seitdem eigentlich meist... 
;-)

In bestimmten Schleifen macht er Sinn, wenn der übersprungene Befehl 
dann der rjmp zum Schleifenanfang ist.

ldi r16, 0x55 ; als Vergleichswert
loop:

in r17,PORTB
cpse r16,r17
rjmp loop

...

loop:
in r17,PORTB
cpi r17,0x55
brne loop

macht hier letztlich das Gleiche und spart ein Register.
Man müßte also wohl gezihlt nach Anwendungen suchen???

Gruß aus Berlin
Michael

Autor: Alexander v. Grafenstein (avogra)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ok, dass könnte gut sein. Ich ärger mich einfach nur jedes mal, wenn 
ich ihn seh :) Danke für die Hinweise !

/edit: ui, geht das hier schnell

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

A. K. schrieb:
> Der ist möglicherweise speziell für Funktionen wie strncpy/memchr...
> vorgesehen, die sowohl einen Zähler als auch einen Wert als
> Abbruchbedingung haben. Läuft dann raus auf sowas wie:
>
> l1: ld   r1,x+
>     dec  r2
>     cpse r1,r0
>     brne l1

Hmmm...

 l1: ld   r1,x+
     dec  r2
     cp   r1,r0
     brne l1

macht das Gleiche, mir iat aber gerade der entscheidende Unterschied 
aufgefallen: CPSE verändert die Flags nicht!

da muß ich mal auf eine Anwendung achten...

Gruß aus Berlin
Michael

Autor: Alexander v. Grafenstein (avogra)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt. Jetzt hab ich auch das Beispiel von A.K. richtig verstanden. Da 
wird das voll ausgenutzt. Hatte gedacht, da fehlt doch noch was, wenn 
auf zwei Abbruch-Kriterien überprüft werden soll. D'oh :)

Sowas kann man dann wirklich seehr elegant machen.

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> l1: ld   r1,x+
>>     dec  r2
>>     cpse r1,r0
>>     brne l1

>Hmmm...

> l1: ld   r1,x+
>     dec  r2
>     cp   r1,r0
>     brne l1

>macht das Gleiche,

Nein macht es nicht. Das BRNE oben bezieht sich auf die Flags die beim 
DEC R2 verändert wurden. In deinem Beispiel bezieht sich BRNE auf den 
Vergleich CP r1,r0 wodurch dann auch das DEC R2 nicht ausgewertet wird 
und somit sinnfällig wäre.

Gruß Hagen

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Hagen schrieb:
>>> l1: ld   r1,x+
>>>     dec  r2
>>>     cpse r1,r0
>>>     brne l1
>
>>Hmmm...
>
>> l1: ld   r1,x+
>>     dec  r2
>>     cp   r1,r0
>>     brne l1
>
>>macht das Gleiche,
>
> Nein macht es nicht. Das BRNE oben bezieht sich auf die Flags die beim
> DEC R2 verändert wurden. In deinem Beispiel bezieht sich BRNE auf den
> Vergleich CP r1,r0 wodurch dann auch das DEC R2 nicht ausgewertet wird
> und somit sinnfällig wäre.
>
> Gruß Hagen

ja, war mir inzwischen aufgefallen, man muß sich eben die Befehle auch 
nach Jahren asm noch genau anschauen... :-)

Gruß aus Berlin
Michael

Autor: Hauke Sattler (hauke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende CPSE sehr gerne.

Für den inversen Fall von CPSE verwende ich zwei CPSE hintereinander .
Weiterhin habe ich meist ein Register auf Null reserviert.
Schleifen werden dadurch einfacher.
.def leer =r2
.def work =r16
clr leer
...
cpse work,leer
  cpse leer,leer
    JMP xxx

Vorteile:
FLAG neutral
Interruptfest
unbegrenzte Sprungmöglichkeiten (im Gegensatz zu Branch)
Festgelegte und konstante Taktanzahl

Für mehrere Vergleiche kann man auch CPSE Kaskaden verwenden, jedoch 
wird dass schnell unübersichtlich und sollte vermieden werden.

cu
Hauke

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der CodeVision-compiler liebt den cpse....
ATmega88 instruction use summary:
adc   :  12 add   :  13 adiw  :  10 and   :   1 andi  :   3 asr   :   0
bclr  :   0 bld   :   0 brbc  :   0 brbs  :   0 brcc  :   2 brcs  :   4
break :   0 breq  :  11 brge  :   0 brhc  :   0 brhs  :   0 brid  :   0
brie  :   0 brlo  :   8 brlt  :   0 brmi  :   0 brne  :  14 brpl  :   0
brsh  :   1 brtc  :   0 brts  :   0 brvc  :   0 brvs  :   0 bset  :   0
bst   :   0 cbi   :   5 cbr   :   1 clc   :   0 clh   :   0 cli   :   4
cln   :   0 clr   :  22 cls   :   0 clt   :   0 clv   :   0 clz   :   0
com   :   0 cp    :   2 cpc   :   5 cpi   :  21 cpse  :   0 dec   :   4
eor   :   0 fmul  :   0 fmuls :   0 fmulsu:   0 icall :   0 ijmp  :   0
in    :  10 inc   :   0 ld    :  28 ldd   :  14 ldi   : 156 lds   :  29
lpm   :   8 lsl   :   2 lsr   :   0 mov   :  19 movw  :  19 mul   :  12
muls  :   0 mulsu :   0 neg   :   0 nop   :   0 or    :   0 ori   :   3
out   :  41 pop   :   5 push  :   5 rcall :  50 ret   :  26 reti  :   6
rjmp  :  50 rol   :  10 ror   :   0 sbc   :   4 sbci  :   8 sbi   :  12
sbic  :   3 sbis  :   5 sbiw  :   8 sbr   :   2 sbrc  :   2 sbrs  :   0
sec   :   0 seh   :   0 sei   :   2 sen   :   0 ser   :   0 ses   :   0
set   :   0 sev   :   0 sez   :   0 sleep :   0 spm   :   0 st    :  27
std   :   8 sts   :  58 sub   :   2 subi  :  14 swap  :   0 tst   :   2

Man könnte mal suchen, wofür eingesetzt.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> cpse  :   0

Wenn ich die Tabelle richtig lese, wird cpse genau 0 mal eingesetzt.

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stop, Irrtum, die 21 sind für cpi.
cpse: 0.

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und aus einem andern Projekt, auch Fehlanzeige.
ATmega8 instruction use summary:
adc   :  23 add   :  19 adiw  :  37 and   :   2 andi  :   6 asr   :   0
bclr  :   0 bld   :  33 brbc  :   0 brbs  :   0 brcc  :   5 brcs  :   4
break :   0 breq  :  88 brge  :   3 brhc  :   0 brhs  :   0 brid  :   0
brie  :   0 brlo  :  34 brlt  :   2 brmi  :   9 brne  :  98 brpl  :   7
brsh  :  14 brtc  :   1 brts  :   1 brvc  :   4 brvs  :   4 bset  :   0
bst   :   3 cbi   :   5 cbr   :   0 clc   :   3 clh   :   0 cli   :   5
cln   :   0 clr   :  52 cls   :   0 clt   :  24 clv   :   0 clz   :   2
com   :   8 cp    :  19 cpc   :  13 cpi   : 137 cpse  :   0 dec   :  10
eor   :  12 fmul  :   0 fmuls :   0 fmulsu:   0 icall :   0 ijmp  :   0
in    :  10 inc   :   6 ld    :  67 ldd   :  96 ldi   : 373 lds   :  45
lpm   :  16 lsl   :  16 lsr   :   2 mov   : 106 movw  :  65 mul   :  15
muls  :   0 mulsu :   0 neg   :   4 nop   :   0 or    :   8 ori   :   7
out   :  50 pop   :  33 push  :  33 rcall : 635 ret   : 151 reti  :   4
rjmp  : 283 rol   :  31 ror   :  12 sbc   :   9 sbci  :  32 sbi   :   9
sbic  :   3 sbis  :   2 sbiw  :  31 sbr   :   1 sbrc  :  23 sbrs  :  46
sec   :   4 seh   :   0 sei   :   3 sen   :   0 ser   :   8 ses   :   0
set   :  20 sev   :   0 sez   :   1 sleep :   0 spm   :   0 st    : 136
std   :  31 sts   :  32 sub   :   6 subi  :  58 swap  :   0 tst   :  36
wdr   :   1
Instructions used: 78 out of 109 (71.6%)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.