hm, kaum zu glauben ... 2300 Assemblerbefehle für 3000 Zeilen C-Code (abzüglich Kommentare)??Zitat von SprinterSB
hm, kaum zu glauben ... 2300 Assemblerbefehle für 3000 Zeilen C-Code (abzüglich Kommentare)??Zitat von SprinterSB
Ich hab da nur mit wc die Zeilen der C-Dateien gezählt. Kommentare sind kaum dabei. Allerdings hab ich meine eigenen Header-Dateien nicht mitgezählt, sondern lediglich die .c-Dateien.
Nicht jede C-Zeile wird zu asm-Code. Elemente wie Block-Begrenzer {}, Sprunglabels, Präprozessor-Direktiven etc. werden natürlich nicht zu Code.
Ich hab einzeilige Kommentare, Leerzeilen, und Zeilen, die nur { oder } enthalten mal rausgewofen, dann bleiben nur noch 2600 Zeilen C-Code.
Immer noch recht ansehnlich, find ich.
Vom Flash entfallen nur ca 4000 Bytes auf Assembler-Code. Der Rest ist Vec-Tab, Startup-Code, Konstanten-Tabellen, Lib-Functions, etc (ca 550 Bytes).
Um den Überblick zu wahren, strukturiert man sein Programm und modularisiert es, bringt Kommentare an, verwendet sprechende Bezeichner, etc. Ganz einfach, komplizierte Zusammenhänge nach einiger Zeit nachzuvollziehen, ist es dennoch nicht. Das liegt eben in der Natur der Sache...
Informationen zu Flow, Code Coverage und Profiling kann man auch mit GCC erzeugen lassen, aber frag mich net wie oder wie man das auswertet bzw darstellt.
Der Code, den ave-gcc generiert, ist jedenfalls sehr gut. Hier und da könnte man eine Asm-Instruktion einsparen, aber insgesamt hab ich wirklich nix am Code auszusetzen (und das soll schon was heissen)
Disclaimer: none. Sue me.
Die eigenhändige Optimierung des Codes kann einem sehr viel bringen!
Ich hab bei meinem ersten Projekt (ein Servo soll per je nach logischen Zustand am Controllereeingang zwei frei programmierbare Endpunkte mit programmierbarer Geschwindig anfahren) mit der Zeit immer wieder überarbeitet.
Weil ich mir das proggen selber beigebracht hab, fielen bei Bascom anfänglich 2040 Bytes an Code an. Durch das ständige Überarbeiten sind trotz mehr Befehlen mittlerweile nur noch rund 1660 Byte übriggeblieben - also fast 20% weniger
@SprinterSB
Die Stärke von Bascom ist sicherlich der schnelle Einstieg bei externer Hardware (z.B. LCD mit I2C / SPI / UART etc. und das noch wahlweise in Software-Emulation). Zum Anfang ist der Flash des Atmegaxx grenzenlos...
Bei größeren Projekten wird man um C nicht herum kommen. Der ellenlange Bascom-Code lässt sich zwar in einem Atmega32/128 unterbringen - nur zeitkritische Anwendungen werden wegen des Code-Marathons unbeherrschbar.
Bascom verknallt alleine in jeder ISR 104 Takte (13µs bei 8Mhz) zum Sichern und Wiederherstellen aller (!) Register.Zitat von SprinterSB
Für Dein Projekt hätte man eine andere Hardwarelösung finden müssen.
Das kann man abschalten in Bascom. Muß aber genau wissen, was man tut. Ohne sichern der register wirds auch anders(nicht Bascom) oftmals nicht gehen. Also für Anfänger ist es nicht zu empfehlen das Sichern der Register abzuschalten.Zitat von -tomas-
Grundsätzlich ist es mir egal ob in C oder Bascom programmiert wird. Es wäre als wenn ich English mit Russisch und Deutsch vergleichen würde. Es ist doch irgendwo quatsch!
Klar kann man das mit Nosave Abschalten, nur muss dann die ISR durchgängig in Assembler programmiert werden, da Bascom nicht dokumentiert, welche Register bei welchen Aktionen verändert werden.
Hatte mal als Workaround den Bascom-Code durch einen Disassembler gejagt, um herauszubekommen, welche Register in einer zeitkritischen ISR mit Push und Pop gesichert werden müssen. Nur bleibt dabei das ungute Gefühl zurück, dass vielleicht beim nächsten Compiler-Lauf andere Register umgeschaufelt werden.
ein Beispiel
d.h. eine ISR mit dem Increment einer Word-Variable verwurstet Bascom zu 130 Byte Code (65 Assemblerbefehle)Code:Int1_int: Incr I 'Word Return 'RETI
ich Poste den Assemblercode mal bewusst in abgerollter Länge damit man mal den Aufbläh-Faktor von Bascom siehtpush r0
push r1
push r2
push r3
push r4
push r5
push r7
push r10
push r11
push r16
push r17
push r18
push r19
push r20
push r21
push r22
push r23
push r24
push r25
push r26
push r27
push r28
push r29
push r30
push r31
in r24, SREG
push r24
ldi r26, 0xF2
ldi r27, 0
call sub_401
pop r24
out SREG, r24
pop r31
pop r30
pop r29
pop r28
pop r27
pop r26
pop r25
pop r24
pop r23
pop r22
pop r21
pop r20
pop r19
pop r18
pop r17
pop r16
pop r11
pop r10
pop r7
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
reti
sub_401:
ld r30, X+ ;Word-Variable I laden
ld r31, X
adiw r30, 1 ;hier erfolgt 'Add Immediate to Word', d.h. unser Word-Increment !!!!!
st X, r31
st -X, r30 ;Variable I sichern
ret
; End of function sub_401![]()
Schon mal im Simulator probiert?Zitat von -tomas-
Klar! Leider werden im Simulator nur die Register angezeigt, die sich verändert haben.
Wen das Register zufällig mit dem gleichen Byte-Wert (z.B. 0) wieder aus einer Routine herauskommt, mit dem es hereingekommen ist, wird es der Simulator nicht anzeigen. Beim nächsten Aufruf ...
Nun man darf das mit Pop und Push aber auch nicht zu schlimm sehen. Es sieht zwar oben im Quelltext lang aus, aber die Ausführungszeit für diese Befehle ist extrem gering.
Zudem sind Push und Pop´s auch in C und Assembler notwendig. Man kann dort auch nur ein paar einsparen wenn man die Registerverwendung des Programmcodes kennt. Ganz ohne gehts fast nie.
In Bascom wären auch Assembler ISR-Routinen denkbar, dann kann man sich ebenfalls leicht auf die verwendeten Register beschränken.
Natürlich wäre es noch schöner wenn Bascom tatsächlich nur die verwendeten Register sichern würde, keine Frage. Die paar Millionstel Sekunden die man da einspart, werden allerdings nur selten ein Problem darstellen.
Aber da Bascom ja doch recht zügig in der Entwicklung fortschreitet, werden sicher auch solche Dinge noch optimiert. Auch in Bezug auf Assemblereinbindung und Generierung ist da in Zukunft nach Aussagen des Entwicklers noch einiges zu erwarten.
Im Wiki hab ich mal einen Codevergleich angefangen.
Es sind ganz einfache Beispiele. Vielleicht flegt jemand, der sich mit Bascom auskennt, die Bascom-Teile nach![]()
Disclaimer: none. Sue me.
Lesezeichen