Hallo, habe ein kleines Problem beim addieren von bytes. Programmiere in WINAVR unter AVRSTUDIO, einen Atmega32. Beispiel: unsigned char Zahl1 = Zahl2 = 0xAA; unsigned char Zahl3 = 0; Zahl1 = Zahl1 + Zahl2; Zahl3 = Zahl3 + CARRY; In Assembler gabs so schöne Befehle die add und adc, aber in C stehe ich gerade total aufm Schlauch. Hoffe das klar geworden ist was ich meine. Also 2 Zahlen addieren und die nächste Zahl soll mit dem Carry Flag zusammen addiert werden, falls es einen Übertrag gab. Vielen Dank und Gruß, fubu.
Ich erinnere mich dunkel das das nicht ging, warum willst du die Anzahl an carrys zählen? Du könntest z.B. einfach nen größeren Datentyp nehmen: int ZahlN, Zahl2 ZahlN += Zahl2 Dann ist ZahlN & 0xFF = dein bisheriges Zahl1 (ZahlN & 0xFF00)>>8 dein bisheriges Zahl3
Ich sehe darin zwar keinen Sinn, aber unter C geht es z.B. so:
1 | unsigned char Zahl1 = Zahl2 = 0xAA; |
2 | unsigned char Zahl3 = 0; |
3 | unsigned short temp; // 16 bit |
4 | |
5 | Zahl1 = Zahl1 + Zahl2; |
6 | temp = Zahl1 + Zahl2; |
7 | Zahl3 += temp >> 8; |
Peter
@ Fabian Ostner (fubu1000) >Also 2 Zahlen addieren und die nächste Zahl soll mit dem Carry Flag >zusammen addiert werden, falls es einen Übertrag gab. Dazu musst du grössere Variablen verwenden und von Hand den Übertrag behandeln. Ist zwar ziemlich ineffizient, geht in C aber nicht anders. Etwa so.
1 | uint16_t z1 = z2 =0xAA; |
2 | uint16_t z3; |
3 | |
4 | z1 = z1 +z2; |
5 | if (z1>255) { |
6 | z1 = z1 - 256; |
7 | z3 = Z3 +1; |
8 | }
|
MFG Falk
Hallo, bin gerade wieder daheim, habs mir fast gedacht. Ziemlich uneffizient alles, glaube programmiere wieder Assembler. NENE. Super Dank an alle und Gruß Fabian.
Damit Ihr mich nicht für total verrückt haltet warum ich sowas frage. Ich lese aus einem Fat16 , z.B. VolumeBootRecord aus wieviele Sektoren reserviert sind. Möchte diese natürlich mit dem Start der VolumeBootRecord addieren, damit ich weiß, wo die die FAT beginnt. In Assembler schmeiss ich einfach das letzte ausgelesene Byte weg (höchste Byte), füge hinten 0x00 an und mach einen "lsl" des untersten Bytes und "adc" mit den folgenden Bytes (Registern). In Assembler super effektiv, aber in C muss ich da mit "long" rumspielen und dann wieder in chars wandeln für Addressierung. Super Uneffektiv ! In Assembler hab ich FAT16 schon in Read und Write umgesetzt und funzt super. Wollte es mal aber ebenso effektiv in C umsetzen. Aber keine Chance ;-( Werde es aber weiter versuchen, muß gehen irgendwie ;-( GRUß UND DANK AN ALLE , FABIAN.
Erstmal heißt es ineffizient ;) Außerdem effektiv != effizient, effektiv ist das alles! :P So Spaß beiseite: Du kannst natürlich inline ASM für die betreffende Stelle verwenden, man kann dort auch auf C Variablen zugreifen. (http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Assembler_und_Inline-Assembler). Außerdem so ineffizient wie das scheint ist das alles nicht, vieleicht 2 - 3 Takte langsamer, und wenn du das als Ausdruck formulierst kann der Compiler da ggf. auch optimieren.
Hi, hier eine mögliche Umsetzung des Vorschlags von Läubi Mail@laeubi.de:
1 | #include <inttypes.h> |
2 | |
3 | uint8_t carry(uint8_t z1, uint8_t z2) { |
4 | uint8_t carry; |
5 | asm volatile( |
6 | "clr %0" "\n\t" |
7 | "add %1,%2" "\n\t" |
8 | "adc %0, %0"
|
9 | : "=r" (carry) |
10 | : "r" (z1), "r" (z2), "0" (carry) |
11 | );
|
12 | return carry; |
13 | }
|
14 | |
15 | int main(void){ |
16 | uint8_t Zahl1, Zahl2; |
17 | volatile uint8_t Zahl3 = 0; |
18 | |
19 | Zahl1=Zahl2=0xAA; |
20 | Zahl3+=carry(Zahl1, Zahl2); |
21 | return 1; |
22 | }
|
Gruß risu
Fabian Ostner wrote: > In Assembler super effektiv, aber in C muss ich da mit "long" rumspielen > und dann wieder in chars wandeln für Addressierung. > Super Uneffektiv ! Du weißt wohl nicht, wie man Effektivität berechnet? Du berechnest ne Adresse und liest dann z.B. 512 Byte von dieser ein. Ein Memcopy dauert 7 Zyklen pro Byte, also 3584 Zyklen. Nun ärgert Dich tierisch, daß die Adreßberechnung vielleicht 5 Zyklen länger dauert, d.h. gerade mal 0,13%. Also ein Unterschied von 0,13% ist nicht super, sondern nur ein Fliegenschiß. Bevor also etwas optimiert, sollte man erstmal prüfen, ob das überhaupt einen merkbaren Effekt hat. Peter P.S.: Man kann einen Quellcode nicht verbal beschreiben. Daher wäre der Assemblerquelltext dieser Funktion sinnvoll, damit man sieht was da überhaupt passiert und wie man das in C machen könnte. Aber wenn eine Funktion nicht mindestens 10% der CPU-Zeit verbraucht, lohnt sich eine Optimierung in den seltensten Fällen.
Hallo Peter, > Man kann einen Quellcode nicht verbal beschreiben. > Daher wäre der Assemblerquelltext dieser Funktion sinnvoll,... das sehe ich auch so. Mir war anhand der Beschreibung des OPs z.B. nicht klar, ob er die Summe, deren Übertrag er benötigt, verwirft oder verwendet. Deshalb habe ich meine Inline-Assembler-C-Stub-Funktion (oder wie immer man die nennt) so ausgerichtet, dass zwar die Summe gebildet, aber nur der Übertrag zurückgegeben wird. Gruß risu
@ Peter Dannegger (peda) >Aber wenn eine Funktion nicht mindestens 10% der CPU-Zeit verbraucht, >lohnt sich eine Optimierung in den seltensten Fällen. Richtig. Alte Programmiererregel. 90% der CPU-Leistung werden in 10% des Programms verbraucht. Diese 10% müssen optimiert werden, der Rest "nur" solide hingeschieben. Siehe Soft-PWM, dort lohnt sich eine Optimierung nur in der ISR. MFg Falk
Hallo, hier die korrigierte Version (nur eine Spielerei; wenn die Funktion wirklich zeitkritisch wäre, würde ich einen größeren Teil des Codes als "*.S" Assembler-Code verpacken):
1 | #include <avr/io.h> |
2 | |
3 | #include <inttypes.h> |
4 | |
5 | uint8_t f_carry(uint8_t z1, uint8_t z2) { |
6 | uint8_t carry; |
7 | asm volatile( |
8 | "clr %0" "\n\t" |
9 | "add %1,%2" "\n\t" |
10 | "adc %0, %0"
|
11 | : "=r" (carry) |
12 | : "r" (z1), "r" (z2), "0" (carry) |
13 | );
|
14 | return carry; |
15 | }
|
16 | |
17 | |
18 | int main(void){ |
19 | uint8_t Zahl1, Zahl2; |
20 | volatile uint8_t Zahl3 = 0; |
21 | |
22 | |
23 | Zahl1=Zahl2=0xAA; |
24 | |
25 | Zahl3+=f_carry(Zahl1, Zahl2); |
26 | return 1; |
27 | }
|
Gruß risu
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.