A. K. schrieb:> zu Lasten von ein paar> Befehlen mehr> diesen mit 9 Takten doch wesentlichen schnellern Code produziert:
Vor diesem Szenario steht man auch öfter bei Asm:
weniger Platz oder mehr Performance. In diesem Fall hab ich weniger
Platzbedarf den Vorzug gegeben.
Johann L. schrieb:> uint16_t *adc = & ADUC[adc_num];> uint16_t sum64 = adc[N_ADCs] += ADC;
Die beiden Zeilen kommen mir total spanisch vor. Liegt sicher nur an
meinem niedrigen Niveau. Warum '+='? 16-Bit-Werte aufaddieren... Das
passt zum Schluss immer noch in 16 Bit? Ich durchschaue den Trick nicht.
(Bitte nicht hauen!)
Und dann noch der extra Index am Zeiger. Ich gebe auf...
Ralf G. schrieb:> Johann L. schrieb:> uint16_t *adc = & ADUC[adc_num];> uint16_t sum64 = adc[N_ADCs] += ADC;>> Die beiden Zeilen kommen mir total spanisch vor. Liegt sicher nur an> meinem niedrigen Niveau. Warum '+='? 16-Bit-Werte aufaddieren... Das> passt zum Schluss immer noch in 16 Bit? Ich durchschaue den Trick nicht.> (Bitte nicht hauen!)>> Und dann noch der extra Index am Zeiger. Ich gebe auf...
Der ADC hat 10 Bit Auflösung, d.h. die 64 aufsummierten Werte haben
jeder höchstens 3FFH.
An dieser kryptischen Darstellung würd ich auch verzweifeln ;-)
Moby A. schrieb:> Falls Du darauf abzielst für solcherlei Berechnungen besser C samt> 32Bit-Controller zu verwenden zielst Du jedenfalls nicht auf typische> 8-Bit Anwendungen. Da sind solche Berechnungen selten.
Hast du schon mal was mit den Sensirion Feuchtesensoren gemacht, SHT11
und Verwandte? Ist meiner Ansicht nach eine durchaus typische 8-Bit
Anwendung, die auf einem x8er AVR in einem Auto-Sensormodul steckt, das
via Bluetooth mit einem Handy kommuniziert (Feuchte, Temperatur und zum
Spass noch Luftdruck).
Ist fast durchweg 8/16-Bit Code und problemlos auch in Asm umsetzbar.
Nur hinter dieser harmlosen letzten Zeile steckt wohl etwas Arbeit:
A. K. schrieb:> Hast du schon mal
Ja hab schon mal.
Einen MS5534c in meiner Wetterstation.
Gleiche Rechenorgie.
Deshalb schrieb ich "selten" .
Aber deshalb auf C/32Bit umsteigen?
Wenn das täglich vorkommen würde...
Ralf G. schrieb:> Ergänzung: Streng geheim!!
Genau. Deshalb sag ichs ja.
Aber kein Grund zur Panik:
> Ich kann nicht mehr. Ich bin weg. :-)
Oder liegts am C-Code? ;-)
Ausnahmsweise:
Moby A. schrieb:> Ja hab schon mal.
Mensch Moby, das war 'ne Steilvorlage!! Falsch. Das war 'n Elfmeter mit
doppelter Torbreite, ohne Torwart, mit zwei Versuchen! Und du
versemmelst das! Ich fass' es nicht.
Ralf G. schrieb:> Johann L. schrieb:>> uint16_t *adc = & ADUC[adc_num];>> uint16_t sum64 = adc[N_ADCs] += ADC;> Die beiden Zeilen kommen mir total spanisch vor.> [...] Und dann noch der extra Index am Zeiger. Ich gebe auf...
Das liegt an der asm-Vorlage. Die 2 Variablen, die zur "Verwaltung"
eines ADC-Kanals gehören, liegen im Speicher verstreut.
Ohnehin ist es recht sinnfrei, einen gegebenen Asm-Code genauso umsetzen
zu wollen — das zeigen schon die magischen Konstanten wie $40. (Die zu
entsorgen freilich auch mit Asm nix kostete. Sie sind der Tribut an
einen Hang zur Kryptophilie).
* Die Variablen, die man zur "Verwaltung" eines ADC-Kanals brauch, wird
man zusammenhalten wollen, z.B. in einer Struktur wie unten.
* Der IRQ-Zähler hat eigentlich nix mit dieser Routine zu tun; den wird
man von außen reingeben. Falls er doch zum Modul gehören sollte, dann
in die gleiche Struktur in der auch die adcs[] leben:
1
typedefstruct
2
{
3
structadc
4
{
5
uint16_tresult,temp;
6
}adcs[4];
7
uint8_tn_irq;
8
}aduc_t;
9
10
aduc_tADUC;
11
12
voidadu(uint8_tn_irq)
13
{
14
uint8_tn_adc=3&(n_irq>>6);
15
structadc*adc=&ADUC.adcs[n_adc];
16
17
uint16_ttemp=adc->temp+=ADC;
18
19
if(0==(n_irq&0x3f))
20
{
21
adc->result=temp>>6;
22
adc->temp=0;
23
24
uint8_trefs=(n_irq&0x80)
25
?(1<<REFS1)|(1<<REFS0)
26
:(1<<REFS0);
27
28
ADMUX=refs|n_adc;
29
}
30
}
Der Code wird dadurch etwas kleiner — n_irq (vormals IC) würde dann wie
gesagt an adäquater stelle (z.B. ISR) verwaltet.
Der avr-gcc Code ist immer noch nicht optimal, das Optimierungspotential
wird gar noch größer; der Code ist aber immer noch kleiner als Mobys
Code.
Aber es geht ja schon längst nicht mehr darum, ob der C-Code ein paar
poplige Bytes länger oder kürzer ist. Er ist auf der Ebene einfach
besser wartbar, z.B. kann ohne Codeänderung die langsame >> 6 Schleife
durch linearen Code ersetzt werden, wie Andereas ja bereits anmerkte.
Es wäre wesentlich schneller gewesen, eine gescheite Dokumentation zu
haben und anhand dieser eine neue Implementation vorzunehmen, anstatt
die Bitgepfriemel reverse-engineeren.
Moby A. schrieb:> Johann L. schrieb:>> Ergo: Wenn Moby seinen optimalen ASM-Code noch optimaler bekommen>> will, lohnt ein Blick über den Tellerrand>> Mir Deine Übersetzung zu Gemüte zu führen
Lass es. Das implementiert man besser komplett neu :-)
Hier noch meine Lösung zum Vergleich gegen 1000000, etwa wie in
1
externvoidf(void);
2
3
voidcaller(uint32_tval)
4
{
5
if(val<1000000)
6
f();
7
}
Lösung:
1
caller:
2
cpi r22,64
3
sbci r23,66
4
sbci r24,15
5
cpc r25,__zero_reg__
6
brsh .L1
7
jmp f
8
.L1:
9
ret
10
.ident "GCC: (GNU) 5.2.1 20150816"
Es ist meine Lösung, weil:
http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.c?r1=179124&r2=179123&pathrev=179124#l3171
Andreas hat sich also doch nicht verzählt...
Moby A. schrieb:> Johann L. schrieb:>> Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an>> Kommentaren und Dokumentation.>> Oh das ist mir neu.>> Johann L. schrieb:>> Ein nicht unwesentlicher Teil der AVR-Entwickler, die sich>> hier tummeln, verwendet ASSEMBLER-Code aus meiner Feder.>> Find ich gut.
Schön, wusst ich's doch.
Der Code wird nämlich von avr-gcc erzeugt :-)
> Ein Blick über den Tellerrand ist immer sinnvoll.> Welche Erkenntnisse das bringt ist die zweite Frage.
Kein Teller is so groß, als dass es jenseits seines Randes nichts Neues,
nicht Interessantes oder nicht Aufregendes zu entdecken gäbe. Inwieweit
wird dazu in der Lage sind, ist keine Frage der Weite des Teller,
sondern eine Frage der Höhe der Mauern im Kopf, der Weite der Phantasie,
der Kühnheit, Eingeschliffenes infrage zu stellen und auf wackligen
Beinen neuen Grund zu betreten, des Mutes, dabei zu stolpern und sich
dem Gelächter alter Hasen auszusetzen, des Strebens, wirklich gute
Lösungen zu finden ohne sich in Perfektionismus zu verhakeln, und der
Muße, guten Dingen und dem Lernen die Zeit zuzugestehen, die ihnen
gebührt.
Johann L. schrieb:> cpi r22,64> sbci r23,66> sbci r24,15> cpc r25,__zero_reg__
Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test
gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche, sondern so
gemischt.
(Ist gleich lang, gleich schnell. Sieht nur 'ungewöhnlich' aus.)
Moby schrieb:> Verstehen hier wirklich so wenige noch Asm?
Keiner hängt sich das Assembler-Täfelchen so nachdrücklich um den Hals
wie du...
Moby A. schrieb:> @TO> In einem öffentlichen wie diesem Thread musst Du mit den Antworten leben
Nicht unbedingt. Es es sein Thread. Er hat ihn eröffnet und darf ihn
zuallererst selber moderieren. Dass ihm Andere seinen Thread
entführen und verunstalten gehört nicht zum guten Umgangston.
Im realen Leben ist es, wie wenn er eine Besprechung einberufen hat, und
einfach jeder sein Zeug bespricht. Das ist zumindest unhöflich...
Schön, daß der Code weiter verbessert wird, obwohl ich immer noch nicht
durchsteige... So kann ich leider noch nicht die Gleichwertigkeit mit
meinem Code abschätzen. Allerdings hab ich den Eindruck, daß meine
Lösung schneller aufs Papier gebracht war, halte Johann L. aber auch die
Zeit fürs Reverse Engineering zugute ;-) Ganz sicher ist aber, daß diese
Form kryptischer Problemlösung niemals die meine werden wird.
Schließlich wollte ich noch die versprochene Lösung für 900ss
nachtragen:
Der C-Vorgabe
> void f (void);>> void caller (uint32_t val)> {> if (val < 1000000)> f();> }
ist die Lösung
> Lösung:caller:> cpi r22,64> sbci r23,66> sbci r24,15> cpc r25,__zero_reg__> brsh .L1> jmp f> .L1:> ret> .ident "GCC: (GNU) 5.2.1 20150816"
nicht ganz äquivalent, weil die Variable verloren geht.
Besser und ohne die Konstante in ihre Bytebestandteile zu zerlegen ist
ganz unspektakulär
1
.equ Konstante = 1000000
2
3
cpi r25,byte4(Konstante)
4
brlo f1
5
cpi r24,byte3(Konstante)
6
brlo f1
7
cpi r23,byte2(Konstante)
8
brlo f1
9
cpi r22,byte1(Konstante)
10
brsh end
11
f1: ...
12
13
end: ret
Das kostet im Maximum 9 Takte.
Lothar M. schrieb:> Moby schrieb:>> Verstehen hier wirklich so wenige noch Asm?> Keiner hängt sich das Assembler-Täfelchen so nachdrücklich um den Hals> wie du...
... mit dem 8-Bit AVR in der Hand. Das bleibt eine ideale Kombination.
Da ist das letzte Wort hier noch lange nicht gesprochen.
> Es es sein Thread. Er hat ihn eröffnet und darf ihn> zuallererst selber moderieren. D
Der TO hat sich lebhaft an der Diskussion beteiligt.
Einige Moderatoren (mit mir) auch (nicht immer sehr sachlich).
Die Beschwerde kam erst in Form einer üblen Beleidigung.
Darum solltet Ihr Moderatoren Euch mal zuallererst kümmern.
> Im realen Leben
sind wir hier nicht.
Das schließt Höflichkeit natürlich nicht aus.
Ralf G. schrieb:> Warum nicht nur Subtraktion bzw. Vergleiche, sondern so> gemischt.
Mist. Meine Assemblerkenntnisse sind doch ganz schön eingerostet. (Der
Vergleich mit Übertrag...)
Moby A. schrieb:> Das kostet im Maximum 9 Takte.
Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem
Thread anmerken muss. Beispielsweise wenn r25 > byte4(...) aber r24 <
byte3(...).
A. K. schrieb:> Moby A. schrieb:>> Das kostet im Maximum 9 Takte.>> Und ist falsch.
Ich fragte mich schon, warum der Johann dem Moby so eine einfache
Aufgabe stellt. Um den Moby an seine Grenzen zu führen, muss doch was
richtig Knackiges her.
Aber offensichtlich war die Aufgabe immer noch zu schwer :(
Und bevor wir hier weiterdiskutieren und immer mehr vom Usprungsthema
abkommen:
Moby, fang doch bitte einen neuen Thread an. Dann beschwert auch keiner
darüber, dass du den Thread kaperst.
Moby A. schrieb:> .equ Konstante = 1000000>> cpi r25,byte4(Konstante)> brlo f1> cpi r24,byte3(Konstante)> brlo f1> cpi r23,byte2(Konstante)> brlo f1> cpi r22,byte1(Konstante)> brsh end> f1: ...>> end: ret
Eben, leider falsch, und sicherheitshalber hier mal zitiert, ansonsten
verschwindet das wieder, wie weiter oben schon einmal ein Detail.
A. K. schrieb:> Moby A. schrieb:>> Das kostet im Maximum 9 Takte.>> Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem> Thread anmerken muss. Beispielsweise wenn r25 > byte4(...) aber r24 <> byte3(...).
Klar, hast recht. So geht das nun nicht. Ist wohl schon zu spät heute
geworden ;-)
Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein.
Dann soll der TO walten wie er will.
Obs dann hier noch lange weitergeht?
A. K. schrieb:> Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem> Thread anmerken muss.
Täusche ich mich oder geht es hier immer noch um den Vergleich zweier
4-Byte-Zahlen? Den Fehler hatte ursprünglich ich eingeschleppt:
Josef G. schrieb:> Vergleich von zwei unsigned 4-Byte-Zahlen A und B> mit 8bit-CPU und Sprung falls A > B>> Die 4 Bytes seien A3,A2,A1,A0 bzw. B3,B2,B1,B0>> Methode 1:>> Teste A3 > B3> Sprung falls A3 > B3> Teste A2 > B2> Sprung falls A2 > B2> Teste A1 > B1> Sprung falls A1 > B1> Teste A0 > B0> Sprung falls A0 > B0>> Methode 2:>> Berechne B0 - A0 mit Carry> Berechne B1 - A1 mit Carry> Berechne B2 - A2 mit Carry> Berechne B3 - A3 mit Carry> Sprung falls Carry gesetzt
Die korrigierte Version von Methode 1 hat A.K.
schon angegeben. Ich würde sie so schreiben:
Teste A3 > B3
Sprung falls A3 > B3
Abbruch falls nicht A3 = B3
Teste A2 > B2
Sprung falls A2 > B2
Abbruch falls nicht A2 = B2
Teste A1 > B1
Sprung falls A1 > B1
Abbruch falls nicht A1 = B1
Teste A0 > B0
Sprung falls A0 > B0
Dabei ist angenommen, dass der compare-Befehl einen Carry und
ein Zero-Flag liefert. Abbruch bedeutet Sprung ans Ende.
Bei Methode 2 ist angenommen, dass die CPU bei der Subtraktion den
Subtrahenden und den Carry am Addierer invertiert (wie bei 8085)
und nicht nur den Subtrahenden invertiert (wie bei 6502), und
dass zu Beginn der Carry Null ist.
Moby A. schrieb:> Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein:
1
.equ Konstante = 1000000
2
3
cpi r25,byte4(Konstante)
4
brlo f1
5
brne end
6
cpi r24,byte3(Konstante)
7
brlo f1
8
brne end
9
cpi r23,byte2(Konstante)
10
brlo f1
11
brne end
12
cpi r22,byte1(Konstante)
13
brsh end
14
f1: ...
15
16
end: ret
Also noch BRNE-3 Takte mehr = Max.12 bei zerstörungsfreier Variable.
Wiegesagt, selten gebraucht bei 8-Bit AVR!
Unbekannt U. schrieb:> Eben, leider falsch, und sicherheitshalber hier mal zitiert, ansonsten> verschwindet das wieder,
Du hast ja hier wirklich wichtige Aufgaben desnachts ;-)
Und der (der Compiler) ist praktisch nur im AVR-Studio auf 'Assembler
Help' gegangen, hat das Beispiel zum 'cpc-Befehl' abgekupfert und auf
vier Bytes erweitert. ;-)
Ralf G. schrieb:> Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test> gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche, sondern so> gemischt.
Für jedes Byte eines Multibyte-Compares wird einzeln die Entscheidung
getroffen, welcher Befehl verwendet wird. Fürs erste Byte gibt es CPI,
für das letzte das Register mit Inhalt 0. Für die anderen wird
nachgesehen, ob die linke Seite überschrieben werden darf. Wenn ja wird
SBCI draus, wenn nicht LDI/CPC. Passt so auf beide Versionen des Codes,
die vorherige mit SBCI und die jetzige mit LDI/CPC. Siehe Johanns Link
oben, das hat er verbrochen.
Würde die Entscheidung über die zu verwendenden Methode vorneweg für
alle Bytes getroffen, statt für jedes Byte einzeln, wäre hier die
Optimierung über das Zero-Register über Bord gefallen.
Anders als Assembler-Programmierern ist Compilern die Eleganz des
entstehenden Codes gleichgültig.
Zu Mobys Fehleinschätzungen gehört wohl die Vorstellung, dass jene
Leute, die C verwenden, deshalb keine Ahnung von Asm hätten. Das trifft
freilich nicht immer zu.
A. K. schrieb:> Für jedes Byte eines Multibyte-Compares [...]Ralf G. schrieb:> Mist. Meine Assemblerkenntnisse sind doch ganz schön eingerostet. (Der> Vergleich mit Übertrag...)
Wie das funktioneren soll, ist mir schon klar. Ich hatte gedanklich in
der Sequenz einen Compare-With-Carry-Befehl drin, der auch Konstanten
verarbeitet. Den gibt's aber gar nicht. Und da kommt? ... natürlich die
Subtraktion ins Spiel.
Ralf G. schrieb:> der Sequenz einen Compare-With-Carry-Befehl drin, der auch Konstanten> verarbeitet. Den gibt's aber gar nicht. Und da kommt? ... natürlich die> Subtraktion ins Spiel.
Ein Compare-With-Carry Befehl ist ohnehin nicht sehr verbreitet. Die
meisten Architekturen kennen ihn nicht. Was freilich auch damit
zusammenhängt, dass er nur bei Architekturen mit mehreren
Rechenregistern im Zusammenspiel mit 2-Register-Befehlen Sinn ergibt.
Bei Akkumulator- oder 3-Register-Befehlen ist er sinnlos.
Recht clever und ebenfalls selten ist auch die Handhabung des Z-Flags in
SBC(I) und CPC, die ein für das Gesamtergebnis gültiges Z-Flag
hinterlässt. Bei den meisten Maschinen ist das Z-Flag nur für das letzte
Wort gültig und daher beim Multiwort-Vergleich nutzlos.
A. K. schrieb:> Recht clever ist auch die Handhabung des Z-Flags in SBC(I) und CPC
Ja. :)
Wie gesagt, ich weiß wo ich nachschlagen muss, da ich mir nicht mehr
alle Befehle geläufig sind. Da habe ich dann gesehen, dass es sowas wie
'cpci' gar nicht gibt. Hätte mich dann sicher für sowas...
A. K. schrieb:> Ergebnis vom Compiler:> cpi r22,64> ldi r18,66> cpc r23,r18> ldi r18,15> cpc r24,r18> cpc r25,__zero_reg__> brge .L1
... entschieden. Aber nicht um zu sagen: 'Bei mir existiert die Variable
aber noch!', sondern weil ich auf die andere Variante gar nicht gekommen
wäre.
Ralf G. schrieb:> sondern weil ich auf die andere Variante gar nicht gekommen wäre.
Das ist einfach nur die übliche Variante für zu Fuss programmierte
Vergleiche von potentiell längeren Strings, auch bei AVR. Allein schon,
weil du bei einem String nicht alle 50 Bytes abklappern willst, wenn es
nach den ersten paar Bytes schon klar ist.
Danke Moby, immerhin hast du deinen Code gepostet. Fazit: Auch
handgeschriebener ASM-Code ist nicht immer besser als der vom Compiler.
Ich verwende wohl weiter den Compiler.... Aber nicht nur deshalb. Alle
Vorteile des Compilers wurden ja schon genannt, selbst bei kleinen
Projekten ist die Verwendung von ASM-Code nur zweifelhaft von Vorteil.
Es gibt Gebiete, wo es sinnvoll ist, ihn einzusetzen (auch schon alles
weiter oben erwähnt), genauso wie ein GOTO in 'C'.
Warum du Moby, so verbissen an ASM festhälst, wird mir auch ein Rätel
bleiben, die von Dir genannten Vorteile sind alle objektiv widerlegt
worden. Deine persönliche Begeisterung für ASM-Code ist OK, wenn du mehr
Spaß daran hast, dann mach es so. Jedem das was er mag. Allerdings
sollte man schon objektiv bleiben und den Tellerrand hat Johann oben ja
schon mit gelungenen Worten erwähnt.
Neugier: Moby, ist programmieren eher aus Hobby betrieben oder verdienst
du dein Geld damit?
Moby A. schrieb:> Ganz sicher ist aber, daß diese Form kryptischer Problemlösung> niemals die meine werden wird.
Kryptisch sind beide; kryptisch, weil sie keine oder nur nixnutzige
Kommentare enthalten.
Johann L. schrieb:> Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an> Kommentaren und Dokumentation.> Schließlich wollte ich noch die versprochene Lösung für 900ss> nachtragen:>> Der C-Vorgabe>>> void f (void);>>>> void caller (uint32_t val)>> {>> if (val < 1000000)>> f();>> }>> ist die Lösung>>> Lösung:>>caller:>> cpi r22,64>> sbci r23,66>> sbci r24,15>> cpc r25,__zero_reg__>> brsh .L1>> jmp f>> .L1:>> ret>> .ident "GCC: (GNU) 5.2.1 20150816">> nicht ganz äquivalent, weil die Variable verloren geht.
Es ist absolut perfekt 100% äquivalent :-))
Der Wert in R22--R25 wird nämlich nicht mehr benötigt — falls doch, hat
Andreas schon eine Lösung gepostet:
A. K. schrieb:> Also gut, dann eben zerstörungsfrei:
1
>voidg(long);
2
>voidf(longx)
3
>{
4
>if(x<1000000)
5
>g(x);
6
>}
> Ergebnis vom Compiler:
1
> cpi r22,64
2
> ldi r18,66
3
> cpc r23,r18
4
> ldi r18,15
5
> cpc r24,r18
6
> cpc r25,__zero_reg__
7
> brge .L1
> Ergebnis von Moby:
1
> cpi r25,byte4(Konstante)
2
> brlo f1
3
> brne end
4
> cpi r24,byte3(Konstante)
5
> brlo f1
6
> brne end
7
> cpi r23,byte2(Konstante)
8
> brlo f1
9
> brne end
10
> cpi r22,byte1(Konstante)
11
> brsh end
Doch Vorsich! Der Moby-Vergleich geht NUR für unsigned. Für
vorzeichenbehaftete Zahlen muss eine andere Lösung her!
> ohne die Konstante in ihre Bytebestandteile zu zerlegen
Der von GCC erzeugte Assembler-Code ist selbsterklärend. Ist ja nicht
die Aufgabe von GCC, jemand Assembler oder Grundarithmetik beizubringen.
Und in Quelle steht "x < 1000000". Da ist nix zerlegt.
Yalu X. schrieb:> A. K. schrieb:>> Moby A. schrieb:>>> Das kostet im Maximum 9 Takte.>>>> Und ist falsch.>> Ich fragte mich schon, warum der Johann dem Moby so eine> einfache Aufgabe stellt.
Nur aus Interesse. Ehrlich gesagt hatte ich nicht erwartet, dass ein
erfahrener Programmierer da strauchelt. Oder zumindest die Haken und
Ösen ahnt und 2x nachdenkt bevor er / sie was schreibt. Ich hatte auch
nicht erwartet, dass er auf Anhieb die beste Sequenz findet, weil es die
eine beste Sequenz nämlich garnicht gibt.
> Aber offensichtlich war die Aufgabe immer noch zu schwer :(
Ich bin mir nicht sicher, ob das politisch korrekt ist, wenn ich hier
mal (in chronologischer Reihenfolge) was zusammenfasse. (Habe den
Beitrag prophylaktisch schon mal selbst gemeldet.) Ich hoffe, die Zitate
sind ohne den Zusammenhang noch sinngemäß.
-----
Weil eine Hochsprache ein Programm quasi aus Fertigbausteinen
zusammensetzt und die Aufgabenstellung damit nur unter Verlusten an
Platz und Performance gegenüber der feiner an die Gegebenheiten
anpassbaren Asm-Programmierung lösen kann.
-----
Hans schrieb:
> Wenn du nur 1:1 "übersetztst", dann wird C niemal kleiner als dein ASM> code werden.
Kleiner? Wie soll denn das passieren? Da muss sich ein Asm-Programmierer
aber schon selten dämlich anstellen :-)
-----
Eine uC-Softwarewelt braucht niemand retten, wenn sie mit pure Asm schon
im Klartext mit allen seinen Möglichkeiten, Transparenzen und Freiheiten
formuliert ist . Immer wieder schön, wenn dann der nächstkleinere
Controller genügt ;-)
-----
Ich möchte mir von keinem Compiler irgendwas vorschreiben und
verschleiern lassen, sondern das Heft des Handelns 100%ig selbst in der
Hand behalten. Wo überall geht das heute noch so einfach wie bei den
kleinen 8-Bittern? Dazu braucht es nur ein paar Dutzend Asm-Anweisungen
und das Datenblatt des Controllers seines Vertrauens.
-----
Die wenigen dutzend simplen Asm-Instruktionen bedeuten aber auch, man
braucht nicht mehr zu seinem Glück, es vereinfacht und macht die Sache
transparent.
-----
Vor der Aufgabe, ein gutes Programm zu schreiben stehen Asm- und C-
Programmierer gleichermaßen. Asm allein ist nun leider keine Garantie
für guten Code [...]
-----
X4U schrieb:
> Sagt mal, was ist an diesem Codeschnipsel eigentlich lesbar
Alles, wenn Du das Datenblatt und die paar Instruktionen kennst.
Klartext- und jeder weiß was gespielt wird.
-----
Das Ergebnis zählt und ein solches ist natürlich auch in C erreichbar.
Das ändert freilich nix an Simplizität und Effizienz von Asm für eine
große Klasse von Anwendungen.
-----
C ist einfach mehr sprachlicher Aufwand für größere, langsamere
Ergebnisse.
-----
[ Meine Lieblingsstelle ;-) , Moby an Rufus ]
Bist Du fähig mein obiges Beispiel als gleichlange C-Version zu liefern?
Nein?
Anfänger. Hauptsache große Klappe.
-----
Das heißt (zumindest) für viele 8-Bit Projekte: Assembler. Das Werkzeug
mit den maximalen Freiheiten und effektivstmöglichen Ergebnissen- mit
geringstem bürokratischen Aufwand.
-----
Autor: Moby AVR (moby-project) , Sommer 2015
PS:
Zählt das eigentlich jetzt schon als Aphorismen
Ralf G. schrieb:> Zählt das eigentlich jetzt schon als Aphorismen
Nö. Ein Aphorismus ist ein in sich widersprüchlicher Satz und ohne
Kontext verständlich.
Ralf G. schrieb:> Ich hätt's beinahe gegoogelt :-)
Vermutlich findet sich dieser Neologismus noch nicht im Duden. Dabei ist
die Bedeutung doch ganz einfach:
- Bei einem Aphorismus bringt jemand einen Gedanken auf den Punkt.
- Bei B-Forismus schreibt jemand in einem Forum immer wieder dasselbe
mit anderen Worten.
:-)
Ralf G. schrieb:> Johann L. schrieb:>> cpi r22,64>> sbci r23,66>> sbci r24,15>> cpc r25,__zero_reg__>> Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test> gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche,> sondern so gemischt.
Weil es so einfacher ist im Compiler:
Der geht alls Bytes von 0 bis N-1 durchund sucht die beste Möglichkeit
für den Byte-Vergleich.
o CPI geht weil 22 >=16.
o CPC 0 geht immer.
o SBCI geht weil 23 >= 16 und das Register danach nicht mehr
verwendet wird.
o CP/CPC geht immer
Wobei hier der Code einfach verbessert werden kann: Anstatt zu testen,
ob das 32-Bit Register noch verwendet wird, könnte getestet werden, ob
das entsprechende 8-Bit Subregister noch verwendet wird:
http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.c?revision=227035&view=markup#l5394
1
for(i=0;i<n_bytes;i++)
2
{
3
/* We compare byte-wise. */
4
rtxreg8=simplify_gen_subreg(QImode,xreg,mode,i);
5
[...]
6
/* Upper registers can compare and subtract-with-carry immediates.
7
Notice that compare instructions do the same as respective subtract
8
instruction; the only difference is that comparisons don't write
9
the result back to the target register. */
10
11
if(ld_reg_p)
12
{
13
if(i==0)
14
{
15
avr_asm_len("cpi %0,%1",xop,plen,1);
16
continue;
17
}
18
elseif(reg_unused_after(insn,xreg))
19
{
20
avr_asm_len("sbci %0,%1",xop,plen,1);
21
continue;
22
}
23
}
Anstatt auf "xreg" wäre also einfach auf "reg8" zu testen.
Ein ideales Einstiegsprojekt für jeden, der schon immer mal am Compiler
rumschrauben wollte!
Testfall:
Johann L. schrieb:> Weil es so einfacher ist im Compiler: [...]
Ich wusste (also, ich ahnte), dass es schwerer ist als
Ralf G. schrieb:> Da habe ich dann gesehen, dass es sowas wie> 'cpci' gar nicht gibt.
;-)
> Doch Vorsich! Der Moby-Vergleich geht NUR für unsigned. Für
vorzeichenbehaftete Zahlen muss eine andere Lösung her!
Das macht nichts. Kleine AVR's brauchen keine Vorzeichen ;-)
Moby's Kühlschrankdisplay zeigt die Temperatur eben in Kelvin an, auch
wenn man dabei ein Byte verschwenden muß, denn 255K sind recht kalt ;-)
Wenn man sich allein die letzten Diskussionen um Georg's
Compilerergebnis anschaut. Soll ich diese Entscheidungen, schnell und
fehlerfrei, bei jedem Vergleich selber machen, oder hab ich verstanden,
wozu es Software gibt. Auch wenn im Fall Software schreiben/Compiler nur
ein Problem gelöst wird, das es ohne IT gar nicht gäbe. Die Aufgabe von
Software ist nämlich solche Gedankengänge maschinenausführbar gemacht.
Man kann natürlich auch zu Fuß ans Ziel kommen. Aktuell machen das
manche zwangsweise um von Griechenland nach DE zu kommen. Aber keiner
wird bestreiten, daß man auf dieses "Vergnügen" zugunsten eines 2 1/2h
Flugs verziechten kann.
So geht's auch denen, die mit Software ihre Brötchen verdienen (mich
eingeschlossen). Die Blasen im Hirn haben sich Georg, Jörg und viele
andere geholt, dem Rest reicht das Ergebnis.
Nur ganz wenige verhandeln mit Atmel wegen Rückgabe unbenützter
Flash-Zellen gegen finanziellen Ausgleich. Für die wäre dann eine
Berufgruppe aus der Gesundheitsbranche zuständig: die Herren mit den
weißen Kitteln.
Horst S. schrieb:> Ich bin jetzt nicht unbedingt davon ausgegangen, dass ein (nicht> optimiertes) Assemblerprogramm in C portiert um 10% größer (und damit> auch langsamer) werden muss. Ist das so?
Nachdem ich schon in den ersten Beiträgen eigentlich eine eindeutige
Antwort auf meine Frage bekommen hatte, möchte ich mich abschließend bei
den Leuten, die sich die Mühe gemacht haben, mein Projekt(chen)
anzuschauen und mit konstruktiven Beiträgen zu verbessern, noch mal ganz
herzlich bedanken.
Ich finde, das ist keine Selbstverständlichkeit und verdient zumindest
die Anerkennung, den Antwortern bis zum Schluss zuzuhören (man muss
nicht jede Idee übernehmen, aber ausprobieren sollte man das schon mal).
Für mich scheint das Problem gelöst, wenn Euch nix Krasses mehr
auffällt, sehe ich mich als entlassen.
Zu den anderen 90% Beiträgen in diesem Threads:
Wenn ich noch mal versehentlich Auslöser solch eines Disputs werde,
probier' ich mal ganz blauäugig den "Beitrag melden"-Link und hoffe das
Beste. Möge ein Moderator mir beistehen, sein Holzbein überstülpen und
(Gregory Peck: "verfluchter Wal") da kräftig mit seiner Harpune
reinpieken.
Hmmm: wer den Film zu Ende geguckt hat, weiss, das hilft auch nicht
immer, aber es sieht zumindest so aus, als ob es Wirkung zeigen könnte.
In diesem Sinne
Gruß Horst
Horst S. schrieb:> Zu den anderen 90% Beiträgen in diesem Threads
Ach, nimm's locker, Horst: allein von Johanns Ausführungen über das,
was er (*) da so im Compiler treibt, kann man hinreichend viel auch
als gestandener Programmierer noch lernen. ;-)
(*) Johann ist derjenige, der in den letzten Jahren am AVR-Backend
des GCC massiv herumoptimiert hat. Davor war er zwar auch schon
brauchbar, aber eben manchmal recht suboptimal (vermutlich eher das,
was Moby sich unter einem Compiler vorstellen würde). Dank Johanns
Engagement hat er aber nochmal massiv zugelegt, und es dürfte
mittlerweile selbst einem gestandenen Assemblerprogrammierer oft
schwer fallen, vergleichbar guten Code zu erzeugen.
Jörg W. schrieb:> und es dürfte mittlerweile selbst einem gestandenen> Assemblerprogrammierer oft schwer fallen, vergleichbar guten Code zu> erzeugen.
Oh, wecke mal keine schlafenden Hunde ;-)
Moby A. schrieb:> Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein.Moby A. schrieb:> .equ Konstante = 1000000> ...
Der interessanteste Benchmark dieser Aufgabe für mich:
1. Moby braucht dafür 1 Stunde und 5 Minuten
2. avr-gcc braucht bedeutend weniger als 1 Sekunde
Frank M. schrieb:> Der interessanteste Benchmark dieser Aufgabe für mich:>> 1. Moby braucht dafür 1 Stunde und 5 Minuten
Johanns Frage: 28.08.2015 23:08
Mobys Antwort: 29.08.2015 23:37 (die falsche)
30.08.2015 02:02 (die richtige)
A. K. schrieb:> Johanns Frage: 28.08.2015 23:08> Mobys Antwort: 29.08.2015 23:37 (die falsche)> 30.08.2015 02:02 (die richtige)
Ich habe lediglich die Differenz der Zeiten aus beiden der oben
zitierten Beiträgen gezogen, weil ich annahm, dass sich Moby dieser
Aufgabe tatsächlich erst ab 30.08.2015 00:57 mit dem nötigen Ernst
annahm. Alles andere davor war einfach so dahingesaut und nicht
ernstzunehmen.
Moby A. schrieb:> Zeigt mal, wie> sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen> lässt. Das würde ja auf mich viel eher Eindruck machen ;-)
Welche Funktionalität denn?
Nirgends wird beschrieben, was der Code überhaupt machen soll!
Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren,
die sagen 0,nix über die Gesamtfunktion aus.
Zu einer ordentlichen Assemblerprogrammdoku gehört auch erstmal die
Beschreibung der Regeln, die Du Dir selbst in Deinem Kopf zurecht gelegt
hast, wie RAM-Aufteilung, Parameterübergabe, Registerreservierung
(zerstörbar, Parameter, Interrupt, Sonderfunktion), Byteorder usw.
Wenn Du denkst, jemand kämpft sich durch Dein Assemblerkauderwelsch, um
es dann in eine Funktionsbeschreibung zurück zu übersetzen, dann bist Du
schief gewickelt.
Du verlangst quasi, den Döner (Assembler) in ne Kuh
(Funktionsbeschreibung) zurück zu verwandeln, um dann ne Roulade (C)
daraus zu machen.
Mache erstmal nen PAP oder beschreibe in Worten, was das Programm machen
soll, dann erst kann man das auch in C umsetzen.
Peter D. schrieb:> Welche Funktionalität denn?> Nirgends wird beschrieben, was der Code überhaupt machen soll!
Ja, genau das hab ich vor paar Tagen auch schon vergeblich
eingefordert...
Moby schrieb:> Es braucht diesbezüglich kein zeitvernichtendes Hinterherhecheln hinter> den neuesten Technologien und Programmiermethoden
Da musste man als C-Progammierer niemals irgendwie hinterherhecheln:
C ist viel älter als der AVR. Der AVR wurde sogar von Atmel zusammen mit
IAR für C-Compiler optimiert.
1
Atmel and IAR Systems have worked together since 1995, when we participated
2
in the design of the successful AVR 8-bit RISC microcontroller core, and
3
delivered a tailor-made C compiler.
(Quelle https://www.iar.com/iar-embedded-workbench/atmel/)
Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller
Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen
Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur
und seinen verbastelten Compiler herumgeärgert hatten.
Und wenn es schon einen optimierten Prozessor und dazu einen kostenlosen
sehr guten Compiler gibt, dann bin ich fertig. Da fange ich nicht mal
mehr für den Tiny9 ein Assemblerprojekt an.
BTW:
Ich kann mir übrigens vorstellen, warum der Thread inzwischen im
Offtopic gelandet ist, obwohl er im ersten Fünftel noch hübsche
technische Ansätze hatte...
Lothar M. schrieb:> Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller> Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen> Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur> und seinen verbastelten Compiler herumgeärgert hatten.
Der 8051 wurde ein einer Zeit entwickelt, in der man solche Aufgaben
nicht in C gelöst hat, sondern meist in Assembler. Und für Aufgaben, die
mit 256 Bytes RAM auskommen. Da ist er ziemlich gut.
Eine Akku-Architektur ist kein Problem für einen C Compiler.
Vorzugsweise mit 16-Bit Akku wie 68x11/12. Auf GCC sollte man dann aber
verzichten, der ist auf Register konzipiert.
Lothar M. schrieb:> Da fange ich nicht mal> mehr für den Tiny9 ein Assemblerprojekt an.
Da stimme ich zu. Ein simpler PWM-Controller auf einem ATtiny10: die
Hälfte vom Flash für eine PWM-Tabelle und der Rest hat immer noch für's
Programm gereicht. Ich bleibe beim Compiler, solange es keinen
zwingenden Grund für Assembler gibt.
Moby A. schrieb:> Hab mal meine bereits weiter oben zur Sprache gekommene ASM Lösung aus> einem anderen Hochsprachen-Thread(problem) angehängt. Zeigt mal, wie> sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen> lässt. Das würde ja auf mich viel eher Eindruck machen ;-)
Deine beiden Codeschnipsel sind Mini-Programme und damit realitätsfern.
Bei realistischen Projekten (erzeugte Codegröße ab ca. 2KB) kann man mit
Assembler nicht mehr mithalten. Je größer das Programm, desto größer
auch der Speicherplatzgewinn mit C. So gut kann kein
Assembler-Programmierer sein, dass er bei mittelgroßen bis großen
Projekten so gut optimiert wie die Maschine. Ein Compiler kann hier
immer noch den Überblick behalten, während der Assembler-Programmierer
diesen so langsam aber sicher verliert.
So Moby, jetzt hab ich mir deinen asm Programm mal angesehen.
Da sind einige Dinge drin, die unsauber sind. zB hier:
1
DATARAM:
2
KEY0S: .DB 1 ;Key0 (0/$ff= un/betätigt Status)
3
KEY0C: .DB 1 ;Key0 (Betätigungsdauer, Counter)
4
KEY1S: .DB 1 ;Key1 (0/$ff= un/betätigt Status)
5
KEY1C: .DB 1 ;Key1 (Betätigungsdauer, Counter)
6
KEY2S: .DB 1 ;Key2 (0/$ff= un/betätigt Status)
7
KEY2C: .DB 1 ;Key2 (Betätigungsdauer, Counter)
Hier definierst Du sechs Variablen, welche hinternander im Speicher
liegen. Ok. Aber hier:
1
systemint:
2
..ldi ZL,low (KEY0S-2)
3
ldi ZH,high(KEY0S-2)
Hier setzt du den Z-Poiter auf zwei Speicherzellen vor das KEY0S. Das
funktioniert zwar, weil Du hier:
1
keyproc:
2
adiw ZH:ZL,2
beim Aufruf immer plus zwei rechnest und die Tasten in exakt der
Reihenfolge abfragst/aufrufst, in der Du die in DATARAM definiert hast.
Aber das ist bei weitem keine ordentliche Lösung. Wie soll ein fremder
Programmierer, der (nur) die Funktion keyproc bekommt/sieht/analysiert.
wissen, was das soll?
Sowas ist kein sauberes Programmieren. Sauberer wäre es, keyproc die
"Taste" im DATARAM mitzugeben.
Weiter:
1
systemint:
2
...
3
sec ;Entprellung Key1 (PB6)
4
sbis PINB,6
5
clc
6
rcall keyproc
Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc
aufgerufen wird. Weiter:
1
keyproc:
2
...
3
ldd XL,Z+0 ;8x alle 5ms testen
4
rol XL ;= 200% Bulletproof ;-)
5
std Z+0,XL
Das LDD/STD speicher/lädt den Wert KEYxS aus DATARAM. Das ROL schiebt
das Carryflag (von der Taste) von rechts rein. Ergebnis: (bleibt) Null,
wenn Taste nicht betätigt. Sonst: 0,1,3,7,15,31,63,127,255,255,255,255
bis wieder losgelassen. Weiter:
1
keyproc:
2
...
3
breq keyproc2
Wird aufgerufen, wenn obiger Zähler Null ist. Also wenn acht Samples
hinternander die Taste nicht gedrückt ist.
...
Lothar M. schrieb:> Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller> Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen> Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur> und seinen verbastelten Compiler herumgeärgert hatten.
Der 8051 hatte noch viele andere geniale Befehle, CJNE, MOVC A,@A+DPTR,
JMP @A+DTPR hab ich sehr oft benötigt.
Und Bitlogik ging auch sehr einfach mit MOV C,bit, ORL C,(/)bit, MOV
bit,C, CPL bit, JBC usw.
Ich fands genial, was der Herr Keil da geleistet hat. Meine
Assemblerprogramme waren durchweg länger, als später in C geschrieben.
Und das Funktionen per default nicht reentrant waren, hat kaum gestört.
Die Idee mit dem SRAM-Overlay hätte man nie in Assembler umsetzen
können, das kann nur ein Compiler.
Matthias L. schrieb:> Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc> aufgerufen wird. Weiter:> keyproc:> ...> ldd XL,Z+0 ;8x alle 5ms testen> rol XL ;= 200% Bulletproof ;-)> std Z+0,XL
Du hättest statt der "..." die entsprechenden Befehle vollständig
hinschreiben sollen:
Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt, im
konkreten Fall mit 0. Somit schiebt ROL in das XL-Register nur Nullen
hinein, was den nett gemeinten Programmiertrick völlig versagen lässt.
Wir wissen zwar nicht, was Mobys Programm tun soll (er verrät es uns ja
nicht), eins kann aber sicher gesagt werden: Es entprellt keine Tasten.
Und was lernen wir daraus?
1. Das Carry-Flag ist eigentlich gedacht für das Zusammensetzen von
Multibyte- aus mehreren Einzelbytebefehlen (Addition, Shift usw.) und
für Vergleiche mit anschließenden bedingten Sprüngen. Dabei wird das
Flag in einem Befehl geändert und im direkt darauffolgenden Befehl
ausgewertet.
Es ist nicht gedacht für den Transport von booleschen Informationen
über weite Strecken innerhalb des Programms. Wenn man das trotzdem
tut, muss man sehr vorsichtig sein, damit man nicht versehentlich
einen Befehl dazwischen einfügt, der das Flag überschreibt.
=> Wenn man schon Assembler programmiert und dabei auzch noch tief in
die Trickkiste greift, sollte man gut ausgeschlafen sein und jede
Code-Änderung dreimal mit dem Auge durchgehen und zusätzlich intensiv
testen.
2. Ich vermute, Moby hat aus seinem Fundus eine ältere keyproc-Routine
übernommen, die zunächst nur für eine einzelne Taste vorgesehen war.
Er hat sie auf mehrere Tasten erweitert, musste dazu aber die
indirekte Adressierung für das Z-Register und damit verbunden den
ADIW-Befehl einführen, was schließlich zu dem Fehler führte.
=> Wiederverwendbarkeit von Code erfordert eine genaue und
vollständige Dokumentation nicht nur der Funktion, sondern auch der
Nebeneffekte. Das ist hier offensichtlich nicht geschehen.
Da Moby der Assembler-Gott ist, der immer alles richtig macht, hat er
auch keinen Bedarf gesehen, die Routine vor ihrer Veröffentlichung
wenigstens einmal zu testen ;-)
3. Hochsprachen sind weniger anfällig gegen solche Fehler, da dort
Information ausschließlich über Variablen transportiert wird.
Wenn eine Variable an einem Punkt geschrieben wird und etliche
Anweisungen später wieder gelesen wird, fällt es normalerweise auf,
wenn dazwischen eine weitere Zuweisung an die Variable erfolgt.
Ausnahme: Die Variable ist global und wird als Nebeneffekt eines
Unterprogrammaufrufs überschrieben. Dann ist der Fehler ähnlich
schwer zu erkennen wie in Mobys Fall. Das ist aber auch der Grund,
warum globale Variablen (vor allem Schreibzugriffe auf dieselben)
vermieden werden sollten.
Aber selbst diese Fehlerursache lässt sich aus der Welt schaffen,
indem man auf der Programmierprachenleiter noch eine Stufe höher
steigt (ich sehe schon Mobys entsetzten Gesichtsausdruck vor mir) und
eine Funktionalsprache verwendet. Damit gehören solche Fehler (und
viele andere auch) endgültig der Vergangenheit an.
Jetzt sind meine Feststellungen ja hier immer noch Thema.
Hatte Mod Yalu nicht angemahnt:
> Und bevor wir hier weiterdiskutieren und immer mehr vom Usprungsthema> abkommen:> Moby, fang doch bitte einen neuen Thread an. Dann beschwert auch keiner> darüber, dass du den Thread kaperst.
Hatte Mod Lothar M. nicht beklagt:
> Dass ihm Andere seinen Thread> entführen und verunstalten gehört nicht zum guten Umgangston.
Nun erklärte ich mich bereit, dem TO Horst S. wieder das Feld zu
überlassen.
Was vom TO folgt ist nun aber nur noch
> möchte ich mich abschließend ... bedanken.
Ja was jetzt? Was willst Du eigentlich? Deine Antworten hast Du also
bekommen. Darf nun darüber hinaus nicht mehr diskutiert werden? Mußtest
Du diesen Kübel Unrat weiter oben über mich ausgießen? Ich frage mich
schon sehr, welche Höflichkeit das nun meinerseits noch wert sein
soll...
Ich werde sobald möglich noch auf einige in der Zwischenzeit
aufgelaufenen Beiträge eingehen. Ein extra Thread dafür ist Blödsinn,
weil man sich nicht mehr sinnvoll auf vorhergehende Beiträge beziehen
kann.
Danke an alle, die sich konstruktiv mit meinen Sourcen
auseinandergesetzt haben. Ich hoffe daß ich auch noch was draus lernen
kann.
>Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt
Das hatte ich sogar noch übersehen.
>Es ist nicht gedacht für den Transport von booleschen Informationen>über weite Strecken innerhalb des Programms
Dafür würde das SREG das T-Flag bieten. Dieses kann frei verwendet
werden und wird nicht bei arithmetischen Ops geändert. Sprungbefehle
dafür gibt es aber genauso.
Peter D. schrieb:> Moby A. schrieb:>> Zeigt mal, wie>> sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen>> lässt. Das würde ja auf mich viel eher Eindruck machen ;-)>> Welche Funktionalität denn?> Nirgends wird beschrieben, was der Code überhaupt machen soll!>> Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren,> die sagen 0,nix über die Gesamtfunktion aus.
Peter, hast du immer noch nicht verstanden, dass Mobys Code quaDefinition selbsterklärend ist?
> Nirgends wird beschrieben, was der Code überhaupt machen soll!
Ich bezieht mich hier mal auf den Code für den LM335:
Mal unabhängig davon, was dieser Asm- oder C- oder
In-was-für-einer-Sprache-auch-Immer-Code genau tut, wäre interessant zu
wissem, wie der Code einzusetzen ist.
Für jeden erzeugten ADC-Wert wird über 64 Werte gemittelt. Warum?
Erhöht das die Genauigkeit? Was ist die maximale Aufruffrequenz für die
Funktion?
Intention ist wohl, die adu-Funktion über eine ADC-ISR aufzurufen, und
der ADC liefert beständig neue Werte / IRQs per ADATE (ADC Auto Trigger
Enable). Problem: Die adu-Funktion fummelt an der ADC-Konfiguration
rum:
o Nach Ändern des Input-MUX dauert es recht lange (*), bis wieder
brauchbare ADC-Werte verfügbar sind. Die ersten ADC-Werte
sind Schrott.
o Vermutlich wurde die Mittelung eingeführt, weil sich damit genauere
Ergebnisse erzielen lassen; die Mittelung maskiert also nur das
MUX-Problem ohne es zu benennen oder zu lösen. Eine Lösung wäre
z.B. den 63. ADC-Wert in den 0. zu kopieren. (Falls die MUX-Zeit
nicht größer als 2 Wandlungen ist, in welchem Falle noch mehr
Werte zu kopieren wären...)
o Vermutlich gilt ähnliches für Rumfummeln an REFSx, also Auswahl
der Referenzspannung.
(*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein
quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis:
Schrott. Das Datenblatt (ATmega8 oder ATmegax IIRC) gab die Info nicht
her, und erst eine Anfrage beim Hersteller ergab Klarheit: Die nach
einer MUX-Umschaltung benötigte Zeit ist so hoch, dass ich den Ansatz
verwarf und schließlich eine komplett andere Lösung wählte.
Irgendwie kann ich mich des Eindrucks nicht erwehren, dass hier eine
nerdig-neurotische Fixierung darauf, das letzte Byte aus einer
Implementierung zu quetschen, den Blick auf die reale Anwendbarkeit des
Codes und deren Einschränkungen verstellt.
Natürlich liegt es in der Verantwortung des Anwenders, der Mobys Code
anwendet, seine Hardware adäquat zu initialisieren. Jedoch erwähnt Moby
in seinem Code diese MUX-Fußangel an keiner Stelle. Da er sich ihrer
offenbar nicht bewusst ist, würd ich darauf tippen, dass sein LM335-Code
nicht getestet ist — zumindest nicht so, dass man ihn guten Gewissens in
einem öffentlichen Forum weitergeben möchte...
Natürlich macht der Code Byte für Byte was sein Autor will — inwieweit
das überhaupt sinnvoll ist oder Mumputz, steht auf einem anderen Blatt;
inzwischen vielleicht sogar im Datenblatt.
Moby schrieb:> Asm allein ist nun> leider keine Garantie für guten Code, wie man beim TO-Programm schön> sehen kann ;-)
Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so
vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne
großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru,
aber einfach abfrühstücken lasse ich mich auch nicht von Dir.
Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung.
> Der 8051 wurde ein einer Zeit entwickelt, in der man solche Aufgaben
nicht in C gelöst hat, sondern meist in Assembler.
Wikipedia:
PLM compilers have been made for 8008, 8080, 8085, 8051, 8052, 8096.
80196, 8086, 80186, 286 and 386.
Nun ist PLM von der Syntax her kein C, aber sonst C ähnlicher als
Assembler. Und wenn man 8008 liest, offenbar ein Zeitgenosse von frühem
C anfang der 70er. Von Intel (und seinen Kunden) wurde mit PLM alles
gelöst was ging.
Ich erinnere mich an eine digitale Regelung um die 4 Farbwerke einer
großen Druckmaschine zu synchronisieren (damit die Farben richtig
übereinander kommen). Das hatte eine Schweizer Firma 1982 (da war ich
Werkstudent in der Druckerei) mit einem 8085-Board in PLM80 gemacht.
Auch das 8085-Entwicklungssystem hatte ein OS (ISIS II) in PLM80
geschrieben. Das Konkurrenzprodukt CP/M bestand in Teilen auch aus
PLM-Code. (grad gesehen: es gibt die CP/M Sourcen in Netz, dabei auch
die F66-Source des Intel PLM80 Compilers. Er soll mit Gnu-FORTRAN
übersetzbar sein)(das ist fast wie Oldtimerhefte durchblättern 8-))
Einziger Nachteil an dem Zeug damals: Intel lies es sich vergolden. Und
heute haben wir den avr-gcc. 0€, satte Gegenleistung.
Ich bekenne: alles Off-Topic, aber das hat in diesem Thread ja Tradition
;-)
Johann L. schrieb:> (*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein> quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis:> Schrott.
Kann ich nicht bestätigen. Ich benutze immer den MUX und habe keinerlei
Übersprechen der anderen Eingänge oder falsche Messungen.
Z.B. wenn ich 6 Eingänge messen will, lege ich ein Array für die 6
Ergebnisse an. Ein Timerinterrupt liest dann die vorherige Messung ins
Array, startet die Messung und schaltet den MUX weiter.
Das Main nimmt sich dann den benötigten Wert, ohne auf den ADC warten zu
müssen.
Nur wenn man die interne Referenz messen will, muß man etwa 8 Meßwerte
wegschmeißen, ehe der Wert stimmt. Vermutlich ist da ein hochohmiger
Widerstand drin und der Sample-Kondensator braucht dadurch lange zum
Umladen.
http://www.avrfreaks.net/comment/493872#comment-493872
Horst S. schrieb:> Moby schrieb:>> Asm allein ist nun>> leider keine Garantie für guten Code, wie man beim TO-Programm schön>> sehen kann ;-)>> Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent
Beispiel:
Bereis diese 3 Zeilen sind ein Albtraum der Unwartbarkeit und ab
weibischer Weitschweifugkeit nicht zu überbieten! Der Kommentar ist
überflüssig und lenkt vom Wesentlichem ab, nämlich dem Code. Er
verwirrt den Leser, ist redundant und verschwendet wertvolle Bytes in
deinem Rechner, auf deiner Festplatte, und in unser aller Birnen!
Die nächste Zeile verwändet abermals die Anti-Pattern Byteverschwendung
und Zeitverschwendung durch dein Assembler-Programm: Die << und |
müssen aufwändigst von deinem Rechner errechnet werden — ein Glück, dass
der Assembler, den du verwendest, von erfahrenen Assembler-Experten
hochoptimiert programmiert wurde. Nur so ist es möglich, dass es nich
Minuten oder gar STunden dauert, bis dein Projekt übersetzt ist!
Aber ich schweife ab... "d0" ist ein sehr guten Ansatz, denn es spart 8
wertvolle Bits gegenüber einem "R16" — und das sogar 2× !. Dennoch:
Solche symbolischen Namen sind die totale Verfehlung und zeigen die
Degeneriertheit deiner Gedankenwelt, ausgelöst durch wiederholten Lesens
von Hochsprachen-Code und Kontakt mit Individuen, welche solche
Widerlichkeiten ernsthaft in Betracht ziehen oder gar ausüben!
Hie noch die selbsterklärende, ultimative Asm-Lösung, die keine Fragen
offen lässt!
1
LDI R16, $db
2
STS 132, R16
Alles andere ist kindischer Schnickschnack!
p.s. ich hab noch eine kürzere Lösung gefunden, die weitere wertvolle
Bytes spart!
>Das hatte eine Schweizer Firma
Ferag AG?
Gerade mal Google befragt:
Bobst, machen heute in Verpackungsmaschinen und nicht mehr in
Druckmaschinenausrüstung.
Horst S. schrieb:> Verdammt, wo soll ich denn dann mit meinen 8GB Ram und 1,3MHz hin? Nur> Fickelfilme gucken?
Musst die Kiste in Assembler programmieren. Andernfalls ist sie (bei
1,3GHz jedenfalls) für normale Anwendungen viel zu schnell. Nur in
Assembler wird es dir gelingen, sie auf vernünftiges Mass zu drosseln.
;-)
Aus dem gesparten RAM machst du dann eine RAM Disk. Fürs Swapfile.
Johann L. schrieb:> Hie noch die selbsterklärende, ultimative Asm-Lösung, die keine Fragen> offen lässt!> LDI R16, $db> STS 132, R16
Das R16 könnte man noch durch die Adresse ersetzen...
Peter D. schrieb:> Johann L. schrieb:>> (*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein>> quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis:>> Schrott.>> Kann ich nicht bestätigen. Ich benutze immer den MUX und habe keinerlei> Übersprechen der anderen Eingänge oder falsche Messungen.> Z.B. wenn ich 6 Eingänge messen will, lege ich ein Array für die 6> Ergebnisse an. Ein Timerinterrupt liest dann die vorherige Messung ins> Array, startet die Messung und schaltet den MUX weiter.> Das Main nimmt sich dann den benötigten Wert, ohne auf den ADC warten zu> müssen.>> Nur wenn man die interne Referenz messen will, muß man etwa 8 Meßwerte> wegschmeißen, ehe der Wert stimmt. Vermutlich ist da ein hochohmiger> Widerstand drin und der Sample-Kondensator braucht dadurch lange zum> Umladen.> http://www.avrfreaks.net/comment/493872#comment-493872
Ich hab nur noch meine Antwort an den Atmel-Support gefunden, aus der
eine Zeit von 125µs hervorgeht:
1
The device is an ATmega8. However, I assumed that all AVRs are
2
equiped with the same input MUX, i.e. you do not taylor input
3
MUXs for every AVR derivative.
4
5
The ATmega8 manual does not mention these 125µs.
6
7
125µs are *very* long. I would expect transition times in the
8
range of ns after a channel selection like in stand alone
Den Datasheets von z.B. ATmega32 und ATtiny26 zufolge betrifft das nur
den differentiellen Modus, und den hat nicht jeder AVR. Der ATmega8 hat
ihn nicht und da steht es folgerichtig auch nicht drin.
"Special care should be taken when changing differential channels. Once
a differential channel has been selected, the gain stage may take as
much as 125µs to stabilize to the new value. Thus conversions should not
be started within the first 125µs after selecting a new differential
channel. Alternatively, conversion results obtained within this period
should be discarded.
The same settling time should be observed for the first differential
conversion after changing ADC reference (by changing the REFS1:0 bits in
ADMUX)."
Jörg W. schrieb:> allein von Johanns Ausführungen über das, was er (*) da so im> Compiler treibt, kann man hinreichend viel auch als gestandener> Programmierer noch lernen. ;-)>> (*) Johann ist derjenige, der in den letzten Jahren am AVR-Backend> des GCC massiv herumoptimiert hat. Davor war er zwar auch schon> brauchbar, aber eben manchmal recht suboptimal (vermutlich eher> das, was Moby sich unter einem Compiler vorstellen würde).
Ja, ein Compiler arbeitet bestimmt nicht so, wie sich Lieschen Müller
das ausmalt. Aber in einem muss ich Moby recht geben: Der erzeugte
Code ist nicht optimal.
Das Verbesserungspotential würd ich mit 10% oder mehr ansetzen. Aber
andererseits ist auch die frage, die weit ein Assemblerprogrammierer vom
Optimum (das wir i.d.R nicht kennen) entfernt ist, insbesondere auch wie
weit er davon entfernt bleiben will weil er seinen Code nicht
kaputt-optimieren mag.
Bei Mobys Code könnte man z.B. einiges an Zeit sparen wenn — wie schon
erwähnt — auf die Schiebeschleife verzichtet würde und zudem die
Funktion inline in der ISR wäre. Dass der Code selbst ein paar Ticks
mehr braucht ist dabei garnicht das Problem, aber bei AVRs sind ISRs in
der Regel blockierend, und die Latenzzeiten aller anderen ISRs werden
höher.
> Dank Johanns Engagement hat er aber nochmal massiv zugelegt,
Leider geht teilweise viel Zeit drauf, manchen Atmel-Änderungen wie dem
Specs-Zeug hinterher zu wischeln. Allein das hat mich mehrere Tage
AVR-Zeit gekostet, was in Real Time dann locker Wochen bis Monate sind
:-(
A. K. schrieb:> Den Datasheets von z.B. ATmega32 und ATtiny26 zufolge betrifft das nur> den differentiellen Modus, und den hat nicht jeder AVR. Der ATmega8 hat> ihn nicht und da steht es folgerichtig auch nicht drin.
Ja, es stand / steht nicht im Datenblatt, und es war für ein Device ohne
differentiellen Modus. Wenn ich's richtig verstand wurde vom
2nd-LevelSupport nachgemessen, und ich musste einige Tage warten bis die
das Ergebnis hatten. Die genaue ADC-Config des ATmega8 hab ich
allerdings nicht mehr, eingestampft wie gesagt.
Na da hat sich ja einiges getan, seit ich in diesen Thread das letzte
mal reingeschaut habe.
Ja, genau so etwas hab ich schon erwartet. Das ist oft der Normalfall,
auch in den Programmierforen. Die ärgesten Assembler-Verfechter glänzen
da bei Assembler Fragen meistens mit Abwesenheit. Aber das das
rückzugsgefechtartige Gestammel von Moby so deutlich ausfallen würde,
das hab ich dann doch nicht erwartet. Besonders schön natürlich das
Bonmont mit der fehlerhaften Adressierung im BST in der ominösen ADC
Routine. Moby, was machst du eigentlich, wenn ich eine andere Verteilung
der Referenzspannungen haben will, oder mehr Kanäle, oder nicht 64
Samples sondern weniger? Oder gar, Gott bewahre, mehr? Dann platzt deine
ach so tolle handoptimierte Bitpfriemelei wie eine Seifenblase und die
Arbeit geht von vorne los. Das alles sind Dinge, die mir in C nur ein
Schulterzucken kosten. Einen Zahlenwert ändern und soll sich doch der
Compiler was überlegen, wie er das anständig umsetzt.
Und sorry. Ich weiss ja nicht, was du für Programme schreibst. Aber die
Welt hört beileibe nicht bei 8 Bit Arithmetik auf. Ein bisschen rechnen
ist ausserdem keineswegs so selten, wie du das hinstellst. Ganz im
Gegenteil: ein paar Werte in ein paar Register schreiben, das ist der
eigentlich geringfügigere Teil in einem Programm. Das kann man gut in
Assembler machen. Allerdings: Das kriegt der Compiler genau so gut hin.
Und wie man gesehen hat, ist der Schwellwert an Komplexität, den du noch
überblicken kannst, so gross dann auch wieder nicht. Ich gebe gerne zu,
dass ich den 32 Bit Vergleich nicht so elegant hingekriegt hätte. Muss
ich auch nicht. Bei mir macht das der Compiler. Mich interessiert es
schlicht und ergreifend nicht besonders wie er das macht. Ich kümmere
mich lieber darum, welche Bedeutung dieser Vergleich im Kontext meines
Programmes hat, warum er da stehen muss, ob es ein kleiner oder doch ein
größer sein muss. Die Details der Umsetzung - die macht der Compiler für
mich. Und wenn er da ein paar Takte zuviel reinhaut stört das in mehr
als 95% aller Fälle nicht die Bohne. Dafür, und diesen Seitenhieb kann
ich mir nicht verkneifen, macht der das zum Ausgleich korrekt und
braucht nicht anderthalb Stunden dafür. Ich hab mit meiner Zeit wirklich
was besseres zu tun, als mich mit Routine-Angelegenheiten rumzuschlagen.
So interessant sind die auch wieder nicht. Aber ein ausgefuchster
Algorithmus, der kann mich dann auch schon ein paar Stunden oder Tage
beschäftigen. Nur - so weit kommst du gar nicht, weil du ihn gar nicht
wegen des Umfangs im absehbarer Zeit implementieren kannst. Oder - was
noch viel wichtiger ist - du kannst gar nicht Varianten davon genauer
studieren, weil du viel zu sehr damit beschäftigt bist, warum das Carry
Flag schon wieder mal an einer Stelle nicht den Wert hat, den es haben
sollte (jetzt nur mal so zum Beispiel). Kurz und gut: du musst dich auf
einer Ebene mit Problemen rumschlagen, die nichts mit der eigentlichen
Aufgabenstellung zu tun haben. Die eigentliche Aufgabenstellung mag
lauten, anhand einer Uhrzeit ein Temperaturprofil mit einem PID Regler
abzufahren. Ob du dabei den X-Pointer oder doch den Z-Pointer zur
Indizierung in die Temperaturtabelle benutzt ist dabei völlig
nebensächlich. Du musst auch mal in etwas größeren Dimensionen denken
als nur "Wenn Taster dann Licht an".
Karl H. schrieb:> rückzugsgefechtartige Gestammel von Moby
Na na nicht so vorschnell. Es soll doch da tatsächlich noch andere Dinge
im Leben geben als hier permanent präsent zu sein. Oder etwa nicht?
Karl H. schrieb:> Besonders schön natürlich das> Bonmont mit der fehlerhaften Adressierung im BST in der ominösen ADC> Routine.
Wir werden doch nun einen Flüchtigkeitsfehler nicht so hoch aufhängen!
Daß es hier im Forum unentschuldbar ist, einen Quelltext mit einem
solchen zu veröffentlichen, ok, daß muß und werde ich zukünftig
berücksichtigen.
Karl H. schrieb:> Moby, was machst du eigentlich, wenn ich eine andere Verteilung> der Referenzspannungen haben will, oder mehr Kanäle, oder nicht 64> Samples sondern weniger? Oder gar, Gott bewahre, mehr? Dann platzt deine> ach so tolle handoptimierte Bitpfriemelei wie eine Seifenblase und die> Arbeit geht von vorne los.
Da platzt gar nichts. Oder ist eine entsprechende Umformulierung nun
gleich High-Tech? Nein, es ist Kiki. Wenngleich
flüchtigkeitsfehleranfällig und damit hier nicht sofort
veröffentlichungswürdig. Aber was man schließlich hat das hat man...
Moby A. schrieb:> Da platzt gar nichts. Oder ist eine entsprechende Umformulierung nun> gleich High-Tech? Nein, es ist Kiki.
Na Moby... wieder ganz der Alte? ;-(
Karl H. schrieb:> rückzugsgefechtartige Gestammel
Da mokieren sich die einen Mods über vaterlandsgefährdende
Threadübernahme, die anderen über Rückzug. Da werden beleidigende
Kommentare von Forumsteilnehmern kritisiert- und Mods schlagen in die
gleiche Kerbe. Diese Forummodlogik für in sich konsistent zu halten
würde ich Gestammel nennen...
Aber so sind sie, die Menschen. Einer wie der andere.
Karl H. schrieb:> Aber die> Welt hört beileibe nicht bei 8 Bit Arithmetik auf.
Sicher nicht. Das für Asm wie für 8-Bit AVR nachteilige Thema hatten wir
schon. Eine große Klasse von Steuerungs-Anwendungen kommt da ohne
aufwendiges 32 Bit aus. Sensoreinlesen, verarbeiten und verschiedene
Ausgaben veranlassen (z.B. an seriell angebundene Aktoren/Webinterfaces)
haben größere Berechnungen selten am Bein.
> Allerdings: Das kriegt der Compiler genau so gut hin.
Berechnungen? Sicher doch. Das ist dann aber nur ein Aspekt von vielen
und ich erspare mir an dieser Stelle weitere Wiederholungen zu den
Vorteilen von Asm.
> Mich interessiert es> schlicht und ergreifend nicht besonders wie er das macht.
Was man in Asm hat das hat man. Über die Jahre begeisterten
Asm-Programmierens kann das eine ganze Menge werden.
> braucht nicht anderthalb Stunden dafür.
Ja es ist wirklich interessant was sich aus den Zeitdaten
veröffentlichter Beiträge so alles ableiten lässt ;-)
> ausgefuchster> Algorithmus, der kann mich dann auch schon ein paar Stunden oder Tage> beschäftigen. Nur - so weit kommst du gar nicht, weil du ihn gar nicht> wegen
fehlender Notwendigkeit eines solchen ;-)
> weil du viel zu sehr damit beschäftigt bist, warum das Carry> Flag schon wieder mal an einer Stelle nicht den Wert hat, den es haben> sollte
C-Programmierer haben da andere, gewichtigere Probleme: Den ganzen
Zirkus von C-Konstruktionen mitsamt komplexer Ausdrücke und
Compileroptionen unter Kontrolle zu behalten... Was ist denn da ein
Carry Flag ;-)
> in etwas größeren Dimensionen denken> als nur "Wenn Taster dann Licht an".
Das Zusammenwirken vieler Sensoren und Aktoren verknüpft über drahtlose
Netze stellt durchaus ein paar Anforderungen. Nur eben weniger an
Berechnungen.
Johann L. schrieb:> Das Verbesserungspotential würd ich mit 10% oder mehr ansetzen.
Meine Rede. Insbesondere bei kurzen Programmen sind die Chancen dieses
Potential zur Geltung zu bekommen hoch.
> Aber> andererseits ist auch die frage, die weit ein Assemblerprogrammierer vom> Optimum (das wir i.d.R nicht kennen) entfernt ist, insbesondere auch wie> weit er davon entfernt bleiben will weil er seinen Code nicht> kaputt-optimieren mag.
Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch
(fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen
Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.
Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich
interessiert allein die effiziente,simple Lösung und kein 32bittiges
Herumprotzen mit Ressourcen und Vernichtung derer mit Hochsprachen.
Falk B. schrieb:> Ich verweise auf die Universalantworten, auch zu diesem Thema
Ja Falk, verweise ruhig was das Zeug hält ;-)
Mein Anspruch ist nun aber die praktikable Lösung-und wenn ich mich in
der Bude so umschaue- sorry Falk, dann kann ich nicht anders als mich
darin total bestätigt zu fühlen ;-)
Der Spaß an der Sache ist allerdings auch nicht zu unterschätzen!
Falk B. schrieb:> Ich verweise auf die Universalantworten,
Hmm..., jaa..., neee...
Da muss es noch was anderes geben.
Moby A. schrieb:> Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich> interessiert allein die effiziente,simple Lösung und kein 32bittiges> Herumprotzen mit Ressourcen und Vernichtung derer mit Hochsprachen.
Das kommt mir wie 'ne Politikerrede vor. Beeindruckende Wortwahl und
nichts dahinter.
Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar.
Klar: nur dort. Schon bei mittleren nämlich nicht mehr. Schließlich
ist auch dein Leben endlich …
Was du generell unterschätzt: die, gegen die du hier ankämpfst, sind
fast durchweg Leute, die eine solche Sturm-und-Drang-Phase, die du
da gerade hast, schon vor ein oder zwei (oder drei) Jahrzehnten
durchlaufen haben. Es sind alles Leute, die teilweise wohl viel
besser als du wissen, wie ein Assembler funktioniert (und der vom
AVR Studio ist in dieser Hinsicht ohnehin nur eine Krücke auf eher
unterem Niveau), die teilweise Assembler-Pamphlets von mehreren
Dutzend Seiten fabriziert und zumindest zur geplanten Funktion
bekommen haben. Im Gegensatz zu dir wissen sie jedoch aus gerade
dieser Erfahrung, dass es um die dabei verschwendete Lebenszeit
schade war, wenn stattdessen eine Maschine einen durchaus vergleichbar
guten Job mittlerweile innerhalb von ein paar Sekunden hinlegt.
Moby A. schrieb:> Da werden beleidigende Kommentare von Forumsteilnehmern
Nur mal so, weil du das immer wieder anbringst: geh' mal zum
Staatsanwalt deines geringsten Misstrauens und befrage ihn, was er
als „Beleidigung“ ansieht. Du wirst dich ziemlich wundern, wie hoch
die Schwelle dafür liegt. Ein paar flapsige Kommentare eines
Forenteilnehmers, dessen Thread du letztlich mit deiner dir üblichen
Penetranz gekapert hast (ohne ihm damit auch nur im geringsten zu
helfen), fallen da ganz gewiss nicht drunter.
Jörg W. schrieb:> Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar.>> Klar: nur dort. Schon bei mittleren nämlich nicht mehr. Schließlich> ist auch dein Leben endlich …
Bei mittleren muß man systematischer rangehen.
Funktionalität als unabhängiges Modul formulieren das sich von weiteren
Nebenabhängigkeiten befreit zum Beispiel flexibel in einem
Timerinterrupt aufrufen lässt. So wie die beiden (ADU+Tastenentprell)
Beispiele.
> Was du generell unterschätzt: die, gegen die du hier ankämpfst, sind> fast durchweg Leute, die eine solche Sturm-und-Drang-Phase, die du da> gerade hast, schon vor ein oder zwei (oder drei) Jahrzehnten durchlaufen> haben. Es sind alles Leute, die teilweise wohl viel besser als du> wissen, wie ein Assembler funktioniert (und der vom AVR Studio ist in> dieser Hinsicht ohnehin nur eine Krücke auf eher unterem Niveau), die> teilweise Assembler-Pamphlets von mehreren Dutzend Seiten fabriziert und> zumindest zur geplanten Funktion bekommen haben. Im Gegensatz zu dir> wissen sie jedoch aus gerade dieser Erfahrung, dass es um die dabei> verschwendete Lebenszeit schade war, wenn stattdessen eine Maschine> einen durchaus vergleichbar guten Job mittlerweile innerhalb von ein> paar Sekunden hinlegt.
Ich möchte gegen niemand ankämpfen.
Schon gar nicht jemand, der aus vielerlei Gründen (beruflich) Lösungen
in Hochsprache undoder 32-bittig umzusetzen hat. Wenn die gleichen Leute
dies aber in einer Form verallgemeinern, die Asm und AVR generell in
Frage stellen wiederspreche ich vehement.
> Nur mal so, weil du das immer wieder anbringst: geh' mal zum> Staatsanwalt deines geringsten Misstrauens und befrage ihn, was er als> „Beleidigung“ ansieht.
Da darf ich Dich beruhigen- sooo wichtig ist mir dann das Forum als
solches nicht ;-)
Moby A. schrieb:> umzusetzen hat
Du siehst das immer noch durch die falsche Brille: wir müssen das
nicht so machen, sondern machen das alle völlig freiwillig so. Weil
wir wissen, dass es auf den von dir beschworenen (und dann ja oft
doch nichtmal wirklich erreichten) letzten Taktzyklus sowieso nur in
0,001 % der Fälle ankommt. Das vorletzte Mal, dass ich das hatte,
war die Diskettenzugriffsroutine meines CP/M-BIOS vor reichlich 25
Jahren. Eine Vierfach-Schleife um die innere Schleife herum (die je
256 Byte einlas) hätte nicht funktioniert, also habe ich sie per
Makro im Assembler wirklich viermal eingefügt. (Dummerweise können
natürlich auch Compiler sowas, das nennt sich dann loop unrolling, und
das machen sie, wenn man sie drängt, auf Geschwindigkeit zu optimieren.)
A. K. schrieb:> Also gut, dann eben zerstörungsfrei:void g(long);> void f(long x)> {> if (x < 1000000)> g(x);> }>> Ergebnis vom Compiler:> cpi r22,64> ldi r18,66> cpc r23,r18> ldi r18,15> cpc r24,r18> cpc r25,__zero_reg__> brge .L1
Schön. Interessant. Dankeschön.
Bei den Takten kommen wir aber auch auf 7...8.
Und das wird noch mehr wenn x>16777215.
Moby A. schrieb:> Und das wird noch mehr wenn x>16777215.
Du meintest eventuell 'wenn x mit einer Konstanten größer 16777215'
verglichen wird? Da schreibt man die Konstante hin und zack!, hat der
Compiler den entsprechenden Code gezaubert.
Jörg W. schrieb:> Du siehst das immer noch durch die falsche Brille: wir müssen das nicht> so machen, sondern machen das alle völlig freiwillig so.
Dann bitte auch gern freiwillig.
Warum auch nicht? Ich bin doch nicht so verrückt anzunehmen, jeder
C-Programmierer sei auf dem Holzweg. Entscheidend ist was hinten
rauskommt.
Da sehe ich den Asm-Programmierer bei typischen 8-Bit Projekten auf
8-Bit Controllern aber im Vorteil. Erreichbare Performance/Codesize sind
auch nur zwei technische Aspekte. Mir fast noch wichtiger sind
übersichtliche Programmstruktur (bei sinnvoller Funktionskommentierung)
wie überhaupt der Bruchteil notwendiger sprachlicher Mittel, um ans Ziel
zu kommen. Direkt. Und daß der unmittelbare Kontakt zum Datenblatt nun
wirklich nicht schadet sieht man weiter oben...
Wir sollten anfangen, die Argumente zu nummerieren. Spart Tipparbeit,
weil man dann in der hiesigen schon heftig entrollten
Argumentationsschleife nur noch die Nummern hinschreiben muss.
A. K. schrieb:> Wie wärs Moby, könntest du deine Variante noch auf 32 Bits mit> Vorzeichen ausdehnen?
Nö. Brauch ich nicht. Wozu? Um hier irgendwas zu beweisen? Ist das
fertig kommst Du mit dem nächsten um die Ecke ;-)
Versuch Du doch umgekehrt mal gegebene Asm-Texte mit C einzudampfen.
Weitere Gelegenheiten werde ich noch liefern.
Moby A. schrieb:> Bei den Takten kommen wir aber auch auf 7...8.
Und da gibts noch einen Nachteil.
Die 7...8 Takte sind bei obiger Compiler-Lösung die Regel, bei meiner
schon fast die Ausnahme ;-)
Horst S. schrieb:> Moby schrieb:> Asm allein ist nun> leider keine Garantie für guten Code, wie man beim TO-Programm schön> sehen kann ;-)>> Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so> vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne> großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru,> aber einfach abfrühstücken lasse ich mich auch nicht von Dir.>> Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung.
Die Entschuldigung kannst Du Dir sparen.
Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das
jedenfalls nicht für Deinen Asm-Code.
Die lange diesbezügliche Rumbastelei am C-Code im übrigen auch nicht für
C.
Moby A. schrieb:> Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das> jedenfalls nicht für Deinen Asm-Code.
Allerdings waren die alternativen (und besseren) C-Varianten, die
Horst geholfen haben, schon nach wenigen Forums-CPU-Takten verfügbar.
Eine alternative Assembler-Variante hast du ihm jedenfalls bis heute
noch nicht angeboten.
Damit bleiben all deine Argumente reine Theoretisiererei, die vielleicht
deinem Ego hilft, aber sonst niemandem.
A. K. schrieb:> Wir sollten anfangen, die Argumente zu nummerieren.
So, wie die beiden Typen mit den Witzen. Gute Idee. :-)
Johann L. schrieb:> Peter D. schrieb:> Welche Funktionalität denn?> Nirgends wird beschrieben, was der Code überhaupt machen soll!> Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren,> die sagen 0,nix über die Gesamtfunktion aus.>> Peter, hast du immer noch nicht verstanden, dass Mobys Code qua> Definition selbsterklärend ist?>> Nirgends wird beschrieben, was der Code überhaupt machen soll!>> Ich bezieht mich hier mal auf den Code für den LM335:
Asm-Code ist selbsterklärend. Es braucht nämlich nur die
Instruktionsbeschreibung und das Datenblatt sowie ein paar
funktionserklärende Kommentare.
Da es aber zu meiner Überraschung offensichtlich Fragen zum Einsatz und
dem Wie&Warum gibt werde ich das in dem entsprechenden Projekte-Beitrag
nochmal thematisieren.
Jörg W. schrieb:> deinem Ego hilft
Das spielt die letzte Geige, sonst wär durchaus schon eine Menge
meiner veröffentlichungsfähigen Entwicklungen in den Projekten. Wenn man
das aber trotzdem verstärkt tun sollte dann weil ich natürlich gemerkt
habe, daß es diesbezüglich hier einen gewissen Nachhol- bzw.
Wissensbedarf gibt und die besten Argumente immer noch überzeugender
Code liefert.
900ss D. schrieb:> Danke Moby, immerhin hast du deinen Code gepostet. Fazit: Auch> handgeschriebener ASM-Code ist nicht immer besser als der vom Compiler.
Wiegesagt, das C-Ergebnis sollte dann aber erstmal wirklich gleichwertig
sein was es so nicht ist.
> Warum du Moby, so verbissen an ASM festhälst, wird mir auch ein Rätel> bleiben, die von Dir genannten Vorteile sind alle objektiv widerlegt
Das sehe ich anders aber es mag sein, daß es noch ein paar
überzeugenderer Beispiele bedarf ;-)
> Neugier: Moby, ist programmieren eher aus Hobby betrieben oder verdienst> du dein Geld damit?
Mobby Hobby.
> Und daß der unmittelbare Kontakt zum Datenblatt nun wirklich nicht schadet
sieht man weiter oben...
Man glaubt zwar kaum, aber auch C-Programmierer dürfen DBs lesen. Und
tun das auch. Und was finden sie da: Codefragment in ASM und C. Zum
direkten Vergleichen. Ob C nun wirklich mehr oder weniger Schlüsselworte
hat, als ein AVR Maschinenbefehle? Auf alle Fälle bringt es beim
Anwenden einer Sprache Vorteile, wenn man nicht ständig in Vokabel- und
Grammatikheft blättern muß. Ich benutze das DB für die Hardware. Die
Sprache kann ich nämlich schon. Und andere (Computer aller
Größenklassen) sprechen die auch. Das ist vielleicht der Unterschied
zwischen (nur) Hobby und 30 Jahre sich selbst und 20 Jahre noch drei
Andere mit Programmieren zu versorgen.
Darf aber jeder selber entscheiden, wie er es machen will. JEDER, nicht
nur Moby! Und damit verbietet sich die Missionstätigkeit spätesten dann,
wenn alle Anderen sagen: "is gut jetzt".
Schreibt ein sich fischiger Haßtiraden sicherer, aktuell sehr müder
Geselle, der bis gerade für Brötchen in einer von wenigen gekannten,
aber von vielen belächelten, auf einer in C und C++ geschriebenen VM
ausgeführten Sprache geschrieben hat, deren Vor- und Nachteile er seit
25 Jahren kennt und sinnvoll einsetzt. Der kann sogar die Opcodes der VM
im Debugger lesen und zum Glück gibt es für diese keinen Assembler, denn
dann bleiben ihm zumindest in dem Umfeld fischige Diskussionen erspart.
Mobby Hobby? Wohl eher Moby Hoby!
Carl D. schrieb:> Auf alle Fälle bringt es beim> Vorteile, wenn man nicht ständig in Vokabel- und> Grammatikheft blättern muß.
Ja, die Grammatik gilt es im Gegensatz zu Asm bei C ja noch zusätzlich
zu beherrschen.
> Und damit> verbietet sich die Missionstätigkeit spätesten dann, wenn alle Anderen> sagen: "is gut jetzt".
Die würde sich für mich nur dann verbieten, wenn meine Erfahrungen mit
Asm denn schlechte wären.
Sind sie aber nicht! Das ist auch kein Wunder, weil Asm alle
Voraussetzungen zum effizienten Programmieren mit allen erdenklichen
Möglichkeiten, zu minimalem Aufwand bietet.
> auf einer in C und C++ geschriebenen VM> ausgeführten Sprache geschrieben hat, deren Vor- und Nachteile er seit> 25 Jahren kennt und sinnvoll einsetzt. Der kann sogar die Opcodes der VM> zum Glück gibt es für diese keinen Assembler, denn> dann bleiben ihm zumindest in dem Umfeld fischige Diskussionen erspart.
Warum werde ich bloß nicht müde zu betonen, für welche Zielplattform
und für welche Anwendungen ich Asm vorn sehe? Warum fühlt sich jeder
Profi bemüßigt, das sogleich auf sein Gebiet- bis hin zur PC
Programmierung zu beziehen?
Wannkappierst du eigentlich, daß dein Ges.... keiner mehr hören kann.
Soll ich dir ständig runterbeten, womit ich schon gute Erfahrungen
gemacht hab? Spätestens nach der Erfahrung, daß andere es nicht mehr
hören wollen, würde ich es für mich behalten und mich ganz allein an der
glückseeligmachen Erkenntnis laben. Und schon garnicht würde ich einer
solchen Gruppe von Ignoranten auch noch demonstrieren, wie rudimentär
ich mein Spezialgebiet tatsächlich nur beherrsche. Aber vielleicht
wollte ich deshalb auch nie Klassenkasper werden. Oder bekommst du
Provision dafür, Threads ins OffTopic zu treiben?
Carl D. schrieb:> der bis gerade für Brötchen in einer von wenigen gekannten,> aber von vielen belächelten, auf einer in C und C++ geschriebenen VM> ausgeführten Sprache geschrieben hat
Siehst Du. Viele belächeln diese. Nichtmal auf dem Level ein
eindeutiges Urteil. Was sagt uns das? Zuvieles jenseits harter Fakten
wird subjektiv erlebt und kann individuell durchaus verschieden bewertet
werden. So erklärt sich dann wohl auch manche Vorliebe in der Diskussion
C vs. Asm.
Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.
Wenn jemand 18 Jahre lang in Assembler programmiert und damit seine
ganze Haussteuerung umgesetzt hat, wird er doch wohl ein paar
fehlerfreie Zeilen Quelltext vorweisen können?!
> Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich> interessiert allein die effiziente,simple Lösung
Die interessiert uns auch. Aber es sind ja Sie, welcher behauptet, die
"effiziente,simple Lösung" zu haben. Belege dafür bleiben Sie schuldig,
unterstellen den Anwesenden aber
> 32bittiges Herumprotzen mit Ressourcen und Vernichtung derer mit> Hochsprachen.
Das interessiert vermutlich die wenigsten hier -- weder die 32 Bit, noch
das Herumprotzen, noch die Vernichtung von Ressourcen. Ich habe auch
noch nie jemanden mit so etwas "herumprotzen" sehen. Sie etwa?
Johann Lay, Jörg Wunsch und Peter Danegger, die sich an diesem Thread ja
mehrmals beteiligt haben, "protzen" jedenfalls nicht mit 32-Bit oder der
"Vernichtung von Ressourcen". Diese Leute könnten mit ihrem fehlerlosen
Code "protzen", und trotzdem tut es keiner. Deren Code hat übrigens auch
keine "Flüchtigkeitsfehler".
Carl D. schrieb:> Wannkappierst du eigentlich, daß dein Ges.... keiner mehr hören> kann.
Du musst hier nichts lesen oder gar schreiben.
Immerhin ist es Dir ja wert auf mich zu reagieren.
Sogar so spät/so früh ;-)
Was meinst Du was ich alles nicht mehr hören mag?
> Provision dafür, Threads ins OffTopic zu treiben?
Tatsächlich sind wir hier nach wie vor bei C vs. Assembler ->
Performance und nicht etwa schon beim Kuchenbacken...
Moby A. schrieb:> Asm-Code ist selbsterklärend.
Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei
einem "selbsterklärenden Code" passieren?
Sheeva P. schrieb:> Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.>> Wenn jemand 18 Jahre lang in Assembler programmiert und damit seine> ganze Haussteuerung umgesetzt hat,
... dann wird ja wohl das allermeiste ohne Fehler funktionieren ;-)
> Aber es sind ja Sie, welcher behauptet, die> "effiziente,simple Lösung" zu haben.
Ich habe nicht die effiziente simple Lösung, sondern sage daß Asm alle
nötigen Mittel dafür bietet.
> Ich habe auch> noch nie jemanden mit so etwas "herumprotzen" sehen. Sie etwa?
In vielen Jahren hier zur Genüge ;-)
> Deren Code hat übrigens auch> keine "Flüchtigkeitsfehler".
Das bestreite ich jetzt einfach mal so.
Wenn sich später in den Projekten auch kaum noch davon was findet. Ich
bin weit davon entfernt, wegen Flüchtigkeitsfehlern die Ohren
hängenzulassen. Aber in die Projektveröffentlichungen (meine erste und
einzige mit Quellcode wohlgemerkt) gehören sie nicht hin. Hatte ich das
nicht weiter oben schon gesagt?
Sheeva P. schrieb:> Moby A. schrieb:> Asm-Code ist selbsterklärend.>> Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei> einem "selbsterklärenden Code" passieren?
Hatte ich eigentlich auch schon erklärt: Der im Einsatz befindliche Code
funktioniert, der für die Projekte leicht veränderte Code (zunächst)
nicht.
Wirst Du mir daraus jetzt den großen Strick drehen?
Bitte bitte nicht, ich flehe um Gnade ;-)
Moby A. schrieb:> Asm-Code ist selbsterklärend.
Auf den Niveau von
> die Instruktionsbeschreibung und das Datenblatt
ist C das auch, das ist aber nicht der Sinn einer ordentlichen
Dokumentation.
Moby A. schrieb:> Sheeva P. schrieb:>> Moby A. schrieb:>> Asm-Code ist selbsterklärend.>>>> Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei>> einem "selbsterklärenden Code" passieren?>> Hatte ich eigentlich auch schon erklärt: Der im Einsatz befindliche Code> funktioniert, der für die Projekte leicht veränderte Code (zunächst)> nicht.>> Wirst Du mir daraus jetzt den großen Strick drehen?> Bitte bitte nicht, ich flehe um Gnade ;-)
Wie kann das sein?
Wow, drei Seiten Diskussionstext in ein paar Tagen. Davon gefühlte 99%
Ping-Pong mit einem Troll. Bei jedem anderen Thema wären die Herren
Moderatoren nicht so zimperlich, aber hier scheints ihnen Spaß zu
machen...
Ich habe gerade zwanzig Benachrichtigungsemails zu diesem Thread
gelöscht. Die Diskussion geht immer noch um dasselbe Nicht-Thema.
Irgendjemand muß sehr, sehr einsam sein.
Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.
Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger
"Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen -
sowohl was Programmier- als auch Prozessoraufwand betrifft.
Moby A. schrieb:> Versuch Du doch umgekehrt mal gegebene Asm-Texte mit C einzudampfen.
Es gibt nur keine vorn Dir. Und wenn doch, konnte gezeigt werden, dass
es mit C kürzer geht - sowohl was Horsts als auch Dein Mini-Progrämmchen
betrifft.
2:0.... Damit bist Du ziemlich im Rückstand, Moby.
> Weitere Gelegenheiten werde ich noch liefern.
Also wenn ich Deine Programmiergeschwindigkeit in ASM hochrechne (einen
simplen Vergleich zu programmieren dauert bei Dir über eine Stunde),
dürftest Du so in ca. einem Jahr etwas praxisrelevantes abliefern.
Du bleibst also weiter bei Deiner Blender-Strategie.
(*) Jedenfalls dann, wenn das Compilat die 1KB-Grenze überschreitet, es
sich also nicht um einen Codeschnipsel handelt, der für sich allein
nicht einsetzbar ist.
@ Walter Tarpan (nicolas)
>gelöscht. Die Diskussion geht immer noch um dasselbe Nicht-Thema.>Irgendjemand muß sehr, sehr einsam sein.
Oder ein ZEN-Meister?
https://de.wikipedia.org/wiki/Zen#Lehre
Sheeva P. schrieb:> Moby A. schrieb:>> Asm-Code ist selbsterklärend.>> Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei> einem "selbsterklärenden Code" passieren?
Der Code erklärt sich halt nur sich selbst, aber nicht anderen.
Zumindest wenn es mehr als ein paar Zeilen sind.
>Der Code erklärt sich halt nur sich selbst, aber nicht anderen.>Zumindest wenn es mehr als ein paar Zeilen sind.
WUrde ja bereits gesehen. Der von mir gepostete Asm COde wurde von Moby
bisher nicht erklärt. Obwohl es doch selbsterklärend ist.
@Matthias Lipinsky (lippy)
>>Der Code erklärt sich halt nur sich selbst, aber nicht anderen.>>Zumindest wenn es mehr als ein paar Zeilen sind.>WUrde ja bereits gesehen. Der von mir gepostete Asm COde wurde von Moby>bisher nicht erklärt. Obwohl es doch selbsterklärend ist.
Das erklärt doch alles!
Falk B. schrieb:> Das erklärt doch alles!
Jetzt bist du uns aber eine Erklärung schuldig! :)
Icke ®. schrieb:> Davon gefühlte 99% Ping-Pong mit einem Troll.
Moby ist kein Troll. Der Unterschied ist, dass ein Troll vorsätzlich
eine Dikussion stört. Moby stört sie auch, es ist auch Vorsatz dabei,
aber ich würde ihm mal nicht unterstellen, dass er sie tatsächlich
stören will. Es ist halt nur seine (sehr, sehr penetrant dargelegte)
Meinung, dass doch seine Philosophie für alle das beste wäre …
Da Horst aber bereits am Anfang des Threads gut und (so ich ihn
verstanden habe) ausreichend geholfen worden ist, denke ich, dass es
nicht übermäßig stört, hier weiterzudiskutieren. Wenn du dir den ein
oder anderen Beitrag mal ansiehst (also eher nicht Mobys, aber
beispielsweise Johanns), dann kann man durchaus noch bisschen dabei
lernen. OK, von Mobys Beiträgen kann man auch lernen, aber wohl nicht
in seinem Sinne. :-))
Moby A. schrieb:> Warum werde ich bloß nicht müde zu betonen, für welche Zielplattform> und für welche Anwendungen ich Asm vorn sehe? Warum fühlt sich jeder> Profi bemüßigt, das sogleich auf sein Gebiet- bis hin zur PC> Programmierung zu beziehen?
Weil du dein Assembler Anpreisung auch nicht auf die von dir vorne
gesehenen Anwendungen beschränkst.
Du kommst mir vor, wie der in Österreich berühmt berüchtigte
Flachlandtiroler, der meint nur weil er zu Hause gerade noch so seine
120 Meter hohe Schutthalde raufschnaufen kann, dass er geradezu
prädestiniert dazu wäre, andere davon zu überzeugen, dass man die Eiger
Nordwand auch mit Sandalen und etwas Bindfaden bezwingen kann.
Moby A. schrieb:> Asm-Code ist selbsterklärend. Es braucht nämlich nur die> Instruktionsbeschreibung und das Datenblatt sowie ein paar> funktionserklärende Kommentare.
Brainfuck, Befunge, Malbolge, FRACTRAN und wie sie alle heißen
(https://de.wikipedia.org/wiki/Esoterische_Programmiersprache) sind
deiner Definition nach ebenfalls selbsterklärend, denn für jede davon
gibt es eine klare Sprachspezifikation, die zudem sogar sehr viel kürzer
ausfällt als das AVR Instruction Set Manual.
Die allerkürzeste Instruktionsbeschreibung haben diese Prozessoren:
https://en.wikipedia.org/wiki/One_instruction_set_computer
Deren Assemblersprache müsste für dich somit das Optimum aller
Programmiersprachen darstellen, was das Selbsterklärendsein betrifft.
Was du bei der Bewertung der Sprachen völlig auser Acht lässt, ist ihre
Ausdrucksstärke, d.h. die maximale Komplexität der Problems, das mit
einer gegebenen Menge an Code gelöst werden können. Die ist bei den eben
erwähnten Sprachen nahezu null, beim AVR-Assembler sehr niedrig, bei C
aber schon recht hoch, wie das obige Beispiel des Vergleichs mit einer
Konstanten deutlich zeigt:
Der aus 9 Zeichen bestehende Term x<1000000 in C ist nicht nur viel
kürzer, sondern darüberhinaus auch noch besser lesbar und leichter
änderbar als die entsprechende CPI/SBCI-Kette in Assembler. Und wie man
gesehen hat, hat selbst ein überzeugter Assembler-Only-Programmierer
immense Schwierigkeiten, dieses noch recht einfache Beispiel erst einmal
fehlerfrei runterzuprogrammieren und dann auch noch zu optimieren.
Eine sehr schöne Routine, die so nur in C praktikabel ist, ist z.B. der
Scheduler:
Beitrag "Wartezeiten effektiv (Scheduler)"
Die original Idee ist nicht von mir, ich habe sie nur etwas auf den 8051
und den AVR optimiert. Durch die Vorsortierung ist das sehr effizient.
Sie läuft unverändert auf jeder anderen CPU und man kann bequem
festlegen, ob die Zeitbasis 8, 16, .. 64bittig ist.
In Assembler wäre das ein Albtraum und weder anpaßbar noch lesbar oder
gar portabel.
Yalu X. schrieb:> Moby A. schrieb:>> Asm-Code ist selbsterklärend.
Moby hat einfach nur Schwierigkeiten zu verstehen, dass wir unter 'Code
erklären' etwas anderes verstehen als er.
Für ihn besteht die 'Erklärung' eines Codes darin, dass er für jeden
Assembler Memnonic ein entsprechendes Wort kennt.
1
ldi r16, 25
erklärt er mit
1
hier wird das Register 16 mit der Konstanten 25 geladen
Und so 'erklärt' er dann den Code ohne zu begreifen, dass er nichts
erklärt, sondern einfach nur vorliest.
Alles schön und gut.
Nur dass das ganze dann in Summe einen Quicksort ergibt, das entzieht
sich seiner Aufmerksamkeit, weil er viel zu sehr mit diesen Low-Level
Details beschäftigt ist, bzw. weil sich der eigentliche Zweck eines
Codestückes in diesen Details verliert.
Wenn Moby C programmieren würde, dann würde er so kommentieren bzw.
erklären
1
i=5;// i mit 5 laden
2
j++;// j um 1 erhöhen
und das ist genau die Art Kommentierung, die komplett am Sinn einer
Kommentierung vorbei geht.
Wie ich in einem anderen Thread schon mal sagte: Man kann die
Funktionsweise einer Raffinerie nicht dadurch ergründen und erklären,
dass man sich alle Schrauben, Muttern und Beilagscheiben ansieht. Klar
sind die für die Funktionsweise wichtig, aber auch sind die CAD
Programme schon so weit, dass sie Schraubverbindungen selbsttätig
dimensionieren und einsetzen. Das CAD, in dem ich zuletzt mitgearbeitet
habe, hatte viele derartige Automatismen. Kein Architekt verbringt mehr
seine Zeit damit, die Sparren eines Dachstuhls einzeln zu zeichnen. Der
zeichnet die Firstlinie, gibt an welches Dach er haben will und das CAD
konstuiert den kompletten Dachstuhl anhand des Grundrisses und der
sonstigen Angaben für ihn.
@ Karl Heinz (kbuchegg) (Moderator)
>Flachlandtiroler, der meint nur weil er zu Hause gerade noch so seine>120 Meter hohe Schutthalde raufschnaufen kann, dass er geradezu>prädestiniert dazu wäre, andere davon zu überzeigen, dass man die Eiger>Nordwand auch mit Sandalen bezwingen kann.
Ein Sandal! ähh, Skandal!
Jörg W. schrieb:> Moby ist kein Troll.
Ich kenne Moby und seine Diskussionskultur schon von anderen Threads.
Deswegen halte ich mich hier auch raus.
> OK, von Mobys Beiträgen kann man auch lernen
Ich habe daraus gelernt, daß jeglicher Versuch, Menschen mit derartig
zementierten Standpunkten (nannte man früher "Betonköpfe") von ihrem
Holzweg abzubringen, selbst unter Zuhilfenahme einleuchtendster
Argumente kläglich scheitert.
Noch ein klein wenig Topic. Ich programmiere auch gern in ASM, aber ich
kenne die Grenzen. Ab einer gewissen Komplexität macht das einfach
keinen Sinn mehr.
Es ist auch schön, per Pedes durch den Wald zu streifen, den Geräuschen
zu lauschen und mit den Füßen direkten Bodenkontakt zu spüren. Und es
macht Sinn, die 100m bis zum Bäcker um die Ecke zu laufen. Aber für den
Großeinkauf oder die Urlaubsfahrt steig ich dann doch lieber ins Auto.
Karl H. schrieb:> und das ist genau die Art Kommentierung, die komplett am Sinn einer> Kommentierung vorbei geht.
In diesem Fall würde ich da eine Ausnahme machen und auch eine
Kommentierung der Bedeutung der einzelnen Statements nahelegen:
Beitrag "Ein Vorschlag zur Intervall-Arithmetik"
Moby A. schrieb:> Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das> jedenfalls nicht für Deinen Asm-Code.
Wenn das Dein einziges Argument ist, gehe ich nicht davon aus, dass Du
Dir die Mühe gemacht hast, das Projekt überhaupt zu öffnen.
Die reinen Zahlen für die intellektuelle Höchstleistung des numerischen
Vergleiches im vierstelligen Bereich (ab der 3. Klasse praktiziert)
waren ja im Thread deutlich ablesbar.
Frank M. schrieb:> Moby A. schrieb:> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.>> Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger> "Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen -> sowohl was Programmier- als auch Prozessoraufwand betrifft.
Dann bin ich schon sehr gespannt...
Wer die realisierte Funktionalität dann kürzer umsetzt gewinnt den
Hauptpreis: Moby hält bzgl. Überlegenheit von Asm die Klappe ;-)
> 2:0.... Damit bist Du ziemlich im Rückstand, Moby.
Geduld, Geduld. Das Spiel läuft noch nicht lange.
> Also wenn ich Deine Programmiergeschwindigkeit in ASM hochrechne (einen> simplen Vergleich zu programmieren dauert bei Dir über eine Stunde)
... schließt Du aus den Zeiten meiner Beiträge?
Du bist ein Fuchs ;-)
Leider mach ich das nicht hauptberuflich und soviel Zeit steht in der
Freizeit nun auch nicht gerade zur Verfügung ;-(
> Du bleibst also weiter bei Deiner Blender-Strategie
Wen meinst Du kann ich hier blenden?
Daß Asm eine Menge Potential hat, nun, da bin ich nicht der Einzige der
das behauptet- und täglich erlebt ;-)
Moby A. schrieb:> Leider mach ich das nicht hauptberuflich und soviel Zeit steht in der> Freizeit nun auch nicht gerade zur Verfügung
Tja, da geht's den Menschen wie den Leuten. Genau sowas ist halt der
Grund, warum so ziemlich alle anderen Mitdiskutanten hier, trotz
teils guter oder sogar sehr guter Kenntnisse der jeweiligen
Assembler-Welt (siehe Johanns Code) ihre Zeit eben nicht damit
verplempern wollen, sich nun zu überlegen, ob in der nächsten Zeile
ein gesetztes oder ein gelöschtes Carry-Flag ausgewertet werden soll,
und ob die Auswertung direkt als bedingter Sprung erfolgen kann oder
wegen eines schier unerreichbaren Sprungziels indirekt (also negiert),
indem der nächste (lange) Sprungbefehl stattdessen ausgelassen wird.
Diesen ganzen aufwändigen Kleinkram beherrscht eine Maschine namens
Compiler einfach mal um mehrere Größenordnungen schneller und vor
allem weniger fehleranfällig, weil sie ständig inhärent alle
Randbedingungen berücksichtigen kann (wie die Länge eines Sprungs
oder eben den adressierbaren Bereich einer BST-Anweisung) und auch
bei doppelter Verneinung noch keinen Knoten im Gehirn bekommt.
Dafür wiederum kann man dann, ganz ohne es hauptberuflich tun zu
müssen, auch mal schnell ein paar Zeilen Code nur für eine Antwort
im Forum zusammenhacken, um einem Menschen, der um Hilfe bittet, schnell
und unbürokratisch zu helfen – nebenbei, neben der ganz normalen Arbeit,
Familie, sonstigen Freizeitbeschäftigungen.
Klaus W. schrieb:> Der Code erklärt sich halt nur sich selbst, aber nicht anderen.> Zumindest wenn es mehr als ein paar Zeilen sind.Das gilt für C genauso. Selbsterklärend im Sinne von 'die
Sprach-Vorkenntnis überflüssig machend' ist keine von beiden. Direkter
Asm-Text sagt aber direkt was nun wirklich Fakt ist und sich bei C nur
über Umwege erschließt. Freilich, man muß es oft gar nicht unbedingt
100%ig wissen. Wenn man auf den Effizienzvorteil von Asm verzichten kann
und seine einschränkende Hochsprache liebt.
Matthias L. schrieb:> Der von mir gepostete Asm COde wurde von Moby> bisher nicht erklärt. Obwohl es doch selbsterklärend ist.
Bitte Geduld Matthias. Siehst ja was hier los ist. Danke für Deine
Analyse, die ist noch auf meinem Stack geparkt ;-)
Falk B. schrieb:> Das erklärt doch alles!
Falk und seine schnellen Erklärungen.
Hattest Du den AVR nicht schon längst in der Steinzeit verortet? Wie zum
Teufel kann der hier heute immer noch so präsent sein?
Karl H. schrieb:> Weil du dein Assembler Anpreisung auch nicht auf die von dir vorne> gesehenen Anwendungen beschränkst.
In der Tat sehe ich für Asm größeres Potential wenn ein paar andere
Randbedingungen erfüllt wären. Das hier zum Thema zu machen wäre aber
uferlos.
Bleiben wir mal bitteschön beim Thread-aktuellen AVR!
Jörg W. schrieb:> Diesen ganzen aufwändigen Kleinkram
Aufwand?
Machen wir mal das AVR Instruction Set nicht aufwendiger als es ist. So
ein AVR ist schön überschaubar. Und der "Kleinkram" ist ja gerade jenes
Kleinteilige was die bessere Anpassbarkeit an die Hardware und damit die
bessere Effizienz von Asm ausmacht!
> weil sie ständig inhärent alle Randbedingungen> berücksichtigen kann (wie die Länge eines Sprungs oder eben den> adressierbaren Bereich einer BST-Anweisung) und auch bei doppelter> Verneinung noch keinen Knoten im Gehirn bekommt.
Das sind gar nicht soviele Randbedingungen. Anders als beim ARM. Daß BST
mit einem falschen Operanden unbemängelt assembliert wird muß wirklich
nicht sein. Und was den Knoten im Gehirn angeht: Der entsteht mit
komplexen C-Ausdrücken sehr viel schneller. Und da reden wir noch nicht
vom weitaus abstrakteren OOP wo der Bezug zur Hardware-Wirklichkeit
vollends den Bach runter geht.
Moby A. schrieb:>> Diesen ganzen aufwändigen Kleinkram>> Aufwand?
Ja. Aufwand. Schließlich hast du dich gerade beklagt, dass dir die
Zeit für bestimmte Dinge fehlt. Glaubst du etwa, die anderen Leute
hier würden hauptamtlich fürs Forum schreiben, hätten alle keine
Familie, keine anderen Hobbys?
Moby A. schrieb:> Und was den Knoten im Gehirn angeht: Der entsteht mit komplexen> C-Ausdrücken sehr viel schneller.
Ganz gewiss nicht. Hier geht's noch um so einfache Dinge wie
1
if(i<1000000)
wie dir oben bereits ausgiebig demonstriert worden ist.
> Und da reden wir noch nicht vom> weitaus abstrakteren OOP wo der Bezug zur Hardware-Wirklichkeit vollends> den Bach runter geht.
Ach ja. Das kannst du bestimmt auch mit Code belegen, oder?
Moby, du bist einfach mal 50 Jahre zu spät geboren worden. Vor 50
Jahren hättest du dir als "Mel" ja vielleicht noch Respekt erheischt.
https://en.wikipedia.org/wiki/The_Story_of_Mel
Yalu X. schrieb:> Brainfuck, Befunge, Malbolge, FRACTRAN> Die allerkürzeste Instruktionsbeschreibung haben diese Prozessoren
Hochsprachen erklären immer mehr oder weniger schlecht was wirklich
vor sich geht. Genau diese Wirklichkeit aber adressiert und erklärt Asm.
Das ist es was für mich zählt. Andere Prozessoren? Wir wollen doch nun
kein neues Faß aufmachen wenn es hier um AVR geht...
> Was du bei der Bewertung der Sprachen völlig auser Acht lässt, ist ihre> Ausdrucksstärke, d.h. die maximale Komplexität der Problems, das mit> einer gegebenen Menge an Code gelöst werden können.
Da stimme ich Dir sogar zu.
Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für
maximale Komplexität bekannt, und das ist gut so ;-)
Ausdrucksstärke/Flexibilität und mögliche Komplexität sind die zwei
Seiten einer Medaille!
> hat selbst ein überzeugter Assembler-Only-Programmierer> immense Schwierigkeiten, dieses noch recht einfache Beispiel erst einmal> fehlerfrei runterzuprogrammieren und dann auch noch zu optimieren.
Nochmal:
1. 32-Bit Arithmetik ist keine AVR/ASM Stärke.
2. Was man hat das hat man. Für AVR gibts auch genügend fertigen Asm-
Beispielcode so denn umfangreichere Berechnungen mal nötig sind.
3. Sind sie ständig nötig ist AVR/ASM die falsche Wahl.
Jörg W. schrieb:> Moby A. schrieb:> Diesen ganzen aufwändigen Kleinkram>> Aufwand?>> Ja. Aufwand. Schließlich hast du dich gerade beklagt, dass dir die> Zeit für bestimmte Dinge fehlt. Glaubst du etwa, die anderen Leute hier> würden hauptamtlich fürs Forum schreiben, hätten alle keine Familie,> keine anderen Hobbys?
Oh welche weiten Zusammenhänge man da doch gleich herstellen kann ;-)
Das AVR-Instruktion Set ist weniger Aufwand als das bücherfüllende
C-Universum. So definier ich das.
> Hier geht's noch um so einfache Dinge wie if (i <> 1000000)
Und? Das in Asm hinzuschreiben ist nun kein Hexenwerk. Ich bezog mich
beim Thema Gehirnknoten auf komplexere Ausdrücke. Beispiele finden sich
weiter oben ;-)
> Ach ja. Das kannst du bestimmt auch mit Code belegen, oder?
Das belegt jeder OOP Code ;-)
> Moby, du bist einfach mal 50 Jahre zu spät geboren worden.
Meinst Du?
Ich hab eher den Eindruck noch gerade richtig, um mit leistungsstarken
kleinen simplen AVRs die Chance zu haben, selber wirklich alles in der
Hand zu behalten und gestalten zu können!
Moby A. schrieb:> Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für> maximale Komplexität bekannt, und das ist gut so ;-)
Warum meinst du, baut Atmel dann AVRs mit 256 KiB und mehr an Flash?
> 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke.
Hier irrst du bezüglich des AVR gewaltig.
Der AVR ist bei der 32-Bit-Arithmetik viel besser als manch anderer
8-Bitter.
Selbst die 32-Bit-Gleitkommaarithmetik von AVR-GCC/avr-libc (und
auch IAR) ist so rasend schnell, dass du Mühe haben wirst, ihr mit
handgefeilter 24-Bit-Ganzzahlarithmetik in deinem Assemblercode das
Wasser zu reichen – wobei du dann immer noch die Grenzen des
Wertebereichs im Blick behalten musst, während float eben in der
Richtung von selbst skaliert.
(OK, Turbo-Pascals 48-Bit-Gleitkomma konnte das auch schon vor 30
Jahren auf dem Z80. Nicht ganz so schnell, aber genauso bequem für
den Anwender.)
> 2. Was man hat das hat man. Für AVR gibts auch genügend fertigen Asm-> Beispielcode so denn umfangreichere Berechnungen mal nötig sind.
Ja, und? Für C gibt es mehr Bibliotheken, als du dir auch nur
ansatzweise ausmalen kannst. Viele davon laufen durchaus auch auf
einem AVR.
> 3. Sind sie ständig nötig ist AVR/ASM die falsche Wahl.
Trenne mal zwischen AVR und ASM. Die beiden sind nicht miteinander
verheiratet (außer in deinem Kopf), und selbst die ältesten
Randnotizen von Atmel bezüglich des AVR zeigen, dass Alf Bogen und
Vegard Wollan schon vor 20 Jahren deiner Denkweise massiv voraus
waren, da sie bereits in der Designphase einen Compilerhersteller
(IAR aus Schweden) mit ins Boot genommen haben. Ihnen war klar, dass
man den damals fest aufgeteilten Markt an Microcontrollern (zwichen
8051, PIC und MC68) nur dann neu aufrollen kann, wenn bereits die
CPU-Architektur möglichst gut auf eine Sprache wie C passt.
Dir ist das selbst 15 Jahre später noch nicht klar.
Peter D. schrieb:> Eine sehr schöne Routine, die so nur in C praktikabel ist, ist> z.B. der Scheduler:> Beitrag "Wartezeiten effektiv (Scheduler)"
Ohne jetzt den Code im Einzelnen durchgegangen zu sein- fürs "Warten
ohne Rechenzeitverschwendung" ist nun wirklich kein C nötig. Meine
Controller haben meist einen mehr oder weniger gleichschnellen
Timerinterrupt für allgemeine Aufgaben, so auch zur zeitgesteuerten
Taskauslösung bzw. Wartezyklen.
Das muß nicht zum Albtraum ausarten.
Moby A. schrieb:> Oh welche weiten Zusammenhänge man da doch gleich herstellen kann ;-)
Diese Zusammenhänge sind so ziemlich jedem hier klar, nur dir nicht.
Aber geben wir's auf, du willst sie ja nicht sehen.
> Das AVR-Instruktion Set ist weniger Aufwand als das bücherfüllende> C-Universum. So definier ich das.
Definieren kannst du natürlich, was du willst. Der Gültigkeitsbereich
der Definition wird dann allerdings auf dein privates Universum
beschränkt bleiben.
AVR-Befehlssatz: irgendwas um die 150 Seiten
C-Sprachbeschreibung (Kapitel 6 im Standard): 135 Seiten
> Ich bezog mich> beim Thema Gehirnknoten auf komplexere Ausdrücke.>> Ach ja. Das kannst du bestimmt auch mit Code belegen, oder?>> Das belegt jeder OOP Code ;-)
OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und
irgendwer hat dir mal gesagt, es sei "komplex".
Jörg W. schrieb:> Warum meinst du, baut Atmel dann AVRs mit 256 KiB und mehr an Flash?
Für Daten?
Und natürlich für ausschweifende Hochsprachen!
> Der AVR ist bei der 32-Bit-Arithmetik viel besser als manch anderer> 8-Bitter.
Und? Deshalb ist ein 32Bitter in diesem Fall immer noch sinnvoller. Aber
freut mich das hier so festgestellt zu wissen ;-)
> Selbst die 32-Bit-Gleitkommaarithmetik von AVR-GCC/avr-libc (und auch> IAR) ist so rasend schnell, dass du Mühe haben wirst, ihr mit> handgefeilter 24-Bit-Ganzzahlarithmetik in deinem Assemblercode das> Wasser zu reichen – wobei du dann immer noch die Grenzen des> Wertebereichs im Blick behalten musst, während float eben in der> Richtung von selbst skaliert.
Klasse wenns so ist!
Für umfangreichere Arithmetik hätte ich aber auch super Asm Code in der
Hinterhand, wenngleich nicht aus meiner Feder.
> Ja, und? Für C gibt es mehr Bibliotheken, als du dir auch nur> ansatzweise ausmalen kannst. Viele davon laufen durchaus auch auf einem> AVR.
Ja und? Deshalb hab ich wiegesagt damit trotzdem keine Mühe. Das mit den
vielen vielen Bibliotheken sehe ich kritisch. Man begibt sich damit in
gewisse Abhängigkeiten, nimmt unbekannte Fehlerquellen in Kauf, oft ist
eine Funktion schneller selbst geschrieben als irgendwo passend gefunden
und verstanden.
> wenn bereits die CPU-Architektur möglichst> auf eine Sprache wie C passt.
Warum sollte das verwundern wenn sich der potentielle Anwenderkreis
damit erweitert? Deshalb bleibt die einfache Architektur weiter
einfachem Asm zugänglich. Asm ist da seeehr flexibel ;-)
Karl H. schrieb:> weil er viel zu sehr mit diesen Low-Level> Details beschäftigt ist
Nö. Mit der Hardware- Wirklichkeit. Und bestmöglicher
programmtechnischer Anpassung an diese. Damit mit der optimalen Chance
auf effizienten Code.
> Wenn Moby C programmieren würde, dann würde er so kommentieren bzw.> erklären i = 5; // i mit 5 laden> j++; // j um 1 erhöhen
So ein Quatsch.
Wenn ich sage daß ldi r16,25 selbsterklärend ist (mit Kenntnis der
Instruktion) dann würde ich doch in C nicht derart kommentieren ;-)
> und das ist genau die Art Kommentierung, die komplett am Sinn einer> Kommentierung vorbei geht.
Richtig. Das wäre so.
Aber ich sehe schon Du krallst Dich wieder an subjektiven
Kommentierungsfragen fest.
Wozu ist eigentlich dieses Forum im allgemeinen und die
Projekte-Abteilung im speziellen da?
Richtig. Zum Fragen.
> Man kann die> Funktionsweise einer Raffinerie nicht dadurch ergründen und erklären,> dass man sich alle Schrauben, Muttern und Beilagscheiben ansieht.
Es muß langen, Funktionalität und Interfaces zu beschreiben. Mehr Doku-
Aufwand treibe ich nicht. Punkt. Alles andere kann erfragt werden.
Asm Quellcode bleibt damit herrlich übersichtlich.
Von langatmigen Klammerwüsten keine Spur ;-)
Jörg W. schrieb:> OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und> irgendwer hat dir mal gesagt, es sei "komplex".Noch einer schrieb:> Beide Aussagen sprechen von einer Überforderung durch> Informationen und Optionen> Im laufe der Jahrzehnte hat sich die Programmierung komplett geändert.> In die Register eines 8-Bit Controllers, oder auch in ein DOS-Programm> konnte man sich noch vollständig einarbeiten. Heutzutage ist es so> umfangreich - bis man alle Detail durchgearbeitet hat, ist es schon> wieder veraltet.> Es spaltet sich auf - der eine schreibt Python-Libraries für> Raspberry-Peripherie, der andere schreibt damit Web-Oberflächen für> Steuerungen. Pic32 liegt vielleicht noch an der Grenze, wo sich einer> alleine in alles einarbeiten kann. Bei Cortex-A geht das nicht mehr.>> Und dann kommt noch etwas total bescheuertes dazu:>> 20 Entwickler lösen innerhalb eines Programmes 30 gleichartige Probleme> auf 40 verschiedene Arten. C++ ist da am schlimmsten. Man findet in> einem Programm alles von K&R bis Java-Stil; Selbst gebastelte Container> mit obskurer Garbage-Collection neben QList, STL und alten C-Arrays;> Präprozessor-Tricksereinen neben Inline-Funktionen.>> Einfach nur nervtötender Kleinkram. Lässt sich nicht aufräumen - während> man einen Bereich auf eine übersichtliche Lösung umstellt, werden schon> wieder 5 neue Änderungen auf 10 unterschiedliche Arten eingebaut.
Soweit zum Thema Komplexität und Kleinkram.
Aufgegabelt in "C++ für Mikrocontroller" gleich nebenan ;-)
Icke ®. schrieb:> Ich habe daraus gelernt, daß jeglicher Versuch, Menschen mit derartig> zementierten Standpunkten (nannte man früher "Betonköpfe") von ihrem> Holzweg abzubringen, selbst unter Zuhilfenahme einleuchtendster> Argumente kläglich scheitert.Das höre ich oft als letztes verbleibendes Argument. Immerhin ist
das aber noch irgendwo verständlich im Gegensatz zu jenen, die glauben,
man müsse nur hinreichend beleidigen.
> Noch ein klein wenig Topic. Ich programmiere auch gern in ASM, aber ich> kenne die Grenzen.
Ich auch. Nur sind die weit weg. Außer es stehen wirklich mal größerer
Berechnungen an ;-)
> Es ist auch schön, per Pedes durch den Wald zu streifen, den Geräuschen> zu lauschen und mit den Füßen direkten Bodenkontakt zu spüren. Und es> macht Sinn, die 100m bis zum Bäcker um die Ecke zu laufen. Aber für den> Großeinkauf oder die Urlaubsfahrt steig ich dann doch lieber ins Auto.
Ja ja die Vergleiche. Habens wirklich in sich.
Yalu X. schrieb:> Matthias L. schrieb:> Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc> aufgerufen wird. Weiter:> keyproc:> ...> ldd XL,Z+0 ;8x alle 5ms testen> rol XL ;= 200% Bulletproof ;-)> std Z+0,XL>> Du hättest statt der "..." die entsprechenden Befehle vollständig> hinschreiben sollen:keyproc: adiw ZH:ZL,2 ;Tastenstatus entprellend> ermitteln> in YH,GPIOR0> mov YL,YH> ldd XL,Z+0 ;8x alle 5ms testen> rol XL ;= 200% Bulletproof ;-)>> Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt, im> konkreten Fall mit 0. Somit schiebt ROL in das XL-Register nur Nullen> hinein, was den nett gemeinten Programmiertrick völlig versagen lässt.
So. Hab mal drübergeschaut.
In der Tat löscht adiw ZH:ZL in jedem Fall das C-Flag.
Vermutlich hab ich das später noch hinzugefügt/umgeändert. Abhilfe:
Aufruf von keyproc mit T- statt C-Flag und nach mov YL,YH ein brtc zum
ldd XL,Z+0 sowie zwischendrin noch ein sec. Also 2 Instruktionen mehr.
Es stimmt, das Programm ist noch nicht getestet, sollte aber auch nur im
ursprünglichen Thread eine einfache Problemlösung in Asm andeuten. Nach
einem Test soll der Main-unabhängige Timerinterrupt-Baustein zur
Tastenentprellung und Feststellung der Betätigungsdauer beliebiger
IO-Pin Tasten in die Codesammlung.
> Wir wissen zwar nicht, was Mobys Programm tun soll
Was sollen solche halbgaren Feststellungen?
Die beabsichtigte Funktionalität ist doch klar definiert.
> Und was lernen wir daraus?> 1. Das Carry-Flag ist eigentlich gedacht
Man muß sich nicht unbedingt daran orientieren wofür etwas gedacht
ist. Damit geht vielleicht ein höheres Risiko für Fehler (wie hier)
einher aber man bewahrt sich alle technischen Möglichkeiten.
> Wenn man schon Assembler programmiert und dabei auzch noch tief in> die Trickkiste greift, sollte man gut ausgeschlafen sein und jede> Code-Änderung dreimal mit dem Auge durchgehen und zusätzlich intensiv> testen.
Flüchtigkeitsfehler sind wirklich nicht die größten Probleme. Die sind
eher systematischer Natur, etwa in Zusammenhang mit unklaren realen
Messwerten.
> Er hat sie auf mehrere Tasten erweitert, musste dazu aber die> indirekte Adressierung für das Z-Register und damit verbunden den> ADIW-Befehl einführen, was schließlich zu dem Fehler führte.
Gut möglich.
> => Wiederverwendbarkeit von Code erfordert eine genaue und> vollständige Dokumentation nicht nur der Funktion, sondern auch der> Nebeneffekte. Das ist hier offensichtlich nicht geschehen.
Richtig.
> Da Moby der Assembler-Gott ist, der immer alles richtig macht, hat er> auch keinen Bedarf gesehen, die Routine vor ihrer Veröffentlichung> wenigstens einmal zu testen ;-)
Schön wärs.
> 3. Hochsprachen sind weniger anfällig gegen solche Fehler
Dafür gegen andere.
Also sollte der C-Flag Fehler der Einzige im Programm gewesen sein bin
ich schon zufrieden. Das Angebot zum kürzeren Formulieren der
beschriebenen Funktionalität in C steht nach wie vor... Dabei muß man
sich auch nicht an meiner Programmlogik orientieren.
Moby A. schrieb:> Jörg W. schrieb:>> OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und>> irgendwer hat dir mal gesagt, es sei "komplex".>> Noch einer schrieb:>> Beide Aussagen sprechen von einer Überforderung durch>> Informationen und Optionen
...
>> Einfach nur nervtötender Kleinkram. Lässt sich nicht aufräumen - während>> man einen Bereich auf eine übersichtliche Lösung umstellt, werden schon>> wieder 5 neue Änderungen auf 10 unterschiedliche Arten eingebaut.>> Soweit zum Thema Komplexität und Kleinkram.> Aufgegabelt in "C++ für Mikrocontroller" gleich nebenan ;-)
Na und? Du bist halt nicht der einzige, der nicht programmieren kann.
Nö, Moby hat in einer Hinsicht schon recht. Von Assembler zu C zu C++
steigern sich Abstraktion und Komplexität - wobei ich damit nicht die
des erzeugten Codes meine. Mit der Länge des Handbuchs ist das nur
unzureichend beschrieben.
So steht der Assembler-Befehl XXX R0,R1 für eine klare Anweisung, genau
an dieser Stelle genau das zu tun, was da steht, und es reicht
weitgehend aus, die Beschreibung des Befehls nachzulesen um zu
verstehen, was die Zeile genau tut. Man kann aufgrund des vielen
Kleinklein zwar das Programm schlechter anhand des Codes erfassen, aber
die einzelnen Zeilen sind einfacher.
Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt
sich die tatsächliche Operation erst aus den Datentypen der Operanden.
So ist nicht von vorneherein klar, ob mit oder ohne Vorzeichen
verglichen wird, weil das von den exakten Datentypen und dem
Typenmodell des Compilers abhängig ist (u16 < i32 => signed, u32 < i32
=> unsigned). Dafür aber sieht man gleich, dass es ein Vergleich ist,
egal ob dahinter nur ein Maschinenbefehl sitzt, oder hunderte.
Die ersten C Compiler waren auch noch auf einer Ebene, der C die
Einstufung als glorifizierter Makroassember verdankte. Sie übersetzten
ziemlich linear den geschriebenen Code in Maschinencode. Wer
Registeroptimierung wollte, der tat das selbst und schrieb "register"
hin. Code wurde nicht wegoptimiert, nicht verschoben. Probleme mit in
Interrupts verwendeten Daten entstanden erst, als die Compiler besser
wurden, weshalb dann "volatile" nachgereicht wurde. Dieses "volatile"
sorgt zwar nur für ein paar Zeilen im Handbuch, hat aber fundamentalen
Einfluss auf bestimmte Programmierkonzepte, wie viele µC-Programmierer
erst lernen müssen. Moby bleibt dies erspart.
Mit C++ setzt sich das fort. So kann man sich bei eigentlich per
Referenz übergebenen Parametern von dummerweise vom Compiler nur
temporär angelegten Daten überraschen lassen, wodurch das Ergebnis im
Nirvana entschwindet. Aus dem Quellcode der Zeile geht das nicht hervor,
da muss man weit mehr überblicken.
Inwieweit das freilich gegen die Programmierung in Hochsprachen spricht
muss jeder für sich entscheiden. Komplexität ist nicht grundsätzlich ein
Nachteil, weil man oft nur aufgrund der Komplexität der Mittel überhaupt
erweiterte Probleme lösen kann. Moby beschränkt sich dann eben auf jene
Probleme, die er lösen kann. Die anderen negiert er gerne, weil "braucht
man kaum".
Das Problem mit Moby ist nicht seine Beschränkung auf Werkzeuge, deren
Komplexität er überblicken kann, sondern sein Sendungsbewusstsein, diese
persönliche Eigenheit zu Mass der Dinge zu erklären und andere davon
überzeugen zu wollen. Ihn schreckt der höhere Abstraktionsgrad höherer
Sprachen, andere Leute aber nicht, und das versteht er nicht.
Moby A. schrieb:> Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für> maximale Komplexität bekannt, und das ist gut so ;-)
Du hast gar keine Ahnung, wie "typische 8-Bit-Apps" für AVRs aussehen.
Da passt schon jede Menge an Funktionalität rein, von denen Du noch
nichtmals zu träumen wagst.
Beschränke Dich mal bei Deinen ganzen Behauptungen auf ATTiny mit
höchstens 1KB Flash. Da machen Deine Argumente (und damit Assembler)
vielleicht noch in einigen Ausnahmefällen überhaupt Sinn.
Deine Welt ist klitzeklein, Moby. Du wüsstest noch nichtmals, was Du mit
einem ATmega328 anfangen könntest. "Typische AVR-Anwendungen" finden
aber eher in diesen Größenordnungen statt.
A. K. schrieb:> So steht der Assembler-Befehl XXX R0,R1 für eine klare Anweisung, ...
...
> Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt...
So kann man aber nicht sinnvoll vergleichen, es sei denn man misst seine
Arbeit in Anzahl Programmzeilen.
Es geht ja in der Regel nicht darum, Text zu produzieren, sondern ein
Problem zu lösen.
Und dann kann man nicht einen C-Ausdruck mit einem Assemblerbefehl
vergleichen, sondern müsste den C-Ausdruck mit der entsprechenden Folge
von Assemblertext vergleichen, der funktional gleichwertig ist.
Und genau dann ist Assembler bei nichttrivialen Problemen eben schon
nicht mehr so klar und übersichtlich - wie man an den Fehlern in Mobys
ach so klaren, übersichtlichen und selbsterklärenden Programmen sieht.
Hier sehe ich den die Crux der ganzen Diskussion (neben dem
Missioniergeist, der mit Verblödung regelmäßig einhergeht in jeder
Religion): EIN Assemblerbefehl ist übersichtlich, klar.
Aber die vielen, die man für ein halbwegs komplexes Problem braucht,
sind es nicht mehr.
Auch ein typisches C-Programm besteht ja nicht mehr aus einem Vergleich,
sondern aus wesentlich mehr.
Wenn man dann für jedes Detail etliche Maschinenbefehle erfassen muß,
hat man einfach keinen Überblick.
Außer man ist so genial wie Moby; ich bin zu doof für sowas.
> ich bin zu doof für sowas.
Viele hier sind zu doof dafür, mich eingeschlossen. Deshalb müssen wir
mit Programmieren unsere Brötchen verdienen. Nur einer macht das als
Hobby, der Mobby! (wie er sich diesen NickName ausgesucht hat. Welch
Weitblick!)
(bin ich froh, daß ich den nicht als Kollegen hab. Obwohl, der ein oder
andere, um den ich einen großen Bogen mache, ist auf einem "guten" Weg)
Klaus W. schrieb:> Und dann kann man nicht einen C-Ausdruck mit einem Assemblerbefehl> vergleichen,
Doch, kann man schon. Man kann Programmzeilen vergleichen und man kann
Lösungen vergleichen.
Ich hatte oben eine Programmzeile verglichen, um den Unterschied der
Komplexität dieser Programmzeile hervorzuheben. Dass man für die gleiche
Lösung wesentlich mehr Asm-Zeilen benötigt ist unstrittig und eine
andere Art von Vergleich.
> Aber die vielen, die man für ein halbwegs komplexes Problem braucht,> sind es nicht mehr.
Klar.
> Außer man ist so genial wie Moby; ich bin zu doof für sowas.
Die Grösse eines Programms, das man noch einigermassen überblicken kann
ist begrenzt. Weshalb die Lösungen, die man noch alleine stemmen kann,
mit der Komplexität des verwendeten Werkzeugs wachsen. Weshalb man in
einer geeigneten Hochsprache komplexere Lösungen stemmen kann als in
Assembler.
Er beschränkt sich auf das, was er überblicken kann, und definiert alles
darüber hinaus als "braucht man nicht". ;-)
A. K. schrieb:> Er beschränkt sich auf das, was er überblicken kann, und definiert alles> darüber hinaus als "braucht man nicht". ;-)
Genau dieser Mikrokosmos von Moby ist der Grund für diesen ellenlangen
Thread.
Moby A. schrieb:>> Wir wissen zwar nicht, was Mobys Programm tun soll>> Was sollen solche halbgaren Feststellungen?> Die beabsichtigte Funktionalität ist doch klar definiert.
Ok, das nehme ich zurück. Ich hatte das mit deinem anderen Code
(adu.asm) verwechselt, dem tatsächlich die Beschreibung der
Gesamtfunktion fehlt.
> Also sollte der C-Flag Fehler der Einzige im Programm gewesen sein bin> ich schon zufrieden.
Ich habe das Programm genauso wenig getestet wie du. Der Fehler mit dem
Carry-Flag ist mir aufgefallen bei dem Versuch, die Funktion des Codes
wenigstens grob zu verstehen. Die meisten Fehler werden aber nicht beim
Durchlesen des Codes, sondern erst beim realen Test aufgedeckt.
Zum Thema
Moby A. schrieb:> Hardware- Wirklichkeit
Es ist sicher kein Fehler, wenn ein C-Programmierer auch ein wenig
Ahnung von Assembler-Programmierung auf der von ihm eingesetzten
Plattform hat, ganz im Gegenteil: Dadurch hat er ein besseres Gefühl
dafür, was er mit bestimmten C-Konstrukten der CPU tatsächlich zumutet.
Ich behaupte mal, dass C-Programmierer, die auch etwas Assembler können,
i.Allg. effizienteren Code schreiben als diejenigen, die nur in
Hochsprachen unterwegs sind.
Umgekehrt gilt das aber auch: Assembler-Programme von Leuten, die auch
regelmäßig in Hochsprachen programmieren, haben i.Allg. eine bessere
Struktur. Dazu gehören bspw. die Vermeidung von Nebeneffekten in
Unterprogrammen (wo möglich), einheitliche Konventionen für den Transfer
der Input- und Outputdaten von Unterprogrammen und die Behandlung
zusammengehörender Daten als eine Einheit (Datenstrukturen). Das kostet
zwar evtl. ein paar Prozent CPU-Leistung, erleichtet dafür aber die
Wiederverwendung von früher geschriebenem Code und reduziert dabei
gleichzeitig die Gefahr von Flüchtigkeitsfehlern, wie sie dir bei der
Anpassung relativ kurzer Code-Abschnitte jetzt schon zweimal passiert
sind.
Mein Rat an dich: Bleib bei deinem Assembler, wenn es dir Spaß macht,
aber versuche parallel dazu, mehr Einblick in die C-Programmierung zu
bekommen. Du wirst dabei immer wieder Aha-Effekte erleben, die dir auch
bei der Assembler-Programmierung zugute kommen. Als Nebeneffekt wirst
du dann auch bei Assembler-vs-C-Diskussionen wie dieser hier von den
anderen ernster genommen :)
Moby A. schrieb:> Asm Quellcode bleibt damit herrlich übersichtlich.> Von langatmigen Klammerwüsten keine Spur ;-)
Du siehst ein C-Programm als eine langatmige Klammerwüste, weil du von C
keine Ahnung hast.
Mir geht es ähnlich, wenn ich mir das von A. K. gepostete APL-Beispiel
anschaue:
A. K. schrieb:> Ich kann da nur wieder dieses Beispiel ans Herz legen
Weil ich von APL keine Ahnung habe, stellt sich das Beispiel für mich
als Wüste von seltsamen Symbolen dar. Ich käme aber nicht auf die Idee,
in einer Diskussion mit APL-Programmierern APL deswegen schlecht zu
reden, denn ich weiß genau:
- Alle anderen Diskussionsteilnehmer verstehen diesen Code und sehen
zwar die Symbole, aber keine Wüste.
- Als einziger Ahnungsloser werde ich von den anderen zunächst
mitleidig belächelt werden.
- Wiederhole ich meine Auffassung, dass APL Käse ist, zu oft, werde
ich irgendwann in hohem Bogen aus der Diskussion hinausfliegen.
Wenn das Wetter am Wochenende schlecht ist, werde ich mir das
APL-Beispiel vielleicht mal genauer anschauen und dann mein erstes
Urteil über diese Sprache bilden. Einen Startpunkt habe ich schon
gefunden: http://tryapl.org/ :)
Yalu X. schrieb:> Es ist sicher kein Fehler, wenn ein C-Programmierer auch ein wenig> Ahnung von Assembler-Programmierung auf der von ihm eingesetzten> Plattform hat, ganz im Gegenteil: Dadurch hat er ein besseres Gefühl> dafür, was er mit bestimmten C-Konstrukten der CPU tatsächlich zumutet.
Das kann ich nur bestätigen. Auch ich habe mal in den 80ern
Z80-Assembler gelernt und konnte nach einiger Übung sogar
Binär-Programme direkt in HEX-Codes in den Rechner eingeben, ohne einen
Assembler bemühen zu müssen - hatte also den Assembler sozusagen
eingeatmet :-)
Auf jeden Fall ist die Kenntnis einiger Assembler Dialekte (später kam
noch 68000 dazu) auch für einen Hochsprachen-Programmierer sehr
nützlich. Denn er weiß dann, wie er dem Compiler "Hilfestellung" beim
Compilieren/Optimieren geben kann. Als Beispiel sei hier nur das
Arbeiten mit Kopien von volatile-Variablen in ISRs genannt.
Auch heute schaue ich noch ab und zu in das vom Compiler generierte
Assembler-File, einfach weil ich neugierig bin, wie er diese oder jene
(kniffligere) Aufgabe gelöst hat und bin manchmal sehr überrascht, wie
effizient die Lösung ist.
> Ich behaupte mal, dass C-Programmierer, die auch etwas Assembler können,> i.Allg. effizienteren Code schreiben als diejenigen, die nur in> Hochsprachen unterwegs sind.
ACK.
> Umgekehrt gilt das aber auch: Assembler-Programme von Leuten, die auch> regelmäßig in Hochsprachen programmieren, haben i.Allg. eine bessere> Struktur.
Sehe ich genauso.
Ich weiß leider nicht, ob Moby aus Deinen Argumenten eine nützliche
Lehre ziehen kann, denn manchmal kommt mir sein Horizont ziemlich
beschränkt vor.
Lasst euch nicht auf fundamentale Assembler-Programmierer, die nichts
anderes können oder (können) wollen, ein. Sie ziehen euch auf ihr Niveau
herunter und besiegen euch mit langjähriger Erfahrung...
Yalu X. schrieb:> Weil ich von APL keine Ahnung habe, stellt sich das Beispiel für mich> als Wüste von seltsamen Symbolen dar.
Ich würde da auch erst mal nach der Baudrate sehen, wenn sowas über eine
serielle Schnittstelle hereinkäme ;-)
Frank M. schrieb:> Denn er weiß dann, wie er dem Compiler "Hilfestellung" beim> Compilieren/Optimieren geben kann.
Das kann allerdings auch in die Hose gehen, wenn man die Maschine
wechselt, neue und alte Maschine sich erheblich unterscheiden und man
die Regeln der alten Welt im Kopf hat.
So verleitet C Programmierung auf 8-Bittern genau diesen Personenkreis
dazu, umfänglich mit globalen oder statischen an Stelle lokaler
Variablen oder Struct-Parametern zu programmieren. Statisch adressieren
können die sehr gut, während sie sich mit Adressierung relativ zu
Pointern mitunter deutlich schwerer tun (insbesondere 8051 und PIC).
Wechseln man dann auf beispielsweise ARM, dann führt das zu
ausgesprochen ineffizienten Programmen, da es bei denen genau umgekehrt
ist. Statische Adressierung ist ineffizient, relative Adressierung
effizient, und man nimmt dem Compiler die Chance zur Optimierung über
Register.
Moby A. schrieb:> Frank M. schrieb:>> Moby A. schrieb:>> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch>> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen>> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen.>>>> Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger>> "Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen ->> sowohl was Programmier- als auch Prozessoraufwand betrifft.> Dann bin ich schon sehr gespannt...> Wer die realisierte Funktionalität
Können wir gerne machen.
Wir vereinbaren einen Zeitpunkt an dem du und ich Zeit haben. Ein paar
Forneteilnehmer denken sich eine Aufgabe aus, irgendjemand (du, ich, wir
beide) wählt eine der Aufgaben aus und dann schaun wir mal, wer
schneller das Programm stehen hat und wer es fehlerfreier hinkriegt.
Ich hab nur eine Bedingung: es darf kein Pipifax Beispiel sein sondern
sollte schon was ordentliches sein. Wir müssen uns noch auf eine zu
verwendende Hardware einigen. AVR, ein paar Taster und ein 2 oder 4
zeiliges LCD. VOn mir aus kann ich auch noch ein paar Lichtschranken
improvisieren. Aber eine CNC Ansteuerung ist zb so für einen
Interessenten nicht machbar, denn keiner von uns beiden hat die Hardware
da und ohne testen zu können mach ich sowas nicht.
Lothar M. schrieb:> Ich würde da auch erst mal nach der Baudrate sehen, wenn sowas über eine> serielle Schnittstelle hereinkäme ;-)
Ich würde dann aber an deiner Stelle auch am Terminal zweifeln. Zeig mir
mal, an welcher Stelle deines 8-Bit Zeichensatzes Symbole wie ⍳, ⌹ oder
⍴ zu finden sind. ;-)
> AVR, ein paar Taster und ein 2 oder 4>zeiliges LCD.
Vielleicht eine Art Laufschrift, welche beim Starten aus dem EEPROM
geladen und dargestellt wird. Mit den Tasten kann man dann in einen
Editiermodus gehen und den Text verändern. Dieser würde dann wieder im
EEPROM abgelegt...
Ich denke, das geht über eine blinkende Led heraus. Aber
Tastenentprellung, LCD-Ansteuerung, etwas EEPROM sind ein klar
abgesteckter Rahmen. Aber eben etwas mehr als ein
>Pipifax Beispiel
einer blinkenden LED.
Matthias L. schrieb:>>Pipifax Beispiel> einer blinkenden LED.
blinkende LED kann ruhig auch dabei sein. 3 oder 4 Stück, die
voneinander unabhängig in einer vom Benutzer eingebbaren Frequenz
blinken sollen. Kleine Menüsteuerung noch dazu, mit der man die LED zb
auf einen Triggereingang 'verkabeln' kann. Eventuell eine kleine
Ablaufsteuerung, damit auch Datenstrukturen ins Spiel kommen. Vielleicht
noch ein oder 2 Servos (wenn Moby welche hat) ...
Irgendsowas. Ein bunter Mix aus Beherrschung der Hardware,
Basistechniken, ein bisschen rechnen, Speicherverwaltung, .....
Aber erst mal muss er den Fehdehandschuh aufgreifen. Mal sehen, obs so
kommt wie es immer kommt, wenn ich sowas anbiete :-)
A. K. schrieb:> Das kann allerdings auch in die Hose gehen, wenn man die Maschine> wechselt, neue und alte Maschine sich erheblich unterscheiden und man> die Regeln der alten Welt im Kopf hat.
Ja, natürlich. Wenn man aber nicht nur in der (eingeschränkten) Welt der
µCs zuhause ist, sondern zum Beispiel auch für diverseste sehr
heterogene UNIX-Umgebungen (beileibe nicht nur x86), programmiert,
bekommt man langsam mit der Erfahrung ein "Gefühl" dafür, was unter
welcher Plattform sinnvoll ist und was nicht.
> Wechseln man dann auf beispielsweise ARM, dann führt das zu> ausgesprochen ineffizienten Programmen, da es bei denen genau umgekehrt> ist. Statische Adressierung ist ineffizient, relative Adressierung> effizient, und man nimmt dem Compiler die Chance zur Optimierung über> Register.
Okay. Manchmal muss man dann halt Kompromisse machen - gerade wenn man
so portabel programmiert, dass ein- und dasselbe Programm sowohl auf ARM
als auch auf AVR und PIC läuft.
Wenn ich aber ein Programm erstelle, dass nur auf einem ARM laufen soll,
gehe ich da mit ganz anderen Methoden dran. Die hier eher üppigen
Ressourcen verleiten mich dazu, den Processor auch als "erwachsene
Maschine" auszunutzen. Dazu gehören auch die Methoden zur Adressierung
von Speicher bzw. dessen Verwaltung. Das macht wesentlich mehr Spaß als
das eher beschränkte Programmieren von 8-Bit-AVRs.
Karl H. schrieb:> blinkende LED kann ruhig auch dabei sein. 3 oder 4 Stück, die> voneinander unabhängig in einer vom Benutzer eingebbaren Frequenz> blinken sollen. Kleine Menüsteuerung noch dazu, mit der man die LED zb> auf einen Triggereingang 'verkabeln' kann.
Mein Vorschlag:
8-Kanal Software-UART (nur Eingänge), um 8 verschiedene LEDs mit SW-PWM
zu steuern. Hierbei kann dann jeder Teilnehmer Skalierbarkeit seiner
Software demonstrieren.
Kleines UART-Protokoll dazu:
Bn<CR> Helligkeit (Brightness) auf n%
Ft,n<CR> Fading innerhalb der Zeit t auf n%
Beispiele:
B80<CR> Helligkeit (Brightness) auf 80%
B00<CR> Ausschalten
B100<CR> Brightness auf 100%
F10,80<CR> Fading innerhalb von 10 Millisekunden auf 80%
F100,00<CR> Fading innerhalb von 100 Millisekunden auf 0%
Diese Aufgabe halte ich für sinnvoller, da die Lösung nachher nicht für
die Tonne ist, sondern durchaus für das eine oder andere Projekt
verwendet werden kann :-)
A. K. schrieb:> Nö, Moby hat in einer Hinsicht schon recht. Von Assembler zu C zu C++> steigern sich Abstraktion und Komplexität
Die Abstraktion steigt, aber auch die Komplexität? Eher nicht. Es gibt
ja schließlich Gründe, warum Spaghetticode wie in Assembler so einen
enorm schlechten Ruf hat und warum dringendst von der Verwendung des
"goto"-Befehls in C und C++ abgeraten wird: weil das den Code
unübersichtlich (vulgo: komplizierter) macht sowie Pflege und
Wiederverwendung erschwert.
Ja, eine einzelne Assembler-Instruktion ist "einfacher" insoweit als sie
nur einen einzigen, winzigen kleinen Teil des Programms ausmacht. Aber
das ist nur der eine Teil der Wahrheit, und der andere Teil lautet: eine
einzelne Instruktion ist eben nur ein winzig kleiner Teil eines deutlich
größeren Programms. Genau da liegen aber die Vorteile einer besseren
Strukturierung und Abstraktion durch die Hochsprachen, im Gegensatz zu
Spaghetticode, in dem zwischen verschiedenen Sprungmarken und Codeteilen
wild hin- und hergesprungen wird.
> Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt> sich die tatsächliche Operation erst aus den Datentypen der Operanden.
Das ist nicht komplizierter, sondern viel einfacher, weil der Compiler
dem Entwickler die Entscheidung, welche Maschineninstruktion(en) zu
verwenden sind, ganz einfach abnimmt. Dank der deklarierten Datentypen
der Variablen weiß der Compiler nämlich, welche Operation benutzt werden
muß, und nimmt automatisch und ohne jedes Zutun die Richtige(tm). Für
den Entwickler ist das eine enorme Vereinfachung und Erleichterung
seiner Arbeit, und nicht zuletzt deswegen ist die Produktivität eines
Entwicklers in Hochsprachen so viel höher als in Assembler.
Richtig ist, daß der Entwickler dabei ein wenig von der Kontrolle
darüber verliert, was sein Code genau macht. Mehr Kontrolle bedeutet
aber immer mehr Arbeit und Komplexität, um die sich der Entwickler
kümmern muß.
Sheeva P. schrieb:> Die Abstraktion steigt, aber auch die Komplexität? Eher nicht.
In aller Kürze: Bei geeigneten Werkzeugen wird die Lösung eines nicht
trivialen Problems durch die Wahl eines komplexeren Werkzeugs oft
einfacher, sofern man nicht an der Komplexität des Werkzeugs scheitert.
Es ist weitaus schneller, nach Malle zu fliegen als zu schwimmen. Aber
man behilft sich dabei eines hochkomplexen Werkzeugs namens "Flugzeug"
und überlässt dessen Komplexität andern Leuten und Automaten. Schwimmen
ist ein Vorgang von weitaus geringerer Komplexität und ist dabei nicht
unmöglich, aber es ist nicht wirklich als Lösungsansatz zu empfehlen.
Gäbe es keine Piloten (inkl. Auto-) und man müsste selber ans Steuer des
Vogels, dann würde viele Leute wohl den Moby machen und in einfacher
erreichbaren heimatlichen Gefilden urlauben.
"Komplexität" ist ein weiter Begriff. Ich bezog mich darauf, dass man
die Abfolge von Assembler-Befehlen relativ leicht anhand der einzelnen
Beschreibungen der Befehle nachvollziehen kann.
In einer Hochsprache hingegen gibt es eine Vielzahl an Faktoren, die in
die exakte Funktion einer Zeile einfliessen können. Viele dieser
Faktoren sind quer über die Sprachbeschreibung gestreut und der
Programmierer muss sie im Kopf haben und zum passenden Zeitpunkt mit der
Zeile assoziieren.
> Ja, eine einzelne Assembler-Instruktion ist "einfacher" insoweit als sie> nur einen einzigen, winzigen kleinen Teil des Programms ausmacht.
Weshalb ich ja auch vorhin schon zwischen der Komplexität der Zeile und
der Komplexität der Lösung unterschied.
>> Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt>> sich die tatsächliche Operation erst aus den Datentypen der Operanden.>> Das ist nicht komplizierter, sondern viel einfacher, weil der Compiler> dem Entwickler die Entscheidung, welche Maschineninstruktion(en) zu> verwenden sind, ganz einfach abnimmt.
Die Codegenerierung ist nur ein Teil der Gesamtproblematik.
Ein häufiges Problem unter C Programmieren ergibt sich aus der
Kombination vorzeichenfreier und vorzeichenbehafteter Typen. Aus if(a <
b)... ergibt sich nicht direkt, ob der Vergleich mit oder ohne
Vorzeichen stattfindet. Auch wenn "unsigned a" und "long b" bekannt sind
ist das noch nicht klar, denn 16- und 32-Bit Maschinen verhalten sich
dann völlig verschieden.
Der Programmierer muss also jenseits der Bedeutung des "<" Operators
auch die in C üblichen Konvertierungsregeln im Kopf haben und diese in
Bezug zur realen Maschine setzen. Es ist diese Art der Komplexität
einer Sprache, auf die ich mich beziehe.
> muß, und nimmt automatisch und ohne jedes Zutun die Richtige(tm).
Er nimmt das, was sich aus den Regeln ergibt. Das ist keineswegs immer
die richtige Wahl in Bezug auf die Lösung des Problems. Das "do what I
mean, not what I say" Problem ist nach wie vor ungelöst.
> Für den Entwickler ist das eine enorme Vereinfachung und> Erleichterung seiner Arbeit,
Richtig. Weshalb ich ja diese Form der Komplexität nicht ablehne. Ich
weise nur darauf hin, dass es sie gibt.
A. K. schrieb:> Doch, kann man schon. Man kann Programmzeilen vergleichen und man kann> Lösungen vergleichen.
Wenn man die Anzahl von Programmzeilen in Assembler, C und, sagen wir,
Ruby vergleicht, wird daraus aber zwangsläufig ein Vergleich von Äpfeln,
Bananen, und Rinderhacksteaks, oder anders gesagt: solche Vergleiche
hinken und sind weder sinnvoll, noch zielführend. Zumal die Zeilen, die
Du vergleichen willst, nicht einmal näherungsweise etwas ähnliches tun.
Das ist aber gerade das, was einen Programmierer interessiert: nämlich
das, was sein Programm tut, also daß das Programm sein Problem löst. Wie
es das Problem dann tatsächlich löst, ist eher nebensächlich.
Programmieren ist schließlich kein Selbstzweck, sondern soll praktische
Probleme lösen, wie hier im Beispiel den Vergleich zweier Zahlen.
> Ich hatte oben eine Programmzeile verglichen, um den Unterschied der> Komplexität dieser Programmzeile hervorzuheben. Dass man für die gleiche> Lösung wesentlich mehr Asm-Zeilen benötigt ist unstrittig und eine> andere Art von Vergleich.
Es ist die einzige Art von Vergleich, die einen Sinn ergibt. Aber auch
wenn wir bei Deinem Vergleich bleiben, zeigt sich, wie viel komplizerter
ASM ist: ein "if(a < b)" versteht sogar jemand, der überhaupt keine
Ahnung von der Programmiersprache C oder überhaupt vom Programmieren
hat. In Assembler steht da etwas wie "cp r16, r17", "cpc r16, r17" oder
"cpi r16, r17", was sich einem Betrachter nur erschließen kann, wenn er
weiß, was "cp", "cpc" und "cpi" tun und was die Register "r16" und
"r17" sind.
Um Dein Assembler-Beispiel aber auch nur halbwegs vergleichbar mit jenem
in C zu machen, kommt allerdings noch der Sprungbefehl hinzu, und erst
wenn man den hinzunimmt, kommt am Ende etwas heraus, das wenigstens im
Ansatz mit dem C-Beispiel äquivalent und vergleichbar ist. Denn das ist
schließlich jener Grad an Komplexität, die der Programmierer letztlich
behandeln und beherrschen muß. Und dann bekommt die Sache einen Sinn:
1
if(a<b)mach_dies();
ist viel einfacher und lesbarer und sogar für Laien verständlicher als
1
cp r16, r17
2
brlo mach_dies
-- und das gilt nur für vorzeichenlose (unsigned) Zahlen in r16 und r17.
Wenn die Zahlen vorzeichenbehaftet (signed) sind, heißt die Instruktion
nicht mehr "brlo", sondern "brlt"... Das erschließt sich jemandem, der
Programmieren kann, aber ein Laie versteht nichtmal, warum es da zwei
verschiedene Instruktionen gibt, die (vermeintlich) dasselbe tun. Und
weil nur Masochisten und Ideologen sich an solcherlei Kinkerlitzchen
aufhalten, reale Programmierer aber praktische Probleme schnell und
effizient lösen wollen, wird Assembler heute nurmehr in wenigen
Ausnahmefällen benutzt. Für einen, der sie beherrscht, sind C und, wo
wir gerade dabei sind, auch C++ sehr viel klarer und einfacher als
Assembler.
für unterschiedliche Leute sind halt verschiedene Sachen eine
'Erklärung/Dokumentation'. Hier mal ein klassischer Filmausschnitt:
https://www.youtube.com/watch?v=rFz2llnnC1o
Es ist ganz klar was dieses Objekt (Zeile Code) tut. Nur das 'wozu'
fehlt.
Sheeva P. schrieb:> Wenn man die Anzahl von Programmzeilen in Assembler, C und, sagen wir,> Ruby vergleicht,
Wir schreiben aneinander vorbei. Ich beziehe mich stets auf die
Komplexität des Werkzeugs und du zählst andauernd Programmzeilen.
Wer ein komplexes Werkzeug beherrscht, der hat bei der Lösung eines für
dieses Werkzeug geeigneten Problems weniger Arbeit als jemand, der mit
einem weitaus einfacheren Werkzeug auskommen muss. Das ändert nichts an
der Komplexität des Werkzeugs, sehr wohl aber den Aufwand zur Lösung
A. K. schrieb:> Wer ein komplexes Werkzeug beherrscht, der hat bei der Lösung eines für> dieses Werkzeug geeigneten Problems weniger Arbeit als jemand, der mit> einem weitaus einfacheren Werkzeug auskommen muss. Das ändert nichts an> der Komplexität des Werkzeugs, sehr wohl aber den _Aufwand zur Lösung_
Akzeptiert und Zustimmung.
Ja ich weiss, du wolltest nur diese Feststellung treffen - und da teile
ich deine Sichtweise. In diesem Sinne ist Assembler natürlich einfacher,
taugt aber trotzdem nicht als tragfähiges Argument.
In diesem Sinne ist auch eine Feinsäge und ein Stechbeitel einfacher als
eine Tischkreissäge samt entsprechendem Zubehör. Aber dieses Zubehör
erlaubt es mir, eine verzinkte Verbindung in windeseile perfekt
herzustellen. Etwas wozu ich mich Feinsäge und Stechbeitel viel länger
brauchen würde und wo ich schon viel Übung benötigen würde, um ein
technisch gleichwertiges Ergebnis hinzukriegen. Dazu kommt noch:
Beherrsche ich mein Zubehör, dann wird jede Verzinkung perfekt und ich
komme jedesmal in den Genuss der Zeitersparnis. Zum Ausgleich kann ich
die gesparte Zeit dann an anderer Stelle in meinem Projekt gut
gebrauchen, indem ich mir die Anordnung der SChubladen im Schrank dann
eben gut überlege und wenn sich rausstellt, dass das alles nicht so
schlau war, dann kann ich ganz schnell neue (verzinkte) Schubladen
herstellen. Ich kann vielleicht (abhängig von meinem Werkzeug) nicht
jedes beliebige Mass in der Verzinkung erreichen - kann aber mit dieser
Einschränkung gut leben.
Eine andere Analogie wäre für mich Schach:
Die möglichen Züge sind so etwas wie Assembler. Einfach, simpel, schnell
zu lernen. Aber Schach ist mehr als nur irgendwelche Züge. Natürlich
lässt sich ein Damengambit letzten Endes auch nur auf Züge reduzieren.
Aber der Sinn der Sache, die Wirkung, erschliesst sich erst, wenn ich
von dieser Zugebene weggehe und mir überlege, wie ich mit einer Zugfolge
Druck auf meinen Gegner aufbauen kann. Um eine der banannten Zugfolgen
wirklich zu verstehen, muss ich die Gesamtheit des Spielbrettes
betrachten und wie sich dort die Kräfte verteilen. Mit Einzelzügen hat
das nicht mehr viel zu tun.
Karl H. schrieb:> Eine andere Analogie wäre für mich Schach:> Die möglichen Züge sind so etwas wie Assembler.
Der Vergleich mit Schach stellt aber auch schnell die Aussage 'Wenn der
Computer(Compiler) besser ist, dann war der
Schachspieler(ASM-Programmierer) nicht gut' stark in Frage. Inzwischen
ist die Menge der 'guten' Schachspieler ja schon die leere Menge.
Dumdi D. schrieb:> Inzwischen> ist die Menge der 'guten' Schachspieler ja schon die leere Menge.
Ich bin gerne bereit zuzugestehen, dass es für praktische Zwecke nicht
akzeptabel ist, dass ein Compiler 20 Minuten an der Übersetzung eines
moderaten Codes arbeitet. Würde man ihm die Zeit geben, dann würde er
auch die perfekte Lösung finden können. Inklusive rumprobieren, welche
Variablen er global in welche Register legt, wie er auf einem AVR das
T-Bit für Einzelbitflags sinnvoll nutzen kann, wie er die Pipeline aufs
Beste befüllt halten kann. etc. Bruth Force vom Feinsten.
Da aber Compiler, anders als die 'großen Schachprogramme', kein
Prestigeobjekt sind, wird da nicht so viel investiert.
Dummerweise wächst der Aufwand extrem mit der Länge und ist daher
allenfalls für relativ kleine Schleifen noch praktikabel.
Für kurze Sequenzen gibt es ein paar Ansätze:
https://en.wikipedia.org/wiki/SuperoptimizationKarl H. schrieb:> Da aber Compiler, anders als die 'großen Schachprogramme', kein> Prestigeobjekt sind
Doch, manchmal schon. Es wurden schon Compilerbauer dabei erwischt, dass
sie Benchmarkcode identifizierten und durch handoptimierten Code oder
Abkürzungen ersetzten.
Hach, wer hätte das ausgerechnet bei 14-Bit PICs vermutet?
"PIC Microcontroller SuperOptimizer
The PIC Microcontroller SuperOptimizer is a program that, given a
function, tries to find the shortest sequence of microcontroller
instructions that implement that function. It tries every sequence of
instructions from a restricted set."
http://freecode.com/projects/picsuperoprimizer
Karl H. schrieb:> Können wir gerne machen.> Wir vereinbaren einen Zeitpunkt an dem du und ich Zeit haben. Ein paar> Forneteilnehmer denken sich eine Aufgabe aus, irgendjemand (du, ich, wir> beide) wählt eine der Aufgaben aus und dann schaun wir mal, wer> schneller das Programm stehen hat und wer es fehlerfreier hinkriegt.>> Ich hab nur eine Bedingung: es darf kein Pipifax Beispiel sein sondern> sollte schon was ordentliches sein.
Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem
Mega2560? :P
Karl H. schrieb:> Da aber Compiler, anders als die 'großen Schachprogramme', kein> Prestigeobjekt sind, wird da nicht so viel investiert.
Der Aufwand, die optimale Lösung zu finden, sollte nicht grösser sein
als die Differenz zur suboptimalen leicht ermittelbaren Lösung.
Das ist wie beim Informatikern wohlbekannten Problem des
Handlungsreisenden. Wenn der erst losfährt, nachdem er seine lange
Reiseroute voll durchoptimiert hat, kann es sehr gut sein, dass er
insgesamt länger braucht als wenn er einfach so frei Nase losgefahren
wäre.
Kaj G. schrieb:> Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem> Mega2560? :P
Da muss ich mich erst mal schlau machen, was das überhaupt ist :-)
Karl H. schrieb:> Kaj G. schrieb:>>> Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem>> Mega2560? :P>> Da muss ich mich erst mal schlau machen, was das überhaupt ist :-)
1
ccTalk (pronounced see-see-talk) is a serial protocol in widespread use
2
throughout the money transaction and point-of-sale industry. Peripherals
3
such as the currency detectors for coins and banknotes found in a diverse
4
range of automatic payment equipment such as transportation, ticketing,
5
payphones, amusement machines, and retail cash management use ccTalk to
Karl H. schrieb:> Karl H. schrieb:>> Kaj G. schrieb:>>>>> Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem>>> Mega2560? :P>>>> Da muss ich mich erst mal schlau machen, was das überhaupt ist :-)> ...> Wie testen wir die Implementierungen?
Das war ja jetzt erstmal nur ein spontaner Vorschlag von mir, weil ich
das in meiner jetzigen Firma schon machen musste. :)
Die Implementierung könnte man Testen, in dem Jemand einen Master
schreibt, der den Slaves (in einer euch unbekannten reihenfolge)
kommandos schickt. Die Reihenfolge muss natürlich für beide Tests gleich
sein. Generell müsste man die Aufgabe aber noch etwas spezifizieren.
So würde ich zum Beispiel sagen, das es 2 Hopper und 1 Münzprüfer als
Slaves sind. Und man müsste nochmal drüber reden ob mit oder ohne
Verschlüsselung.
Die Spezifikationen zu ccTalk gibt es hier: http://www.cctalk.org/
Auf der rechten Seite: Download Part 1 - 4
Wie gesagt, war jetzt einfach nur ein spontaner Vorschlag :)
Das ganze gibt es auch noch mit MDB (
https://de.wikipedia.org/wiki/Multi-Drop_Bus ), davon hab ich aber keine
ahnung.
Matthias L. schrieb:> Könnte man das dann gleich praktisch nutzen? Zb für gratis Bahnfahrten?
Wenn du die Verschlüsselung (wo jeder Hersteller seine eigene haben
dürfte, so wie wir) nachbauen/knacken kannst, klar :)
Kaj G. schrieb:> Wenn du die Verschlüsselung (wo jeder Hersteller seine eigene haben> dürfte, so wie wir) nachbauen/knacken kannst, klar :)
Nicht ist so verlässlich unsicher, wie selbstgebaute Verschlüsselung.
;-)
A. K. schrieb:> Nicht ist so verlässlich unsicher, wie selbstgebaute Verschlüsselung.
Stimmt schon, aber lass dir gesagt sein:
Wenn man es wie wir mit organisierter Kriminalität zu tun hat, steckt da
sehr viel Zeit, Geld, und auch entsprechende versuche (von sehr
kreativen/kompetenten leuten), das ding zu knacken, drin ;)
Oder anders gesagt:
Selbst wenn du den Algorithmus kennst, kannst du die Verschlüsselung
nicht brechen ;)
Also "können" schon, dafür muss man dann aber unverhältnis mäßig viel
aufwand treiben.
So, mal zurück zum Thema:
Kaj G. schrieb:> Die Implementierung könnte man Testen, in dem Jemand einen Master> schreibt,
Das reicht aber nicht, denn wirklich interessant wird es erst, wenn
jemand "das Gerät bedient", also z.B. "Geld einwirft und ausgezahlt
haben möchte". Geld einwurf könnte man z.B. durch Taster simulieren (10,
20, 50 cent, 1 und 2 euro, je münze ein taster).
Ich denke mögliche Aufgaben gibt es genug. Nur wie wird das ganze dann
nachher effektiv verglichen, und was ist wann besser?
Geht es nur um den Asm-Code, oder auch sachen wie "Lesbarkeit"? geht es
um die laufzeit?
Was genau will man nachher wie vergleichen? Und wer beurteilt am Ende,
was jetzt "besser" ist?
Oder geht es nur um "selbstgeschriebenen Asm" vs. "vom Compiler
erzeugten Asm"?
(Ja ich geb zu, ich hab irgendwo nach 150 Beiträgen auf gehört zu lesen
und hab erst jetzt wieder angefangen)
Frank M. schrieb:> Diese Aufgabe halte ich für sinnvoller, da die Lösung nachher nicht für> die Tonne ist, sondern durchaus für das eine oder andere Projekt> verwendet werden kann :-)
Sorry, Kay, aber Franks "Anforderung" bezüglich Wiederverwenbarkeit hat
was! ;-)
> Ich würde dann aber an deiner Stelle auch am Terminal zweifeln. Zeig mir mal, an
welcher Stelle deines 8-Bit Zeichensatzes Symbole wie ⍳, ⌹ oder ⍴ zu finden sind.
;-)
Es gab zu APL auch spezielle Schablonen, die man auf
MainFrameTerminalTastaturen legte, damit man auch eintippen konte, was
auf dem Display zu sehen war. Das Terminal war dabei im APL-Mode. APL
hab ich zwar nie benutzt, aber an diese komischen Schablonen kann ich
mich erinnern.
Konrad S. schrieb:> Sorry, Kay, aber Franks "Anforderung" bezüglich Wiederverwenbarkeit hat> was! ;-)
Ist ja völlig legitim.
Ich hatte ja einfach nur was in den Raum/Chat geworfen :-)
Kaj G. schrieb:> Geht es nur um den Asm-Code, oder auch sachen wie "Lesbarkeit"? geht es> um die laufzeit?
Zuallererst geht es um die Funktionsfähigkeit. Und zwar fehlerfrei :-)
Laufzeit ist ein natürlich ein Thema. Da kann sich Moby was aussuchen.
Zeitbedarf in der Erstellung ist ebenfalls ein Thema. Speziell wo doch
Moby eh so wenig Zeit für sein Familie hat (Sorry, could not resist)
> Was genau will man nachher wie vergleichen? Und wer beurteilt am Ende,> was jetzt "besser" ist?
Da hätt ich einen fiesen Ansatz :-)
Jeder von uns beiden baut einen Fehler in seine Version ein. Und dann
schaun wir mal, welche Fraktion (Assembler oder C) den Fehler schneller
findet. :-)
Aber kein Sorge.
Wenn die Dinge so laufen, wie sie eigentlich immer laufen, wird es nie
zu so einem Wettstreit kommen.
Ich bin übrigens das Wochenende über unterwegs. Daher nicht wundern,
wenn ich (falls doch etwas zu stande kommt), nicht zeitnah antworte.
> Oder geht es nur um "selbstgeschriebenen Asm" vs. "vom Compiler> erzeugten Asm"?
Es geht darum, die vollmundigen Aussagen endlich mal auf einen Prüfstand
zu stellen. Und zwar mit ein bischen mehr als Micky Mouse "Wenn Taster
gedrückt, dann LED ein" Programmen (oder Variationen davon). Da Moby
kein Profi ist, gestehe ich ihm eine Beschränkung der Komplexität der
Aufgabenstellung zu. Aber auch nicht zu trivial.
Frank M. schrieb:> 8-Kanal Software-UART (nur Eingänge), um 8 verschiedene LEDs mit SW-PWM> zu steuern
Oh die Idee klingt gut. Ein Programmierkontest :-)
Aber ich steige jetzt schon aus wenn Johann mitmacht. Ich kenne den
Source seiner Scopeuhr ;-)
Karl H. schrieb:> Da Moby kein Profi ist,
Also wenn ich die erste Seite dieses Threads richtig verstehe, macht
Moby seit 18 Jahren Asm, da sollte man doch schon zu den "Profis"
zählen, oder? :)
Kaj G. schrieb:> Karl H. schrieb:>> Da Moby kein Profi ist,> Also wenn ich die erste Seite dieses Threads richtig verstehe, macht> Moby seit 18 Jahren Asm, da sollte man doch schon zu den "Profis"> zählen, oder? :)
Hätte ich auch gesagt. Aber auf der anderen Seite wenn ihn ein 32 Bit
Vergleich schon vor so unübeerwindliche Hürden stellt.
(Den Fehler im ADC Beispiel seh ich so wie er nicht als verzeihlichen
Flüchtigkeitsfehler an, sondern der ist schon massiv mittelprächtig
schwer und genau von der Sort, vor denen wir Asm-Programmierer immer
warnen: du musst dir bei einer Änderung ALLES ansehen. Und ALLES meint
auch wirklich alles. Du musst dich um jeden Kleinscheiss selber kümmern:
Adressierung, Flags, Registerbenutzung. So gesehen wäre genau dieser
Fehler das beste Argument, warum ein Compiler sinnvoll ist. Aber seis
drum. Wir alle machen mal Fehler das man sich hinterher nur noch auf den
Kopf greift und fragt: Wie konnte das passieren?)
Moby A. schrieb:> Das Angebot zum kürzeren Formulieren der beschriebenen> Funktionalität in C steht nach wie vor... Dabei muß man> sich auch nicht an meiner Programmlogik orientieren.
Du schreibst, du willst den optimalen Code? Warum sparst zu dann auf
Teufel-komm-raus 1, 2 läppische Instruktionen anstatt SCHNELLEN Code zu
schreiben?
Z.B dein Code für den LM335:
o Ob der der 2 Byte kürzer oder länger ist, ist sooo egal, egaler
geht's nicht.
o Der Code läuft in einer ISR. Warum machst du den Code extra
lahm, obwohl er in einer ISR laufen soll??? Es ist doch total
hirnrissig, paar Bytes zu sparen wenn der Code schnell sein soll!
Fangen wir mal mit der Erbsenzählerei an:
o RCALL, RET und dein arschlahmer Rechtsschift kosten
2 + 5 = 7 Instruktionen.
o Ohne große Verrenkungen macht man den 16-Bit Rechtsshift
in 9 Instruktionen OGOTTOGOTT 9 INSTRUKTIONEN HÖLLE!!!
o Zieh die 7 Instruktionen für CALL + RET + Schnach-Schift ab, und
es bleiben 2 Mehrinstruktionen.
o Wenn der Code eh in der ISR laufen soll, wozu dann CALL und RET?
Sind doch unnötig wien Kropf!
Und jetzte schaust du NICHT auf deinen Codelängenfetisch, sondern
schaust dir mal eine SIMULATION an und hälst die SIMULIERTEN BEFEHLE
nebeneinander!
DAS ist nähmlich, was hier zählt.
> 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke.
Das ist doch Käse.
Assembler ist ein exzellentes Einsatzgebiet für Arithmetik. Und wenn
ich solchen Assembler schreibe, dann fuchse ich auch um jedes Byte und
jeden Tick. Aber der Code landet dann auch nicht in der Tonne, sondern
wird von Tausenden von Compiler-Anwendern eingesetzt.
900ss D. schrieb:> Aber ich steige jetzt schon aus wenn Johann mitmacht.> Ich kenne den Source seiner Scopeuhr ;-)
Ja, die Scope-Uhr; Morpheus und Rudi. Ist momentan eingemottet, was
aber nicht an Morpheus liegt ("Morpheus" is der Projektname der
Software), sondern an Rudi ("Rudi" ist der Projektname für die
Handware).
Es gab sogar schon Interesse die Uhr zu vermarkten, aber dazu müsste es
eine vermarktbare Hardware geben, und mit dem Zeug kenn ich mich nicht
aus. Um das professionell und verkaufbar zu machen müsste jemand vom
Fach her...
Übrigens hab ich "Morpheus" als Name für die Software gewählt, weil ich
Gimmiks wie folgendes implementieren wollte:
Beitrag "Re: Wie Parametrisierung für Kurve finden?"https://www.mikrocontroller.net/attachment/52470/A-ani.gifhttps://www.mikrocontroller.net/attachment/52552/AB-ani.gif
Moby A. schrieb:> Das Angebot zum kürzeren Formulieren der beschriebenen Funktionalität> in C steht nach wie vor... Dabei muß man sich auch nicht an meiner> Programmlogik orientieren.
"Angebot" angenommen ;-)
Es geht doch um deinen Assemblercode in diesem Beitrag:
Moby A. schrieb:> Hab mal meine bereits weiter oben zur Sprache gekommene ASM Lösung aus> einem anderen Hochsprachen-Thread(problem) angehängt.
Im Anhang findest du den entsprechenden C-Code, der bis auf ein paar
Kleinigkeiten die gleiche Funktion wie dein Assemblercode hat.
Die Unterschiede:
- Die Anzahl der zu verarbeitenden Tasten ist statt auf 8 nur durch die
Anzahl der verfügbaren Portpins limitiert. Für jede Taste wird ein
zusätzliches RAM-Byte benötigt, dafür bleibt aber das GPIOR0-Register
frei. Für die Erweiterung auf mehr als 3 Tasten müssen nur das Makro
KEYS auf den entsprechenden Wert gesetzt und zusätzliche Aufrufe von
debounce in der Funktion processAllKeys hinzugefügt werden.
- Die Anzahl der Abtastwerte lässt sich mit dem Makro DEBOUNCE_SAMPLES
leicht ändern. Insbesondere sind auch Werte größer als 8 möglich (für
besonders stark prellende Taster).
- Es wird nicht nur die Dauer des Tastendrucks, sondern auch die des
Loslassens gemessen. Dieses Feature braucht man zwar eher selten, aber
wenn doch, dann ist es bereits da und muss nicht mehr implementiert
werden.
- Die Funktion debounce wird wie bei dir die Routine keyproc für
jede Taste aufgerufen, allerdings ist die Aufrufreihenfolge von
debounce unwichtig. So kann bspw. die Auswertung einzelner Tasten
ausgelassen werden, wenn diese in einer bestimmten Situation gar nicht
aktiv sein müssen, was dann etwas CPU-Zeit spart.
- In deinem Code muss man bei der Erweiterung der Aktionsroutinen
(key<i>pressed und key<i>released) darauf achten, dass darin die
Register R27 (XH), R30 (ZL) und R31 (ZH) nicht versehentlich
überschrieben werden, da in diesen Informationen zwischen zwei
Aufrufen von keyproc aufgehoben werden. Das wird – wie schon beim
Carry-Flag geschehen – ganz sicher zur Falle, wenn du deinen Code nach
ein paar Monaten wieder herauskramst, um ihn zu erweitern ;-)
Beim C-Code besteht diese Gefahr nicht.
- Die Entprellung der Tasten und die Ausführung der davon abhängigen
Aktionen (key<i>Pressed und key<i>Released) erfolgt bei mir nicht in
der Interruptroutine, sondern in der Hauptschleife des Programms (aber
trotzdem interruptgetriggert). Dadurch werden – insbesondere bei etwas
aufwendigeren Aktionen – weitere Interrupts, die vielleich später
hinzukommen – nicht unnötig blockiert.
- Zudem erlaubt es diese Ablaufstruktur der CPU, sich während des
Nichtstuns zwischen zwei Timer-Interrupts schlafen zu legen und damit
Strom zu sparen.
Die Entprellroutine ist ganz klassisch, ohne jegliche Tricks und damit
für jeden C-Programmierer (hoffentlich) leicht nachvollziehbar mit zwei
Zählern (für die eigentliche Entprellung die Gedrücktzeitmessung)
realisiert. Man könnte den Code mit Kniffen wie den vertikalen Zählern
in Peter Danneggers Routine sicher noch straffen. Peters Routine ließe
sich auch relativ problemlos auch auf 8 Abtastwerte erweitern.
Allerdings wäre der Code dann nicht mehr so klar verständlich und man
müsste Einschränkungen bzgl. der Erweiterbarkeit in Kauf nehmen (maximal
8 Tasten, die alle an denselben I/O-Port angeschlossen sein müssen).
Trotz der höheren Flexibilität und der für die meisten sicher leichter
verständlichen Programmlogik kann der C-Code größenmäßig gut mit deinem
Assemblercode mithalten:
1
Mobys Asm-Code Yalus C-Code
2
—————————————————————————————————————————————————
3
Flash-Verbrauch 266 256
4
RAM-Verbrauch¹ 6 + 1 GPIOR 9
5
Stack-Verbrauch 2 4
6
Quellcodezeilen² 143 91
7
Quellcodezeichen³ 1614 1707
8
—————————————————————————————————————————————————
9
¹) ohne Stack
10
²) ohne Leer- und Kommentarzeilen
11
³) ohne Kommentare, Leerraum und Zeilenvorschübe
12
13
Compiler: GCC 4.7.4
14
Assembler/Linker: Binutils 2.25.1
15
C-Standardbibliothek: AVR-Libc 1.8.1
Die 26 Interruptvektoren und die Routine zur Initialisierung des
genutzten RAM-Bereichs mit Nullen sind übrigens in den 256 Flash-Bytes
enthalten, auch wenn sie nicht explizit im C-Quellcode auftauchen. Da
übernimmt die C-Toolchain also netterweise eine weitere lästige Aufgabe.
Die versteckte Startroutine initialisiert übrigens auch den Stackpointer
und das Statusrgister, was beim ATmega88 nicht unbedingt erforderlich
ist. Eine dahingehend optimierte Startroutine würde noch einmal 10 Bytes
sparen.
Wenn man die Startroutine aber sowieso anpasst, könnte man bei dieser
Gelegenheit gleich noch den Aufruf des nie endenen Hauptprogramms
optimieren, was weitere 6 Bytes Flash und 2 Bytes Stack spart. Damit
läge der Flash-Verbrauch mit 240 Bytes fast 10% unter dem deines
Assemblerprogramms.
Die Quellcodegröße in Zeichen ist beim C-Code immerhin knapp 6% größer
als beim Assemblercode. Mit kürzeren Variablennamen, die dann ähnlich
nichtssagend wären wie die Registernamen R18, XL, ZH usw. n deinem
Assemblerprogramm könnte auch dieses Manko behoben werden, aber das
lasse ich besser bleiben ;-)
Abschließende Anmerkungen:
Den C-Code habe ich mangels einer Schaltung mit dem ATmega88, den
Tastern und den LEDs nicht auf dem Zielsystem laufen lassen. Allerdings
habe ich die Funktion debounce mit simulierten Eingaben auf dem PC
getestet, so dass ich mit ziemlich sicher bin, dass diese Funktion
korrekt ist. Eventuelle Fehler in anderen Programmteilen (Tasten lesen,
Ergebnis von debounce abfragen, LEDs schalten usw.) sollten mit
minimalen Änderungen und ohne Erhöhung des Flash- und RAM-Verbrauchs
korrigiert werden können.
Die Initialisierung des Timers habe ich ohne Prüfung von Mobys Code
übernommen in der Hoffnung, dass sie fehlerfrei ist.
Yalu X. schrieb:> "Angebot" angenommen ;-)
Gut gemacht :-)
Bin mal gespannt wie groß der Moby's Assemblercode denn wird wenn er all
deine Features auch noch implementiert
Kommt, die Sache ist doch schon erledigt.
Laut Moby:
Moby A. schrieb:> Horst S. schrieb:>> Moby schrieb:>> Asm allein ist nun>> leider keine Garantie für guten Code, wie man beim TO-Programm schön>> sehen kann ;-)>>>> Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so>> vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne>> großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru,>> aber einfach abfrühstücken lasse ich mich auch nicht von Dir.>>>> Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung.>> Die Entschuldigung kannst Du Dir sparen.> Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das> jedenfalls nicht für Deinen Asm-Code.
Da sich sein Asm-Code auch mit C locker unterbieten lässt, kann er
selber laut seiner Argumentation keinen guten Code schreiben.