Ich steige beim Atmel nicht durch die Befehle des Vergleichens!
Ich habe zwar schon Befehle wie:
BREQ
BRLT
BRLO
gefunden, aber ich habe noch kein
"Springe wenn wahr" gesehen.
Wo ist dieser Sprungbefehl?
Bei rjmp macht man doch das gleiche wie bei jmp, oder?
OH jetzt habe ich es.
Da ist auch ein CP Befehl.
Heißt dass, dass man einen bedingten Sprung jetzt so macht
CP R17,R18
BRLO MeinLabel
???????????
Naja in der Beschreibung steht, dass man damit vergleicht und
anscheinend gleich den nächsten Befehl überspringt wenn es gleich ist.
Damit kann man sicher was machen, z.B.: kann man irgendwohin springenl,
wenn es gleich ist und irgendwoanders hin, wenn es kleiner ist.
Das kombiniert wäre ...
Naja das bekommt man mit cmp auch hin.
Der Befehl spart vielleich eine Zeile Programmierarbeit :-)
Dieser Befehl ist so speziell, dass es ganz bestimmte wichtige
Anwendungen dafür geben muss, ansonsten gäbe es ich nicht. Aber
welche?
Bislang gefunden: memchr/strnlen und dergleichen:
l1: ld r1,x+
dec r2
cpse r1,r0
brne l1
Ohne CPSE
l2: ld r1,x+
cp r1,r0
breq l3
dec r2
brne l2
l3:
ist es auch nur 1 Takt langsamer.
Hallo Leute, schön zu sehen, daß ich nicht der einzige bin, dem der cpse
Befehl sehr sinnfrei vorkommt. Ich habe dutzende Fälle, wo ich genau das
Gegenteil von dem cpse bräuchte, also cpsne (z.B. für switch case
Blöcke). Aber ich hatte bisher nur einen Fall, wo ich den cpse
einsetzen konnte:
; RAM löschen
clr r16
ldi r17,HIGH(RAMEND)
ldi r18,LOW(RAMEND)
ldi XH,HIGH(SRAM_START)
ldi XL,LOW(SRAM_START)
main_clear_ram:
st X+,r16
cpse r17,XH
rjmp main_clear_ram
cpse r18,XL
rjmp main_clear_ram
Und ohne CPSE wäre das dann noch ein bißchen kürzer:
; RAM löschen
clr r16
ldi XH,HIGH(SRAM_START)
ldi XL,LOW(SRAM_START)
main_clear_ram:
st X+,r16
cpi XL,LOW(RAMEND)
brne main_clear_ram
cpi XH,HIGH(RAMEND)
brne main_clear_ram
Kommt halt wirklich auf den Anwendungsfall an und der ist bei CPSE sehr
selten.
MfG
Andi
gibt es sowas wie CPSE auch für ungleich ? vielleicht CPSNE ?
Alternativ, gibt es vielleicht ein BREQ mit Rücksprungfunktion (wie
rcall)
Ich muss in eine Subroutine springen, wenn zwei Register gleich sind.
Label sparen?
Das ist wirklich, woran man nicht sparen braucht.. Denn Label sind und
bleiben halt nur Label: Namen für Adressen.
Und wenn du wirklich so faul bist da ein Label hin zu schreiben, dann
wirst du wahrscheinlich auch deine codes nicht kommentieren.
Viel spaß in einem halben Jahr, wenn du die wieder auskramst und wider
verwenden willst. (Oder achtest du nicht auf portabilität usw?)
Tut mir leid, dass ich so'n faules Arschloch bin, dass obendrein auch
noch die Frechheit besitzt zu fragen!!!!
Solche unqualifizierten Bemerkungen kannst Du Dir sparen !
Ich weiss nicht ob Du's schon mal gehört hast aber auf einen 2313 einen
512MB Chip zu stecken geht nicht.
Da könnte man vielleicht von vorn herein versuchen den Code knapp zu
halten.
Das hat mit Faulheit nichts zu tun.
Keine Sorge, meine Kommentare sind schon ausreichend. Die werden M.E.
auch nicht in den Controller geschrieben.
So ein Label denke ich aber schon, zumal dann noch mindestens ein
Befehl dazu kommt.
viele Labels machen aber die Symbol-Tabelle oder xref etwas
unübersichtlich.
Es geht alternativ aber auch so:
cp r0,r1
brne PC + 2
rcall LABEL_EQ
....
--------------------------
LABEL_EQ:
ret
> Es geht alternativ aber auch so:> cp r0,r1> brne PC + 2> rcall LABEL_EQ> ....
Ja und zwar solange, bis das rcall <label> durch ein anderen 1- oder
3-Bytebefehl ausgetauscht wird... :-(
Die Verwendung dieses "Tricks" ist eher fragwürdig.
> Oder achtest du nicht auf portabilität usw?
Portabilität? Ich dachte wir sprechen hier von Assembler? :-) Da
gibt's sowas nicht...
> nicht in den Controller geschrieben [...] So ein Label denke ich> aber schon, zumal dann noch mindestens ein Befehl dazu kommt.
Labels und Befehle haben keinen Zusammenhang. Und daß durch Labels kein
Speicherverbrauch resultiert, hat Hannes ja schon geschrieben.
----, (QuadDash).
@-----
Wo es beim AVR 1 ... 3 Byte Befehle gibt, ist mit schleierhaft :-)
Da gibt`s nur 1 oder 2 word Befehle und der nachfolgende zu
überspringende Befehl ist ja bekannt. als kann ich PC + 2 oder PC + 3
kodieren.
Hallo,
wo wir grad beim Thema Label sind:
Dass Label keinen Speicher brauchen ist schon klar, aber dennoch gehen
einem ja irgendwann die Namen aus.
Mein Problem jetzt ganz konkret: Angenommen in mache soetwas wie eine
Select-Anweisung. Da kommt als Abfrage immer soetwas wie
ProzedurName_3:
cpi rArg, 0x02
brne ProzedurName_4
; rArg == 0x02, also irgendwas tun
ProzedurName_4:
; nächste Abfrage
Wenn man jetzt nochmal kurz eine weitere Abfrage vor diese Abfrage
schreiben will, ist man schon mit Problemen überhäuft: Welches Label?
Oder doch lieber alle folgenden Label um eine Nummer am Ende erhöhen?
Hier würde ich mir Wünschen etwas wie das folgende benutzen zu können
@@:
cpi rArg, 0x02
brne @F
; rArg == 0x02, also irgendwas tun
@@:
; nächste Abfrage
und so weiter. Dabei hiesse z.B. @F nächstes auftretendes Label mit
Namen "@@" und @B das vorige Label mit Namen "@@". Eine Erweiterung
zu @BB und @FF wäre auch noch denkbar für die übernächsten und
vor-vorigen... Dann könnte man einfach eine weitere Anweisung einfügen
und hätte gleich alle Referenzerneuerungen vom Assembler gelöst.
Gibt es das schon oder ist es erst in Planung?
PS: Ich kenne das aus dem MacroAssembler von Microsoft für Intel
x86-Architekturen... eine sehr praktische Sache.
Schöne Grüße, Clemens
> @-----> Wo es beim AVR 1 ... 3 Byte Befehle gibt, ist mit schleierhaft :-)
1- oder 3-Byte Befehle gibts da wo es auch 5-strichige _Quad_dashs
gibt. ;-)
Ok, auch wenns diese Längen nicht gibt, es wurde ja klar, was ich damit
gemeint habe.
----, (QuadDash).
Oder wie wärs mit nen Macro?
.macro RCallEQ ;Relative Call to @0 if @1 <> @2
cp @1,@2
brne continue
rcall @0
continue:
.endm
Dieses kleine Macro kann man sich in seine eigene Macro-Dateien
einfügen welche man natürlich im Hauptprogramm am Anfang includen
sollte.
Aufruf, bzw. Einbindung ist dann wie folgt:
RCallEQ Subroutine, r16, r17
Falls das jemand ab Mega16 und größer verwenden will und ein RCALL
nicht ausreicht macht man noch folgendes Macro:
.macro CallEQ ;Call to @0 if @1 <> @2
cp @1,@2
brne continue
call @0
continue:
.endm
Aufruf dann z. B. mit
CallEQ Subroutine, r16, r17
Für andere Vergleiche wie CC (Carry Clear), CS (Carry Set) usw. macht
man sich eine Kopie und bennent es z. B. in RCallCS.
Man muß das brne dann in brcc ändern, eben das Gegenteil.
Ist zwar auch nicht des Weisen letzter Schluss aber Macros schaffen
Übersicht.
MfG
Andi
@dotdash:
kaum portabilität (das betrifft auch die portierung von einem gerät auf
ein anderes - schlimmer noch die portierung auf einen anderen
controller-typ), aber wiederverwendbarkeit (man achte auf das usw in
meinem ersten Kommentar)!
oder erfindest du das rad immer wieder neu?
@andi
dann solltest du aber auch die labels neu machen (durchnummerieren oder
so) sonst hast du ganz schnell viele "continue:"s in deinem asm code
So was mußte ja wieder kommen!
Du kennst den Macro-Assembler von AVR-Studio noch nicht.
Jedes Macro, und wenn es 1000 mal im Hauptprogramm mit dem selben
"continue" aufgerufen wird, ist ein Teil für sich.
In alten Versionen des AVR-Studios ging das noch nicht, da mußte man
sich mit "PC+2" etc. rumplagen.
Jetzt handelt das AVR-Studio. Man kann sogar Macros in Macros aufrufen,
ausser sich selbst natürlich da AVR-Studio ab 7 oder 8 Rekursionen
schimpft.
Wozu sind denn Macros da, um sich das Leben (programmieren) zu
vereinfachen.
MfG
Andi