Forum: Compiler & IDEs Frage Effektivität C-Code


von Manni (Gast)


Lesenswert?

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

von A.K. (Gast)


Lesenswert?

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.

von tex (Gast)


Lesenswert?

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

von Hans (Gast)


Lesenswert?

ä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

von A.K. (Gast)


Angehängte Dateien:

Lesenswert?

Nicht recht nachvollziehbar. Kommt in C praktisch das gleiche raus wie
in Assembler. 6 Takte hier wie dort. Siehe Anhang.

von A.K. (Gast)


Lesenswert?

Ok, mit Imagecraft siehts schlechter aus, 10 Takte. Aber dessen
Compiler-Technik ist auch ziemlich vorsintflutlich.

von tex (Gast)


Lesenswert?

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

von A.K. (Gast)


Lesenswert?

AVR Studio hat keinen C-Compiler. Jedenfalls nicht von Haus aus. Man
kann wohl welche einbinden, z.B. IAR.

von Sebastian (Gast)


Lesenswert?

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

von A.K. (Gast)


Lesenswert?

@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.

von Manni (Gast)


Lesenswert?

< 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

von Jörg Wunsch (Gast)


Lesenswert?

Normalerweise rechnet er auch ,,in zweiter Ebene'', aber sicher
kannst
du dir wirklich nur sein, wenn du den generierten Assemblercode mal
ansiehst.

von Fritz Ganter (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.