Zahl In RR[4:7] in 2er Kompl. wandeln. Geht es einfacher? clr A com RR4 :setzt carry com RR5 com RR6 com RR7 ; C=1 wird gleich als +1 verwendet adc RR4,A adc RR5,A adc RR6,A adc RR7,A ; carry wird verworfen
Hi
>Geht es einfacher?
Einem Befehl kann man sparen:
[avrasm}
com r16
com r17
com r18
com r19
subi r16,Low(-1)
sbci r17,byte2(-1)
sbci r18,byte3(-1)
sbci r19,byte4(-1)
[/avrasm}
MfG Spess
Verstehe es nicht ganz. subi und sbci geht immediate ist klar, darum kein clr A o.k. aber dann? wo ist der byte Zähler Danke Rudi
:
Bearbeitet durch User
Ich brauche doch etwas Nachhilfe In der AVR-Hilfe unter expressions findet sich z.B. byte2(expression) was ident ist mit high(expression), dass dies das 2.Byte eines Ausdruckes liefert. Gut! Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann byte2 oder byte3 oder byte4(-1) zurück? Wenn es 0 ist, so verstehe ich die Antwort von spess53. In meiner nicht so großen Erfahrung würde ich aber dann schreiben, wenn es richtig ist: [avrasm} com r16 com r17 com r18 com r19 subi r16,(-1) ; ident mit add 1 sbci r17,0 ; wenn Übertrag, dann nur carry addieren sbci r18,0 sbci r19,0 [/avrasm} Aber ist das richtig? Bitte um Nachhilfe
:
Bearbeitet durch User
Hi >Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann >byte2 oder byte3 oder byte4(-1) zurück? Assembler Hilfe: BYTE2(expression) is the same function as HIGH BYTE3(expression) returns the third byte of an expression BYTE4(expression) returns the fourth byte of an expression In diesem Fall ist expression = -1 oder $FFFFFFFF >Wenn es 0 ist, so verstehe ich die Antwort von spess53. Der Befehl com ist das Einerkomplement (oder Negation) und mit Rd ← $FF - Rd definiert. Das Zweierkomlement (neg) mit Rd ← $00 - Rd. Also ist neg(Wert) = com(Wert)+1. Da es keine ADDI/ADCI-Befehle gibt, werden die in dem Fall durch subi/sbci -1 ersetzt. Funktioniert bei mir seit Jahren. Teste es einfach im Simulator. MfG Spess
Rudi D. schrieb: > Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann > byte2 oder byte3 oder byte4(-1) zurück? Das bezieht sich auf Konstanten oder konstante berechnete Ausdrücke im Assembler, nicht auf Werte in Registern. Solche Ausdrücke werden vom Assembler in 32 Bits gerechnet.
:
Bearbeitet durch User
A. K. schrieb: > Rudi D. schrieb: >> Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann >> byte2 oder byte3 oder byte4(-1) zurück? > > Das bezieht sich auf Konstanten oder konstante berechnete Ausdrücke im > Assembler, nicht auf Werte in Registern. Solche Ausdrücke werden vom > Assembler in 32 Bits gerechnet. Das hat mir gefehlt. Wo steht das im AVR Studio, habs nie gefunden.
spess53 schrieb: > Der Befehl com ist das Einerkomplement (oder Negation) und mit > Rd ← $FF - Rd definiert. Das Zweierkomlement (neg) mit Rd ← $00 - Rd. > Also ist neg(Wert) = com(Wert)+1. Da es keine ADDI/ADCI-Befehle gibt, > werden die in dem Fall durch subi/sbci -1 ersetzt. Das hab ich ja schon geschriebn, ist ja klar. Aber sollte es nicht heißen: subi r16,Low(-1) sbci r17,byte2(0) sbci r18,byte3(0) sbci r19,byte4(0) Es soll ja nur das ev. Carry addiert werden und nicht r18 = r18 - ffh -C Wo steh ich auf der Leitung?
Rudi D. schrieb: > Wo steh ich auf der Leitung? -1 = 0xFFFFFFFF Bei dir: 0x000000FF. Negation: B = Invertiere(A) + 1 Oder: B = Invertiere(A) - -1 Und zwar in 32 Bits Breite. aber wenn dir das zu kompliziert ist: clr r20 clr r21 movw r22, r20 sub r20, r16 sbc r21, r17 sbc r22, r18 sbc r23, r19 Ergebnis in R20-23
:
Bearbeitet durch User
Hi >Es soll ja nur das ev. Carry addiert werden und nicht >r18 = r18 - ffh -C Als 32-Bit-Zahl ist aber -1 = $FFFFFFFF und nicht nur $000000FF- MfG Spess
spess53 schrieb: > [avrasm} > com r16 > com r17 > com r18 > com r19 > subi r16,Low(-1) > sbci r17,byte2(-1) > sbci r18,byte3(-1) > sbci r19,byte4(-1) > [/avrasm} spess, das kann IMHO nicht richtig sein. Um vom 1er Komplement, zum 2er Komplement zu kommen, ist ein einziges Mal 1 zu addieren und nicht 4 x Kann aber auch sein, dass ich diese Schreibweise nicht verstehe.
Der AVR-GCC meint dazu:
1 | 38: 50 95 com r21 |
2 | 3a: 40 95 com r20 |
3 | 3c: 30 95 com r19 |
4 | 3e: 21 95 neg r18 |
5 | 40: 3f 4f sbci r19, 0xFF ; 255 |
6 | 42: 4f 4f sbci r20, 0xFF ; 255 |
7 | 44: 5f 4f sbci r21, 0xFF ; 255 |
8 | return -x; |
Rudi D. schrieb: > spess53 schrieb: >> [avrasm} >> com r16 >> com r17 >> com r18 >> com r19 >> subi r16,Low(-1) >> sbci r17,byte2(-1) >> sbci r18,byte3(-1) >> sbci r19,byte4(-1) >> [/avrasm} > > spess, das kann IMHO nicht richtig sein. > > Um vom 1er Komplement, zum 2er Komplement zu kommen, ist ein einziges > Mal 1 zu addieren und nicht 4 x Du addierst aber nicht +1, sondern du subtrahierst -1 Arithmetisch kommt das aufs gleiche raus. Nur: Wenn du -1 subtrahierst, dann musst du auch wirklich -1 subtrahieren. Und das in allen 4 Bytes der 32 Bit Zahl! Denn es kann ja einen Übertrag von einem Byte ins nächste geben. Dezimal: 99 + 1 ist ja auch 100 und du hast einen Übertrag von der 2.ten zur 3.ten Stelle. 999999 + 1. Hier wimmelt es nur so von Überträgen von einer Stelle zur nächsten. Es reicht nicht, einfach nur in der Einerstelle die 1 zu addieren. 999999 + 1 ergibt eben nicht 999990 sondern der Übertrag wandert die Ziffern nach vorne.
:
Bearbeitet durch User
Darum hab ich ja in meiner 9 Lines Lösung 1addiert und 3x mögliche carries berücksichtigt. GCC braucht nur 7 Befehle. Danke auch peda, jetzt hab ich's. Lg
:
Bearbeitet durch User
Peter Dannegger schrieb: > Der AVR-GCC meint dazu: >
1 | > 38: 50 95 com r21 |
2 | > 3a: 40 95 com r20 |
3 | > 3c: 30 95 com r19 |
4 | > 3e: 21 95 neg r18 |
5 | > 40: 3f 4f sbci r19, 0xFF ; 255 |
6 | > 42: 4f 4f sbci r20, 0xFF ; 255 |
7 | > 44: 5f 4f sbci r21, 0xFF ; 255 |
8 | > return -x; |
9 | >
|
Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen lassen oder wer kann sonst so eine optimale Lösung erfinden?
Rudi D. schrieb: > Peter Dannegger schrieb: >> Der AVR-GCC meint dazu: >>
1 | >> 38: 50 95 com r21 |
2 | >> 3a: 40 95 com r20 |
3 | >> 3c: 30 95 com r19 |
4 | >> 3e: 21 95 neg r18 |
5 | >> 40: 3f 4f sbci r19, 0xFF ; 255 |
6 | >> 42: 4f 4f sbci r20, 0xFF ; 255 |
7 | >> 44: 5f 4f sbci r21, 0xFF ; 255 |
8 | >> return -x; |
9 | >>
|
> > Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen > lassen oder wer kann sonst so eine optimale Lösung erfinden? Der GCC optimiert halt sehr gut. Darum muss ich auch immer schmunzeln wenn irgendwelche ASM-Gurus ankommen und was von Performance und Codegröße schwadronieren, wenn es mal wieder gegen C geht. Meist verliert sogar der fortgeschrittene ASM Programmierer locker gegen den GCC Optimierer.
Rudi D. schrieb: > Peter Dannegger schrieb: >> Der AVR-GCC meint dazu: >>
1 | >> 38: 50 95 com r21 |
2 | >> 3a: 40 95 com r20 |
3 | >> 3c: 30 95 com r19 |
4 | >> 3e: 21 95 neg r18 |
5 | >> 40: 3f 4f sbci r19, 0xFF ; 255 |
6 | >> 42: 4f 4f sbci r20, 0xFF ; 255 |
7 | >> 44: 5f 4f sbci r21, 0xFF ; 255 |
8 | >> return -x; |
9 | >>
|
> > Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen > lassen oder wer kann sonst so eine optimale Lösung erfinden? In diesem Falls: Ja. Es ist eine "fest" vorgegebene Sequenz, die ausgegeben wird, wenn: Ein 32-Bit int zu negieren ist und Ein- und Ausgaberegister übereinstimmen und es sich dabei um obere Register handelt. Falls es keine oberen Register sind, so wird 1 Instruktion mehr ausgegeben:
1 | com r17 |
2 | com r16 |
3 | com r15 |
4 | com r14 |
5 | adc r14,__zero_reg__ |
6 | adc r15,__zero_reg__ |
7 | adc r16,__zero_reg__ |
8 | adc r17,__zero_reg__ |
Negation eines 16-Bit int ist übrigens immer mit 3 Instruktionen machbar, auch in den unteren Registern:
1 | neg r15 |
2 | neg r14 |
3 | sbc r15,__zero_reg__ |
Johann L. schrieb: > Falls es keine oberen Register sind, so wird 1 Instruktion mehr > ausgegeben: > com r17 > com r16 > com r15 > com r14 > adc r14,__zero_reg__ > adc r15,__zero_reg__ > adc r16,__zero_reg__ > adc r17,__zero_reg__ Das ist ja fast ident mit der Frage im 1. Beitrag von mir. Aber wie wird "__zero_reg__" dann übersetzt, da es für die unteren Register ja kein immediate gibt. Darum hab ich ja "clr A" dazugenommen. Bin ja nur gelegentlich als Hobby in Assembler unterwegs. DDS und so Projekte auf elektronik-labor.de zu lesen.
Rudi D. schrieb: > hat sich das der Programmierer von GCC einfallen > lassen oder wer kann sonst so eine optimale Lösung erfinden? Es gibt nicht "den" GCC-Entwickler. Einen Compiler baut nie jemand allein in seinem stillen Kämmerlein, sondern daran können 10.000 und mehr Leute beteiligt sein. Das Wissen vieler ist nunmal größer, als das eines einzelnen. Ich war auch schwer enttäuscht, als ich meine 16Bit-Mul/Div für den 8051 entwickelt hatte und dann mal den Keil C51 reassembliert habe. Dessen Code war halb so groß, dafür doppelt so schnell. Auch hatte ich haufenweise Push/Pop-Orgien in meinen Assemblerprogrammen, der C51 hat das mit Registern für Argumente und Overlay für Variablen viel effektiver gelöst. Von Assembler nach C umgeschriebene Programmer wurden daher kleiner und schneller. Und der Herr Keil wird auch nicht alles allein gemacht haben.
Peter Dannegger schrieb: > Es gibt nicht "den" GCC-Entwickler. Allen vielen Dank. Ich denke das Thema ist erschöpfend abgehandelt worden. LG Rudi
Rudi D. schrieb: > Aber wie wird "__zero_reg__" dann übersetzt, da es für die unteren > Register ja kein immediate gibt. Darum hab ich ja "clr A" dazugenommen. Nachtrag: Dieses Register, s.o. bezieht sich auf den GCC Inline Assembler und ist R1 lt. GCCdoc. Es wird immer auf NULL gehalten. Näheres https://gcc.gnu.org/wiki/avr-gcc?action=fullsearch&context=180&value=__zero_&fullsearch=Text Es gilt nicht für den Assembler von AVRStudio4. o.k.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.