Hallo zusammen, Ich bin absoluter C Neueinsteiger (Jedenfalls in Sachen Mikrocontroller).Habe jetzt erfolgreich meine ersten C-Programme geschrieben. Was mir auffällt: Ein C Programm braucht doch mehr Speicherresourcen als ein identisches Assembler Progamm. Bei mir ungefähr das doppelte. Ist das immer so oder liegt das nur an meinem schlechten C-Stil? Wie ist da eure Erfahrung. Optimierungslevel war bei mir übrigens -Os. Wie sind eure Erfahrungen dazu? Grüsse Thilo
Es liegt wohl erstmal mehr daran, dass du ein Trivialprogramm vergleichst. Da die C-Umgebung einen festen Overhead für ihre Initialisierung besitzt, fällt dieser bei einem "Hello world!"-Programm deutlich mehr ins Gewicht, als bei einer richtigen Applikation.
Kommt auch ganz erheblich auf den C-Compiler an. Habe mal ein Programm für nen Mega16 spaßeshalber mit CodeVision und mit AVR-GCC compiliert. CodeVision: 940 Bytes, AVR-GCC : 1280 Bytes. Beides Size-optimiert. Grundsätzlich gilt: Codesize ist bei Hochsprache-Programmierung signifikant größer als bei (geschickter) Assembler-Programmierung. Und das auch bei AVR, obwohl die Controller an sich (bzw. der Befehlssatz) schon für Hochsprache optimiert sind... Gruß Johnny
Mich würde mal interessieren, wie man Code am besten handoptimiert. Gibt es bspw. eine Möglichkeit zu sehen, welche genutzten Bibliotheksfunktionen wieviel Speicher benötigen? Wenn ich z.B. durch Ersetzen von "printf" durch "puts" an ein paar Stellen signifikant Code-Speicher sparen könnte, würde ich das tun. Speicher ist im konkreten Projekt noch lange nicht knapp, mich nerven nur allmählich die Zeiten fürs Flashen. Gruß, Falk P.S.: Wenn ich 127KB in einem Prozessor wegen C benötige aber in Assembler mit 65KB auskäme, hätte ich (bei gegebenem Controller) 62KB nutzlosen Speicher gespart.
> Mich würde mal interessieren, wie man Code am besten handoptimiert. Mit der Hand. ;-) > Gibt es bspw. eine Möglichkeit zu sehen, welche genutzten > Bibliotheksfunktionen wieviel Speicher benötigen? $ avr-nm --size-sort --print-size *elf | grep ' T ' 000000b2 0000000c T uart_putc 000000a4 0000000e T UART_Init 00000d96 00000012 T strlen_P 0000110a 00000014 T memset 0000008e 00000016 T Timerinit 00000dbe 00000016 T strnlen 00000da8 00000016 T strnlen_P 00000ebc 0000002a T printf 00000ee6 00000038 T calloc 00000e62 0000005a T fputc 0000013c 0000007a T main 000000be 0000007e T __vector_19 00000dd4 0000008e T fdevopen 00001052 000000b8 T free 00000f1e 00000134 T malloc 000004b4 000008e2 T vfprintf Relativ gut zu erkennen, dass vfprintf hier der absolute Klopper in diesem Programm ist. ;-) > Wenn ich z.B. durch Ersetzen von "printf" durch "puts" an ein paar > Stellen signifikant Code-Speicher sparen könnte, würde ich das tun. Ja, auf jeden Fall kannst du das. Wobei natürlich, falls deine fprintf's keine wirklichen Formate haben, sondern so aussehen wie: fprintf("Hello, world\n"); dann wird sie der Compiler bereits zu puts("Hello, world"); umformen (Vorausseztung: es ist kein -ffreestanding angegeben). Hat natürlich nur Sinn, wenn du kein einziges printf() mit einem wirklichen Format hast. Dass printf (bzw. dessen Herzstück vfprintf) riesig ist, da es ja für alle (benutzten und nicht benutzten) Formate den Code vorhalten muss, ist völlig logisch. > P.S.: Wenn ich 127KB in einem Prozessor wegen C benötige aber in > Assembler mit 65KB auskäme, hätte ich (bei gegebenem Controller) > 62KB nutzlosen Speicher gespart. ...ohne einen einzigen Cent dabei einzusparen. ;-) Wenn du natürlich stattdessen mit 63 KB auskämst und dann auch noch so viel davon produzierst, dass die eingesparten Kosten für den kleineren Controller den Aufwand für die Handoptimierung wieder wett machen, dann hätte die Sache Sinn. Solange man in einem sowieso bereits festgelegten Controller noch reichlich Speicher hat, bekommt man eh' keinen Rabatt dafür, dass man ihn nur zum Teil benutzt...
Die grep-Anweisung sollte übrigens ... | grep ' [Tt] ' oder ... | grep -i ' t ' heißen, damit auch static deklarierte Funktionen mit erfasst werden.
Vielen Dank, Jörg, das hilft schon sehr weit. (Ich liebe Lösungen mit "Kommando | Kommando | wc -l oder sort ...) Dann gehe ich mal nachsehen, was "mein" strlen* noch so heimlich nebenbei treibt ;-) 0000238c 000005aa T vfprintf ... 00002980 00000016 T strnlen 00002996 00000016 T strnlen_P 73, Falk
Wieso, mit 24 Bytes sind die doch nun wirklich kurz. Die erste Spalte ist die Adresse, die zweite die Größe.
> Die erste Spalte ist die Adresse, die zweite die Größe.
Autsch ;-)
Man sollte natürlich mit "| sort" nicht alles kaputtmachen, wenn
"avr-nm --size-sort --print-size" es schon mundgerecht geliefert
hat.
Falk,
der jetzt mal "000009e2 0000069e T read_sms" näher anguckt...
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.