Hallo, als Anfänger (C, Assembler und MCU) spiele ich derzeit die einfachsten Sachen im Atmel Studio (4.10.356 mit Mega16) durch, um zu lernen. Folgendes kann ich nicht so ganz verstehen: #define ALPHA 3 #define BETA 5 #define RK 2000 int RW, ADC; int main (void) { RW=(ALPHA+BETA)*RK; ADC=RW/10; } braucht in der .text-Sektion 266 und insgesamt 303 Prozessortakte zum Endergebnis. Wenn ich statt RW die Formel zur Berechnung von RW einsetze #define ALPHA 3 #define BETA 5 #define RK 2000 int RW, ADC; int main (void) { RW=(ALPHA+BETA)*RK; ADC=(ALPHA+BETA)*RK/10; } braucht es in der .text-Sektion nur 184 und insgesamt nur 70 Prozessortakte. Das ist ja ein enormer Unterschied. Warum? In der Assemblerausgabe kann ich es leider aus Unkenntnis nicht ergründen. Daß obiges Beispiel mit Konstanten für ALPHA etc. schneller und platzsparender ist als die Werte in Variablen zu verpacken ist einleuchtend (auf die muß immer erst zugegriffen und der Wert geladen werden). Zusatzfrage: Überall habe ich gelesen, daß Kommazahlen vermieden werden sollten, da sie irren Rechenaufwand erzeugen würden. Wenn ich aber für ALPHA und BETA Kommazahlen nehme (z.B. 3.6 und 5.1) bleiben Speicherverbrauch und Prozessortakte gleich ?! Gruß Manni
Der zweite Code enthält nur Konstanten. Die Berechnung übernimmt der Compiler. Folglich braucht's auch keine Laufzeitroutine für Division. Der grösste Teil des Codes ist bei einem derart winzigen Programm ohnehin der "Wasserkopf" für Initialisierung.
Hallo Manni! Deine Frage in einem praktischen Beispiel. Ich musste ein Bit togeln um zu messen, ob mein Prozesor im richtigen Takt arbeitet. (Ich hatte da Zweifel) In C hatte ich eine Taktfrequenz von 60kHz, oder sowas In ASM hatte ich 1,3 Mhz Soviel zur Effektivität
ähm... wie hast du da getoggelt ?? der gcc nimmt normal alles als int16 an... also schön auf int8 runtercasten...dann sollte toggeln in einer schleife genau so schnell sein... oder zumindest um faktor 10 schneller zumindest... 73 de oe6jwf
Nicht recht nachvollziehbar. Kommt in C praktisch das gleiche raus wie in Assembler. 6 Takte hier wie dort. Siehe Anhang.
Ok, mit Imagecraft siehts schlechter aus, 10 Takte. Aber dessen Compiler-Technik ist auch ziemlich vorsintflutlich.
naja PORTB ^= 0x01; kenn ich noch nicht. Sweit habe ich in dem C-Buch noch nicht gelesen. Ich habs halt so gemacht while(1) { PORTB = 0x55; PORTB = 0xaa; } Damit hab ich zwar 8 Bit getoggelt, aber soweit ich das gelesen habe macht das beim AVR keinen Unterschied. Compiler war das AVR-Studio
AVR Studio hat keinen C-Compiler. Jedenfalls nicht von Haus aus. Man kann wohl welche einbinden, z.B. IAR.
doch, das macht einen riesen unterschied. aus : PORTB = 0x55; PORTB = 0xaa; wird in asm: out PORTB, 0x55; out PORTB, 0xAA; dabei macht du eine explizite zuweisung. bei PORTB ^= 0x01; liest du Port B zurück, und nimmst es exklusiv oder bit bit0, du veränderst also nur das eine bit und lässt die anderen sozusagen völlig unangetastet. MfG Sebastian
@Sebastian: Macht schon einen Unterschied, aber nicht hinsichtlich der Laufzeit. Denn Compiler und Assembler(-Programmieren) haben beide das gleiche Problem. Diesen OUT Befehl gibt's übrigens nicht. Wodurch es sein kann, dass der Compiler den fixeren Code erzeugt, denn grad der GNU-Compiler pflegt recht konsequent schleifeninvarianten Code (OUT port,0x55 = LDI tmpreg,0x55; OUT port,tmpreg - darin also der erste Befehl) aus der Schleife raus zu befördern. Anders ein auf Übersichtlichkeit angelegter Assembler-Programmieren, der ebendiesen "fehlenden" Befehl oft durch einen Macro ersetzt.
< Der zweite Code enthält nur Konstanten. Die Berechnung übernimmt der < Compiler. Folglich braucht's auch keine Laufzeitroutine für Division. Na guck, das könnte es sein. Ich komme wohl auch um ein (nicht geplantes) Vertiefen meiner Assemblerkenntnisse rum, um Schritt für Schritt zu verfolgen, was der Compiler da so fabriziert. Also kann der Compiler "in erster Ebene" noch rechnen, in "zweiter Ebene" nicht mehr. Er führt also keine weitere Analyse aus, obwohl er auch im anderen Fall schon alle Zahlen zum rechnen hätte. Danke und Gruß Manni
Normalerweise rechnet er auch ,,in zweiter Ebene'', aber sicher kannst du dir wirklich nur sein, wenn du den generierten Assemblercode mal ansiehst.
Es ist auch ein grosser Unterschied ob du mit -O0 oder mit -O2 übersetzt.
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.