Hallihallo,
folgende Sachlage: Ich habe ein Programmchen für einen ATMega168 zuerst
auf Assemblerbasis erstellt und anschließend auf gcc portiert. Das
funktioniert auch alles (zumindest nicht schlechter als in Assembler),
was mich aber zur Zeit etwas die Augenbrauen hochziehen lässt:
Warum benötige ich im Assembler-Projekt "nur" 2910 Bytes, in C aber
"satte" 3278 Bytes?
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?
Was ich bisher gemacht habe:
- Ich habe mal alle Optimierungen durchprobiert. Die 3278 Bytes sind das
Beste, was ich mit meinem AVRStudio 4.10 herauskitzeln kann.
- Ich hab mir die eingebundenen Header mal angeschaut. Dabei habe ich
viele #defines, aber kein Grund für das absonderliche Wachstum gefunden.
Ich häng mal die Projekte als Zip an.
Zur Info:
- Die Projekte kommunizieren über zwei PortPins per PS/2 mit einem
Maussensor (SPCP168A). Empfangene Werte werden in DataRead.MouseBuffer
geschrieben. Der Wert von DataWrite.MouseCommand wird über PS/2 an den
Sensor übergeben.
DataRead und DataWrite werden mit einem PC über UART ausgetauscht. Zum
Austausch von Datenblöcken habe ich in UARTTelegramm.c für das C-Projekt
und rs232Telegram.asm für das Assemblerprojekt ein unverfängliches
Protokoll aufgesetzt. (Der PC liest zuerst die implementierte
Peripherie-Tabelle, um die Adressen der Datenblöcke zu lesen.
Anschließend kann er direkt auf Datenblöcke (hier DataRead und
DataWrite) über die vier implementierten Read-/Write-/-Device/-Mem
zugreifen.
Prinzipiell funktionieren sowohl der PS/2- als auch das UART-Protokoll
als Statemachines über Funktionspointer. In Assembler regeln das im
wesentlichen die Macros "PrepareJump" und "Jump".
Etwas Eigenartig vielleicht für den Außenstehenden das Mapping der
Register r16..r23 auf d0..d7 im Assembler(ich war mal
68000er-Fetischist).
Vielleicht fällt Euch ja ein, was ich in C noch optimieren könnte.
(und reißt mir nicht den Kopf ab, das ist mein Erstlingswerk mit gcc).
@ Horst S. (hdc)
>was mich aber zur Zeit etwas die Augenbrauen hochziehen lässt:>Warum benötige ich im Assembler-Projekt "nur" 2910 Bytes, in C aber>"satte" 3278 Bytes?
Wen interessieren diese läppischen 10% im Jahr 2015, wo selbst 32 Bit
CPUs für wenige Euros verkauft werden?
>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?
Nö, es ist erstmal nur 10% größer. Ob es auch 10% langsamer ist, ist
damit noch lange nicht gesagt. Du kämpfst gegen Windmühlen.
https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung
kannst man das nicht eine packen und mitgeben welches Byte man haben
will?
1
voidPS2ReceiveBit0();
2
voidPS2ReceiveBit1();
3
voidPS2ReceiveBit2();
4
voidPS2ReceiveBit3();
5
voidPS2ReceiveBit4();
6
voidPS2ReceiveBit5();
7
voidPS2ReceiveBit6();
8
voidPS2ReceiveBit7();
auch das sollte sich doch wohl über eine Funktion abbilden lassen.
Auch kommt mir volatile viel zu oft vor. sicher das die ganzen Variablen
in einer ISR und dem Hauptprogramm verwendet werden?
1
voidSetLED1()
2
{
3
asm("sbi _SFR_IO_ADDR(PORTB), LED1""\t\n");
4
//asm ("sbi PORTB, LED1" "\t\n");
5
}
warum hier noch asm? Das sollte sich mit Makros ohne Funktion machen
lassen.
1
for(inti=0;i<=255;i++)
2
DataRead.MouseBuffer[i]=0;
konstanten im code sind böse, was ist wenn die größe vom Puffer sich mal
ändert?
Peter II schrieb:> auch das sollte sich doch wohl über eine Funktion abbilden lassen.>> Auch kommt mir volatile viel zu oft vor. sicher das die ganzen Variablen> in einer ISR und dem Hauptprogramm verwendet werden?
Ich hab's so 1:1 aus Assembler umgesetzt. Wie gesagt, der
Funktionpointer wird aus der letzten aufgerufenen Funktion für den
nächsten Interrupt umgesetzt. Das war in Assembler eine super Sache, da
ich keinen Schleifenzähler zwischen den Interrupts puffern musste.
Wenn ich's ändere, wird der C-Code zwar kleiner, die Vergleichbarkeit
zum Assembler ist allerdings dann wech.
Die volatile-Variablen puffern Zustände für folgende ISR-Aufrufe. Wenn
ein Datenblock über WriteDevice beschrieben wird, bemisst das Protokoll
z.B. über den Zähler RxDDataLength, wann der PC fertig ist und wann das
Quittierungstelegramm zu starten ist.
Peter II schrieb:> konstanten im code sind böse, was ist wenn die größe vom Puffer sich mal> ändert?> memset( &DataRead, 0, sizeof(DataRead) );> würde ich hier vorschlagen.
guter Plan, das!
Peter II schrieb:> warum hier noch asm? Das sollte sich mit Makros ohne Funktion machen> lassen.
Das ist allerdings auch noch eine offene Frage für mich: Wie ist die
Umsetzung des sbi/cbi-Befehls in C?
Ist ein "PORTB |= 0x01" wirklich dann ein "sbi PORTB, 1"?
Oder baut mir der Compiler daraus ein:
in r16, PORTB
ori r16, 0x01
out PORPB, r16
Das wäre mir unangenehm!
Horst S. schrieb:> Ich hab's so 1:1 aus Assembler umgesetzt. Wie gesagt, der> Funktionpointer wird aus der letzten aufgerufenen Funktion für den> nächsten Interrupt umgesetzt. Das war in Assembler eine super Sache, da> ich keinen Schleifenzähler zwischen den Interrupts puffern musste.> Wenn ich's ändere, wird der C-Code zwar kleiner, die Vergleichbarkeit> zum Assembler ist allerdings dann wech.
macht für mich wenig sinn. C schreibt man um sich weniger arbeit zu
machen. Da überlässt man einige Details dem Compiler. So wie du es
gemacht hast, verhinderst du zum teil Optimierungen.
> Die volatile-Variablen puffern Zustände für folgende ISR-Aufrufe. Wenn> ein Datenblock über WriteDevice beschrieben wird, bemisst das Protokoll> z.B. über den Zähler RxDDataLength, wann der PC fertig ist und wann das> Quittierungstelegramm zu starten ist.
wenn sie NUR in der ISR genutzt werden, braucht man kein volatile.
> Das ist allerdings auch noch eine offene Frage für mich: Wie ist die> Umsetzung des sbi/cbi-Befehls in C?> Ist ein "PORTB |= 0x01" wirklich dann ein "sbi PORTB, 1"?
ja, zur Sicherheit schaut man einfach mal in den ASM code.
Das "PS2.c" ist aber wirklich von hinten durch die Brust ins Auge.
Funktionspointer sind da viel zu umständlich.
Alle Bit0..7-Funktionen machen doch dasselbe. Also wäre es viel
bequemer, eine Zählvariable zu benutzen, wann ein Byte um ist. Nimm
einfach ein switch/case, das ist dann auch viel besser lesbar.
Tom schrieb:> Weil die LED dann 1µs später angeht?
Eher, weil aus dem Vordergrund aufgerufen, ein zwischendurch im
Interrupt umgesetzter Pin auf dem gleichen Port im Zweifelsfall wieder
zurückgesetzt wird?
Peter II schrieb:> wenn sie NUR in der ISR genutzt werden, braucht man kein volatile.
Oh, ich seh's:
Umdeklariert zu static, kompiliert und siehe da, 3210 Bytes.
Nicht schlecht.
Nach Einfügen der String.h und dem MemSet-Aufruf wieder 3220 Bytes, aber
so viel Komfort muss wohl sein.
Horst S. schrieb:> Ist ein "PORTB |= 0x01" wirklich dann ein "sbi PORTB, 1"?
Nein, glücklicherweise nicht. Daraus wird
sbi PORTB, 0
Vorausgesetzt der PORT ist bitadressierbar. Andernfalls geht es in
Assembler auch nicht.
Falk B. schrieb:> Wen interessieren diese läppischen 10% im Jahr 2015
Interessant und gefragt war woher diese 10% stammen.
> wo selbst 32 Bit CPUs für wenige Euros verkauft werden?
Wen interessiert das wenn ein Easy AVR und kein 32-Bit Monstrum
Verwendung finden soll
Horst S. schrieb:> Warum benötige ich im Assembler-Projekt "nur" 2910 Bytes, in C aber> "satte" 3278 Bytes?
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.
Peter II schrieb:> So wie du es gemacht hast, verhinderst du zum teil Optimierungen.
Rücksichtnahmen, die sich mit Asm generell erübrigen.
Moby du hast keine Ahnung also lass gut sein!
Horst S. schrieb:> Peter II schrieb:>> auch das sollte sich doch wohl über eine Funktion abbilden lassen.>>>> Auch kommt mir volatile viel zu oft vor. sicher das die ganzen Variablen>> in einer ISR und dem Hauptprogramm verwendet werden?>> Ich hab's so 1:1 aus Assembler umgesetzt. Wie gesagt, der> Funktionpointer wird aus der letzten aufgerufenen Funktion für den> nächsten Interrupt umgesetzt. Das war in Assembler eine super Sache, da> ich keinen Schleifenzähler zwischen den Interrupts puffern musste.> Wenn ich's ändere, wird der C-Code zwar kleiner, die Vergleichbarkeit> zum Assembler ist allerdings dann wech.
Naja so must du einen Funktionspointer "puffern"
Mach doch einen static oder einen globalen counter, dann brauchst du
garnix puffern...
Damit sparst du dir dann nebenbei auch 1 byte ram weil aus dem 16-bit
pointer ein 8bit int wird :)
Wenn du nur 1:1 "übersetztst", dann wird C niemal kleiner als dein ASM
code werden.
Wenn du den compiler machen lasst und sauberen code schreibst, dann
sollte der compiler schon noch was rausholen.
73
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 :-)
Sebastian V. schrieb:> War ja nur eine Frage der Zeit bis Moby hier auftaucht... Jegliche> Argumente für Hochsprachen sind damit hinfällig.
Solche Untersuchungen sollte es hier noch viel häufiger geben, bis allen
Beteiligten die immergleichen Ergebnisse in Fleisch und Blut
übergegangen sind ;-)
müssen alle Register auf dem Stack gesichert werden, das man schon ein
paar Byte + performace aus. Da ist es viel sinnvoll darin auch gleich
den code auszuführen.
Horst S. schrieb:> Ich hab's so 1:1 aus Assembler umgesetzt. Wie gesagt, der> Funktionpointer wird aus der letzten aufgerufenen Funktion für den> nächsten Interrupt umgesetzt.
In Assembler kannst Du Dir Register reservieren, das ist in C tabu.
D.h. der Compiler spart für Funktionspointer in Interrupts nichts,
sondern das Gegenteil ist der Fall.
Obendrein weiß er nicht, was Du damit aufrufst, muß also alle
zerstörbaren Register sichern.
Hast Du Dir mal im Assemblerlisting angesehen, was für ein riesen Bohei
da generiert wird.
Und dazu noch der Mehrverbauch für 8 einzelne Funtionen statt für 0.
Naja lieber moby, ein geübter Hochsprachenprogrammierer wird versuchen
möglichst wenig code zu kopieren.
Daher wäre in dem Fall eine Zählervariable und keine Funktionspointer
die folge gewesen was schonmal 1 Byte weniger Ram bedeutet hätte.
Ganz nebenbei würde es auch kein copy-paste in den PS2 Files geben und
das würde nochmal einiges bringen (was oben ja schon steht).
73
Peter II schrieb:> Wegen deinem Aufruf in ISR(PCINT1_vect)> PS2JumpAddress();>> müssen alle Register auf dem Stack gesichert werden, das man schon ein> paar Byte + performace aus. Da ist es viel sinnvoll darin auch gleich> den code auszuführen.
Oh mann, ich seh's: Da ist das Assembler-Konzept nu' wirklich schlecht
übertragbar (obwohl ich auch im Assembler-Projekt nicht immer mit
Register--Pushen und -Poppen gegeizt habe).
- Was ich noch finde: Der Optimizer kotzt mir immer wieder in der
lss-Datei Fragmente der TxDSendByte-Routine vor die Füße. Mag der keine
call-Befehle?
Horst S. schrieb:> Was ich noch finde: Der Optimizer kotzt mir immer wieder in der> lss-Datei Fragmente der TxDSendByte-Routine vor die Füße. Mag der keine> call-Befehle?
vermutlich macht er den code inline, damit ist es etwas unüberschaubar.
gehe erst mal davon aus, das er es richtig macht.
Einzig interessant noch, wie lange der Code jetzt in der ISR "steht".
Zumindest bin ich jetzt im Verbrauch des Speichers mit 2648 Bytes klar
unterhalb der Assemblerversion.
Eigentich müsste der Compiler die beiden Funktionen automatisch inlinen.
Beim Switch/Case müsstest du im listing schaun was der compiler daraus
macht. Teilweise ist ein if-else-if kleiner... das hängt aber von der
architekur und dem jeweiligen anwendungsfall ab.
73
Oberflächlich mit dem Oszilloskop betrachtet (Messung der Länge von
PCInt1), sieht die Sache nicht soooo schlecht aus.
Bei laufend sendender Maus (da hängt ja der Maussensor an der
PS/2-Schnittstelle) habe ich während der Übertragung eine
Interruptauslastung von ca. 12..15%, und zwar in beiden Fällen, also
Assembler und C. (Bei C ist etwas mehr Jitter, was wohl die Switch
Sprunghierarchie als Ursache hat).
Etwas länger als gemessen, müsste der C-Interrupt noch dauern, da noch
der Push-Pop-Kram reinkompiliert wird, da kam ich mit dem Setzen des
Messpins im C-Code nicht zwischen (in Assembler kein Problem), aber ich
denke mal, nach den 16 Takten kräht der Hahn auch nicht mehr.
Horst S. schrieb:> Etwas länger als gemessen, müsste der C-Interrupt noch dauern, da noch> der Push-Pop-Kram reinkompiliert wird,
sollte aber nicht für alles Register sein, wenn es doch so ist stimmt
etwas nicht. Dann inlined er bestimmt eine Funktion nicht. Prüfe ob alle
Funktion in der ISR static sind.
Poste mal den ASM code
Hans schrieb:> Ich hoffe ich hab' mich nirgends vertippt
Ja, ich mag if-else Ketten nicht, das wird schnell unübersichtlich.
Der AVR-GCC mag switch-case und optimiert es recht gut.
Hans schrieb:> Eigentich müsste der Compiler die beiden Funktionen automatisch inlinen.
Macht er, wenn man sie ordentlich als "static" deklariert. Dann
weiß er, dass sie ohnehin niemand mehr von außerhalb aufrufen kann.
Oder einfach -flto.
Was auch kleineren Code machen kann sind: -fno-caller-saves sowie
-fno-tree-loop-optimize und / oder -fno-move-loop-invariants. Und
natürlich -mrelax --gc-sections und -ffunction-sections nicht vergessen.
Peter D. schrieb:> Hans schrieb:>> Ich hoffe ich hab' mich nirgends vertippt>> Ja, ich mag if-else Ketten nicht, das wird schnell unübersichtlich.> Der AVR-GCC mag switch-case und optimiert es recht gut.
stand ja noch ein "Nachdem der switch sehr "unbefüllt" ist würde ich das
sogar so machen:" drüber ;)
Hast aber natürlich recht. Von Fall zu Fall sollte man sich das trotzdem
anschauen was schneller/kleiner ist...
73
Horst S. schrieb:> - Was ich noch finde: Der Optimizer kotzt mir immer wieder in der> lss-Datei Fragmente der TxDSendByte-Routine vor die Füße. Mag der keine> call-Befehle?
Er versucht, kurze Funktionen inline umzusetzen, um damit den zeitlichen
Overhead der Calls zu sparen und den Inhalt der Funktion im Kontext
ihres Aufrufs besser zu optimieren.
Hans schrieb:> Beim Switch/Case müsstest du im listing schaun was der compiler daraus> macht. Teilweise ist ein if-else-if kleiner... das hängt aber von der> architekur und dem jeweiligen anwendungsfall ab.
Sollte an sich nicht passieren. Der Compiler ist normalerweise schon so
clever, bei einem switch/case zu erkennen, ob eine Sprungtabelle oder
eine Reihe von Vergleichen effizienter ist.
Johann L. schrieb:> Oder einfach -flto.>> Was auch kleineren Code machen kann sind: -fno-caller-saves sowie> -fno-tree-loop-optimize und / oder -fno-move-loop-invariants. Und> natürlich -mrelax --gc-sections und -ffunction-sections nicht vergessen.
Nicht zu vergessen -mcall_prologues, falls man viele (grössere)
Funktionen hat. Dann werden die Push-Pop-Orgien "an einer Stelle
gebündelt". Das hat beim Transistor-Tester schon mal geholfen rund 20%
Flash einzusparen.
Bei -flto ist zu beachten, daß fur bestes Ergebnis Compiler UND Linker
dieses Option brauchen UND beide die selbe Optimierungs-Option. z.B. -Os
haben sollten.
Hans schrieb:> Beim Switch/Case müsstest du im listing schaun was der compiler daraus> macht. Teilweise ist ein if-else-if kleiner... das hängt aber von der> architekur und dem jeweiligen anwendungsfall ab.
Überlass das ruhig dem Compiler. Der analysiert die Datenverteilung und
sucht sich dann unter den implementierten Varianten eine passende aus.
Darunter sind auch einfache aufeinander folgende Vergleiche oder
sukzessive Subtraktionen (bei AVR bringt das nichts, anderswo schon).
Bei einer nicht zu kleinen Anzahl numerisch verstreuter Fälle
implementiert er auch gerne einen Vergleichsbaum. Das ist eine Technik,
die praktisch nur ein Compiler zustande bringt.
A. K. schrieb:> Bei einer nicht zu kleinen Anzahl numerisch verstreuter Fälle> implementiert er auch gerne einen Vergleichsbaum. Das ist eine Technik,> die praktisch nur ein Compiler zustande bringt.
Und das macht avr-gcc besser als früher: https://gcc.gnu.org/PR49903
Ich hab's jetzt mal mit einem Watchdog versehen, der bei fehlenden
Flanken den State zurücksetzt. Dazu habe ich den leidigen state aus der
Funktion allerdings zur Modulvariable deklarieren müssen.
Zum Switch fiel mir dann noch ein: "Wozu gibt's den Default-Zweig?"
(Hilft gegen Augenkrebs).
Nachdem ich die LED-Funktionen als "extern Inline" im Header-File habe,
sieht auch die Rettungsaktion auf dem Stack wieder übersichtlich aus:
Listing .lss:
1
//++++++++++++++++++++++++++++++++++++++++++
2
//External PCINT PinChange Interrupt
3
//++++++++++++++++++++++++++++++++++++++++++
4
ISR(PCINT1_vect)
5
{
6
866:1f92pushr1
7
868:0f92pushr0
8
86a:0fb6inr0,0x3f;63
9
86c:0f92pushr0
10
86e:1124eorr1,r1
11
870:2f93pushr18
12
872:8f93pushr24
13
874:9f93pushr25
14
876:ef93pushr30
15
878:ff93pushr31
16
}
17
18
19
externinlinevoidSetLED3()
20
{
21
PORTD|=(1<<LED3);
22
87a:5e9asbi0x0b,6;11
23
.
24
.
25
.
26
.
Modul PS2 (V3)
1
#include"structs.h"
2
#include"Ports.h"
3
#include"LED.h"
4
#include<inttypes.h>
5
#include<avr/interrupt.h>
6
#include<string.h>
7
8
9
staticuint8_tPS2Byte;
10
staticuint8_tPS2Checksum;
11
staticuint8_tPS2Watchdog=0;
12
staticuint8_tPS2State=0;//Listen
13
#define MSK_PS2Listen 0x00
14
#define MSK_PS2BitCounter 0x0F
15
#define MSK_PS2SendStart 0x10
16
#define MSK_PS2Send 0x30
17
18
19
20
21
voidPS2Init()
22
{
23
PCMSK1=(1<<PCINT11);//Enable Pin change inerrupt on PC3 ()PCINT11)
24
PCICR=(1<<PCIE1);//Enable external interrupt for PCINT14:8
25
26
//Reset variables
27
DataRead.LastOffset=0;
28
DataWrite.MouseCommand=0;
29
PS2Byte=0;
30
memset(&DataRead,0,sizeof(DataRead));
31
}
32
33
34
35
voidPS2TestWatchdog()
36
{
37
if(PS2Watchdog==0)return;
38
39
PS2Watchdog--;
40
if(PS2Watchdog==0)
41
PS2State=0;
42
}
43
44
staticvoidRetriggerPS2Watchdog()
45
{
46
PS2Watchdog=4;
47
}
48
49
//Basic Port functions
50
staticvoidPS2PullDownClock()
51
{
52
PORTC&=~(1<<PS2Clock);
53
DDRC|=(1<<PS2Clock);
54
}
55
56
staticvoidPS2ReleaseClock()
57
{
58
DDRC&=~(1<<PS2Clock);
59
}
60
61
staticvoidPS2PullDownData()
62
{
63
PORTC&=~(1<<PS2Data);
64
DDRC|=(1<<PS2Data);
65
}
66
67
68
staticvoidPS2ReleaseData()
69
{
70
DDRC&=~(1<<PS2Data);
71
}
72
73
74
75
76
voidPS2Send(uint8_tbt)
77
{
78
79
// set a save state
80
PS2State=MSK_PS2SendStart;
81
//Prepare checksum
82
83
PS2Checksum=MakeChecksumOfByte(bt);
84
85
// pull down Clock for 100u
86
PS2PullDownClock();
87
Wait100u();
88
PS2Byte=bt;
89
90
91
92
// pulldown data and release clock
93
PS2PullDownData();
94
PS2ReleaseClock();
95
PS2State=MSK_PS2Send;
96
}
97
98
99
//++++++++++++++++++++++++++++++++++++++++++
100
//External PCINT PinChange Interrupt
101
//++++++++++++++++++++++++++++++++++++++++++
102
ISR(PCINT1_vect)
103
{
104
SetLED3();
105
if((PINC&(1<<PS2Clock))==0)// Do something,while clock is low
106
{
107
switch(PS2State)
108
{
109
case0://Receive Startbit
110
SetLED2();
111
PS2Byte=0;
112
PS2State++;
113
break;
114
115
case0x09://Recieve PS2ReceiveParity
116
PS2State++;
117
break;
118
119
case0x0A://Receive complete-> Transfer byte to target
Horst S. schrieb:> "Wozu gibt's den Default-Zweig?"> (Hilft gegen Augenkrebs).
naja, übersichtlicher finde ich das nicht wirklich. So mal dann dort
wieder nach senden und empfangen unterschieden wird.
Peter II schrieb:> naja, übersichtlicher finde ich das nicht wirklich. So mal dann dort> wieder nach senden und empfangen unterschieden wird.
Hehe, da hat Basic die Nase vorn. Da kann man auch
@ Horst S. (hdc)
>Das ist ja lustig:>Mit dem Default-Zweig bin ich bei 2528 Bytes.>Wenn ich die case-Bereiche verwende, spare ich noch 4 Bytes.
Damit wirst du die Welt retten . . .
Falk B. schrieb:> Damit wirst du die Welt retten . . .
Zumindest nicht Mobys Welt, denn sein C-Programm ist ja nun schon
mehr als 10 % kleiner als sein altes Assemblerprogramm. :)
Jörg W. schrieb:> Zumindest nicht Mobys Welt, denn sein C-Programm ist ja nun schon> mehr als 10 % kleiner als sein altes Assemblerprogramm. :)
und wir sind erst in der ps2 quelle - das ist noch einige zu machen.
Kleiner Hinweis an den C-Lernenden.
Wenn du versucht bist, solche Kommentare zu schreiben
1
switch(PS2State)
2
{
3
case0://Receive Startbit
dann solltest du dir überlegen, ob du nicht für deine magischen
Konstanten benannte Bezeichner einführen willst. Im einfachsten Fall
sind das einfach nur ein paar #define, mit denen du den Zahlen im Code
'einen Namen' gibst. Für den Compiler kommt das auf dasselbe heraus,
denn der sieht letzt Endes ohnehin wieder die Zahl, nachdem der
Präprozessor die Textersetzung durchgeführt hat. Aber für dich als
Programmierer macht es einen Unterschied. Vor allen Dingen in ein paar
Wochen bzw. Monaten, wenn du noch Erweiterungen am Programm vornehmen
willst. Denn irgendwas willst du ja jetzt mit dem freigespielten
Speicher machen :-)
Ein
1
PS2State=WAIT_FOR_STARTBIT;
liest sich viel besser und erzählt mir in der Anweisung alles was ich
wissen muss. Auf jeden Fall mehr als ein
1
PS2State=0;//Fallback to listen
Zudem hab ich durch die Bezeichnung einen Begriff, nach dem ich im Code
suchen kann und der mich dann eben direkt zu
1
switch(PS2State)
2
{
3
caseWAIT_FOR_STARTBIT:
4
...
bringt, ohne dass ich erst mal alle Stellen, an denen 0 vorkommt beim
Suchen überspringen muss.
Alles was du dazu brauchst, ist ein
1
#define WAIT_FOR_STARTBIT 0
und die Sache ist geritzt (selbiges natürlich auch für die anderen
States bzw. die anderen magischen Konstanten).
Darauf solltest du dein Augenmerk legen und nicht darauf, ob du deinen
Prozessor nun zu 17.6% oder doch zu 18.5% ausnutzt. Das interessiert
nämlich niemanden. Was aber interessiert, das ist dass dein Programm
auch in Zukunft noch wartbar bleibt.
Du setzt im Moment die falschen Prioritäten. Hast du ein Problem damit,
dass dein Programm zu groß werden würde um ins Flash zu passen? Nein?
Dann interessiert das momentan auch nicht. Kümmere dich lieber erst mal
um die wirklich wichtigen Dinge und nicht um solche Kinkerlitzchen.
Alternativ: einen enum einführen. Ist für Zustandsautomaten fast
immer sinnvoll. Man muss auch nicht zwanghaft alle Zustände
benennen, auch sowas geht:
1
enumps2_state{
2
PS2ReceiveStartBit=0,
3
PS2ReceiveParity=9,
4
PS2ReceiveComplete=10,
5
};
Ein enum ist in C nichts anderes als ein paar Namen für einen "int"
(in C++ ist es viel stärker ein eigenständiger Datentyp als in C).
ist auch schlecht. Wähle Bezeichnungen nach ihrer Funktion und nicht
nach technischen Begebenheiten (zumindest nicht im Normalfall). Die LED
erfüllt eine Funktion. Das mag zb die LED sein, die einen Fehler
anzeigt. Dann nenn das auch so. Ein
1
TurnOnErrorLED();
erzählt mir an dieser Stelle im Code viel mehr als dein profanes
SetLED2. Heute magst du noch wissen, dass die LED 2 die Fehlerled ist.
Aber in 3 Monaten sieht das alles ganz anders aus. Denn da muss ich erst
mal in der Funktion nachsehen, ob
* mit 'Set' gemeint ist, dass die LED eingeschaltet wird. Oder doch
ausgeschaltet?
* ich nachsehen muss, was denn die Bedeutung der LED 2 war. Denn genau
die interessiert mich, wenn ich nachvollziehen will oder muss, was denn
eigentlich hier
1
if((PINC&(1<<PS2Data))!=0)
2
SetLED2();
3
else
4
ClearLED2();
passiert.
(Und nein, du brauchst mir jetzt nicht erklären was hier passiert. Darum
geht es nicht. Es geht darum, dass ich als Code-Lesender hier mir die
Dinge zusammensuchen muss und das man das mit den richtigen Bezeichnern
auch vermeiden kann. Zudem sinkt die Fehlerchance, weil einem der Code
schon beim Durchlesen seltsam vorkommt, weil das Niedergeschriebene
keinen Sinn ergibt.
Ein
1
x=x1+x2;
kann richtig oder falsch sein. Mann weiss es nicht. Aber das bei
1
NrCars=PriceBrutto+TimeToPack;
irgendwas nicht stimmen kann, ist unmmittelbar ersichtlich. Die 3
Begriffe, die hier verwendet werden, können in keinen irgendwie
sinnvollen Zusammenhang gebracht werden. Dass die alle gemeinsam in
einer Anweisung in dieser Form auftauchen ist sehr wahrscheinlich
falsch. Dazu brauch ich vom Rest des Programms nichts wissen.
Und noch was: In 3 Monaten ist dein Vorteil des Entwicklers fast auf 0
zusammengeschmolzen. Wenn du in 3 Monaten wieder an den Code rann gehst,
dann geht es dir nicht besser als jemandem, der von diesem Code noch nie
etwas gesehen hat. D.h. du musst heute den Code so schreiben, dass du
ihn in 3 Monaten auch noch nachvollziehen kannst. Das ist eine der
Bedeutungen von 'wartbarem Code'.
Das ist auch einer der Gründe warum man überhaupt 'Hochsprachen'
verwendet. Weil man sich auf die Verfahren konzentrieren kann ohne sich
um den technischen Kleinkram kümmern zu müssen.
)
was ganz gerne auch was bringt, sind structs statt globale.
Damit "erzwingt" man quasi indirekten zugriff und spart sich das 16-bit
pointer-laden hin und wieder.
also aus
1
staticuint8_tPS2Byte;
2
staticuint8_tPS2Checksum;
3
staticuint8_tPS2Watchdog=0;
4
staticuint8_tPS2State=0;//Listen
1
structPS2VariableStruct{
2
uint8_tPS2Byte;
3
uint8_tPS2Checksum;
4
uint8_tPS2Watchdog=0;
5
uint8_tPS2State=0;//Listen
6
}
7
8
staticPS2VariableStructPS2Variables;
Wobei ehrlich gesagt du eigentlich schon quasi objekt orientiert
unterwegs bist und sich C++ schon anbieten würde...
Karl H. schrieb:> Kleiner Hinweis an den C-Lernenden.
Der C-Lernende ist in diesem Fall äußerst verwöhnt (fast schon versaut,
weil ich kann mir Namen mittlerweile wirklich nur noch so lange merken,
bis sie aus dem Bildschirm raus sind)
In C# hätte ich's wegen IntelliSense benamt. Hier bin ich ehrlich gesagt
unentschlossen. Ich bin auch kein Fan von dem Gedanken, ein Protokoll
anhand von Quellcode zu studieren, da bin ich eher Dokumentöse:
Aber in der Realität hätte ich wahrscheinlich nur notiert, welche
State-Bereiche Empfang und Senden regeln und wo/warum das Sperren des
Empfangs über die 100us-Pause erfolgt.
Jörg W. schrieb:> Zumindest nicht Mobys Welt, denn sein C-Programm ist ja nun schon> mehr als 10 % kleiner als sein altes Assemblerprogramm. :)
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 ;-)
Aber nicht, daß ich die ehrlichen Optimierbemühungen hier ohne Sympathie
verfolgen würde. Ist nur blöd, wenn der Fehler am System liegt- zur
eigentlichen zu entwickelnden Programmlogik immer noch zusätzlich die
Suche nach dem besten der groben C-Bausteine samt passender
Verkettungsausdrücke
hinzukommt. Und als besonderes Extra schließlich die Code-Optimierung
anhand der Befindlichkeiten des verwendeten Compiler-Werkzeugs.
Schreibts im Klartext, dann brauchts keine Disassemblierung zum
Klarwerden darüber, was nun klarerweise geschieht.
Ingo schrieb:> Ich kann mich täuschen, aber ich habe noch nirgends ne Zeile ASM von> Moby gesehn...
Du täuscht Dich ;-)
Moby schrieb:> Aber nicht, daß ich die ehrlichen Optimierbemühungen hier ohne Sympathie> verfolgen würde. Ist nur blöd, wenn der Fehler am System liegt- zur> eigentlichen zu entwickelnden Programmlogik immer noch zusätzlich die> Suche nach dem besten der groben C-Bausteine samt passender> Verkettungsausdrücke> hinzukommt.
Ich schau hier auch nur das erste mal über meinen Tellerrand, allerdings
kann ich jetzt nach zwei Tagen Arbeit mit dem C-Gedöns sagen:
Den Kram, den der Optimierer da zusammenbaut, den hätte ich in Assembler
weder so optimiert hinbiegen können, noch hätte ich danach eine Chance
zu verstehen, was ich da warum programmiert habe.
Nachteil (ganz klar): Du lieferst Dich der Stabilität des Compilers aus.
Und wehe Dir, der baut Mist.
Aber so weit bin ich noch nicht gekommen...
@Horst S.:
Glückwunsch daß du den Tellerrand übersprungen hast. Ganz ehrlich
gemeint. Leider zeigen sich hier immer nur die, die den Tellerrand
nichtmal erahnen können.
Moby schrieb:> Immer wieder schön, wenn dann der nächstkleinere> Controller genügt ;-)
Den es in Wirklichkeit gar nicht gibt. Heutzutage ist die Diegröße und
damit der wirkliche Preis nur durch die Anzahl der IO-Pads bestimmt. Da
leere Flächen auf dem Die nicht wirklich Sinn machen, wird er mit Flash
und RAM gefüllt. Da manche Spezialisten immer noch glauben, größer
kostet mehr, kann man durch einfache Bondoptionen den Kleinkunden für
den gleichen Chip mit freigeschaltetem Speicher mehr abnehmen. Den
Einkäufern von Großabnehmern kann man das natürlich nicht erzählen, die
zahlen für den (in Wirklichkeit gar nicht) größeren Chip das Selbe.
Ist wie mit der Bandbreite bei manchen Scopes, die kleinere gibt es
technisch nicht wirklich. Und die Preisdifferenz verhandelt ein
erfahrener Einkäufer schnell weg.
Horst S. schrieb:> Nachteil (ganz klar): Du lieferst Dich der Stabilität des Compilers aus.> Und wehe Dir, der baut Mist.
Und der Vorteil, du lieferst dich der Qualität vieler Compilerentwickler
aus und bist nicht dem einen Assemblernerd ausgeliefert, der mit der
nächsten Chipgeneration schon nichts mehr anfangen kann. Und wehe, der
hat Mist gebaut.
MfG Klaus
Moby schrieb:> Immer wieder schön, wenn dann der nächstkleinere> Controller genügt ;-)
War das C-Programm hier nicht kleiner oder hab ich was verpasst?
> nächstkleinere Controller
Zu welchem Preis? Wenn ich für sagen wir mal 1€ mehr den µC mit Speicher
bekommen kann nutze ich gerne den Komfort einer Hochsprache.
(ASM-)Handoptimierung zahlt sich -wenn überhaupt- erst bei hohen
Stückzahlen aus..
Klaus schrieb:> Assemblernerd ... der mit der> nächsten Chipgeneration schon nichts mehr anfangen kann.
Und auch nicht muß, weil die AVRs schon lange Zeit und noch für lange
Zeit dicke reichen. C-Code bedeutet für eine neue Chipgeneration (z.B.
ARM) im übrigen auch nicht, unverändert übernommen werden zu können.
qwerty schrieb:> (ASM-)Handoptimierung
Die optimale Ausnutzung der Hardware ist aber gerade das was den Vorteil
von Asm ausmacht- ansonsten ist es auch nicht mehr als gewöhnliches
(zuweilen wesentlich weniger textlastiges) Codeschreiben.
Man kann drüber streiten, welche Programmierung im Bereich kleiner
Controller bequemer und zeitsparender ist (eine entsprechende
Softwarebasis vorausgesetzt). Man kann nicht darüber streiten, daß es
subjektive Vorlieben für das eine oder andere gibt.
Aber Hand aufs Herz- alles hat irgendwo seinen Preis. Der bedeutet im
Fall der (bequemeren?) Hochsprachenverwendung immer Platz-und
Performancenachteile. Ganz gleich, wie gut ein Compiler sein mag. Der
kann weder schlechte Programmierung ausgleichen noch überhaupt jede
konkrete Absicht des Programmierers erahnen. Erfordert um halbwegs
effizient zu werden viel Herumkonfiguriererei.
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.
> Dazu braucht es nur ein paar Dutzend
Asm-Anweisungen ...
Womit die Größenverhältnisse klar dargelegt wurden. Ja, auch so kleine
Programme kann man auf einem AVR laufen lassen. Sollte man aber keine
Sub-μs-Timing-Anforderungen haben und wo braucht man das schon, dann ist
Handoptimierung pure Verschwendung. Selbst wenn ich statt ein paar
Dutzend aller 256 Befehlsworte eines Tiny4 brauchen sollte, who cares.
Kleiner wird der nimmer. Und eins ist bei mir sehr knapp: Lebenszeit!
Die will ich nicht mit Register-Allokieren verbringen.
Aber das wird Troll-by wieder ganz anders sehen. Sein Erkenntnisgewinn
aus dem Thread, der die "entscheidende Frage" mal wirklich untersucht
und feststellt, daß die vermeintlichen Geisterfahrer doch in die
richtige Richtung fahren: exakt NULL!
Carl D. schrieb:> Sollte man aber keine> Sub-μs-Timinganforderungen haben und wo braucht man das schon, dann> Handoptimierung pure Verschwendung.
Ob nun ein konkretes Projekt von Asm-Platz- und Performanceersparnis
profitiert steht sicher auf einem anderen Blatt. Aber es könnte doch
größer werden (müssen). Es ist da sehr beruhigend mehr Reserven, wie
überhaupt die totale Kontrolle in der Hinterhand zu wissen und seinen
Controller im ungünstigen Falle nicht "auslöten" sprich wechseln zu
müssen...
Die wenigen dutzend simplen Asm-Instruktionen bedeuten aber auch, man
braucht nicht mehr zu seinem Glück, es vereinfacht und macht die Sache
transparent.
> Und eins ist bei mir sehr knapp: Lebenszeit!> Die will ich nicht
... mit Programmierung von Code und Werkzeug verschwenden und auch
nicht mit unnützen Controllerwechseln und mit stetig neuen Architekturen
und stetig neuen Werkzeugen und und und...
> Geisterfahrer
gibts nicht, solange man erfolgreich programmiert. Das allerdings geht
mehr oder weniger effizient und vorausschauend ;-)
Moby schrieb:> immer Platz- und Performancenachteile.
War das C-Programm hier nicht kleiner oder hab ich was verpasst?
> Ganz gleich, wie gut ein Compiler sein mag. Der> kann weder schlechte Programmierung ausgleichen noch überhaupt jede> konkrete Absicht des Programmierers erahnen.
Das kann ein Assembler noch weniger, der überetzt 1:1 ohne jegliche
Optimierung.
In Zeiten, in denen 32-Bitter inzwischen weniger kosten als 8-Bitter ist
es müßig, über die "bessere" Ausnutzung durch ASM zu reden.
Bei der Portierung 8-Bit zu 32-Bit macht es durchaus einen Unterschied,
ob man bei ASM 100% des Codes überarbeiten muss oder bei C nur die I/O
Bereiche - die in meinem Fall vielleicht 5-10% ausmachten.
Beispiel: Der STM32F030 kostet bei Farnell aktuell 1,10 Eur bei
Einzelabnahme. TSSOP20, 16KFlash, 4KRam, 12-Bit A/D, SPI/I2C/Uart, DMA,
16-Bit Timer. AVRs sind bei mir ausgelistet....
Moby schrieb:> Und auch nicht muß, weil die AVRs schon lange Zeit und noch für lange> Zeit dicke reichen.
Für dich vielleicht, es soll aber auch Leute geben die größeres vorhaben
als
> ein paar Dutzend Asm-Anweisungen> C-Code bedeutet für eine neue Chipgeneration (z.B.> ARM) im übrigen auch nicht, unverändert übernommen werden zu können.
Mit einer guten Abstraktion geht das. Arduino Code z.B. läuft
unverändert auf einem UNO (ATmega328) und einem DUE (SAM3X8E ARM
Cortex-M3).
> Die optimale Ausnutzung der Hardware ist aber gerade das was den> Vorteil von Asm ausmacht
Wozu einen alten AVR optimal ausnutzen wenn man für 1,10€ schon einen
STM32 haben kann?
Ich kann Mobys Freude am Register schieben und asm programmieren
verstehen. Total. Es ist ja anscheinend auch definitiv Hobby. Da kann
ich voll nachvollziehen, dass es ihm Spaß macht den alten dil Atmel in
der Lochrasterplatine ans Laufen zu bekommen. Das ist weder zynisch noch
sarkastisch gemeint.
Ebenso halte ich nicht besonders viel davon im Hobby aus Prinzip den
32-bitter zu benutzen. Das fordern jetzt Leute, die der Arduino Fraktion
im nächsten Thread vorwerfen planlos und resourcenverschwendend drauf
los zu programmieren.
Ich kann sogar Moby's Angst vorm Unbekannten und neuen Sachen in
gewisser Weise nachvollziehen.
Aber das bornierte Auftreten und völlige ignorieren von Argumenten und
Einwänden kann ich nicht nachvollziehen und auch nicht akzeptieren. So
disqualifiziert man sich für mich. Das kann ich mir allenfalls im
Alteheim in der Demenzabteilung vorstellen. Erschreckend, dass auch hier
die Leute nur und ausschließlich schwarz weiß denken können.
Was ist denn jetzt mit der Codegröße???
Christian F schrieb:> Ich kann Mobys Freude am Register schieben und asm programmieren> verstehen. Total. Es ist ja anscheinend auch definitiv Hobby.
Klar kann das Spaß machen. Ich hatte auch mal Spaß daran, Assemblercode
auf Papier zu schreiben, von Hand zu Assemblieren und das Ergebnis dann
in eine Hex-Tastatur einzutipppen. Ist doch vollkommen ok.
Aber Moby stellt es als das einzig wahre Allheilmittel dar, mit dem man
mit geringstem Aufwand µC-Projekte beliebigen Umfangs auf einem AVR ans
laufen bekommt und daß alles andere vollkommener Unsinn ist.
Das einzige Beispiel, das ich bisher mal von ihm gesehen habe - im
Rahmen eines Threads über C++ auf µC - war eine blinkende LED. Zu viel
mehr reicht die Vorstellungskraft offenbar nicht. Ich warte ja immer
noch auf seine FAT-Implementation oder den TCP/IP-Stack in Assembler.
> Ebenso halte ich nicht besonders viel davon im Hobby aus Prinzip den> 32-bitter zu benutzen.
Es kommt drauf an, was das Ziel ist. Wenn man Lust dazu hat, in ASM
jeden Taktzyklus einzeln rauszukitzeln und eine bestimmte Aufgabe auf
einem möglichst kleinen µC umzusetzen, ist es ja legitim, den AVR zu
nutzen.
Es gibt ja auch heute noch Leute, die Spiele für den C64 entwickeln, und
das finde ich duraus cool.
Wenn man dagegen ein größeres Projekt umsetzen und sich mehr auf die
eigentliche Funktion konzentrieren will, dann ist die Effizienz beim
Schreiben des Programms wichtiger als bei dessen Ausführung. Und wenn
man merkt, daß man doch noch eine größere Zusatzfunktion haben will, ist
auch die Option, mit vertretbarem Aufwand auf einen ganz anderen
Controller wechseln zu können, wichtig.
In beiden Fällen ist es unerheblich, ob der Controller nun einen Euro
mehr oder weniger kostet.
> Ich kann sogar Moby's Angst vorm Unbekannten und neuen Sachen in> gewisser Weise nachvollziehen.
Wenn man aber so die Klappe darüber aufreißt, wie er, sollte man es
zumindest mal richtig verstanden haben.
> Aber das bornierte Auftreten und völlige ignorieren von Argumenten und> Einwänden kann ich nicht nachvollziehen und auch nicht akzeptieren.
Moby kommt halt in jedem Thread, in dem es um [beliebige Hochsprache]
geht, zu irgendeinem Zeitpunkt daher und bringt dann immer und immer
wieder das gleiche an. In den meisten dieser Threads wurde nicht mal
nach Assembler gefragt. Das ist so, als ob im Heimwerker-Forum zu jedem
beliebigen Thread über Akkuschrauber (z.B. zum Vergleich zwischen
Hersteller X und Hersteller Y) einer reinkommt und empfielt, doch lieber
den klassischen Schraubenzieher zu nehmen, weil der die Fitness
verbessert und viel mehr Leistung hat (wenn man denn stark genug ist).
Diese übertriebene Vehemenz, die offenbar auch keinerlei Nutzen für
irgendwen bringt, hat dazu geführt, daß Moby von den meisten hier
belächelt und nicht mehr ernst genommen wird.
Rolf M. schrieb:> Diese übertriebene Vehemenz, die offenbar auch keinerlei Nutzen für> irgendwen bringt, hat dazu geführt, daß Moby von den meisten hier> belächelt und nicht mehr ernst genommen wird.
Früher™, im Usenet, hätte man bei Antwortbeiträgen auf ihn dann
entsprechend ein
Hans W. schrieb:> 73
Jetzt hab ich Dich: Was ist das? Dein Alter? Die Anzahl Deiner
Nachfahren?
Hat sich der Supercomputer doch mit 42 verrechnet?
(Wollte ich doch letztens schon fragen.)
Hallo Rolf,
Rolf M. schrieb:> Aber Moby stellt es als das einzig wahre Allheilmittel dar, mit dem man> mit geringstem Aufwand µC-Projekte beliebigen Umfangs auf einem AVR ans> laufen bekommt und daß alles andere vollkommener Unsinn ist.> Das einzige Beispiel, das ich bisher mal von ihm gesehen habe - im> Rahmen eines Threads über C++ auf µC - war eine blinkende LED. Zu viel> mehr reicht die Vorstellungskraft offenbar nicht.
Er kann eben einfach nicht mehr als eine LEDs blinken lassen, zu mehr
reicht es bei ihm mit seinem geliebten Assembler nicht. Deswegen faselt
er ja auch immer von "ein paar Dutzend Instruktionen", die angeblich
einfacher seien als die 32 Schlüsselworte in C, weil er von den ~ 130
Instruktionen, die so ein AVR kennt, eben nur gerade mal zwei Dutzend
beherrscht. Das ist schade, aber zum Glück ja nur für ihn. ;-)
Liebe Grüße,
Karl
Diese Entwicklung habe ich auch durchgemacht :-)
Horst S. schrieb:> Ich schau hier auch nur das erste mal über meinen Tellerrand, allerdings> kann ich jetzt nach zwei Tagen Arbeit mit dem C-Gedöns sagen:> Den Kram, den der Optimierer da zusammenbaut, den hätte ich in Assembler> weder so optimiert hinbiegen können, noch hätte ich danach eine Chance> zu verstehen, was ich da warum programmiert habe.
Ab einem gewissen Projektumfang muss man eben auch in Assembler 'ein
bisschen Struktur' reinbringen, um die Übersicht zu behalten. Allerdings
muss das den Compiler nicht interessieren...
> Ab einem gewissen Projektumfang muss man eben auch in Assembler 'ein
bisschen Struktur' reinbringen, um die Übersicht zu behalten.
Ich bevorzuge da eben eine Problembeschreibungssprache mit höherem
Abstraktionsgrad. Und überlasse die Transformation in HW-Befehle der
dafür spezialisierten Software. Diese optimiert im Übrigen nicht nur für
die Zielplattform, sondern schon vorher auf einem abstrakteren Level.
Programme werden nicht lesbarer, wenn man z.B. (ganz simples) bei
Schleifen die gemeinsamen Ausdrücke herauszieht. Man muß diese
(Knuth-Eval-)Optimierungschritte beim Lesen/Verstehen immer wieder
rückgängig machen. Schön wenn da welche ein Programm geschrieben habe,
das sowas kann. Und denen morgen ein noch besserer Kniff einfällt. Dann
einfach nochmal "Build". Die Abhängigkeit vom OS-Projekt GCC kann ich
verschmerzen, verglichen mit so Dingen wie BASCOM, AvrLuna, ... wo gerne
auch mal Einzelpersonen dahinterstehen.
qwerty schrieb:> War das C-Programm hier nicht kleiner oder hab ich was verpasst?
Na ja, wer aufmerksam gelesen hat wird diesen Umstand von mir schon mit
klaren Worten, aber ohne persönlich zu werden kommentiert sehen ;-)
qwerty schrieb:> Das kann ein Assembler noch weniger, der überetzt 1:1 ohne jegliche> Optimierung.
Die Unzulänglichkeiten grober C-Bausteine müssen hier auch nicht
optimiert werden. 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, wie man beim TO-Programm schön
sehen kann ;-)
Hans W. schrieb:> Interessanterweise habe ich übrigens noch keinen Thread gesehen wo Moby> ein ASM ergebnis geliefert hat das tatsächlich wesentlich kleiner ist...
Gelegenheiten gab es schon, mit C gegenzuhalten...
Aber natürlich ist es das keinem Hochsprachler wert.
Könnte ja dumm ausgehen. Es wird von mir weiter Code in der
Projekte-Abteilung geben. Versprochen. Jeder sei dann herzlichst
eingeladen, kürzere, schnellere C-Lösungen zu präsentieren! Passieren
wird aber nix vermute ich.
Marvin M schrieb:> In Zeiten, in denen 32-Bitter inzwischen weniger kosten als 8-Bitter ist> es müßig, über die "bessere" Ausnutzung durch ASM zu reden.Markus schrieb:> Wozu einen alten AVR optimal ausnutzen wenn man für 1,10€ schon einen> STM32 haben kann?
In Zeiten, in denen 8-Bitter sehr viele Aufgaben einfacher lösen sind
noch lang nicht vorbei. Das kann einem durchaus sogar der eine oder
andere Cent mehr wert sein.
Markus schrieb:> Für dich vielleicht, es soll aber auch Leute geben die größeres vorhaben
Absolut einverstanden. Den Code des TO würde ich aber noch lange nicht
dazuzählen.
Christian F schrieb:> dass es ihm Spaß macht den alten dil Atmel in> der Lochrasterplatine
Lochrasterplatine?
Na dann wär ein großer Vorteil kleinster AVRs aber hinfällig: Die
Baugröße! So eine winzige Platine wie ein kleines
Beitrag "Kleines Tiny13 Sensorboard"
zum Beispiel.
Christian F schrieb:> Ich kann sogar Moby's Angst vorm Unbekannten und neuen Sachen in> gewisser Weise nachvollziehen.
Warum den Angst? Die Dinge für Projekte möglichst einfach zu halten ist
kühle rationale Abwägung. Diese sollen möglichst schnell, möglichst
simpel ihren Zweck erfüllen. Es braucht diesbezüglich kein
zeitvernichtendes Hinterherhecheln hinter den neuesten Technologien und
Programmiermethoden- da würde man ja nie fertig. Wenn das jemand als
Schwarz-Weiß Denken bezeichnet kann ich damit leben. Ich nenn es
Konzentration auf das Wesentliche.
Jörg W. schrieb:> Followup-To: de.alt.gruppenkasper
Das mache ein User hier mal mit einem Mod.
Der wird dann aber sowas von schnell zum Lösch-Mod und verweist auf
Forenregeln ;-)
Karl Käfer schrieb:> Er kann eben einfach nicht mehr als eine LEDs blinken lassen, zu mehr> reicht es bei ihm mit seinem geliebten Assembler nicht.
Nun ja, ein Karl Käfer kennt sich da eben aus.
Für Dich steht da allerdings auch noch eine Aufgabe an:
Dem SerialComInstruments wirklich Paroli zu bieten ;-)
...Und wenn dein Projekt ebenfalls in c problemlos auf dem Tiny
umzusetzen wäre?
Der code ist händisch so optimiert, dass jedes Bit gesetzt ist und kein
Platz mehr da ist? Ram ist voll? Dann wäre das Projekt fragwürdig: null
Chance auf Erweiterung bzw. nötige Fehlerbehebung ist nicht unbedingt
eine gute Basis.
Moby schrieb:> Gelegenheiten gab es schon, mit C gegenzuhalten...> Aber natürlich ist es das keinem Hochsprachler wert.> Könnte ja dumm ausgehen. Es wird von mir weiter Code in der> Projekte-Abteilung geben.
Vielleicht mal ein-zwei Links auf diese Projekte? (Vielleicht auch nicht
gerade die kleinsten)
Christian F schrieb:> Der code ist händisch so optimiert, dass jedes Bit gesetzt ist und kein> Platz mehr da ist? Ram ist voll? Dann wäre das Projekt fragwürdig: null> Chance auf Erweiterung bzw. nötige Fehlerbehebung ist nicht unbedingt> eine gute Basis.
In dieser Situation wäre dann aber nicht Asm fragwürdig, sondern
wirklich die Controller-Auswahl. Gewisse Reserven sollten schon vorrätig
sein. Bei Asm mehr, bei Hochsprache noch viel mehr...
Dumdi D. schrieb:> Vielleicht mal ein-zwei Links auf diese Projekte?
Ja, wie gesagt ich werde nicht untätig bleiben.
> Vielleicht auch nicht gerade die kleinsten
Natürlich nur kleine.
Oder meinst Du, daß größere die Chance erhöhen, daß sich ein C-ler die
Arbeit macht?
Wenn man wirklich den kleinsten Code haben will, dann sollte man einen
8051 verwenden. Der hat einen so kompakten Befehlssatz, da kann der AVR
lange nicht mithalten.
Moby schrieb:> In dieser Situation wäre dann aber nicht Asm fragwürdig, sondern> wirklich die Controller-Auswahl. Gewisse Reserven sollten schon vorrätig> sein. Bei Asm mehr, bei Hochsprache noch viel mehr...
Bei Hochsprache eher weniger. Basisfunktionen sind ja schon mit drin.
Und wie Du siehst, ist das C-Programm jetzt schon kleiner als das
Assembler-Programm.
> Dumdi D. schrieb:>> Vielleicht mal ein-zwei Links auf diese Projekte?>> Ja, wie gesagt ich werde nicht untätig bleiben.
Und, wo sind sie? Ach, noch gar nicht veröffentlicht? Warum hast Du den
Leser hier darüber so lange im Irrtum gelassen? Du hast es nämlich so
dargestellt, als ob Deine Projekte schon seit einer Ewigkeit unter
"Projekte & Code" zu finden seien.
Darf ich Dich in die Kategorie "Blender" stecken?
> Natürlich nur kleine.> Oder meinst Du, daß größere die Chance erhöhen, daß sich ein C-ler die> Arbeit macht?LED-Blinken ist natürlich in Assembler kürzer. Das Projekt sollte schon
anspruchsvoller sein. Dann wirst Du sehen, dass ein adäquates Programm
in C insgesamt kürzer sein kann als in Assembler, wo der Programmierer
wegen Übersichtsverlust gar nicht mehr weiter optimieren kann.
Ich finde die Aufgabe hat sehr schön die Vorteile von C aufgezeigt.
Das Switch/Case ist nicht nur deutlich besser lesbar, als ein Wust von
vielen fast gleichen Funktionen + ICALL, sondern erzeugt auch viel
weniger Code.
Was will man mehr?
Moby schrieb:> Die wenigen dutzend simplen Asm-Instruktionen bedeuten aber auch, man> braucht nicht mehr zu seinem Glück, es vereinfacht und macht die Sache> transparent.
Tatsächlich? Vergleiche z.B. mal Assembler einer CISC und einer RISC
CPU. Auf dem ersten Blick mag RISC einfacher und übersichtlicher sein,
wenn man dann aber mal ein bisschen Code schreibt, merkt man schnell
dass RISC den Code ganz schön aufbläst (die ständigen LOAD- und
STORE-Instruktionen zum Beispiel). Die Übersicht leidet zunehmend auch
darunter etc. . Also doch nur täuschende Einfachheit, die dann ins
Gegenteil umschlägt?
Peter D. schrieb:> Wenn man wirklich den kleinsten Code haben will, dann sollte man> einen> 8051 verwenden. Der hat einen so kompakten Befehlssatz, da kann der AVR> lange nicht mithalten.
Mag ja sein. Der AVR ist aber ein Gesamtpaket vorteilhafter
Eigenschaften. Die simple Asm-Programmierbarkeit ist da nur ein
Argument.
Daß man im übrigen an der schönen Kombination AVR/ASM für einfache bis
mittlere Projekte schon so lange festhalten kann ist einer einfachen
Tatsache geschuldet: Größere 32-Bit (ARM) Chips machen es heute eben
noch nicht viel anders, nur viel komplizierter...
Moby schrieb:> Größere 32-Bit (ARM) Chips machen es heute eben> noch nicht viel anders, nur viel komplizierter...
Andere Umschreibung für "Moby hat keine Ahnung". Du machst Dich gerade
zum Brot, lass das lieber.
TriHexagon schrieb:> Moby schrieb:>> Die wenigen dutzend simplen Asm-Instruktionen bedeuten aber auch, man>> braucht nicht mehr zu seinem Glück, es vereinfacht und macht die Sache>> transparent.>> Tatsächlich? Vergleiche z.B. mal Assembler einer CISC und einer RISC> CPU. Auf dem ersten Blick mag RISC einfacher und übersichtlicher sein,> wenn man dann aber mal ein bisschen Code schreibt, merkt man schnell> dass RISC den Code ganz schön aufbläst (die ständigen LOAD- und> STORE-Instruktionen zum Beispiel). Die Übersicht leidet zunehmend auch> darunter etc. . Also doch nur täuschende Einfachheit, die dann ins> Gegenteil umschlägt?
Ja ich kann das nachvollziehen da ich wie viele auch aus der Z80-CISC
Welt komme. RISC und CISC haben aber beide ihre Vor-und Nachteile.
Load-Store Operationen im Speziellen kann man bei AVR aber recht
speichersparend über die Index-Befehle abwickeln...
Die Übersicht tät ich bei vielen komplexen C-Ausdrücken verlieren;-)
Frank M. schrieb:> Moby schrieb:>> Größere 32-Bit (ARM) Chips machen es heute eben>> noch nicht viel anders, nur viel komplizierter...>> Andere Umschreibung für "Moby hat keine Ahnung". Du machst Dich gerade> zum Brot, lass das lieber.
Na was machen sie den groß anders? Lass mal Deine Ahnung sprechen.
Steckt da etwa mehr Intelligenz drin die mir tatsächlich Arbeit
abnimmt oder läuft es nicht doch viel mehr nur auf eine Potenzierung von
Konfigurationsarbeiten hinaus? Falls Du bestreiten möchtest daß diese
Chips komplexer zu programmieren sind können wir an dieser Stelle gleich
abbrechen...
Moby schrieb:> Na was machen sie den groß anders?
Allein schon die 32-Bit lassen viele Barrieren fallen, mit denen Du auf
einem 8-bittgem AVR zu kämpfen hast.
> Lass mal Deine Ahnung sprechen.
Nö, googlen kannst Du selber. Stell Dich nicht blöder an als Du bist.
> Steckt da etwa mehr Intelligenz drin die mir tatsächlich Arbeit> abnimmt oder läuft es nicht doch viel mehr nur auf eine Potenzierung von> Konfigurationsarbeiten hinaus?
Unter Assembler ist es natürlich ein erheblicher Aufwand, einen
STM32-Pin auf Output zu programmieren. Kein Wunder, dass Du diese Arbeit
scheust und Dich auf Deiner kleinen AVR-Insel verkriechst.
Wenn ich an Moby denke, denke ich immer an einen Einsiedler, der schon
vor zwanzig Jahren auf einer einsamen Insel zusammen mit einem ATTiny
gestrandet ist und seitdem die weitere Entwicklung komplett verschlafen
hat.
> Falls Du bestreiten möchtest daß diese> Chips komplexer zu programmieren sind können wir an dieser Stelle gleich> abbrechen...
Da ist überhaupt nichts "komplexer". Man hat nur etwas mehr
Schreibarbeit. Aber das macht Komplexität bestimmt überhaupt nicht aus!
Wie wärs mit der Portierung von IRMP und IRSND in Assembler?
Du hast die Wahl zwischen AVR (ATTiny, ATmega, Xmega), PIC, STM32 und
diversen anderen ARM-Prozessoren. Da läuft nämlich ein und derselbe
IRMP-C-Code drauf. Du musst ja nicht direkt auf alle portieren.
ATTiny würde reichen.
Oder ist die Aufgabe für Dich zu "komplex"?
Frank M. schrieb:> Da ist überhaupt nichts "komplexer". Man hat nur etwas mehr> Schreibarbeit. Aber das macht Komplexität bestimmt überhaupt nicht aus!
Schön, damit hast Du Deine Ahnung gerade nett demonstriert.
Du machst Dich gerade zum Brot, also lass das lieber.
Schade eigentlich, denn IRMP ist eine interessante Software, bei der
auch mal wirklich der C-Portiervorteil zum Tragen kommt.
Horst S. schrieb:> ISR_OT_73:> push r16> in r16, SREG> push r16> call WinkeWinke> pop r16> out SREG, r16> pop r16> ISR_OT_73_End:> reti
Sagt mal, was ist an diesem Codeschnipsel eigentlich lesbar (für nicht
AVRer), wartbar (für nicht Assemblerfreaks), oder gar portabel (was ja
per Definition nur bedeutet das ganze auf eine andere Plattform zu
übertragen zu können)?
X4U schrieb:> Sagt mal, was ist an diesem Codeschnipsel eigentlich lesbar
call WinkeWinke
> wartbar (für nicht Assemblerfreaks)
call WinkeWinke
> oder gar portabel
call WinkeWinke
Das wars aber auch schon.
>merkt man schnell>dass RISC den Code ganz schön aufbläst (die ständigen LOAD- und>STORE-Instruktionen zum Beispiel).
Meine Erfahrung sagt genau das Gegenteil. Während des Studiums hatte ich
mit einem SAB80C85 (oder so ähnlich) und einem Motorola-uC zu tun.
Da diese beiden CISC Vertreter nur einen Akku und paar Spezialregister
hatten, musste dauernd gePUSHd und gePOPd werden. Denn alle Operationen
(Addition, Prüfung auf irgendwas) konnten nur mit dem AKKU durchgeführt
werden.
Bei einem AVR dagegen, hat man (fast) 32 gleichwertige Register. Da kann
man Operationen von jedem Register zu jedem Register durchführen...
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.
Was gibt es demgegenüber für herrlich komplexe C-Ausdrücke!
Um da durchzublicken brauchts schon etwas mehr.
Aber vermutlich ist es gerade das, auf das sich hier mancher C-Freak was
einbildet?
Moby schrieb:> Hätte er.
Ich bin auch nur auf dieses eine Projekt gestoßen. Fand es aber nicht
erwähnenswert.
> Aber das wird er nicht wollen ;-)
Aber du willst das doch nicht so stehenlassen? Mach' doch einfach mal
eine Linkliste für die Unwissenden. Dürfte doch kein großer Aufwand
sein.
>Alles, wenn Du das Datenblatt und die paar Instruktionen kennst.>Klartext- und jeder weiß was gespielt wird.>Was gibt es demgegenüber für herrlich komplexe C-Ausdrücke!
[asm]
> ISR_OT_73:> push r16> in r16, SREG> push r16> call WinkeWinke> pop r16> out SREG, r16> pop r16> ISR_OT_73_End:> reti
[/asm]
vs:
Ralf G. schrieb:> Moby schrieb:>> Hätte er.> Ich bin auch nur auf dieses eine Projekt gestoßen. Fand es aber nicht> erwähnenswert.
Musst Du auch nicht. Um hier für Vergleiche herzuhalten ists ohnehin zu
klein. Die Erwähnung durch den Mod folgte wahrscheinlich einer ganz
anderen Absicht.
> Aber du willst das doch nicht so stehenlassen? Mach' doch einfach mal> eine Linkliste für die Unwissenden. Dürfte doch kein großer Aufwand> sein.
Schau mal, ich veröffentliche hier wann und genau das was mir passt
und das wird auch weiter geschehen. Der Aufwand ist ja leider auch
meine Sache. Das wird mich nicht davon abhalten, hier meine
Meinung zu äußern auch wenn mancher, um diese ernstzunehmen, erst große
Vorzeigeprojekte braucht. Die brauch ich aber -hier- nicht.
Matthias L. schrieb:> [asm]>> ISR_OT_73:>> push r16>> in r16, SREG>> push r16>> call WinkeWinke>> pop r16>> out SREG, r16>> pop r16>> ISR_OT_73_End:>> reti> [/asm]>> vs:> ISR_OT_73> {> WinkeWinke();> }
Na sonderlich komplex ist der C-Ausdruck nun aber nicht gelungen.
Und was versteckt sich eigentlich hinter der C-Funktion???
Insofern ist das ein Vergleich von Äpfeln mit Birnen.
Das würde ich zum Punkt Hochsprachen-Intransparenz rechnen!
Warum WUSSTE ich, dass das wieder mal so ausgeht? Der allwöchentliche
"Assembler ist supertoll" Thread.
Ich verweise nur auf den nach dem selben Schema ebenfalls aus dem Ruder
gelaufenen Beitrag "Re: C-Code optimieren (passt nicht in Attiny2313) :("Dumdi D. schrieb:> Vielleicht mal ein-zwei Links auf diese Projekte?> (Vielleicht auch nicht gerade die kleinsten)
Würde mich auch interessieren. Ich hatte da im
Beitrag "Re: C-Code optimieren (passt nicht in Attiny2313) :(" schon mal was
angeregt...
Horst S. schrieb:> Ich habe ein Programmchen für einen ATMega168 zuerst auf Assemblerbasis> erstellt und anschließend auf gcc portiert. Das funktioniert auch alles> (zumindest nicht schlechter als in Assembler), was mich aber zur Zeit> etwas die Augenbrauen hochziehen lässt:> Warum benötige ich im Assembler-Projekt "nur" 2910 Bytes, in C aber> "satte" 3278 Bytes?
Dieser klitzekleine(!) Mehrpreis ist das, was du dafür bezahlst, dass du
dein Programm auch in 1 Jahr noch verstehst, erweitern und warten
kannst.
Oder andersrum: passt es noch in den Controller? Ist es schnell genug?
Gut. Fertig. Du bekommst die mit Assembler "eingesparten" 300 Bytes
nicht ausgezahlt...
Moby schrieb:> Alles, wenn Du das Datenblatt und die paar Instruktionen kennst.> Klartext- und jeder weiß was gespielt wird.
Nachdem ich das ganze gelernt und diverse Datenblätter gewälzt habe sehe
ich das ein paar Daten von Register X nach Speicher Y verschoben werden.
Unter "Klartext" verstehe ich etwas ganz anderes.
> Was gibt es demgegenüber für herrlich komplexe C-Ausdrücke!> Um da durchzublicken brauchts schon etwas mehr.
Man kann sich in jeder Sprache (auch einer natürlichen) so Ausdrücken
das keiner was versteht ;-).
> Aber vermutlich ist es gerade das, auf das sich hier mancher C-Freak was> einbildet?
Mir ist das egal. Hab mit Assembler, Basic Html C Pascal Lisp usw.
gearbeitet.
Mich interessiert das Ergebnis (ganz schmerzfrei).
Der sieht so aus:
Die "C_Freaks" haben die Codegröße 10% unter die des Assemblers
gedrückt, bei ähnlicher Performance. Dazu haben Sie nur wenige Postings
gebraucht.Die Assembler-Freaks haben dem bisher nichts entgegen zu
setzen.
Moby schrieb:> Na sonderlich komplex ist der C-Ausdruck nun aber nicht gelungen.
Da staunst du jetzt, was? So einfach ist 'C'!
> Und was versteckt sich eigentlich hinter der C-Funktion???
Gegenfrage(n):
Was versteckt sich eigentlich hinter der gleichnamigen ASM-Funktion? Das
hast du gleich rausgefunden? Oder hast du die gar überlesen? ASM ist
wohl doch nicht so übersichtlich... ^^
Hans schrieb:> was ganz gerne auch was bringt, sind structs statt globale.>> Damit "erzwingt" man quasi indirekten zugriff und spart sich das 16-bit> pointer-laden hin und wieder.
Der AVR-GCC ist nicht blöd, ihm ist das schnurz.
Er erkennt, daß die Struct global liegt und nimmt trotzdem LDS/STS.
Ist zwar etwas mehr Code (2Wort-Befehle), dafür aber 2 Zyklen für das
Pointer laden gespart.
Zum indirekten Zugriff kannst Du ihn nur zwingen, indem Du den Pointer
übergibst und das Inlinen verbietest.
Matthias L. schrieb:> Meine Erfahrung sagt genau das Gegenteil. Während des Studiums hatte ich> mit einem SAB80C85 (oder so ähnlich) und einem Motorola-uC zu tun.> Da diese beiden CISC Vertreter nur einen Akku und paar Spezialregister> hatten, musste dauernd gePUSHd und gePOPd werden. Denn alle Operationen> (Addition, Prüfung auf irgendwas) konnten nur mit dem AKKU durchgeführt> werden.>> Bei einem AVR dagegen, hat man (fast) 32 gleichwertige Register. Da kann> man Operationen von jedem Register zu jedem Register durchführen...
Stimmt, aber moderne CISC haben heutzutage auch eine Menge Register. Die
paar Transistoren mehr sind heute einfach kein Problem. Beim x86_64
wurden zum Beispiel auch mehr Allzweckregister hinzugefügt.
Lothar M. schrieb:> Dieser klitzekleine(!) Mehrpreis ist das, was du dafür bezahlst, dass du> dein Programm auch in 1 Jahr noch verstehst, erweitern und warten> kannst.>> Oder andersrum: passt es noch in den Controller? Ist es schnell genug?> Gut. Fertig. Du bekommst die mit Assembler "eingesparten" 300 Bytes> nicht ausgezahlt...
Nein, bekomme ich nicht. Allerdings war der Thread im ersten Drittel
auch noch als sachlich zu betiteln (und ich hab was dabei gelernt).
Lothar M. schrieb:> Dieser klitzekleine(!) Mehrpreis ist das, was du dafür bezahlst, dass du> dein Programm auch in 1 Jahr noch verstehst, erweitern und warten> kannst.
Nö, Lothar, inzwischen ist doch sein C-Programm sogar kleiner als die
ursprüngliche Assembler-Version. Insofern war der Thread ja für Horst
durchaus nützlich.
Jörg W. schrieb:> Nö, Lothar, inzwischen ist doch sein C-Programm sogar kleiner als die> ursprüngliche Assembler-Version.
Ach Mann, das habe ich im ganzen Gebashe übersehen... :-/
Aber es ist doch prinzipiell so schon beeindruckend, dass auch ohne
die ganzen Kniffe, Interna und Tricks der Code vom Compiler so klein
ist. Ich ziehe meinen Hut (ich habe wirklich einen) vor den
Compilerbauern.
Horst S. schrieb:> Allerdings war der Thread im ersten Drittel auch noch als sachlich zu> betiteln
Das ist der übliche Verlauf eines üblichen "C vs. Assembler" Threads.
> (und ich hab was dabei gelernt).
Na bitte, darum gehts.
Lothar M. schrieb:> Ach Mann, das habe ich im ganzen Gebashe übersehen... :-/
Das ist schade, dass immer nur maximal der TE den Inhalt mitbekommt. Wer
zu spät einsteigt, sieht immer zuerst die aufgestellten Stinkefinger und
fängt lieber neu bei 0 an.
TriHexagon schrieb:> Vergleiche z.B. mal Assembler einer CISC und einer RISC> CPU. Auf dem ersten Blick mag RISC einfacher und übersichtlicher sein,
Die RISC Philosophie adressierte von Anfang an ausdrücklich die Nutzung
von Compilern, nicht Assembler-Programmierung. Adressierung ist oft
umständlicher, weil von der Distanz abhängig. Konstanten kann man
abhängig vom Wert auf verschiedene Art laden, usw. Das ist zwar auch für
den Compilerbauer zusätzlicher Aufwand - aber nur einmal.
TriHexagon schrieb:> Stimmt, aber moderne CISC haben heutzutage auch eine Menge Register. Die> paar Transistoren mehr sind heute einfach kein Problem.
Im Kontext der von dir genannten AMD/Intel Architekturen gibt es kaum
noch einen Zusammenhang zwischen der Anzahl sichtbarer Register und der
Anzahl real intern vorhandener Register. Intern haben heutige
Implementierungen dank renaming eine dreistellige Anzahl Register.
So art viele moderne CISCs gibt es allerdings nicht, was die
Befehlssatzarchitektur angeht. Die meisten, soweit es noch aktuelle
Implementierungen gibt, stammen im Kern aus den 70/80ern und wurden
allenfalls mal modernisiert wie x86 oder Coldfire.
Peter D. schrieb:> Zum indirekten Zugriff kannst Du ihn nur zwingen, indem Du den Pointer> übergibst und das Inlinen verbietest.
Meiner Erfahrung nach nimmt er mal LDS/STS und mal LD/ST R+. Eine
einfach nachvollziehbare Regel habe ich noch nicht gefunden. Und nicht
immer ist die Wahl optimal.
A. K. schrieb:> So art viele moderne CISCs gibt es allerdings nicht, was die> Befehlssatzarchitektur angeht. Die meisten, soweit es noch aktuelle> Implementierungen gibt, stammen im Kern aus den 70/80ern und wurden> allenfalls mal modernisiert wie x86 oder Coldfire.
Mein Gefühl sagt mir ohnehin, dass heutzutage kaum noch reine CISC und
RISC Prozessoren entwickelt werden. Das sind irgendwie alles Hybriden,
welche versuchen die Vorteile beider Welten zu vereinen.
TriHexagon schrieb:> Mein Gefühl sagt mir ohnehin, dass heutzutage kaum noch reine CISC und> RISC Prozessoren entwickelt werden.
Eine der neuesten mir bekannten Architekturen ohne Vorgänger ist
MaxQ2000. Die ist noch deutlich weiter reduziert als Load/Store-RISC,
weil es noch nicht einmal klare Lade/Speicherbefehle gibt.
> Das sind irgendwie alles Hybriden,> welche versuchen die Vorteile beider Welten zu vereinen.
Was die Befehlssatzarchitektur angeht, also das, was der Programmierer
sieht? Was wären da solche neueren Entwicklungen?
A. K. schrieb:>> Das sind irgendwie alles Hybriden,>> welche versuchen die Vorteile beider Welten zu vereinen.>> Was die Befehlssatzarchitektur angeht, also das, was der Programmierer> sieht? Was wären da solche neueren Entwicklungen?
Das habe ich falsch formuliert, ganz vergessen dass sich RISC und CISC
nur an die Befehlssatzarchitektur bezieht. An die RISC/CISC Architektur
hält man sich heute noch strikt.
Was ich meinte war, dass Eigenschaften die früher RISC/CISC vorbehalten
waren, heutzutage bei beiden Arten zu finden sind. Also z.B. hatten
früher nur die RISC Prozessoren viele Register, im Gegensatz waren
Pipelinening und Sprungvorhersage (evtl. auch Caching) den CISC
Prozessoren vorbehalten. Heute muss man sich nur mal den ARM Cortex-M4
oder noch besser den M7 anschauen, der hat so einiges eingebaut.
Wobei das größtenteils die logische Konsequenz aus dem Verkleinern von
Strukturen etc. ist. Aber warum hatten die CISC früher dann so wenig
Register? Die paar Flip-Flops machen neben den vielen anderen
Transistoren auch nicht mehr viel aus.
A. K. schrieb:> Peter D. schrieb:>> Zum indirekten Zugriff kannst Du ihn nur zwingen, indem Du den Pointer>> übergibst und das Inlinen verbietest.>> Meiner Erfahrung nach nimmt er mal LDS/STS und mal LD/ST R+. Eine> einfach nachvollziehbare Regel habe ich noch nicht gefunden. Und nicht> immer ist die Wahl optimal.
Wer ne Idee hat, wie das besser get, bitte vortreten und erklären :-)
Als Preis gibt's dann mindestens Lothars Hochachtung und die der avr-gcc
Nutzer :-)
TriHexagon schrieb:> Also z.B. hatten> früher nur die RISC Prozessoren viele Register,
Immerhin 16 Stück bei VAX und IBM 360.
> im Gegensatz waren> Pipelinening und Sprungvorhersage (evtl. auch Caching) den CISC> Prozessoren vorbehalten.
Nein.
2208!
UART rennt jetzt mit zwei dicken Switches, allerdings wird's durch die
eingestellte Baudrate auch nicht schneller.
Ich vergleiche morgen noch die Längen der ISR (wenn ich Muße hab).
TriHexagon schrieb:> Aber warum hatten die CISC früher dann so wenig> Register?
In der Anfangsphase der 8-Bitter war die Anzahl Transistoren nicht ganz
so unerheblich. Der 6502 hatte grad mal 3500 Transistoren. Ausserdem war
der Prozessor damals nicht wesentlich schneller als der Speicher. Als
sich das änderte kamen Register auf.
> Die paar Flip-Flops machen neben den vielen anderen> Transistoren auch nicht mehr viel aus.
Die 256 Bits der 16 16-Bit-Register des RCA 1802 machen einen nicht
unerheblichen Teil des Dies aus. Ein statisches CMOS Flipflop hat 6-8
Transistoren.
http://www.visual6502.org/images/1802E/RCA_1802E_die_20x_top_p067152_1600w.jpg
@A. K. danke für die ganzen Hintergrundinformationen. Ich bin wohl etwas
zu jung um sowas zu wissen.
Wow gerade mal 3500 Transistoren, es hat sich einiges getan in der Zeit.
Rolf M. schrieb:> Ich warte ja immer> noch auf seine FAT-Implementation oder den TCP/IP-Stack in Assembler.
Oh ja, bitte Moby!
Ich verspreche, dass ich mir dann auch die Mühe mache und das ganze für
den gcc nutzbar zu machen, damit dann alle etwas von einer kleinen,
weitgehend fehlerfreien Implementierung haben, die dann auch noch keinen
einzigen Taktzyklus und kein einziges Byte im Flash herschenkt.
Das heisst: nachdem natürlich gegen einen der weiter verbreiteten
C-Versionen geprüft wurde, ob dem auch wirklich so ist.
Alles was ich von Moby's ASM-Künsten in den Projekten finden konnte,
sine 33 Maschinenbefehle, die irgendwie den ADC benutzen. Was sie genau
tun ist leider nicht dokumentiert, es scheint auch nur ein Fragment zu
sein und ich vermute in C wäre das sowas wie:
ADC_init() und ADC_read() wobei letzteres wohl in einem TimerInt
aufgerufen werden sollte. Zur Doku würden auch die benutzten Register
gehören, denn ein Sicher von solchen ist nicht Bestandteil der "Lib".
In dem Thread geht es übrigens hauptsächlich um einen
Meßbereicheumsetzer LM335 an 5V AVR-ADC. "Elektronische" verhält sich M.
dabei genau so wie "programmatisch".
Was jetzt noch zum aufhübschen fehlt:
- Vielleicht mal ein paar Konstanten für Baudrate,...
- Ich hab's noch nicht so ganz durchschaut: Bringt es etwas, wenn ich
aus einer Modulvariable eine statische Variable in der Funktion mache?
(Bis auf den Scope)
- Das mit der Zusammenfassung der Variablen zur Struktur wollte ich noch
ausprobieren.
Hmm, wenn ich mir jetzt den zeitlichen Verlauf meiner Code-Sparaktion
als Kurve weiter interpoliere, müsst ich doch in 4 oder 5 Tagen den
Speicher restlos von Code befreit haben. Ob das Programm dann wohl noch
läuft?
>müsst ich doch in 4 oder 5 Tagen den Speicher restlos von Code befreit >haben.
Wenn das so ist/wäre, hättest du durch >5Tage Arbeit jetzt den uC
eingespart. Also >5Tage Arbeit für (wieviel?) 10Euro oder weniger?
Wenn der Materialpreis des uC natürlich (drastisch) höher als dein
Gehalt für die Zeit ist, lohnt sich das ja auch ;-)
Falsch gerechnet! Er hat gelernt, wie er auch ohne ASM ans Ziel kommt,
was sich schon bei wenigen switch/case Optimierung, die der Compiler in
ms macht, auszahlt.
Horst S. schrieb:> 2032!> Die 2k-Grenze hab' ich geknackt.
Nur Pech für dich, dass es in der Serie keinen kleineren Controller
als einen ATmega48 gibt. :-)
> UARTTelegramV3.c
Bitte lieber als Anhang posten.
> - Vielleicht mal ein paar Konstanten für Baudrate,...> - Ich hab's noch nicht so ganz durchschaut: Bringt es etwas, wenn ich> aus einer Modulvariable eine statische Variable in der Funktion mache?> (Bis auf den Scope)
Nur den Scope, du kannst dir also sicher sein, dass die Daten niemand
von außen manipulieren kann.
Matthias L. schrieb:> Wenn der Materialpreis des uC natürlich (drastisch) höher als dein> Gehalt für die Zeit ist, lohnt sich das ja auch ;-)
Sorry, wenn ich das rechne, bekomme ich eine Nulldivision. Für's Proggen
zahl ich mir nix.
Jörg W. schrieb:> Bitte lieber als Anhang posten.Jörg W. schrieb:> Nur den Scope, du kannst dir also sicher sein, dass die Daten niemand> von außen manipulieren kann.
Werd's mir merken.
@Horst
welche Compileroptionen verwendest du?
Bei Projekten mit vielen Dateien hilft "-Os -flto -fuse-linker-plugin"
viel. Das muss in die CFLAGS und LDFLAGS. Ist erst ab gcc-4.9 wirklich
sinnvoll.
Hallo Moby,
Moby schrieb:> Für Dich steht da allerdings auch noch eine Aufgabe an:> Dem SerialComInstruments wirklich Paroli zu bieten ;-)
Lesen lernen: das hab' ich schon.
Liebe Grüße,
Karl
Lothar M. schrieb:> Horst S. schrieb:>> Warum benötige ich im Assembler-Projekt "nur" 2910 Bytes, in C aber>> "satte" 3278 Bytes?> Dieser klitzekleine(!) Mehrpreis ist das, was du dafür bezahlst, dass du> dein Programm auch in 1 Jahr noch verstehst, erweitern und warten> kannst.
Äh, Lothar (fast hätte ich Löthar geschrieben, das hätte aber wohl eher
in "Platinen" gepaßt ;-)), wir sind hier schon weiter. Mit ein paar
wenigen Handgriffen ist das C-Kompilat mittlerweise über 13% kleiner als
der von Horst gepostete Assembler-Code, und Horst hat in dankenswerter
Offenheit eingestanden, daß er selbst wohl nie auf die Optimierungen
gekommen wäre, die der C-Compiler vorgenommen hat. Deshalb sind Mobys
"Beiträge" diesmal noch lächerlicher und absurder als sonst. ;-)
Liebe Grüße,
Karl
avion23 schrieb:> Bei Projekten mit vielen Dateien hilft "-Os -flto -fuse-linker-plugin"> viel. Das muss in die CFLAGS und LDFLAGS. Ist erst ab gcc-4.9 wirklich> sinnvoll.
"-Os -flto" läuft auch schon in 4.7.2 sehr gut und spart jede Menge ein.
C hat den Charme, man kann sich voll auf den Algorithmus konzentrieren
und muß sich nicht durch LD,ST,PUSH,POP und weiteren Ballast unnötig
ablenken lassen.
Ich kenn das auch noch aus meiner Assemblerzeit, man war heilfroh,
überhaupt eine funktionierende Lösung gefunden zu haben und hatte wenig
Lust daran noch weiter zu feilen. Und man dachte, die CPU ackert zu 99%,
kann also nichts anderes mehr machen.
Aber später unter C nen anderen Algorithmus probiert und schwups waren
es nur noch 10% Auslastung. Und dann überlegt man, was mache ich bloß
für andere Tasks mit hinein, daß die CPU wieder gut zu tun hat?
Hallo Moby,
Moby schrieb:> Karl Käfer schrieb:>> Lesen lernen: das hab' ich schon.>> Verstehen lernen: Simpel geht anders.lol Für Könner ist das trivial. Kinder, Hausfrauen und Vorstände
können das natürlich nicht verstehen.
> Aber ich weiß ja, das kannst Du nicht ;-)
Solange es reicht, um Dich zu überfordern, ... :-)
Liebe Grüße,
Karl
Karl Käfer schrieb:>> Aber ich weiß ja, das kannst Du nicht ;-)>> Solange es reicht, um Dich zu überfordern, ... :-)
Könntet ihr diese Art von Plänkeleien bitte auf private Emails
verlagern? Danke.
Ich verstehe das ganze Geschreibe hier wieder einmal nicht so ganz. Es
geht wieder lediglich um diese Nerd typischen Kompetenz- und
Selbstdarstellungsspielchen . Jedem der halbwegs was vom Programmieren
versteht und mal einen Schritt zurück tritt und einen objektiven Blick
auf das ganze wirft, wird anerkennen müssen das natürlich Assembler
wenn's von einem programmiert wird der es kann den kompaktesten und
performensten Code erzeugen wird. Im Falle eines idealen Compilers -den
gibt es aber nicht- ist der Maschinencode gleich schnell und gleich
groß, aber niemals größer oder langsamer als der Compilercode. Nicht
einmal theoretisch ist das möglich. Klar das man in der Realität
komplexe Anwendungen nicht zur Gänze in Assembler schreiben wird, es sei
man hat zu viel Zeit oder ist Masochist. Meine persönliche Strategie mit
der ich bisher immer gut gefahren bin bezüglich Performance und Codesize
ist es C/C++ mit Assembler zu kombinieren. So habe ich im Laufe der Zeit
viele Funktionen aus der Standard Lib des GCC durch eigene, in Assembler
programmierte ersetzt. ISR's oder Funktionen zur direkten
HW-kommunikation mit Peripheriebausteinen werden ebenfalls in Ass
geschrieben. Jegliche Ablaufsteuerung geht in der Hochsprache auf. Für
mich ist es dass beste Konzept und erleichtert zudem in den meist
kritischen Bereichen des Programms das Debuggen ungemein. Ich werde dies
auch so weiter machen. Selbst nach dem umstieg auf IAR gibt es
Optimierungsmöglichkeiten an der Arbeit des Compilers.
Thomas H. schrieb:> Jedem der halbwegs was vom Programmieren> versteht und mal einen Schritt zurück tritt und einen objektiven Blick> auf das ganze wirft, wird anerkennen müssen das natürlich Assembler> wenn's von einem programmiert wird der es kann den kompaktesten und> performensten Code erzeugen wird.
Das habe ich auch mal gedacht, würde es aber inzwischen bestreiten.
Außer der Programmierer ist wirklich bereit unwartbaren Code zu
schreiben. Dazu sollte ein ernsthafter ASM-Programmierer aber nicht
bereit sein. Und selbst wenn behaupte ich auch mal gibt es nicht so
viele Programmierer die mit einem modernen Compiler mithalten können
(vielleicht gibt es sogar keinen?)
Dumdi D. schrieb:> Das habe ich auch mal gedacht, würde es aber inzwischen bestreiten.
Meine Betrachtung war technisch theoretisch. Daran gibts nichts zu
bestreiten. Ein Compiler ordnet und kombiniert letzten Endes
Assemblermakros. Die mal von einem Assemblerprogrammierer erstellt
wurden. Er kann also niemals kleinern Code ausspucken als ein
Assembler-Programmierer. Das keiner der noch alle Latten im Zaun hat
komplexe Programme zur Gänze händisch ohne das Hilfsmittel Compiler in
Assembler schreibt habe ich auch mehr als deutlich zum Ausdruck
gebracht.
Thomas H. schrieb:> Er kann also niemals kleinern Code ausspucken als ein> Assembler-Programmierer.
Sollte man etwas anders formulieren: Er kann also niemals kleinern Code
ausspucken als die weltbesten Assembler-Programmierer.
Bereiche in denen ASM die Nase vorn hat sind meiner Meinung nach bei
Instructions für die es in C so kein Ersatz gibt. Zum Beispiel Add with
Carry. In C kann man zwar auch rauskriegen ob eine Addition ein Carry
produziert und dann später auf die höherwertigen Bytes draufaddieren.
Ich habe es ehrlich gesagt noch nicht ausprobiert aber mich würde es
wundern wenn der Compiler das durchschaut und merkt, dass das ganze Zeug
eigentlich nur eine Instruction ist. Andere Beispiele sind
Multiplikationen bei denen man aus zwei n-Bit ints ein 2n-Bit Ergebnis
kriegt und Divisionen wo man den Rest auch gleich dazu kriegt. Für sowas
gibts immerhin Intrinsics die ich immer dann benutze wenns richtig
schnell werden muss (nicht AVR bezogen, sondern auf dem PC). Die
Autovectorizer von Compilern funktionieren auch nicht wirklich
zufriedenstellend. Da kann man auch besser direkt die SIMD Intrinsics
hinschreiben die man braucht.
Thomas H. schrieb:> Er kann also niemals kleinern Code ausspucken als ein> Assembler-Programmierer.
Das ist natürlich richtig. Aber es gibt Code, der sich mit vertretbarem
Aufwand nur automatisch erzeugen lässt.
Ich hatte oben einen binären Suchbaum aus Vergleichen erwähnt, als
Implementierung von switch. Sinngemässer als rekursiver Generator:
1
vergleiche X mit A
2
goto L1 wenn grösser
3
goto case(A) wenn gleich
4
betrachte auf die gleiche Weise alle Fälle von X < A
5
L1: betrachte auf die gleiche Weise alle Fälle von X > A
Nun ist so ein Code zwar länger als der kürzestmögliche, passt also
nicht exakt zum Thread, aber er ist bei zufällig verteilten switch-Daten
der schnellste Code für eine nichttriviale Anzahl Fälle, in denen eine
Sprungtabelle nicht einsetzbar ist.
Für einen Assembler-Programmierer ist das ein mittlerer Alptraum, denn
dazu müssen die Werte sortiert werden und ein Wert aus der Mitte des
jeweiligen Intervalls rausgepickt werden. Das ist hässlich viel Arbeit
und die fällt mit jeder Änderung der zu unterscheidenden Fälle
vollständig neu an.
Wenn man dann noch die Kosten von Sprungbefehlen und Sprungvorhersage
einfliessen lassen muss, um bestimmte Arten von Sprüngen zu bevorzugen,
dann ist die schon die Entscheidung arg schwierig, ob dieses Verfahren
sinnvoll ist oder nicht.
Addiere dann noch Profiling hinzu, also die Optimierung anhand von
Testläufen mit daraus resultierender realer Datenverteilung, und aus dem
mittleren Alptraum wird ein schwerer.
Es mag Makroassembler geben, mit denen dieser rekursive Ansatz eines
Vergleichsbaums prinzipiell implementierbar ist, aber mit klassischer
Assembler-Programmierung hat das dann nur noch wenig zu tun.
Ein weiteres Beispiel für Code, der einem Assembler-Programmierer
deutlich Kopfzerbrechen bereitet, ist Optimierung der Abhängigkeiten bei
Prozessoren mit ausgeprägtem Pipelining. Also wenn man drauf achten
sollte, dass je nach Art der Operation eine vom Ergebnis abhängige
Folgeoperation eine Mindestanzahl von Takten entfernt sein sollte.
Das ist sowieso schon nicht trivial und wird dadurch nicht besser, dass
jede neue Generation der Implementierung des Befehlssatzes neue Regeln
für eine solche und ähnliche Optimierung bringt. Da kann der gleiche
Code vorher wunderbar effizient sein, nur um dann aufgrund einer
bestimmten Eigenschaft der Implementierung des Cores bös auf die Nase zu
fallen (z.B. INC/DEC Befehle beim Pentium 4 gegenüber Pentium III).
Mit einem Compiler braucht man den Code bloss für den neuen Core neu
übersetzen.
Das ist zwar bei heutigen vollintegrierten Mikrocontrollern à la Cortex
Mx noch kaum relevant, aber warten wir mal ein paar Jährchen...
Thomas H. schrieb:
> Er kann also niemals kleinern Code ausspucken als ein> Assembler-Programmierer.
Das ist falsch!
Richtig wäre "als der ideale Code". Aber dazu braucht man für
nichttriviale Probleme den einen allerbesten Programmierer. Die Frage
ist eher, wieviel Prozent der ASM-Programmierer bekommen das besser hin,
als der Compiler, und in einem konkreten Fall, ist man selbst unter
diesen. Besonders in zweiten Punkt kann man sich massiv verschätzen.
Nichts spricht natürlich dagegen, die ISR, die nur ein GPOIR0-Bit
setzen soll, in (Inline-)Assembler hinzuschreiben. Wenn man sicher ist,
daß man da nichts mehr dran bauen will/muß.
Carl D. schrieb:>> Er kann also niemals kleinern Code ausspucken als ein>> Assembler-Programmierer.>> Das ist falsch!
Was ein Compiler erzeugen kann, das kann rein theoretisch betrachtet
auch ein Assembler-Programmierer erzeugen. Dem Prinzip nach.
Nur kann es sein, dass dafür der frisch von der Ausbildung weg
eingestelle Assembler-Programmierer vor Beendigung seiner Arbeit in
Rente geht. ;-)
Soll heissen: Was theoretisch zutrifft kann praktisch falsch sein, weil
nicht realistisch machbar.
A. K. schrieb:> Das ist natürlich richtig. Aber es gibt Code, der sich mit vertretbarem> Aufwand nur automatisch erzeugen lässt.
Na immerhin gibt es zumindest einen der es verstanden hat.
Wenn ich theoretisch Assembler mit C oder einer anderen Hochsprache
vergleiche, dann habe ich dabei keinen komplexen Algorithmus im Kopf
oder gar eine Komplexe Applikation, sondern ein einfaches Codesegment.
Das reicht mir aus um eine Aussage über den Vergleich Assembler vs
Compiler machen zu können. Denn komplexes Programm ist nichts anderes
als eine Aneinanderreihung einfacher codesegmente und letzen Endes
einfacher Instruktionen . Der Compiler macht nichts anderes als den
komplexen Code in einfache Teilaufgaben zu zerlegen. Um die Aussage zu
tätigen das dies theoretisch von einem Assemblerprogrammierer mit
gleichem oder im Falle aller real existierenden Compiler besser erledigt
werden könnte reicht der Vergleich einer so simplen Codesequenz. Weder
habe ich eine Aussage über die Zeit die der Programmierer dazu hat
gemacht noch über die Anzahl der Assemblerprogrammierer auf die Aufgabe
verteilt werden könnte. Auch habe ich klar -und ich sage es zum zweiten
male- zum Ausdruck gebracht das man in der Realität keine Komplexen
Aufgaben nur in Assembler lösen wird.
Carl D. schrieb:> Nichts spricht natürlich dagegen, die ISR, die nur ein GPOIR0-Bit> setzen soll, in (Inline-)Assembler hinzuschreiben. Wenn man sicher ist,> daß man da nichts mehr dran bauen will/muß.
Ich habe nach 36J Assemblerprogramierung schon die eine oder andere ISR
erstellt, die ein wenig mehr macht als lediglich einen Portbit zu
bedienen. Wer allerdings float Berechnungen oder anderen Aufgaben in
einer ISR erledigt von denen er denkt das ginge nur in einer
Hochsprache, der hat eh etwas essentielles nicht verstanden. Auch bin
ich in der Lage später noch etwas an meinem Code zu modifizieren. Von
inline Assembler wie er in GCC zelebriert wird lasse ich prinzipiell die
Finger.
Carl D. schrieb:> Und wir wollten ja mit dem Code fertig sein, bevor Atmel die> AVR-Vertigung einstellt, oder? ;-)
Ob Du weißt, welche Codemassen in Asm für AVR schon existieren? Warum
wohl? Und daß die 8-Bitter jemals obsolet werden wird wohl keiner hier
mehr erleben ;-)
A. K. schrieb:> Was ein Compiler erzeugen kann, das kann rein theoretisch betrachtet> auch ein Assembler-Programmierer erzeugen.
Genau das will er aber gar nicht.
Sondern es selbst in der Hand haben.
Mit all den vielen Vorteilen, die damit einhergehen.
Was den erhöhten Zeitbedarf anbetrifft machen sich viele hier falsche
Vorstellungen.
Der erste Trick ist, bei einer vielseitigen,
/hinreichend/leistungsstarken, typenreichen Architektur zu bleiben. Die
man dann gut kennt. Der zweite, sich universell einsetzbare Programm- &
Peripherie-Codebausteine und eine grundlegende immergleiche
Programmstruktur zuzulegen. Dann ist der Rest nicht viel mehr als
sinnvolle Verknüpfung.
Sicher gibt es programmierer- und projektabhängig irgendwo eine
sinnvolle Grenze, die höhere Sprachen erforderlich macht. Die sehe ich
bei den kleinen AVR Maschinen aber weit weit weg.
Durch Assembler beim assemblerfreundlichen AVR bleiben können- so wird
ein Schuh draus. Hochsprachenverwendung ist einer der wichtigsten
Treiber für permanente Controller-, Architektur- und Programmiermittel-
Wechsel.
Moby schrieb:> Genau das will er aber gar nicht.> Sondern es selbst in der Hand haben.
Du möchtest vielleicht alles selbst in der Hand haben. Das ist okay,
genauso wie Leute nur an einem Esstisch sitzen wollen, den sie höchst
persönlich mit dem Taschenmesser aus einem Baumstamm geschnitzt haben.
Professionelle Entwickler programmieren Lösungsorientiert. Da steht dann
sowohl Performance als auch Codegröße hinter effizienter, fehlerfreier
und langfristig wartbarer Entwicklung weit zurück.
Moby schrieb:> Der zweite, sich universell einsetzbare Programm- &> Peripherie-Codebausteine und eine grundlegende immergleiche> Programmstruktur zuzulegen. Dann ist der Rest nicht viel mehr als> sinnvolle Verknüpfung.
Oder man nimmt sich einen Compiler mit Standard Bibliotheken, der genau
das tut (Programm - und Codebausteine kombinieren und zu optimieren),
nur auf Basis der Erfahrung tausender Hochkarätiger Compilerentwickler.
Im übrigen widerspricht das deiner Forderung danach alles perfekt zu
optimieren. Das sah man dann deinem Tastenentprellen-Blinky Beispiel das
du vor einiger Zeit gepostet hast. Obwohl noch massig Register frei
waren, hat dein Programm völlig unnötig RAM genutzt. Eben weil du statt
komplett handoptimierten Assembler, fertige - selbstgeschriebene - Bibs
verwendet hast.
> Kompliment.> Das möchte ich auch noch erreichen.> Die Hälfte hab ich schon ;-)
ich denke ich mach mit dem GCC und meinen 6 Jahren C kleineren und
wartbareren Code als Du mit deinen 18 Jahren ASM ;)
#MalWiederHolzAuflegen
scelumbro schrieb:> Professionelle Entwickler programmieren Lösungsorientiert.
Ach?
Ich sollte meine vielen funktionierenden Ergebnisse nochmal danach
bewerten, ob es sich wirklich um Lösungen handelt ;-)
> nur auf Basis der Erfahrung tausender Hochkarätiger Compilerentwickler.
Die ist ja toll und die braucht es sicherlich auch- nur nicht bei den
simplen AVRs.
> Im übrigen widerspricht das deiner Forderung danach alles perfekt zu> optimieren.
Von Perfektion rede selbst ich nicht.
> Obwohl noch massig Register frei> waren, hat dein Programm völlig unnötig RAM genutzt.
Ob dahinter auch eine Absicht gesteckt haben könnte? Das war nämlich
eines von vielen kombinierbaren Modulen. Wenn da jedes eigene Register
beanspruchen würde... Hilfe! Nein, da hast Du nur das System nicht
verstanden...
Sich allein auf Register zu beschränken kann man bei ganz kleinen Sachen
machen bei denen sich absehen lässt, daß sie nicht mehr erweitert
werden.
Ingo schrieb:> wartbareren Code
Bildet Euch doch darauf nicht zuviel ein.
Alles eine Frage des Systems, der Doku und eben der Programmiersprache:
Asm als Klartext ist selbsterklärend.
Hallo Thomas,
Thomas H. schrieb:> Jedem der halbwegs was vom Programmieren> versteht und mal einen Schritt zurück tritt und einen objektiven Blick> auf das ganze wirft, wird anerkennen müssen das natürlich Assembler> wenn's von einem programmiert wird der es kann den kompaktesten und> performensten Code erzeugen wird. Im Falle eines idealen Compilers -den> gibt es aber nicht- ist der Maschinencode gleich schnell und gleich> groß, aber niemals größer oder langsamer als der Compilercode.
Dein Ansatz geht davon aus, daß es perfekte Assembler-Programmierer
gibt, solche also, die perfekten Code schreiben können. Das gibt es
tatsächlich aber nur bei den allertrivialsten Programmen.
Mit zunehmender Funktionalität, mithin Größe des Codes, wird die Sache
aber immer schwieriger. Irgendwann sind die Grenzen des menschlichen
Fassungsvermögens erreicht, auch des besten Programmierers aller Zeiten.
Spätestens da schlägt dann die Stunde der Compiler, die zwar weniger
kreativ sein mögen als ein menschlicher Programmierer und Optimierer,
die dafür aber ein schier unerschöpfliches Fassungsvermögen haben.
Der Punkt, auf den ich hinauswill, ist: im realen Leben gibt es leider
keinen perfekten Programmierer, und von daher ist die Annahme, daß ein
perfekter Programmierer den perfekten Code schreiben könnte, letztlich
schlicht unrealistisch. Wenn Du von dieser Prämisse ausgehen wolltest,
müßtest Du einen perfekten Programmierer mit einem perfekten Compiler
vergleichen, und am Ende würden beide genau denselben perfekten Code
hervorbringen.
Wenn man also etwas vom Programmieren versteht, einen Schitt zurück
tritt und einen objektiven Blick auf das Ganze werfen will, dann kommt
man nicht an der Erkenntnis vorbei, daß es so etwas wie perfekte
Programmierer oder perfekte Compiler in der realen Welt nicht gibt. Das
bedeutet, daß wir uns mit unseren eigenen Unzulänglichkeiten als
Menschen und auch mit jenen der Maschinen arrangieren müssen, und daß es
nunmal Tätigkeiten gibt, die eine Maschine besser, schneller und
fehlerärmer erledigen kann als wir. Sonst würden wir ja gar keine
Maschinen bauen und benutzen, oder?
Daher gilt für Compiler, daß sie auch bei nichttrivialen Programmen
immer noch alle Variablen und Verzweigungen quasi "im Kopf" behalten
können, wo unser Verstand schon längst mit einem Pufferüberlauf
ausgestiegen ist, so daß ein Compiler mit zunehmender Komplexität des
Programms immer bessere Ergebnisse erzielt als ein noch so guter
Programmierer.
Deswegen haben die Hochsprachen heute längst gewonnen, überall. Bei den
Atmel AVRs wurde sogar das Hardware-Design eigens für die Benutzung mit
Hochsprachen ausgelegt, so daß es etwas anachronistisch und ewiggestrig
erscheint, ausgerechnet diese Mikrocontroller vollständig mit Assembler
programmieren zu wollen. Die Daseinsberechtigung von Assembler auf AVRs
erschöpft sich daher heute in nur zwei Anwendungsfällen: für besonders
zeitkritische Programmteile, die mit in C eingebettetem Assembler-Code
eine bessere Kontrolle über das Timing ermöglichen, sowie zweitens als
Zwischenschritt der Kompilierung einer Hochsprache.
Liebe Grüße,
Karl
PS: Lieber Jörg, ich werde zu gerne darauf verzichten, Nickeligkeiten
mit diesem "Herrn" auszutauschen, sowohl hier, als auch per E-Mail. Ich
würde mich aber freuen, wenn ich nicht ständig grundlos von ihm
provoziert und beim ersten Gegenhalten meinerseits zurechtgewiesen
würde. Immerhin gibt es da ja so etwas wie Ursache und Wirkung. Nix für
ungut, danke.
Thomas H. schrieb:> Jedem der halbwegs was vom Programmieren versteht und mal> einen Schritt zurück tritt und einen objektiven Blick auf das> ganze wirft, wird anerkennen müssen das natürlich Assembler> wenn's von einem programmiert wird der es kann den kompaktesten> und performensten Code erzeugen wird.
Nicht selten ist das dann so wie mit physikalischen Theorien; zu einer
solchen meinte Hawking mal:
"That's nice. Too bad it's wrong".
Auf kiki Architekturen wir AVR ist es noch mehr oder weniger trivial,
effizienten und korrekten Assembler zu schreiben.
Aber auf einer multiskalaren Maschine mit 20-schrittigen Pipelines,
Caches, Prefetch-Buffers, oder netten "Features" wie exposed Pipeline,
Out-of-Order Execution etc.
Selbt ohne all diese Nettigkeiten ist die beste Codesequenz nicht
naheliegend. Instruktives Beispiel: Laden eines Immediate auf ARM:
Für den Fall, dass die Konstante besser direkt geladen wird (anstatt sie
in einem const-Pool abzulegen u vo ndort zu lagen) verwenden GCC über
1000 Zeilen seiner Quellen. Ich würd mal sagen, dass ein
Asm-Programmiere nicht ad hoc die beste Sequenz findet.
Übel wird es auch, wenn neue Konstanten zum const-Pool hinzugefügt
werden und Sprungbefehle eingefügt werden müssen um den Pool zu
umspringen. In Asm tut sich das doch niemand an, oder?
unbelegt und falsch schrieb:> Moby schrieb: Asm als Klartext ist selbsterklärend.>> Schon mal in das Programm eines anderen Programmieres gelinst?> Klingt nicht so.
Ja muß man das nun auch noch erklären?
Steht mit Asm nicht etwa genau das auf dem Papier was passiert? Eine
kurzer Kommentar zur Funktion noch und gut ist!
Zum Verständnis gehört im Falle des Falles aber immer das Datenblatt.
Was auch C-Programmierern keinesfalls schadet!
Moby schrieb:> scelumbro schrieb:>> Obwohl noch massig Register frei>> waren, hat dein Programm völlig unnötig RAM genutzt.>> Ob dahinter auch eine Absicht gesteckt haben könnte? Das war nämlich> eines von vielen kombinierbaren Modulen. Wenn da jedes eigene Register> beanspruchen würde... Hilfe! Nein, da hast Du nur das System nicht> verstanden...> Sich allein auf Register zu beschränken kann man bei ganz kleinen Sachen> machen bei denen sich absehen lässt, daß sie nicht mehr erweitert> werden.
Ich habe dein System sehr wohl verstanden. Dein genialer selbst
Entwickelter Ansatz ist der Hochsprachenwelt seit Jahrzehnten bekannt.
Es kommt ja auch kein C Programmierer auf die Idee, printf & Co selbst
zu implementieren.
Aber einerseits redest du andauernd vom Compiler bloat, andererseits
erzeugst du - auf dieses konkrete Projekt bezogen - ganz eindeutig
unnötigen Code Bloat mit der Verwendung eines handgebauten aber nicht
projektoptimierten Moduls. Ist Compiler generierter Bloat schlechter als
handgenerierter Bloat? Schau dir auch bitte mal die Geschichte der C
Compiler an, vielleicht wird dir dann klar das du ein uraltes Rad neu
erfindest - und dann auch noch viereckig.
Johann L. schrieb:> Auf kiki Architekturen wir AVR ist es noch mehr oder weniger trivial,> effizienten und korrekten Assembler zu schreiben.
Na also. Genauso ist es.
Und das Schönste: Mit kiki läßt sich immer noch jede Menge anstellen.
Und zwar kiki im Vergleich zu hochgezüchteten C auf ARM Lösungen...
scelumbro schrieb:> Moby schrieb:> scelumbro schrieb:> ganz eindeutig> unnötigen Code Bloat mit der Verwendung eines handgebauten aber nicht> projektoptimierten Moduls.
Na mein Eindruck ist ganz eindeutig,daß Du das System eben nicht
verstanden hast und auch nicht vorhast, es zu verstehen.
> vielleicht wird dir dann klar das du ein uraltes Rad neu> erfindest - und dann auch noch viereckig.
Auf das System als solches erhebe ich weißgott keine Urheberansprüche.
Ich weiß aber, daß es auf diese Weise recht schnell rund läuft und eben
nicht viereckig ;-)
Moby schrieb:> Na mein Eindruck ist ganz eindeutig,daß Du das System eben nicht> verstanden hast und auch nicht vorhast, es zu verstehen.
Erleuchte mich und die anderen Jünger des großen Compilers doch bitte.
scelumbro schrieb:> Erleuchte mich und die anderen Jünger des großen Compilers doch bitte.
Lies einfach noch mal meine Erklärung weiter oben warum ich im konkreten
Fall das heilige RAM anzapfe.
Und meinst Du wirklich, ich hätte den Anspruch zu "erleuchten" ?
Es kann ja sein daß Simplizität und Effizienz von Asm nicht in die
heutige Zeit passt wo es heisst: Komplex ist cool und macht Eindruck.
Trotzdem gebe ich meine Erfahrungen weiter, und die stehen unter der
Maxime: Keep it simple!
Karl Käfer schrieb:> Daher gilt für Compiler, daß sie auch bei nichttrivialen Programmen> immer noch alle Variablen und Verzweigungen quasi "im Kopf" behalten> können, wo unser Verstand schon längst mit einem Pufferüberlauf> ausgestiegen ist, so daß ein Compiler mit zunehmender Komplexität des> Programms immer bessere Ergebnisse erzielt als ein noch so guter> Programmierer.
Deshalb schrieb ich:
Thomas H. schrieb:> Wenn ich theoretisch Assembler mit C oder einer anderen Hochsprache> vergleiche, dann habe ich dabei keinen komplexen Algorithmus im Kopf> oder gar eine Komplexe Applikation, sondern ein einfaches Codesegment.> Das reicht mir aus um eine Aussage über den Vergleich Assembler vs> Compiler machen zu können. Denn komplexes Programm ist nichts anderes> als eine Aneinanderreihung einfacher codesegmente und letzen Endes> einfacher Instruktionen . Der Compiler macht nichts anderes als den> komplexen Code in einfache Teilaufgaben zu zerlegen. Um die Aussage zu> tätigen das dies theoretisch von einem Assemblerprogrammierer mit> gleichem oder im Falle aller real existierenden Compiler besser erledigt> werden könnte reicht der Vergleich einer so simplen Codesequenz. Weder> habe ich eine Aussage über die Zeit die der Programmierer dazu hat> gemacht noch über die Anzahl der Assemblerprogrammierer auf die Aufgabe> verteilt werden könnte. Auch habe ich klar -und ich sage es zum zweiten> male- zum Ausdruck gebracht das man in der Realität keine Komplexen> Aufgaben nur in Assembler lösen wird.Karl Käfer schrieb:> so daß es etwas anachronistisch und ewiggestrig> erscheint, ausgerechnet diese Mikrocontroller vollständig mit Assembler> programmieren zu wollen.
Exact was ich geschrieben habe.
Bastler schrieb:> Wenn 18 Jahre Assembler zu diesem Ergebnis führen:> Beitrag "Re: Analoger Sensor (LM355) mit Operationsverstärker (+AVR> Asm-Code)"> dann hätte man die Zeit besser in was anderes investiert.> (andere Beispiele für Code von unserem Freund sind leider nicht zu> finden)
Stell Dir vor, das Ding ist im Einsatz und es macht seine Sache gut.
Kann aber verstehen, wenn es mancher gern komplizierter gelöst hätte ;-)
Moby schrieb:> Bastler schrieb:>> Wenn 18 Jahre Assembler zu diesem Ergebnis führen:>> Beitrag "Re: Analoger Sensor (LM355) mit Operationsverstärker (+AVR>> Asm-Code)">> dann hätte man die Zeit besser in was anderes investiert.>> (andere Beispiele für Code von unserem Freund sind leider nicht zu>> finden)>> Stell Dir vor, das Ding ist im Einsatz und es macht seine Sache gut.> Kann aber verstehen, wenn es mancher gern komplizierter gelöst hätte ;-)
Eine Lösung dieses Problemchens in einer Hochsprach würde nur für
jemanden komplizierter Aussehen, der diese Hochsprache nicht verstünde.
Moby schrieb:> Stell Dir vor, das Ding ist im Einsatz und es macht seine Sache gut.
Die "Sache" ist so ein kleines Problem, wenn du da noch etwas verkehrt
gemacht hättest, dann stimme ich dem Vorposter 2x zu. So aber auf
jedenfall einmal.
Du machst deine Rolle als Gruppenkasper noch besser als
Assemblerprogrammierer ;-) Um Längen sogar.
Thomas H. schrieb:> Von inline Assembler wie er in GCC zelebriert wird lasse ich prinzipiell> die Finger.
GCCs Inline-Assembler ist einsame Spitze. Wenn du mal eine Krücke
wie den IAR da gesehen hast, bei dem du dich im Inline-Asm bestenfalls
auf globale Variablen verlassen kannst (alles andere könnte sich
bereits in der nächsten Compilerversion ja geändert haben, weil es
letztlich implementation defined ist), dann weißt du, warum die auf
den ersten Blick umständlich und kryptisch anmutende Variante des GCC
wirklich gut ist: sie gestattet es, dort, wo man es tatsächlich mal
braucht, handoptimierten Assemblercode einzuflechten, der auch über
ein paar Generationen des Compilers Bestand haben kann, ohne dabei
dem Compiler bei seinen Optimierungsstrategien im Weg herum zu stehen.
(Bezüglich der „Krücke“: der IAR ist sonst ein wirklich guter Compiler.
Aber an dieser Stelle ist er einfach nur <zensiert>.)
unbelegt und falsch schrieb:>> Moby schrieb: Asm als Klartext ist selbsterklärend.>> Schon mal in das Programm eines anderen Programmieres gelinst?
Das einzige Schnipsel Code, was wir von ihm hier bislang sehen durften,
führt seine Behauptung doch bereits komplett ad absurdum. Damit
erübrigt sich jegliche weitere Diskussion.
Jörg W. schrieb:>>> Moby schrieb: Asm als Klartext ist selbsterklärend.>>>> Schon mal in das Programm eines anderen Programmieres gelinst?>> Das einzige Schnipsel Code, was wir von ihm hier bislang sehen durften,> führt seine Behauptung doch bereits komplett ad absurdum. Damit> erübrigt sich jegliche weitere Diskussion.
Was ist an
Moby schrieb:> Steht mit Asm nicht etwa genau das auf dem Papier was passiert? Eine> kurzer Kommentar zur Funktion noch und gut ist!> Zum Verständnis gehört im Falle des Falles aber immer das Datenblatt.> Was auch C-Programmierern keinesfalls schadet!
absurd?
Absurd ist höchstens Dein Einwand...
Jörg W. schrieb
> Wenn du mal eine Krücke> wie den IAR da gesehen hast, bei dem du dich im Inline-Asm bestenfalls> auf globale Variablen verlassen kannst (alles andere könnte sich> bereits in der nächsten Compilerversion ja geändert haben, weil es> letztlich implementation defined ist), dann weißt du, warum die auf> den ersten Blick umständlich und kryptisch anmutende Variante des GCC> wirklich gut ist: sie gestattet es, dort, wo man es tatsächlich mal> braucht, handoptimierten Assemblercode einzuflechten, der auch über> ein paar Generationen des Compilers Bestand haben kann, ohne dabei> dem Compiler bei seinen Optimierungsstrategien im Weg herum zu stehen.
Probleme gibts...
Ich finde die Art der Assembler-Integration sehr gut. Sie ist zwar
gewöhnungsbedürftig, erlaubt aber eine sehr effiziente Integration
kleiner Assembler-Einsprengsel in C Code. Man muss wirklich nur das
absolute Minimum in Asm codieren. Das, was anders nicht geht.
Gleichzeitig behindern diese Sequenzen die Optimierung nicht, weil der
Compiler die dazu nötige Information erhält.
Jörg W. schrieb:> GCCs Inline-Assembler ist einsame Spitze
Spitze von unterirdisch vieleicht. Ich schreibe meinen Assemblercode
extern und linke zusammen.
Jörg W. schrieb:> Wenn du mal eine Krücke> wie den IAR da gesehen hast, bei dem du dich im Inline-Asm bestenfalls> auf globale Variablen verlassen kannst
Habe ich und dem stimme ich zu.
Jörg W. schrieb:> handoptimierten Assemblercode einzuflechten, der auch über> ein paar Generationen des Compilers Bestand haben kann
ein externenes .s File übersteht das hervorragend. Sowohl beim GCC als
auch beim IAR.
Jörg W. schrieb:> Bezüglich der „Krücke“: der IAR ist sonst ein wirklich guter Compiler
Der beste im Moment auf dem Markt.
Thomas H. schrieb:> Spitze von unterirdisch
vieleicht. Ich schreibe meinen Assemblercode
> extern und linke zusammen.
Beides ergibt Sinn, je nachdem um was es geht.
Wer einen kompletten Interrupt-Handler in Asm fomulieren will, der ist
mit einem separaten File besser bedient.
Wer einen einzelnen Befehl oder Sequenzen aus wenigen Befehlen
integrieren will, wie etwa Semaphor-Befehle oder Spezialbefehle für
Steuerregister, der ist mit inline-Asm wesentlich effizienter bedient.
In konventionellem Inline-Asm würde man die gesamten Semphor-Funktionen
von ARM als Asm implementieren. Im GCC Inline-Asm reicht es, die beiden
relevanten Befehle entsprechend zu definieren. Sie Semaphor-Sequenz kann
dann normal in C programmiert werden.
Hallo Thomas,
Thomas H. schrieb:> Exact was ich geschrieben habe.
Das hatte ich in Deinem ersten Beitrag anders verstanden. Mein Fehlerm
entschuldige bitte.
Liebe Grüße,
Karl
Thomas H. schrieb:> Ich schreibe meinen Assemblercode extern und linke zusammen.
Klar, aber das ist ja nicht das Zielgebiet des Inline-Assemblers.
Dort, wo man so hantieren kann, ist doch die Welt auf diese Weise
völlig in Ordnung, und das ist dann sicherlich der beste Weg.
Der Inline-Assembler des GCC ist dort gut, wo man eine möglichst
nahtlose inline Integration eines Stückchens Assemblercode braucht
(also alles, was man eher nicht als eigene Funktion implementieren
will). Dann muss ich mich eben nicht auf ein konkretes Register
festlegen (das der Compiler vielleicht an dieser Stelle lieber mit
etwas anderem belegen würde), sondern kann dem Compiler sagen: „ich
brauche hier irgendein Register“ oder „ich brauche hier eines der
Zeigerregister“.
avion23 schrieb:> @Horst> welche Compileroptionen verwendest du?> Bei Projekten mit vielen Dateien hilft "-Os -flto -fuse-linker-plugin"> viel. Das muss in die CFLAGS und LDFLAGS. Ist erst ab gcc-4.9 wirklich> sinnvoll.
Ich hab hier gcc 4.3.3 (stand zumindest in der html des WInAVR-Pakets).
Ich muss ehrlich gestehen, ich kann mich nicht mehr erinnern, wann ich
den mal installiert hatte und ob die Version an mein altes AVRStudio
(4.10) gebunden war.
Moby schrieb:> Durch Assembler beim assemblerfreundlichen AVR bleiben können- so wird> ein Schuh draus. Hochsprachenverwendung ist einer der wichtigsten> Treiber für permanente Controller-, Architektur- und Programmiermittel-> Wechsel.
Für mich war der Treiber zum Wechsel des Programmiermittels, dass ich
endlich auf den Fischen nicht nur Daten hin- und herschieben will,
sondern vielleicht auch gelegentlich mal etwas RECHNE.
Wenn Du also in Deiner Bastelkiste so was, wie die math.lib (mit den
trigonometrischen Funktionen) schon seit geraumer Zeit in optimierter
Performance in asm herumliegen hast - her damit - find ich gut. Die
gcc-Programmierer küssen Dir sicherlich auch die Füße, wenn Du Sinus und
ArcSin in weniger als 100us berechnen kannst (dann aber bitte ohne
Sprungtabelle, also code- UND performanceoptimiert).
Moby schrieb:> Und meinst Du wirklich, ich hätte den Anspruch zu "erleuchten" ?
warum tauchst du dann regelmaessig in threads zu hochsprachen auf und
zwingst deine missionierung auf? obwohl es die leute nervt?
> Es kann ja sein daß Simplizität und Effizienz von Asm nicht in die> heutige Zeit passt wo es heisst: Komplex ist cool und macht Eindruck.> Trotzdem gebe ich meine Erfahrungen weiter, und die stehen unter der> Maxime: Keep it simple!
asm ist nicht simpel und auch nicht effizient. es zwingt dazu, wie ein
prozessor zu denken statt wie ein mensch. das lenkt vom problem ab, das
man loesen will. das komplexe sieht man dem fertigen programm sowieso
nicht an. es waere dumm, etwas unnoetig komplex zu machen, wenn es
hinterher sowieso keiner bewundert.
Horst S. schrieb:> Für mich war der Treiber zum Wechsel des Programmiermittels, dass ich> endlich auf den Fischen nicht nur Daten hin- und herschieben will,> sondern vielleicht auch gelegentlich mal etwas RECHNE.
Stimmt. Erwischt. In meinen Projekten gibt es meist nur wenige
aufwendige Berechnungen. Wenn, dann bediene ich mich ausnahmsweise mal
an fremden Routinen, so wie sie zum Beispiel in den empfehlenswerten
Asm-Büchern von Manfred Schwabl-Schmidt oder im Netz zu finden sind.
Im Punkt Berechnungen ist man mit Hochsprache zugegebenermaßen bequemer
unterwegs. Das ist dann aber auch schon der einzige Moment, neidisch
hinüberzuschielen :-)
Klaus Peters schrieb:> warum tauchst du dann regelmaessig in threads zu hochsprachen auf und> zwingst deine missionierung auf? obwohl es die leute nervt?
Aufzwingen? Werd doch nicht albern. Und wer fragt denn was mich nervt?
Also das kann wirklich kein Kriterium sein. Wenn das Darstellen der
Vorteile von Asm missionierend wirkt, dann vielleicht wegen der Vorteile
von Asm ?
> asm ist nicht simpel und auch nicht effizient. es zwingt dazu, wie ein> prozessor zu denken statt wie ein mensch. das lenkt vom problem ab, das> man loesen will. das komplexe sieht man dem fertigen programm sowieso> nicht an. es waere dumm, etwas unnoetig komplex zu machen, wenn es> hinterher sowieso keiner bewundert.
In diesem Einwand kommt für mich nur mangelnde Erfahrung mit Asm zum
Ausdruck, sorry.
Das zunächst bequemer scheinende C bringt in der Folge nur mehr und mehr
künstliche Probleme mit sich, die man ohne nicht hat. C-Threads sind
voll davon... Ein AVR braucht i.d.R. keine Hochsprache. Asm passt
perfekt.
So, das Bullshit-Bingo ist ja jetzt schon mehr als voll...
Mit den ganzen Zeichen hier die nichts mit der Sache zu tun haben, hätte
man glaube ich schon ein Atomkraftwerk programmieren können ;-)
Moby schrieb:>> asm ist nicht simpel und auch nicht effizient. es zwingt dazu, wie ein>> prozessor zu denken statt wie ein mensch. das lenkt vom problem ab, das>> man loesen will. das komplexe sieht man dem fertigen programm sowieso>> nicht an. es waere dumm, etwas unnoetig komplex zu machen, wenn es>> hinterher sowieso keiner bewundert.>> In diesem Einwand kommt für mich nur mangelnde Erfahrung mit Asm zum> Ausdruck, sorry.
Du scheinst noch nie großartig pure Logik implementiert zu haben. Denn
wenn das Problem eben nicht technischer Art ist, sondern logischer, dann
ist eine "technische" Sprache (ASM) eben doch hinderlich und trägt nur
zur Verkomplizierung der Lösung bei. "Wer als Werkzeug nur einen Hammer
hat, sieht in jedem Problem einen Nagel." :P
Moby schrieb:> Ein AVR braucht i.d.R. keine Hochsprache. Asm passt> perfekt.
Nein danke, wenn ich mit einem AVR Dateien auf einer SD Karte lesen und
schreiben muss (FAT Dateisystem), kann ich gern auf Assembler
verzichten. Der Umgang mit "komplexeren" Datenstrukturen ist mit
Assembler ziemlich mühselig.
Moby schrieb:
> Aufzwingen? Werd doch nicht albern.
merkst du es nicht? sind die anderen die geisterfahrer? echt jetzt?
> Und wer fragt denn was mich> nervt?
niemand draengt sich dir auf. nur andersrum.
> Also das kann wirklich kein Kriterium sein. Wenn das Darstellen der> Vorteile von Asm missionierend wirkt, dann vielleicht wegen der> Vorteile> von Asm ?
wegen der penetranz, besserwisserei und unbelehrbarkeit, die du an den
tag legst. viele hier sind lange asm-progger und aus gutem grund zu den
hochsprachen gegangen.
du ignorierst alle argumente, die dir nicht in den kram passen, zeigst
nur kinderkrams und laberst die ganze zeit nur herum. sogar solche
fachleute wie peter danegger widersprechen dir und merkst nix.
>> asm ist nicht simpel und auch nicht effizient. es zwingt dazu, wie > ein>> prozessor zu denken statt wie ein mensch. das lenkt vom problem ab, > das>> man loesen will. das komplexe sieht man dem fertigen programm> sowieso>> nicht an. es waere dumm, etwas unnoetig komplex zu machen, wenn es>> hinterher sowieso keiner bewundert.>> In diesem Einwand kommt für mich nur mangelnde Erfahrung mit Asm zum> Ausdruck, sorry.
sorry es waren drei einwaende. 1. dass asm zum denken als prozessor
zwingt, 2. dass es deswegen vom problem ablenkt, 3. dass es bescheuert
waere dinge komplex zu machen wenn einen dafür keiner bewundern kann.
> Das zunächst bequemer scheinende C bringt in der Folge nur mehr und > mehr> künstliche Probleme mit sich, die man ohne nicht hat.
so ein quatsch. willst du etwa sagen, dass man asm nicht koennen muss?
oder laesst du das nur fuer was gelten, das du nicht kannst?
> C-Threads sind> voll davon...
cthreads sind voll davon, weil mehr leute c benutzen. sogar die meisten
anfaenger sind klug genug.
> Ein AVR braucht i.d.R. keine Hochsprache. Asm passt> perfekt.
er ist fuer die hochsprache c designt worden. sagt atmel selbst.
Klaus Peters schrieb:> Moby schrieb:>> Aufzwingen? Werd doch nicht albern.> merkst du es nicht? sind die anderen die geisterfahrer? echt jetzt?
Was soll die Übertreibung? Was soll dieses Entweder Oder?
Unfug. 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.
> er ist fuer die hochsprache c designt worden. sagt atmel selbst.
Ja das ist so. Die neueren XMegas sogar noch besser.
Daß schmälert umgekehrt aber seine Eignung für Asm in keinster Weise.
Asm ist da aus Prinzip nämlich sehr flexibel ;-)
TriHexagon schrieb:> Du scheinst noch nie großartig pure Logik implementiert zu haben. Denn> wenn das Problem eben nicht technischer Art ist, sondern logischer, dann> ist eine "technische" Sprache (ASM) eben doch hinderlich und trägt nur> zur Verkomplizierung der Lösung bei.
Nun, für viele viele MSR- und Steuerungsanwendungen brauchts das nicht.
Und stell Dir vor, für Logik gibts eigene Controller-Befehle!
Das muß man bei weitem nicht so hoch hängen...
> Nein danke, wenn ich mit einem AVR Dateien auf einer SD Karte lesen und> schreiben muss (FAT Dateisystem), kann ich gern auf Assembler> verzichten. Der Umgang mit "komplexeren" Datenstrukturen ist mit> Assembler ziemlich mühselig.
In diesem konkreten Fall magst Du Recht haben.
Diese Sorte Probleme kann man allerdings auch auf speziellere Hardware
auslagern. Schau, ich hab für solche Fälle ein einfach ansteuerbares
VDIP Modul im Einsatz. Was meinst Du wie das flutscht. Solcherlei
Zusatzhardware gibts in großer Fülle. Das muß man heute wirklich nicht
mehr selbst machen!