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).
:
Gesperrt durch Moderator
@ 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
Horst S. schrieb: > Vielleicht fällt Euch ja ein, was ich in C noch optimieren könnte. ich finde du hast zu viele Funktionen.
1 | void RxDCommandWriteMemGetFirstTargetByte(uint8_t receivedByte); |
2 | void RxDCommandWriteMemGetSecondTargetByte(uint8_t receivedByte); |
3 | void RxDCommandWriteMemGetFirstLengthByte(uint8_t receivedByte); |
4 | void RxDCommandWriteMemGetSecondLengthByte(uint8_t receivedByte); |
kannst man das nicht eine packen und mitgeben welches Byte man haben will?
1 | void PS2ReceiveBit0(); |
2 | void PS2ReceiveBit1(); |
3 | void PS2ReceiveBit2(); |
4 | void PS2ReceiveBit3(); |
5 | void PS2ReceiveBit4(); |
6 | void PS2ReceiveBit5(); |
7 | void PS2ReceiveBit6(); |
8 | void PS2ReceiveBit7(); |
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 | void SetLED1() |
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 (int i =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?
1 | memset( &DataRead, 0, sizeof(DataRead) ); |
würde ich hier vorschlagen.
:
Bearbeitet durch Moderator
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.
War ja nur eine Frage der Zeit bis Moby hier auftaucht... Jegliche Argumente für Hochsprachen sind damit hinfällig.
:
Bearbeitet durch User
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 ;-)
Wegen deinem Aufruf in ISR(PCINT1_vect)
1 | 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.
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
kannst ja mal mit dem code testen:
1 | //++++++++++++++++++++++++++++++++++++++++++
|
2 | //External PCINT PinChange Interrupt
|
3 | //++++++++++++++++++++++++++++++++++++++++++
|
4 | ISR(PCINT1_vect) |
5 | {
|
6 | |
7 | SetLED3(); |
8 | if ((PINC & (1<<PS2Clock)) == 0) { |
9 | static state = 0; |
10 | switch(state) { |
11 | case 0: |
12 | SetLED2(); |
13 | PS2ReceivedByte = 0; |
14 | break; |
15 | case 1: |
16 | case 2: |
17 | case 3: |
18 | case 4: |
19 | case 5: |
20 | case 6: |
21 | case 7: |
22 | if (PINC & (1<<PS2Data)) { |
23 | PS2ReceivedByte |= 0x80; |
24 | }
|
25 | PS2ReceivedByte = (PS2ReceivedByte >> 1); |
26 | case 8: |
27 | //todo PS2ReceiveParity
|
28 | break; |
29 | case 9: |
30 | //todo Stop - jetzt muss doch bestimmt jemand benachrichtig werden?
|
31 | break; |
32 | }
|
33 | |
34 | state++; |
35 | if ( state > 9 ) { |
36 | state = 0; |
37 | }
|
38 | }
|
39 | }
|
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.
Nachdem der switch sehr "unbefüllt" ist würde ich das sogar so machen:
1 | //++++++++++++++++++++++++++++++++++++++++++
|
2 | //External PCINT PinChange Interrupt
|
3 | //++++++++++++++++++++++++++++++++++++++++++
|
4 | ISR(PCINT1_vect) |
5 | {
|
6 | |
7 | SetLED3(); |
8 | if ((PINC & (1<<PS2Clock)) == 0) { |
9 | static int8_t state = 0; |
10 | |
11 | if (state==0) { |
12 | SetLED2(); |
13 | PS2ReceivedByte = 0; |
14 | } else if (state<8) { |
15 | if (PINC & (1<<PS2Data)) { |
16 | PS2ReceivedByte |= 0x80; |
17 | }
|
18 | PS2ReceivedByte = (PS2ReceivedByte >> 1); |
19 | } else if ( state == 9 ) { |
20 | state = -1; |
21 | }
|
22 | |
23 | state++; |
24 | |
25 | }
|
26 | }
|
Ich hoffe ich hab' mich nirgends vertippt... ging nicht durch einen compiler... 73
Ja, ganz so einfach war's nicht, (ich wollte im ISR ja auch senden), aber ich sehe schon, welche Richtung das einschlägt...
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 | static uint8_t PS2ReceivedByte; |
10 | static uint8_t PS2SendByte; |
11 | static uint8_t PS2SendByteChecksum; |
12 | static uint8_t PS2SendState = 0; |
13 | |
14 | |
15 | |
16 | void PS2Init() |
17 | {
|
18 | PCMSK1 = (1<<PCINT11); //Enable Pin change inerrupt on PC3 ()PCINT11) |
19 | PCICR = (1<<PCIE1); //Enable external interrupt for PCINT14:8 |
20 | |
21 | //Reset variables
|
22 | DataRead.LastOffset =0; |
23 | DataWrite.MouseCommand = 0; |
24 | PS2ReceivedByte =0; |
25 | memset( &DataRead, 0, sizeof(DataRead) ); |
26 | }
|
27 | |
28 | |
29 | void PS2Send(uint8_t bt) |
30 | {
|
31 | PS2SendByte = bt; |
32 | |
33 | //Prepare checksum
|
34 | PS2SendByteChecksum= MakeChecksumOfByte(PS2SendByte); |
35 | |
36 | // pull down Clock for 100u
|
37 | PS2SendState=1; |
38 | PS2PullDownClock(); |
39 | Wait100u(); |
40 | |
41 | |
42 | // pulldown data and release clock
|
43 | PS2PullDownData(); |
44 | PS2ReleaseClock(); |
45 | PS2SendState=2; |
46 | |
47 | }
|
48 | |
49 | |
50 | //++++++++++++++++++++++++++++++++++++++++++
|
51 | //External PCINT PinChange Interrupt
|
52 | //++++++++++++++++++++++++++++++++++++++++++
|
53 | ISR(PCINT1_vect) |
54 | {
|
55 | if (PS2SendState == 1) return; //Ignore clocks from device while wait100u |
56 | |
57 | SetLED3(); |
58 | if ((PINC & (1<<PS2Clock)) == 0) |
59 | {
|
60 | static state = 0; |
61 | if (PS2SendState==0) //RECEIVE |
62 | {
|
63 | switch(state) |
64 | {
|
65 | case 0: //Startbit |
66 | SetLED2(); |
67 | PS2ReceivedByte = 0; |
68 | state++; |
69 | break; |
70 | case 1: |
71 | case 2: |
72 | case 3: |
73 | case 4: |
74 | case 5: |
75 | case 6: |
76 | case 7: |
77 | case 8: |
78 | PS2ReceivedByte = (PS2ReceivedByte >> 1); |
79 | if (PINC & (1<<PS2Data)) { |
80 | PS2ReceivedByte |= 0x80; |
81 | }
|
82 | state++; |
83 | break; |
84 | case 9: |
85 | //todo PS2ReceiveParity
|
86 | state++; |
87 | break; |
88 | case 10: |
89 | DataRead.MouseBuffer[DataRead.LastOffset] = PS2ReceivedByte; |
90 | DataRead.LastOffset++; |
91 | state = 0; |
92 | break; |
93 | }
|
94 | |
95 | |
96 | }
|
97 | |
98 | else //SEND |
99 | {
|
100 | switch(state) |
101 | {
|
102 | case 0: |
103 | case 1: |
104 | case 2: |
105 | case 3: |
106 | case 4: |
107 | case 5: |
108 | case 6: |
109 | case 7: |
110 | if ((PS2SendByte & 0x01) != 0) |
111 | PS2ReleaseData(); |
112 | else
|
113 | PS2PullDownData(); |
114 | |
115 | PS2SendByte = (PS2SendByte>>1); |
116 | state++; |
117 | break; |
118 | |
119 | case 8: //Parity |
120 | if((PS2SendByteChecksum & 0x01) !=0) |
121 | PS2PullDownData(); |
122 | else
|
123 | PS2ReleaseData(); |
124 | state++; |
125 | break; |
126 | |
127 | case 9: //Stopbit |
128 | PS2ReleaseData(); |
129 | state++; |
130 | break; |
131 | |
132 | case 10: //Ack from device |
133 | if ((PINC & (1<<PS2Data)) != 0) |
134 | SetLED2(); |
135 | else
|
136 | ClearLED2(); |
137 | state =0; |
138 | //Fallback to listen
|
139 | PS2SendState = 0; |
140 | break; |
141 | |
142 | }
|
143 | |
144 | }
|
145 | }
|
146 | ClearLED3(); |
147 | }
|
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.
Du kannst gefahrlos 2 Funktionen dafür machen:
1 | if (...) { |
2 | Receive(); |
3 | } else { |
4 | Send(); |
5 | }
|
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.
> static state = 0;
mach mal uint8_t draus. Sonst hast du ein int (16bit) was sinnlos seit
kostet.
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.
:
Bearbeitet durch User
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: 1f 92 push r1 |
7 | 868: 0f 92 push r0 |
8 | 86a: 0f b6 in r0, 0x3f ; 63 |
9 | 86c: 0f 92 push r0 |
10 | 86e: 11 24 eor r1, r1 |
11 | 870: 2f 93 push r18 |
12 | 872: 8f 93 push r24 |
13 | 874: 9f 93 push r25 |
14 | 876: ef 93 push r30 |
15 | 878: ff 93 push r31 |
16 | }
|
17 | |
18 | |
19 | extern inline void SetLED3() |
20 | {
|
21 | PORTD |= (1<<LED3); |
22 | 87a: 5e 9a sbi 0x0b, 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 | static uint8_t PS2Byte; |
10 | static uint8_t PS2Checksum; |
11 | static uint8_t PS2Watchdog = 0; |
12 | static uint8_t PS2State = 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 | void PS2Init() |
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 | void PS2TestWatchdog() |
36 | {
|
37 | if (PS2Watchdog == 0) return; |
38 | |
39 | PS2Watchdog--; |
40 | if (PS2Watchdog == 0) |
41 | PS2State = 0; |
42 | }
|
43 | |
44 | static void RetriggerPS2Watchdog() |
45 | {
|
46 | PS2Watchdog = 4; |
47 | }
|
48 | |
49 | //Basic Port functions
|
50 | static void PS2PullDownClock() |
51 | {
|
52 | PORTC &= ~(1<<PS2Clock); |
53 | DDRC |= (1<<PS2Clock); |
54 | }
|
55 | |
56 | static void PS2ReleaseClock() |
57 | {
|
58 | DDRC &= ~(1<<PS2Clock); |
59 | }
|
60 | |
61 | static void PS2PullDownData() |
62 | {
|
63 | PORTC &= ~(1<<PS2Data); |
64 | DDRC |= (1<<PS2Data); |
65 | }
|
66 | |
67 | |
68 | static void PS2ReleaseData() |
69 | {
|
70 | DDRC &= ~(1<<PS2Data); |
71 | }
|
72 | |
73 | |
74 | |
75 | |
76 | void PS2Send(uint8_t bt) |
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 | case 0: //Receive Startbit |
110 | SetLED2(); |
111 | PS2Byte = 0; |
112 | PS2State++; |
113 | break; |
114 | |
115 | case 0x09: //Recieve PS2ReceiveParity |
116 | PS2State++; |
117 | break; |
118 | |
119 | case 0x0A: //Receive complete-> Transfer byte to target |
120 | DataRead.MouseBuffer[DataRead.LastOffset] = PS2Byte; |
121 | DataRead.LastOffset++; |
122 | PS2State = MSK_PS2Listen; |
123 | break; |
124 | |
125 | case 0x38: //Send Parity |
126 | if((PS2Checksum & 0x01) !=0) |
127 | PS2PullDownData(); |
128 | else
|
129 | PS2ReleaseData(); |
130 | PS2State++; |
131 | break; |
132 | |
133 | case 0x39: //Send Stopbit |
134 | PS2ReleaseData(); |
135 | PS2State++; |
136 | break; |
137 | |
138 | case 0x3A: //Ack from device |
139 | if ((PINC & (1<<PS2Data)) != 0) |
140 | SetLED2(); |
141 | else
|
142 | ClearLED2(); |
143 | PS2State = 0; //Fallback to listen |
144 | break; |
145 | |
146 | |
147 | case MSK_PS2SendStart: // In 100us pause |
148 | break; //Nothing to do |
149 | |
150 | |
151 | |
152 | default:
|
153 | if ((PS2State & MSK_PS2Send) == MSK_PS2Send) //Send bit 0..7 |
154 | {
|
155 | if ((PS2Byte & 0x01) != 0) |
156 | PS2ReleaseData(); |
157 | else
|
158 | PS2PullDownData(); |
159 | |
160 | PS2Byte = (PS2Byte>>1); |
161 | PS2State++; |
162 | break; |
163 | }
|
164 | else //Receive Bit 0..7 |
165 | {
|
166 | PS2Byte = (PS2Byte >> 1); |
167 | if (PINC & (1<<PS2Data)) |
168 | {
|
169 | PS2Byte |= 0x80; |
170 | }
|
171 | PS2State++; |
172 | }
|
173 | }
|
174 | }
|
175 | RetriggerPS2Watchdog(); |
176 | ClearLED3(); |
177 | |
178 | |
179 | }
|
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
1 | Select bla |
2 | case 16 to 64: |
3 | .
|
4 | .
|
5 | .
|
6 | end select |
schreiben.
Jörg W. schrieb: > Kannste beim GCC auch, ist aber nicht portabel: > > https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html Das ist ja lustig: Mit dem Default-Zweig bin ich bei 2528 Bytes. Wenn ich die case-Bereiche verwende, spare ich noch 4 Bytes.
@ 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 | case 0: //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 | case WAIT_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.
:
Bearbeitet durch User
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 | enum ps2_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).
Das hier
1 | SetLED2(); |
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. )
:
Bearbeitet durch User
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 | static uint8_t PS2Byte; |
2 | static uint8_t PS2Checksum; |
3 | static uint8_t PS2Watchdog = 0; |
4 | static uint8_t PS2State = 0; //Listen |
1 | struct PS2VariableStruct { |
2 | uint8_t PS2Byte; |
3 | uint8_t PS2Checksum; |
4 | uint8_t PS2Watchdog = 0; |
5 | uint8_t PS2State = 0; //Listen |
6 | }
|
7 | |
8 | static PS2VariableStruct PS2Variables; |
Wobei ehrlich gesagt du eigentlich schon quasi objekt orientiert unterwegs bist und sich C++ schon anbieten würde...
Hans schrieb: > und spart sich das 16-bit > pointer-laden hin und wieder. Kannst Du näher ausführen was Du damit meinst?
Naja X mit der Basis-Adresse vom Struct laden und dann
1 | LD r0, X+ |
2 | LD r1, X+ |
3 | LD r2, X+ |
4 | LD r3, X |
Würde alle 4 Variablen in einem Rutsch laden... Am ARM macht der GCC sowas, am AVR muss ich gestehen weiß ich das nicht. 73
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:
1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2 | // Further PS2 protocol informations:
|
3 | // http://www.computer-engineering.org/ps2protocol/
|
4 | // http://www.computer-engineering.org/ps2mouse/
|
5 | //
|
6 | // PS2 Protocol is executed by Pin change interrupt PCINT1 and controlled via PS2State variable.
|
7 | // RECEIVING A BYTE
|
8 | // PS2State | State
|
9 | // 0x00 | listening, wait for start bit from device
|
10 | // 0x01 | wait for first data bit (LSB)
|
11 | // ... | ...(wait for data bits 1..6)
|
12 | // 0x08 | wait for last data bit (MSB)
|
13 | // 0x09 | wait for parity from device
|
14 | // 0x0A | wait for stop bit from device.
|
15 | // | Successful received stop bit:
|
16 | // | - Reading completed
|
17 | // | - transfer byte to next level
|
18 | // | - Reset PS2State to listen state
|
19 | //
|
20 | // SENDING A BYTE
|
21 | // PS2State | State
|
22 | // 0x10 | Set by PS2Send function. Prepare send by pulldown clock line for 100us
|
23 | // | At this time transfer from device will be interrupted
|
24 | // 0x30 | Set by PS2Send function. Clock has been released and was pulled down by device
|
25 | // | -> Set first data bit (LSB)
|
26 | // ... | ...(set data bits 1..6)
|
27 | // 0x37 | Set last data bit (MSB)
|
28 | // 0x38 | Set parity bit (odd)
|
29 | // 0x39 | Set stop bit
|
30 | // 0x3A | Get ack from device. Transfer complete, go back to Listen (PS2State=0x00)
|
31 | //
|
32 | // Remark: PS2State is incremended each step, if not otherwise noted.
|
33 | //
|
34 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
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 Nun wart doch mal ab, das ist nur die Ruhe vor dem Sturm. Moby optimiert noch den Assemblercode ;-)
Ich kann mich täuschen, aber ich habe noch nirgends ne Zeile ASM von Moby gesehn...
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!
:
Bearbeitet durch User
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
1 | Followup-To: de.alt.gruppenkasper |
gesetzt. ;-)
Interessanterweise habe ich übrigens noch keinen Thread gesehen wo Moby ein ASM ergebnis geliefert hat das tatsächlich wesentlich kleiner ist... 73
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.)
Kennst Du nicht? Das sind Abkürzungen in der Amateurfunk-Telegrafie (oder auch woanders?). Siehe: https://de.wikipedia.org/wiki/Betriebstechnik_%28Amateurfunk%29
Na, dann:
1 | ISR_OT_73:
|
2 | push r16 |
3 | in r16, SREG |
4 | push r16 |
5 | call WinkeWinke |
6 | pop r16 |
7 | out SREG, r16 |
8 | pop r16 |
9 | ISR_OT_73_End: |
10 | reti
|
11 | //OT-Ende: Ich widme mich mal meiner UART.
|
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...
Frank M. schrieb: > Darf ich Dich in die Kategorie "Blender" stecken? Ein Projekt lässt sich finden: Beitrag "Re: Analoger Sensor (LM355) mit Operationsverstärker (+AVR Asm-Code)"
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"?
:
Bearbeitet durch Moderator
Jörg W. schrieb: > Frank M. schrieb: >> Darf ich Dich in die Kategorie "Blender" stecken? > > Ein Projekt lässt sich finden: > > Beitrag "Re: Analoger Sensor (LM355) mit Operationsverstärker (+AVR Asm-Code)" Zu trivial. Mehr ist da nicht? Du als Moderator hast wahrscheinlich bessere Suchmöglichkeiten ;-)
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)?
Frank M. schrieb: > Du als Moderator hast wahrscheinlich > bessere Suchmöglichkeiten ;-) Hätte er. Aber das wird er nicht wollen ;-)
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:
1 | ISR_OT_73
|
2 | {
|
3 | WinkeWinke(); |
4 | }
|
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.
:
Bearbeitet durch User
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?
:
Bearbeitet durch User
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.
TriHexagon schrieb: > Wow gerade mal 3500 Transistoren, es hat sich einiges getan in der Zeit. Schöne Übersicht: https://en.wikipedia.org/wiki/Transistor_count
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".
2032! Die 2k-Grenze hab' ich geknackt. Die Switch-Anweisungen sehen jetzt schon etwas undurchschaubar aus. UARTTelegramV3.c
1 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2 | // UARTTelegram: PC controlled UART protocol with 4 commands
|
3 | //V3 state compressed version
|
4 | //
|
5 | // ReadMem/WriteMem: Direct Reading/Writing a block of memory (specified by start address and block length) from/to this device
|
6 | // ReadDevice/ WriteDevice: Indirect reading/writing a blöck of memory (specified by start address and block length)
|
7 | //
|
8 | //WRITEMEM
|
9 | // PC Sends |OldState |NewState |RxDTask
|
10 | // TelID |0x00 |0x01 |buffer telegramID
|
11 | // cmd 0x01 |0x01 |0x10 |prepare receiving target address low byte
|
12 | // Targ. addr lb |0x10 |0x11 |get target address low byte
|
13 | // Targ. addr hb |0x11 |0x12 |get target address high byte
|
14 | // Length lb |0x12 |0x13 |get length low byte
|
15 | // Length hb |0x13 |0x14 |get length high byte
|
16 | // data |0x14 |0x14/5 | set data to RAM, decrement length.
|
17 | // | If length = 0, set state to 0x15 and start ack telegram by sending TelegramID
|
18 | // | SWITCH TO TxD
|
19 | // - |0x15 |0x16 | Send writemem ack (0x81)
|
20 | // - |0x16 |0x00 | Send checksum and terminate transfer by setting state to 0x00 (listen)
|
21 | //
|
22 | //
|
23 | //READMEM
|
24 | // PC Sends |OldState |NewState |RxDTask
|
25 | // TelID |0x00 |0x01 |buffer telegramID
|
26 | // cmd 0x02 |0x01 |0x20 |prepare receiving target address low byte
|
27 | // Targ. addr lb |0x20 |0x21 |get target address low byte
|
28 | // Targ. addr hb |0x21 |0x22 |get target address high byte
|
29 | // Length lb |0x22 |0x23 |get length low byte
|
30 | // Length hb |0x23 |0x24 |get length high byte, and start ack telegram by sending TelegramID
|
31 | // | SWITCH TO TxD
|
32 | // - |0x24 |0x25 | Send readmem ack (0x82)
|
33 | // - |0x25 |0x25/0x00 | Send data, dec. length. If length = 0, send checksum and
|
34 | // - | terminate transfer by setting state to 0x00 (listen)
|
35 | //
|
36 | //
|
37 | //WRITEDEVICE
|
38 | // PC Sends |OldState |NewState |RxDTask
|
39 | // TelID |0x00 |0x01 |buffer telegramID
|
40 | // cmd 0x03 |0x01 |0x30 |prepare receiving peripherie ID
|
41 | // Peri. addr |0x30 |0x31 |get periphrie address
|
42 | // Length lb |0x31 |0x32 |get length low byte
|
43 | // Length hb |0x32 |0x33 |get length high byte, check lock state
|
44 | // data |0x33 |0x33/4 | set data to Peripherie ram if not locked, decrement length.
|
45 | // | If length = 0, set state to 0x34 and start ack telegram by sending TelegramID
|
46 | // | SWITCH TO TxD
|
47 | // - |0x34 |0x35 | Send writedevice ack (0x83)
|
48 | // - |0x35 |0x00 | Send checksum and terminate transfer by setting state to 0x00 (listen)
|
49 | //
|
50 | //
|
51 | //READDEVICE
|
52 | // PC Sends |OldState |NewState |RxDTask
|
53 | // TelID |0x00 |0x01 |buffer telegramID
|
54 | // cmd 0x04 |0x01 |0x40 |prepare receiving peripherie ID
|
55 | // Peri. addr |0x40 |0x41 |get periherie address
|
56 | // Length lb |0x41 |0x42 |get length low byte
|
57 | // Length hb |0x42 |0x43 |get length high byte, and start ack telegram by sending TelegramID
|
58 | // |!!!!If device is locked, wait for unlock
|
59 | // | SWITCH TO TxD
|
60 | // - |0x43 |0x44 | Send readDevice ack (0x84)
|
61 | // - |0x44 |0x44/0x00 | Send data, dec. length. If length = 0, send checksum and
|
62 | // - | terminate transfer by setting state to 0x00 (listen)
|
63 | |
64 | |
65 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
66 | |
67 | |
68 | |
69 | #include "structs.h" |
70 | #include <inttypes.h> |
71 | #include <avr/interrupt.h> |
72 | #include "LEDV2.h" |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | //Forward references
|
79 | PeripherieTableEntry* GetPeripherieTableEntry(uint8_t ID); |
80 | void TxDSendByte(uint8_t sendByte); |
81 | void RefreshRS232TimeOutWatchdog(); |
82 | |
83 | |
84 | //Variables
|
85 | static uint8_t UARTTimeOutWatchdog = 15; |
86 | static uint8_t UARTPeripherieID; |
87 | static uint8_t UARTChecksum; |
88 | static uint8_t UARTReadWriteDeviceStatus; //Used to signal success of ReadDevice/ WriteDevice commands |
89 | |
90 | static uint8_t UARTState; //Used to signal success of ReadDevice/ WriteDevice commands |
91 | static uint8_t UARTTelegrammID; |
92 | static uint8_t UARTCommand; |
93 | static uint8_t* UARTTargetAddress; |
94 | static uint16_t UARTDataLength; |
95 | |
96 | |
97 | |
98 | #define MSK_RxD_RWDSError 0x40 // 0: SUCCEEDED, 0x40: ERROR
|
99 | #define PT_LOCK_TWICurrentWrite_Mask 0x01 // Bit 0: TWICurrentWrite (Locked state for RS232)
|
100 | #define PT_LOCK_RS232CurrentWrite_Mask 0x02 // Bit 1: RS232CurrentWrite (Locked state for TWI)
|
101 | #define PT_LOCK_NewWriteData_Mask 0x04 // Bit 2: NewWriteData
|
102 | #define PT_LOCK_TWICurrentRead_Mask 0x08 // Bit 3: TWICurrentRead (Locked state for RS232)
|
103 | #define PT_LOCK_RS232CurrentRead_Mask 0x10 // Bit 4: RS232CurrentRead (Locked state for RS232)
|
104 | |
105 | |
106 | //******************************************
|
107 | //RxD
|
108 | //******************************************
|
109 | ISR(USART_RX_vect) |
110 | {
|
111 | RefreshRS232TimeOutWatchdog(); |
112 | uint8_t receivedByte = UDR0; |
113 | |
114 | PeripherieTableEntry* tableEntry; |
115 | |
116 | switch (UARTState) |
117 | {
|
118 | case 0x00: //buffer telegramID |
119 | UARTTelegrammID = receivedByte; |
120 | UARTState++; |
121 | break; |
122 | |
123 | case 0x01: //get command byte |
124 | UARTCommand = receivedByte; // buffer actual command |
125 | if((UARTCommand > 0) && (UARTCommand <=4)) |
126 | UARTState = (UARTCommand<<4); |
127 | else
|
128 | UARTState =0; |
129 | break; |
130 | |
131 | case 0x10: //get target address low byte |
132 | case 0x20: //get target address low byte |
133 | UARTTargetAddress = (uint8_t*) &receivedByte; |
134 | UARTState++; |
135 | break; |
136 | |
137 | case 0x11: //get target address high byte |
138 | case 0x21: //get target address high byte |
139 | UARTTargetAddress+= (int)receivedByte * 256; |
140 | UARTState++; |
141 | break; |
142 | |
143 | case 0x12: //get length low byte |
144 | case 0x22: //get length low byte |
145 | case 0x31: //get length low byte |
146 | case 0x41: //get length low byte |
147 | UARTDataLength = receivedByte; |
148 | UARTState++; |
149 | break; |
150 | |
151 | case 0x13: //get length high byte |
152 | UARTDataLength += (int)receivedByte * 256; |
153 | UARTState = 0x14; |
154 | break; |
155 | |
156 | |
157 | case 0x14: //set data to RAM, decrement length. |
158 | *UARTTargetAddress = receivedByte; |
159 | UARTTargetAddress++; |
160 | |
161 | if (0 != UARTDataLength) |
162 | UARTDataLength--; |
163 | else
|
164 | {
|
165 | // Prepare and start Answer Telegramm
|
166 | UARTState = 0x15; |
167 | TxDSendByte(UARTTelegrammID); |
168 | }
|
169 | break; |
170 | |
171 | |
172 | case 0x23: //get length high byte, and start ack telegram by sending TelegramID |
173 | UARTDataLength+= (int) receivedByte * 256; |
174 | // Prepare and start Answer Telegramm
|
175 | UARTState = 0x24; |
176 | TxDSendByte(UARTTelegrammID); |
177 | break; |
178 | |
179 | |
180 | case 0x30: //get periphrie address |
181 | case 0x40: //get periherie address |
182 | UARTPeripherieID = receivedByte; |
183 | UARTState++; |
184 | break; |
185 | |
186 | |
187 | |
188 | case 0x32: //get length high byte, check lock state |
189 | UARTDataLength+= (int)receivedByte * 256; |
190 | UARTState = 0x33; |
191 | tableEntry = GetPeripherieTableEntry(UARTPeripherieID); |
192 | if (tableEntry < (PeripherieTableEntry*) &PeripherieTableEndAddress) |
193 | {
|
194 | if ((tableEntry->LockByte & PT_LOCK_TWICurrentWrite_Mask) != 0) |
195 | {
|
196 | //Table entry is locked by TWI->Error set in answer telegram
|
197 | UARTReadWriteDeviceStatus = MSK_RxD_RWDSError;//Signal Error for answer telegram |
198 | }
|
199 | else
|
200 | {
|
201 | tableEntry->LockByte |= PT_LOCK_RS232CurrentWrite_Mask; |
202 | UARTTargetAddress = (uint8_t*) &tableEntry->Comm_WriteBufferAddress; |
203 | UARTReadWriteDeviceStatus=0;//Signal Success for answer telegram |
204 | }
|
205 | }
|
206 | else
|
207 | {
|
208 | // PeripherieID not found->Error set in answer telegram
|
209 | UARTReadWriteDeviceStatus = MSK_RxD_RWDSError;//Signal Error for answer telegram |
210 | }
|
211 | break; |
212 | |
213 | |
214 | case 0x33: //set data to Peripherie ram if not locked, decrement length. |
215 | // If length = 0, set state to 0x34 and start ack telegram by sending TelegramID
|
216 | if (UARTReadWriteDeviceStatus == 0) |
217 | {
|
218 | // Access granted
|
219 | *UARTTargetAddress = receivedByte; |
220 | UARTTargetAddress++; |
221 | }
|
222 | |
223 | |
224 | UARTDataLength--; |
225 | if (0== UARTDataLength) |
226 | {
|
227 | // last byte
|
228 | UARTState =0x34; |
229 | //Unlock table entry and set NewData Flag
|
230 | tableEntry = GetPeripherieTableEntry(UARTPeripherieID); |
231 | tableEntry->LockByte &= ~PT_LOCK_RS232CurrentWrite_Mask; |
232 | |
233 | // Prepare and start Answer Telegramm
|
234 | TxDSendByte(UARTTelegrammID); |
235 | }
|
236 | break; |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | case 0x42: //get length high byte, and start ack telegram by sending TelegramID |
243 | // !!!!If device is locked, wait for unlock
|
244 | UARTDataLength+= (int)receivedByte * 256; |
245 | UARTState = 0x43; |
246 | |
247 | tableEntry = GetPeripherieTableEntry(UARTPeripherieID); |
248 | if (tableEntry < (PeripherieTableEntry*) &PeripherieTableEndAddress) |
249 | {
|
250 | tableEntry->LockByte = 100; |
251 | sei(); |
252 | while((tableEntry->LockByte & PT_LOCK_TWICurrentRead_Mask) != 0); |
253 | cli(); |
254 | tableEntry->LockByte |= PT_LOCK_RS232CurrentRead_Mask; // Lock it |
255 | UARTTargetAddress = (uint8_t*) &tableEntry->Comm_ReadBufferAddress; |
256 | UARTReadWriteDeviceStatus=0; |
257 | // Start answer telegram
|
258 | TxDSendByte(UARTTelegrammID); |
259 | }
|
260 | break; |
261 | }
|
262 | }
|
263 | |
264 | |
265 | |
266 | |
267 | |
268 | ISR(USART_TX_vect) |
269 | {
|
270 | RefreshRS232TimeOutWatchdog(); |
271 | PeripherieTableEntry* tableEntry; |
272 | |
273 | switch(UARTState) |
274 | {
|
275 | |
276 | case 0x15: //Send writemem ack (0x81) |
277 | case 0x24: //Send readmem ack (0x82) |
278 | case 0x34: //Send writedevice ack (0x83) |
279 | case 0x43: //Send readDevice ack (0x84) |
280 | UARTState++; |
281 | TxDSendByte(UARTCommand | 0x80); |
282 | break; |
283 | |
284 | |
285 | case 0x16: //Send checksum and terminate transfer by setting state to 0x00 (listen) |
286 | case 0x35: //Send checksum and terminate transfer by setting state to 0x00 (listen) |
287 | UARTState = 0x00; |
288 | TxDSendByte(UARTChecksum); |
289 | break; |
290 | |
291 | case 0x25: //Send data, dec. length. If length = 0, send checksum and |
292 | // terminate transfer by setting state to 0x00 (listen)
|
293 | if (0!= UARTDataLength) |
294 | {
|
295 | UARTDataLength--; |
296 | TxDSendByte(*UARTTargetAddress); |
297 | UARTTargetAddress++; |
298 | }
|
299 | else
|
300 | {
|
301 | UARTState = 0x00; |
302 | TxDSendByte(UARTChecksum); |
303 | }
|
304 | break; |
305 | |
306 | case 0x44: //Send data, dec. length. If length = 0, send checksum and |
307 | // terminate transfer by setting state to 0x00 (listen)
|
308 | if (0 == UARTDataLength) |
309 | {
|
310 | //Unlock table
|
311 | tableEntry = GetPeripherieTableEntry(UARTPeripherieID); |
312 | if (tableEntry < (PeripherieTableEntry*) &PeripherieTableEndAddress) |
313 | {
|
314 | tableEntry->LockByte &= ~PT_LOCK_RS232CurrentRead_Mask; |
315 | }
|
316 | UARTState = 0x00; |
317 | TxDSendByte(UARTChecksum); |
318 | }
|
319 | else
|
320 | {
|
321 | UARTDataLength--; |
322 | TxDSendByte(*UARTTargetAddress); |
323 | UARTTargetAddress++; |
324 | }
|
325 | break; |
326 | }
|
327 | }
|
328 | |
329 | |
330 | //***************************************************************************
|
331 | // COMMON
|
332 | //***************************************************************************
|
333 | |
334 | uint8_t MakeChecksumOfByte(uint8_t bt) |
335 | {
|
336 | uint8_t rval=0; |
337 | for (int i = 0; i < 8; i++) |
338 | {
|
339 | rval += (bt &0x01); |
340 | bt = (bt >> 1); |
341 | }
|
342 | return rval; |
343 | }
|
344 | |
345 | //***********************************************************************
|
346 | // INIT
|
347 | //***********************************************************************
|
348 | void UARTTelegramInit() |
349 | {
|
350 | UARTState =0; |
351 | }
|
352 | |
353 | |
354 | |
355 | //***********************************************************************
|
356 | // RefreshRS232TimeOutWatchdog:
|
357 | // Called from subroutines in this module.
|
358 | // Signals a running data transfer by initializing a watchdog counter
|
359 | // if watchdog counter (decremented by MainTimer.asm) is timed out,
|
360 | // RxD/TxD state machines are switcheing to 1st State
|
361 | //***********************************************************************
|
362 | void RefreshRS232TimeOutWatchdog() |
363 | {
|
364 | UARTTimeOutWatchdog = 15; |
365 | }
|
366 | |
367 | |
368 | |
369 | //***********************************************************************
|
370 | // TestRS232TimeOutWatchdog:
|
371 | // Called from MainTimerInterrupt: If Counter is timed out,
|
372 | // RxD/TxD state machines are switcheing to 1st State
|
373 | //***********************************************************************
|
374 | void TestRS232TimeOutWatchdog() |
375 | {
|
376 | if (UARTTimeOutWatchdog > 0) |
377 | {
|
378 | UARTTimeOutWatchdog--; |
379 | if (0 == UARTTimeOutWatchdog) |
380 | UARTTelegramInit(); |
381 | }
|
382 | }
|
383 | |
384 | |
385 | //****************************************************************************
|
386 | // GetPeripherieTableEntry: Used by WriteDevice/ ReadDevice
|
387 | // returns a pointer to table entry identified by ID in peripherie table
|
388 | // if Pointer > &PeripherieTable + sizeof(PeripherieTable), no appropriate entry was found
|
389 | //****************************************************************************
|
390 | PeripherieTableEntry* GetPeripherieTableEntry(uint8_t ID) |
391 | {
|
392 | PeripherieTableEntry* rval = (PeripherieTableEntry*) &PeripherieTable; |
393 | for (int i=0; i< 2; i++) |
394 | {
|
395 | if (rval->ID == ID) |
396 | return rval; |
397 | rval++; |
398 | }
|
399 | return rval; |
400 | }
|
401 | |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | void TxDSendByte(uint8_t sendByte) |
409 | {
|
410 | while ((UCSR0A & (1<<UDRE0)) == 0); // wait for UART data register empty flag |
411 | UDR0 = sendByte; |
412 | }
|
413 | |
414 | void UART_Init() |
415 | {
|
416 | ///***********
|
417 | // 9600 Baud
|
418 | ///***********
|
419 | UBRR0H=0; |
420 | UBRR0L=51; |
421 | |
422 | // Set frame format: 8data, 1 Stop bit, no parity
|
423 | UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); |
424 | |
425 | //Transmitter/Receiver enabled/interrupt enabled
|
426 | UCSR0B = (1<<TXCIE0) | (1<<RXCIE0) | (1<<TXEN0) | (1<<RXEN0); |
427 | }
|
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
Karl Käfer schrieb: > Lesen lernen: das hab' ich schon. Verstehen lernen: Simpel geht anders. Aber ich weiß ja, das kannst Du nicht ;-)
Was wäre die Welt ohne Religionskriege . . . ? ASM akubar!
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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...
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
Thomas H. schrieb: > Ich habe nach 36J Assemblerprogramierung Kompliment. Das möchte ich auch noch erreichen. Die Hälfte hab ich schon ;-)
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: > auf Basis der Erfahrung tausender Hochkarätiger Compilerentwickler Danke für die Blumen
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?
>Moby schrieb: Asm als Klartext ist selbsterklärend.
Schon mal in das Programm eines anderen Programmieres gelinst?
Klingt nicht so.
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.
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)
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.
Hmmmm schrieb: > Du machst deine Rolle als Gruppenkasper Hmmmm, ob Du auch was zur Sache beitragen kannst? Gute Unterhaltung ist aber auch was wert ;-)
Hmmmm schrieb: > Moby schrieb: >> ob Du auch was zur Sache beitragen kannst? > > Könnte ich sicher, lohnt aber nicht :-) Das glaub ich Dir ;-)
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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: > Ich hab hier gcc 4.3.3 (stand zumindest in der html des WInAVR-Pakets). Besorg dir bitte wenigstens die aktuelle Atmel-Toolchain... http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx
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!
Klaus Peters schrieb: > du ignorierst alle argumente, die dir nicht in den kram passen Den Eindruck hat man meistens von der Gegenseite ;-) Zunächst sollte man die eigene Erfahrung nicht ignorieren. > fachleute wie peter danegger widersprechen dir und merkst nix. Die eigene Erfahrung zählt wiegesagt... Die spür ich zuallererst. Darüber kann man sich doch ganz unaufgeregt austauschen- oder geht das etwa nicht? > 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. Obwohl ohne Hoffnung, es einem Nicht-ASMler zu erklären dazu soviel: Punkt1: Wie ein Controller zu denken spielt sich noch (mindestens) eine Ebene tiefer ab. Asm zwingt in allererster Linie zur Kenntnis des Controllers. Ermöglicht ja gerade dadurch die feinere Anpassung an den Controller. Ermöglicht ja gerade dadurch jenes Plus an Performance und Minus an Platzbedarf. Sicher ermöglicht Hochsprache, Probleme abstrakter fassen zu können. Mit allen bekannten Nachteilen. Ich als ASMler bin darauf nicht angewiesen. Und viele andere auch (Punkt2). Punkt3: Kompliziert gehts prinzipiell in jeder Sprache. ASM vereinfacht insofern, als daß die Dinge auf direkte Weise angepackt werden. Viele viele künstliche Konstruktionen der Hochsprache überflüssig werden. Nimm sowas dämliches wie einen Cast-Operator... Ein typisches Kunstproblem, daß man sich mit erst mit dem Datentypkonzept einhandelt. Und was die Bewunderung anbetrifft... Jo mei. Die notwendige Komplexität meiner Haussteuerung zum Beispiel soll doch in erster Linie nur funktionieren! Dann bin ich schon glücklich.
Moby schrieb: > Ermöglicht ja gerade dadurch jenes Plus an Performance und > Minus an Platzbedarf. Schon wieder erzählst du uns von dem 'Plus an Performance und Minus and Platzbedarf', veröffentlichst aber Code der offensichtlich noch nicht optmiert ist. Ja was den nun? > Nimm sowas dämliches wie einen Cast-Operator... Ein typisches > Kunstproblem, daß man sich mit erst mit dem Datentypkonzept einhandelt. Glaubst du wirklich, der Compiler könnte nicht von alleine Casts setzen wenn die Compilerprogrammierer es wollten? Explizite Casts sind dazu da, Fehler zu vermeiden in dem sie den Programmierer zwingen 1. nochmal darüber nachzudenken ob ein Cast zwischen inkompatiblen Datentypen an dieser Stelle überhaupt richtig ist 2. Einen potentiell 'gefährlichen' Cast durch explizites hinschreiben zu dokumentieren. Hier geht es also allein darum Programmierfehler zu vermeiden. Im generierten Maschinencode ist übrigens die Cast operation nicht mehr zu sehen, kostet also weder Performance noch Platz. Und 'komplexer' wird der Code nicht, im Gegenteil er wird besser lesbar - wenn man den C lesen kann. Es sei den du misst Komplexität an der Anzahl der für den Programmcode benötigten Zeichen. Und spätestens wenn du mal statt 8-Bit Ints mit 32 Bit ints oder gar floats rechnen darfst, ist das mit der 'Komplexität' sowieso ein anderes Thema. Für den C Programmierer ist es nur ein anderer Datentyp. > Und was die Bewunderung anbetrifft... Jo mei. Die notwendige Komplexität > meiner Haussteuerung zum Beispiel soll doch in erster Linie nur > funktionieren! Dann bin ich schon glücklich. Publizier doch bitte mal deine Haussteuerung. Ein Haussteuerungsprojekt komplett in ASM, wäre wirklich ein schönes Beispiel für ein großes Projekt.
Scelumbro schrieb: > Schon wieder erzählst du uns von dem 'Plus an Performance und Minus and > Platzbedarf', veröffentlichst aber Code der offensichtlich noch nicht > optmiert ist. Ja was den nun? Der ist für seine geplanete Anwendung sogar schon sehr gut optimiert. So gut, daß sich bislang keiner getraut hat, mit mit C gegenzuhalten. Den kann ich gern nochmal anhängen- allein, ich vermute, ein echtes Interesse besteht da nicht. Hier gehts eher um Bashing gegen ASM... > Explizite Casts sind dazu > da, Fehler zu vermeiden in dem sie den Programmierer zwingen 1. nochmal > darüber nachzudenken ob ein Cast zwischen inkompatiblen Datentypen an > dieser Stelle überhaupt richtig ist 2. Einen potentiell 'gefährlichen' > Cast durch explizites hinschreiben zu dokumentieren. Hier geht es also > allein darum Programmierfehler zu vermeiden. Die man in ASM gar nicht erst macht ;-) Da gibts kein "inkompatible Datentypen"-Wissenschaft. > Im generierten > Maschinencode ist übrigens die Cast operation nicht mehr zu sehen, > kostet also weder Performance noch Platz. Ach? Hatte ich das vermutet? Ich spiele auf sinnlos Verkomplizierung des Quellcodes durch Konzepte/Konstruktionen aller Art an- war das nun nicht eindeutig? > Und spätestens wenn du mal statt 8-Bit Ints mit 32 Bit ints oder gar > floats rechnen darfst Ja ja rechnen. Ist ja gut und schön. Braucht man für AVR-MSR aber nur selten. > Publizier doch bitte mal deine Haussteuerung. Ein Haussteuerungsprojekt > komplett in ASM, wäre wirklich ein schönes Beispiel für ein großes > Projekt. Das könnte Dir so passen... Sonst noch Wünsche? Und jetzt kommt die Frechheit: Trotzdem sag ich weiter meine Meinung ;-)
Ich kann die ganze Diskussion um Assembler <-> C überhaupt nicht verstehen. Wer sich einfach mal die letzten 20 Jahre anschaut, wird erkennen, dass Hardware sich stetig weiterentwickelt. Dagegen sind Software-Algorithmen in der Entwicklungsgeschwindigkeit lahme Schnecken. Algorithmen, die man einmal programmiert hat, kann man auch 20 Jahre später weiter verwenden. Die Hardware jedoch nicht, die bekommt man noch nichtmals mehr zu kaufen. Wer Assembler programmiert, denkt keine 5 Meter weit. Er schreibt ein unportables Programm, dass bei einem Hardware-Wechsel komplett weggeworfen und neu geschrieben werden muss. Ein C-Programmierer muss sein Programm einfach an die neue Hardware anpassen - fertig. Nicht portable Programme braucht kein Mensch. Denn sie sind morgen schon tot.
Notiz an mich selbst: Nicht "mal eben" in der Frühstückspause µC.net lesen. Man kommt nicht mehr davon los und die Kollegen wundern sich über das laute lachen.
Frank M. schrieb: > Wer sich einfach mal die letzten 20 Jahre anschaut, wird erkennen, dass > Hardware sich stetig weiterentwickelt. Dagegen sind Software-Algorithmen > in der Entwicklungsgeschwindigkeit lahme Schnecken. > > Algorithmen, die man einmal programmiert hat, kann man auch 20 Jahre > später weiter verwenden. Die Hardware jedoch nicht, die bekommt man noch > nichtmals mehr zu kaufen. Ach was. AVR gibts schon so lange und die langen noch für viele weitere... Lasst Euch doch durch technische Entwicklungen nicht so unter Druck setzen. Aber OK, als Hobbyist kann man das entspannter sehen. > Wer Assembler programmiert, denkt keine 5 Meter weit. Er schreibt ein > unportables Programm, dass bei einem Hardware-Wechsel Lies nochmal weiter oben zu den Treibern für Hardware-Wechsel... > Nicht portable Programme braucht kein Mensch. Denn sie sind morgen schon > tot. Also meine liebe 128erMega Haussteuerung läuft bald ein ganzes Jahrzehnt :-)
Walter T. schrieb: > Notiz an mich selbst: Nicht "mal eben" in der Frühstückspause > µC.net > lesen. Man kommt nicht mehr davon los Ja hast Recht. Kann süchtig machen. Deshalb werd ich mich jetzt auch wieder anderen Dingen zuwenden und den Thread zur Ruhe kommen lassen ;-) Einen schönen Tag allen Beteiligten!
Moby schrieb: > Also meine liebe 128erMega Haussteuerung läuft bald ein ganzes Jahrzehnt > :-) Wie süß. Ich verdiene mein Geld unter anderem mit C-Programmen. Eines davon, das nach wie vor aktiv weiterentwickelt wird, gibt es seit Herbst 1992. Das ist immer noch C, auch wenn der Compiler schon etliche Male durch einen neuen, besseren ersetzt wurde, und das Betriebssystem, auf dem das ganze läuft, natürlich auch schon diverse Iterationen und Verschlimmbesserungen mitgemacht hat. Und auch wenn die Zielarchitektur bislang immer x86 war, würde es mich ein müdes Arschrunzeln kosten, mein Programm auf irgendwas anderem laufen zu lassen, sofern es mindestens 32 Bit breit ist.
Moby schrieb:
> den Thread zur Ruhe kommen lassen
Endlich!
Warum nicht gleich so.
:
Bearbeitet durch User
Moby schrieb: > Scelumbro schrieb: >> Schon wieder erzählst du uns von dem 'Plus an Performance und Minus and >> Platzbedarf', veröffentlichst aber Code der offensichtlich noch nicht >> optmiert ist. Ja was den nun? > > Der ist für seine geplanete Anwendung sogar schon sehr gut optimiert. > So gut, daß sich bislang keiner getraut hat, mit mit C gegenzuhalten. > Den kann ich gern nochmal anhängen- allein, ich vermute, ein echtes > Interesse besteht da nicht. Hier gehts eher um Bashing gegen ASM... Ja, bitte, bitte einmal posten... so das es kompilierfähig ist...idealerweise mit stats von dir (ram/flash/eep verbrauch). 73
>Das ist dann aber auch schon der einzige Moment, neidisch >hinüberzuschielen :-) > Viele >viele künstliche Konstruktionen der Hochsprache überflüssig werden. Ist das so? Wie sieht denn der asm Code für folgendes künstliche Konstrukt aus:
1 | volatile
|
2 | struct
|
3 | {
|
4 | uint8_t u8CntFct; |
5 | void ( *apfct[8] ) (void); |
6 | //---------------------------------------------------------
|
7 | uint32_t u32TickMs; |
8 | uint32_t u32TickSec; |
9 | }
|
10 | scEsc_SysTick; |
11 | |
12 | |
13 | |
14 | |
15 | void SysTick_Handler(void) |
16 | {
|
17 | //-- TimeTick erhöhen -------------------------------------
|
18 | scEsc_SysTick.u32TickMs++; |
19 | |
20 | //-- UserFunktion aufrufen --------------------------------
|
21 | uint8_t u8Idx = 0; |
22 | uint8_t u8Max = (uint8_t) ( sizeof(scEsc_SysTick.apfct ) |
23 | / sizeof(scEsc_SysTick.apfct[0]) ); |
24 | while ( u8Idx != u8Max ) |
25 | {
|
26 | void ( *pfct ) (void) = scEsc_SysTick.apfct[u8Idx++]; |
27 | if ( pfct != 0 ) |
28 | {
|
29 | (*pfct) (); |
30 | }
|
31 | }
|
32 | //---------------------------------------------------------
|
33 | return; |
34 | }
|
Matthias L. schrieb: > Wie sieht denn der asm Code für folgendes künstliche Konstrukt aus: Warum sieht das nur so aus, als wollte jemand auf biegen und brechen einen objektorientierten Ansatz in C emulieren?
>Warum sieht das nur so aus, als wollte jemand auf biegen und brechen >einen objektorientierten Ansatz in C emulieren? Weil es eben nur C ist. Oder fragst Du auch immer, wenn jemand über ein Array iteriert: "Warum sieht das nur so aus, als wollte jemand auf biegen und brechen ein for each in C emulieren?"
Walter T. schrieb: > Warum sieht das nur so aus, als wollte jemand auf biegen und brechen > einen objektorientierten Ansatz in C emulieren? Weil du das auf biegen und brechen darin siehst? Ist ein ganz gewöhnliches Verfahren für Timer-Handler.
>>Warum sieht das nur so aus, als wollte jemand auf biegen und brechen >>einen objektorientierten Ansatz in C emulieren? Aber indirekt sagst du es ja damit. Weil solche "Konstrukte" mühsam selbst herzustellen sind, wurde die Sprache C in C++ erweitert, wo sowas dann als Befehl verfügbar wurde. Genauso entstand aus ASM mal C. Als man sich nicht mehr damit beschäftigen wollte, mühsam Schleifen in asm zu schreiben. Das Ziel war ja nicht die Schleife selbst, sondern das, was in der Schleife abgearbeitet werden sollte...
Matthias L. schrieb: > Ist das so? > > Wie sieht denn der asm Code für folgendes künstliche Konstrukt aus: > volatile > struct > { > uint8_t u8CntFct; > void ( *apfct[8] ) (void); > //--------------------------------------------------------- > uint32_t u32TickMs; > uint32_t u32TickSec; > } > scEsc_SysTick; > > void SysTick_Handler(void) > { > //-- TimeTick erhöhen ------------------------------------- > scEsc_SysTick.u32TickMs++; > > //-- UserFunktion aufrufen -------------------------------- > uint8_t u8Idx = 0; > uint8_t u8Max = (uint8_t) ( sizeof(scEsc_SysTick.apfct ) > / sizeof(scEsc_SysTick.apfct[0]) ); > while ( u8Idx != u8Max ) > { > void ( *pfct ) (void) = scEsc_SysTick.apfct[u8Idx++]; > if ( pfct != 0 ) > { > (*pfct) (); > } > } > //--------------------------------------------------------- > return; > } Ist doch einfach (ganz intuitiv runter geschrieben):
1 | .file "a.c" |
2 | __SP_H__ = 0x3e |
3 | __SP_L__ = 0x3d |
4 | __SREG__ = 0x3f |
5 | __tmp_reg__ = 0 |
6 | __zero_reg__ = 1 |
7 | .comm scEsc_SysTick,25,1 |
8 | .text |
9 | .global SysTick_Handler |
10 | .type SysTick_Handler, @function |
11 | SysTick_Handler: |
12 | push r28 |
13 | push r29 |
14 | rcall . |
15 | rcall . |
16 | in r28,__SP_L__ |
17 | in r29,__SP_H__ |
18 | /* prologue: function */ |
19 | /* frame size = 4 */ |
20 | /* stack size = 6 */ |
21 | .L__stack_usage = 6 |
22 | lds r24,scEsc_SysTick+17 |
23 | lds r25,scEsc_SysTick+17+1 |
24 | lds r26,scEsc_SysTick+17+2 |
25 | lds r27,scEsc_SysTick+17+3 |
26 | adiw r24,1 |
27 | adc r26,__zero_reg__ |
28 | adc r27,__zero_reg__ |
29 | sts scEsc_SysTick+17,r24 |
30 | sts scEsc_SysTick+17+1,r25 |
31 | sts scEsc_SysTick+17+2,r26 |
32 | sts scEsc_SysTick+17+3,r27 |
33 | std Y+1,__zero_reg__ |
34 | ldi r24,lo8(8) |
35 | std Y+2,r24 |
36 | rjmp .L2 |
37 | .L3: |
38 | ldd r24,Y+1 |
39 | ldi r25,lo8(1) |
40 | add r25,r24 |
41 | std Y+1,r25 |
42 | mov r24,r24 |
43 | ldi r25,0 |
44 | lsl r24 |
45 | rol r25 |
46 | subi r24,lo8(-(scEsc_SysTick+1)) |
47 | sbci r25,hi8(-(scEsc_SysTick+1)) |
48 | mov r30,r24 |
49 | mov r31,r25 |
50 | ld r24,Z |
51 | ldd r25,Z+1 |
52 | std Y+4,r25 |
53 | std Y+3,r24 |
54 | ldd r24,Y+3 |
55 | ldd r25,Y+4 |
56 | sbiw r24,0 |
57 | breq .L2 |
58 | ldd r24,Y+3 |
59 | ldd r25,Y+4 |
60 | mov r30,r24 |
61 | mov r31,r25 |
62 | icall |
63 | .L2: |
64 | ldd r25,Y+1 |
65 | ldd r24,Y+2 |
66 | cp r25,r24 |
67 | brne .L3 |
68 | nop |
69 | /* epilogue start */ |
70 | pop __tmp_reg__ |
71 | pop __tmp_reg__ |
72 | pop __tmp_reg__ |
73 | pop __tmp_reg__ |
74 | pop r29 |
75 | pop r28 |
76 | ret |
77 | .size SysTick_Handler, .-SysTick_Handler |
78 | .ident "GCC: (GNU) 4.8.1" |
79 | .global __do_clear_bss |
A. K. schrieb: > Ist ein ganz gewöhnliches Verfahren für Timer-Handler. Gibt es da eine Beschreibung zu? An "Good Practice"-Ansätzen bin ich immer interessiert.
Klaus W. schrieb: > Ist doch einfach (ganz intuitiv runter geschrieben): Reingefallen. ;-) Das ist ein Interrupt-Handler, muss also prozessorspezifisch entsprechend umgesetzt werden.
:
Bearbeitet durch User
>Ist doch einfach (ganz intuitiv runter geschrieben): Und Du meinst, das das leserlicher ist? Immerhin hat ja >Walter Tarpan (nicolas) >>Warum sieht das nur so aus, als wollte jemand auf biegen und brechen >>einen objektorientierten Ansatz in C emulieren? sofort erkannt, was es macht.
Matthias L. schrieb: > Und Du meinst, das das leserlicher ist? Hat dein Ironie-Detektor grad Urlaub?
Walter T. schrieb: > Gibt es da eine Beschreibung zu? An "Good Practice"-Ansätzen bin ich > immer interessiert. Stimmt, eines hätte ich zum Thema "Good Practice" anzumerken: Da der Code stark nach 32-Bit riecht, würde ich raten, lokale Variablen nicht ohne Not als 8/16-Bit Typen zu deklarieren. GCC kriegt hier zwar spitz, dass er dafür keine Verrenkungen machen muss, aber das schafft er nicht immer.
Klaus W. schrieb: > Ist doch einfach (ganz intuitiv runter geschrieben): Ist ja Schummel, Du hast die Optimierung ausgeschaltet. -Os:
1 | void SysTick_Handler(void) |
2 | {
|
3 | 32: cf 93 push r28 |
4 | 34: df 93 push r29 |
5 | //-- TimeTick erhöhen -------------------------------------
|
6 | scEsc_SysTick.u32TickMs++; |
7 | 36: 80 91 71 00 lds r24, 0x0071 |
8 | 3a: 90 91 72 00 lds r25, 0x0072 |
9 | 3e: a0 91 73 00 lds r26, 0x0073 |
10 | 42: b0 91 74 00 lds r27, 0x0074 |
11 | 46: 01 96 adiw r24, 0x01 ; 1 |
12 | 48: a1 1d adc r26, r1 |
13 | 4a: b1 1d adc r27, r1 |
14 | 4c: 80 93 71 00 sts 0x0071, r24 |
15 | 50: 90 93 72 00 sts 0x0072, r25 |
16 | 54: a0 93 73 00 sts 0x0073, r26 |
17 | 58: b0 93 74 00 sts 0x0074, r27 |
18 | 5c: c0 e0 ldi r28, 0x00 ; 0 |
19 | 5e: d0 e0 ldi r29, 0x00 ; 0 |
20 | uint8_t u8Idx = 0; |
21 | uint8_t u8Max = (uint8_t) ( sizeof(scEsc_SysTick.apfct ) |
22 | / sizeof(scEsc_SysTick.apfct[0]) ); |
23 | while ( u8Idx != u8Max ) |
24 | {
|
25 | void ( *pfct ) (void) = scEsc_SysTick.apfct[u8Idx++]; |
26 | 60: fe 01 movw r30, r28 |
27 | 62: ee 0f add r30, r30 |
28 | 64: ff 1f adc r31, r31 |
29 | 66: e0 5a subi r30, 0xA0 ; 160 |
30 | 68: ff 4f sbci r31, 0xFF ; 255 |
31 | 6a: 01 80 ldd r0, Z+1 ; 0x01 |
32 | 6c: f2 81 ldd r31, Z+2 ; 0x02 |
33 | 6e: e0 2d mov r30, r0 |
34 | if ( pfct != 0 ) |
35 | 70: 30 97 sbiw r30, 0x00 ; 0 |
36 | 72: 09 f0 breq .+2 ; 0x76 <__SREG__+0x37> |
37 | {
|
38 | (*pfct) (); |
39 | 74: 09 95 icall |
40 | 76: 21 96 adiw r28, 0x01 ; 1 |
41 | |
42 | //-- UserFunktion aufrufen --------------------------------
|
43 | uint8_t u8Idx = 0; |
44 | uint8_t u8Max = (uint8_t) ( sizeof(scEsc_SysTick.apfct ) |
45 | / sizeof(scEsc_SysTick.apfct[0]) ); |
46 | while ( u8Idx != u8Max ) |
47 | 78: c8 30 cpi r28, 0x08 ; 8 |
48 | 7a: d1 05 cpc r29, r1 |
49 | 7c: 89 f7 brne .-30 ; 0x60 <__SREG__+0x21> |
50 | (*pfct) (); |
51 | }
|
52 | }
|
53 | //---------------------------------------------------------
|
54 | return; |
55 | }
|
56 | 7e: df 91 pop r29 |
57 | 80: cf 91 pop r28 |
58 | 82: 08 95 ret |
Klaus W. schrieb: > Ist doch einfach (ganz intuitiv runter geschrieben): > > .ident "GCC: (GNU) 4.8.1" Der war gut. :-) Matthias L. schrieb: > Und Du meinst, das das leserlicher ist? Der war nicht so gut. :-)
Hmm, ist der hier...
1 | void SysTick_Handler(void) |
...und der hier...
1 | (*pfct) (); |
...nicht genau der, wo mir weiter oben nahegelegt wurde, ich solle das wegen fehlender Inline-Möglichkeiten lassen?
Horst S. schrieb: > ...nicht genau der, wo mir weiter oben nahegelegt wurde, ich solle das > wegen fehlender Inline-Möglichkeiten lassen? So viel zum Prinzipienreiten. ;-) Die codeseitig optimierte Version schreibt alle Aktionen direkt in die ISR um beim AVR push/pop-Orgien zu reduzieren. Die modulare Version macht das wie hier und nimmt einen grösseren Aufwand in Kauf. Da der Code allerdings mit den Cortexen im Hinterkopf geschrieben wurde ist das wieder fast egal. Da ist der Unterschied gering. Das im Grunde die generelle Frage bei Optimierung: auf was man optimiert. Soll der Prozessor schnellstmöglich fertig werden? Oder soll der Programmierer schnellstmöglich fertig werden? Letzteres nimmt einen bisweilen etwas höheren Resourcenverbrauch billigend in Kauf.
:
Bearbeitet durch User
@Moby (falls du noch mitliest): Etwas offtopic und nur aus Interesse: In dem von Jörg verlinkten Beitrag mit dem ADC-Code für den LM335 kommen folgende Programmzeilen vor, die mich etwas stutzig machen:
1 | : |
2 | bst IC,7 ;IC7=0: 5V0, IC7=1: 1V1 |
3 | : |
4 | bst IC,6 |
5 | : |
6 | |
7 | ;In SRAM (Variablen) |
8 | ;=================== |
9 | |
10 | .DSEG |
11 | |
12 | IC: .BYTE 1 ;Interrupt Counter |
13 | : |
BST erwartet normalerweise ein Register als erstes Argument. Bei dir steht da aber ein Label (IC), das für eine 16-Bit-Datenadresse steht. Beim GNU-Assembler führt dies zu einer Fehlermeldung, der Atmel- Assembler hingegen scheint es zu akzeptieren. Ich frage mich nur, welchen Binärcode er daraus generiert. Wenn du nicht geschrieben hättest, dass der Code im Einsatz ist und seine Sache gut macht, hätte ich das für einen Flüchtigkeitsfehler angesehen. Oder ist BST in Wirklichkeit ein Makro (sofern ein Makro überhaupt gleich wie ein CPU-Befehl heißen darf), hinter dem sich etwas in der Art verbirgt:
1 | push r0 |
2 | lds r0,<addr> |
3 | bst r0,<bitno> |
4 | pop r0 |
Ich habe kein Atmel-Studio installiert, sonst würde ich es schnell ausprobieren. Yalu, der Assemblerprogrammierung in den meisten Fällen für sinnlos hält, manchmal jedoch trotzdem einen Heidenspaß daran hat, den letzten Taktzyklus aus dem Prozessor zu herausquetschen :)
Yalu X. schrieb: > BST erwartet normalerweise ein Register als erstes Argument. Bei dir > steht da aber ein Label (IC), das für eine 16-Bit-Datenadresse steht. Möglicherweise haben die Register-Aliase in Atmels Assembler einen eigenen Namespace und Moby hat der besseren Übersichtlichkeit zuliebe den Namen doppelt verwendet.
A. K. schrieb: > So viel zum Prinzipienreiten. ;-) Ich dachte nur: Wollt Ihr Moby jetzt 'ne Steilvorlage geben? A. K. schrieb: > Soll der Prozessor schnellstmöglich fertig werden? Oder soll > der Programmierer schnellstmöglich fertig werden? Der war gut, da hab ich mich echt schlapp drüber gelacht. (Besser hätte man es wohl nicht ausdrücken können.)
> @Moby:
Zeig mal was du kannst:
Beitrag "Problem mit asm Routine"
Auf solche Fragen wie in dem Beitrag, hat noch keiner was von Moby
gehört. Das wäre ja viel zu konkret. Außerdem ganz ohne Hochsprache, die
man hassen könnte. ;-)
Carl D. schrieb: > Auf solche Fragen wie in dem Beitrag, hat noch keiner was von Moby > gehört. Das wäre ja viel zu konkret. Außerdem ganz ohne Hochsprache, die > man hassen könnte. ;-) Solche Probleme hat er einfach nicht. Er kramt seine Standardroutinen für UART raus und fertig. Ok, fast fertig, wäre es nicht genau dieser eine µC, der die UART nur mit LDS/STS adressieren kann...
Yalu X. schrieb: > @Moby (falls du noch mitliest): > > Etwas offtopic und nur aus Interesse: > > bst IC,6 > .DSEG > IC: .BYTE 1 > > BST erwartet normalerweise ein Register als erstes Argument. > Bei dir steht da aber ein Label (IC), das für eine > 16-Bit-Datenadresse steht. > Beim GNU-Assembler führt dies zu einer Fehlermeldung, Aber nur, wenn IC >= 32 ist. Ansonsten wird es als Registernummer interpretiert. Anstatt ein AND "R0, R2" geht mit avr-as also auch "AND 0, 1+1". Das ist ok weil sich bei AVR die Typen der Operanden eindeutig aus den Mnemonics ergeben. > Yalu, > der Assemblerprogrammierung in den meisten Fällen für sinnlos hält, > manchmal jedoch trotzdem einen Heidenspaß daran hat, den letzten > Taktzyklus aus dem Prozessor zu herausquetschen :)
Bitte nicht weiter den Kopf zerbrechen, das ist ein Fehler. Das Original, in dem IC ein Register ist, habe ich hier zur universellen Verwendung als Modul mit IC im RAM (nicht ganz vollständig) umformuliert. Wird korrigiert. Etwas erschrocken bin ich freilich, daß es erst jetzt jemandem auffällt... Verstehen hier wirklich so wenige noch Asm? Dann wird mir allerdings mancher "kundige" Kommentar hier viel verständlicher ;-)
Carl D. schrieb: > @Moby: > > Zeig mal was du kannst: > Beitrag "Problem mit asm Routine" > > Auf solche Fragen wie in dem Beitrag, hat noch keiner was von Moby > gehört. Na ich fürchte von manchem anderen auch nicht. Wie schauts da mit Dir aus? Für Projekte aller Art hätte ich auch noch viel Arbeit zu vergeben ;-)
Und schon haben wir ein Datentypenproblem in ASM gefunden, nur wäre der C Compiler so nett einen zu warnen wenn man einen Funktionspointer als Datenpointer verwenden will, wodurch es erst Datentypenproblem auffällt. Nur weil einen der Assembler nicht warnt/es verbietet heißt das noch lange nicht dass es das nicht gibt.
A. K. schrieb: > Solche Probleme hat er einfach nicht. Er kramt seine Standardroutinen > für UART raus und fertig. Ok, fast fertig, wäre es nicht genau dieser > eine µC, der die UART nur mit LDS/STS adressieren kann... Die sind einfach nur Teil fertiger, Controller-spezifischer Vorlagen. Zugriff via In/Out, Lds/Sts oder ganz Xmega-modern als DMA Variante...
Tse schrieb: > Und schon haben wir ein Datentypenproblem in ASM gefunden, nur > wäre der C Compiler so nett einen zu warnen wenn man einen > Funktionspointer als Datenpointer verwenden will, wodurch es erst > Datentypenproblem auffällt. Haben wir nicht. BLD/BST sollten schlicht nur mit Registern bewaffnet als OK durchgehen, so schlau sollte der Assembler dann schon sein.
Moby schrieb: > BLD/BST sollten schlicht nur mit Registern bewaffnet als OK durchgehen, > so schlau sollte der Assembler dann schon sein. Das macht es im Prinzip auch. Nur du solltest dich mal schlau machen, was die 'Spezialbezeichnung' Register überhaupt bedeutet.
Moby schrieb: > so schlau sollte der Assembler dann schon sein. Ach? Nun auf einmal doch? ;-) Assembler ist GIGO-Programmierung. Garbage In, Garbage Out.
Johann L. schrieb: > Yalu X. schrieb: >> BST erwartet normalerweise ein Register als erstes Argument. >> Bei dir steht da aber ein Label (IC), das für eine >> 16-Bit-Datenadresse steht. >> Beim GNU-Assembler führt dies zu einer Fehlermeldung, > > Aber nur, wenn IC >= 32 ist. Ansonsten wird es als Registernummer > interpretiert. Aber nur, wenn IC konstant und dem Assembler bekannt ist. In diesem Fall ist IC aber eine Adresse, die sich erst der Linker ausdenkt. Deswegen meint der Assembler:
1 | Error: constant value required |
Moby schrieb: > Bitte nicht weiter den Kopf zerbrechen, das ist ein Fehler. Das > Original, in dem IC ein Register ist, habe ich hier zur universellen > Verwendung als Modul mit IC im RAM (nicht ganz vollständig) > umformuliert. Ok, aber warum schreibst du dann, der Code sei bereits im Einsatz, wenn er quasi neu und wahrscheinlich noch nicht einmal durch den Assembler gelaufen ist? > Etwas erschrocken bin ich freilich, daß es erst jetzt jemandem > auffällt... Verstehen hier wirklich so wenige noch Asm? Na, wenn der Fehler sogar dir als Assembler-Gott passiert ist, was erwartest du dann von den anderen? ;-)
Yalu X. schrieb: > Assembler-Gott :-) Und ich hatte gerade an 'selbsternannter Assembler-Papst' gedacht.
TriHexagon schrieb: > "Wer als Werkzeug nur einen Hammer > hat, sieht in jedem Problem einen Nagel." :P Oder: "Wer bis jetzt nur Nägel als Problem hatte, sieht in einem Hammer das einzig wahre Werkzeug."
Moby schrieb: > BLD/BST sollten schlicht nur mit Registern bewaffnet als OK durchgehen, > so schlau sollte der Assembler dann schon sein. Wäre der Assembler in Assembler geschrieben, wäre das natürlich nicht passiert! Moby schrieb: > [...], das ist ein Fehler. [...] Etwas erschrocken bin ich freilich, > daß es erst jetzt jemandem auffällt... Weil keiner deinen grottogen Code liest. > Verstehen hier wirklich so wenige noch Asm? Dann wird mir > allerdings mancher "kundige" Kommentar hier viel verständlicher Kier können viele Asm. Aber dier gezeigte Code wäre in einer Hochsprache genauso Sch.... weil deine Code-"Kommentare" vermutlich genauso Sch.... wären.
Moby schrieb: > Etwas erschrocken bin ich freilich, daß es erst jetzt jemandem > auffällt... Daran kannst du sofort erkennen, dass keiner deinen Code benutzt.
Jörg W. schrieb: > Daran kannst du sofort erkennen, dass keiner deinen Code benutzt. Nicht mal er selber :-) Johann L. schrieb: > Wäre der Assembler in Assembler geschrieben, wäre das natürlich nicht > passiert! Aber es wäre viel schneller nicht passiert!
Jörg W. schrieb: > Moby schrieb: > Etwas erschrocken bin ich freilich, daß es erst jetzt jemandem > auffällt... > > Daran kannst du sofort erkennen, dass keiner deinen Code benutzt. Vor dem Benutzen kommt aber schon Lesen und Verstehen ;-) Ralf G. schrieb: > selbsternannter Assembler-Papst Nur weil ich von Asm überzeugt bin ? Daran ändern auch Fehler (die natürlich sonst niemand macht) kein Jota. Yalu X. schrieb: > Ok, aber warum schreibst du dann, der Code sei bereits im Einsatz. Na ja,bis auf Kleinigkeiten ;-)
Johann L. schrieb: > weil deine Code-"Kommentare" vermutlich > genauso Sch.... wären. Die haben auch nicht den Anspruch jemandem Asm beizubringen. Auch nicht, das Datenblatt zu ersetzen. Gönne jedem Hochsprachler ja die Genugtuung, auf den Fehler eines ASMlers mit dem Finger zu zeigen. Wenn die Absicht der abwertenden Kommentare nur nicht so eindeutig wäre...
> Wenn die Absicht der abwertenden Kommentare nur nicht so > eindeutig wäre... tit for tat
:
Bearbeitet durch User
Moby schrieb: > Die haben auch nicht den Anspruch jemandem Asm beizubringen. Das wäre auch nicht nötig. Aber wenn man beim Draufgucken auf den Code weder sieht, was da wirklich passiert (geht bei Assembler nicht so einfach, viele Zwischenschritte) noch es passend in Kommentaren erklärt wird, was glaubst du, wer dann noch gewillt ist, eine weitere Minute darin zu verschwenden, das auch zu benutzen? Gerade Assemblercode muss ordentlich kommentiert sein, damit jemand anders überhaupt eine Idee hat, nicht was du da treibst (das kann man im Referenzhandbuch der CPU nachlesen), sondern warum du es genau so gemacht hast. Um dir mal eine Idee zu geben (Funktion strlen_P() der avr-libc, Autor ist Marek Michalkiewicz):
1 | #define src_hi r25 |
2 | #define src_lo r24 |
3 | |
4 | ; 11 words, (14 + __strlen_P(src) * 8) cycles |
5 | |
6 | ASSEMBLY_CLIB_SECTION |
7 | .global _U(__strlen_P) |
8 | .type _U(__strlen_P), @function |
9 | _U(__strlen_P): |
10 | X_movw ZL, src_lo |
11 | .L_strlen_P_loop: |
12 | X_lpm r0, Z+ |
13 | tst r0 |
14 | brne .L_strlen_P_loop |
15 | ; return Z - 1 - src = (-1 - src) + Z = ~src + Z |
16 | com src_lo |
17 | com src_hi |
18 | add src_lo, ZL |
19 | adc src_hi, ZH |
20 | ret |
21 | .L_strlen_P_end: |
22 | .size _U(__strlen_P), .L_strlen_P_end - _U(__strlen_P) |
Dazu gehört allerdings noch die Beschreibung der eigentlichen Funktionalität:
1 | /** \ingroup avr_pgmspace
|
2 | \fn size_t strlen_P(PGM_P src)
|
3 | |
4 | The strlen_P() function is similar to strlen(), except that src is a
|
5 | pointer to a string in program space.
|
6 | |
7 | \returns The strlen_P() function returns the number of characters in src.
|
8 | */
|
Das das ein C-artiger Kommentar ist, hängt damit zusammen, dass er von Doxygen dann eingesammelt wird und zum Nutzerhandbuch verarbeitet. Das ist das, weshalb die Nutzer die Funktion am Ende auch benutzen, nicht weil sie irgendwie cool implementiert ist, sondern weil sie eine brauchbare Beschreibung ihrer Funktionalität bekommen.
So, der kleine Fehler ist korrigiert! Lenkt Eure Aufregung nun wieder in produktive Bahnen: Hab mal meine bereits weiter oben zur Sprache gekommene ASM Lösung aus einem anderen Hochsprachen-Thread(problem) angehängt. Zeigt mal, wie sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen lässt. Das würde ja auf mich viel eher Eindruck machen ;-)
Zu deiner Info, falls es dir immer noch niemand erzählt hat: Eine LED blinken zu lassen, ist das dämlichste Beispiel, um zu entscheiden, welche Sprache sinnvoll ist. Einfach, weil man das einmal am Anfang macht (normale Leute zumindest) und dann richtige Programme kommen. Inzwischen nervt es wirklich...
:
Bearbeitet durch User
Jörg W. schrieb: > Gerade Assemblercode muss ordentlich kommentiert sein, damit jemand > anders überhaupt eine Idee hat, nicht was du da treibst (das kann > man im Referenzhandbuch der CPU nachlesen), sondern warum du es > genau so gemacht hast. Die Art zu kommentieren mag ich nun ganz und gar nicht diskutieren, weil ich die zu großen Teilen für wenig objektiv begründbar halte. Entsprechend variabel sind auch die Kommentierungen, die man so sieht. In Asm muss man nicht jede Zeile kommentieren weil schlicht da steht was los ist. Kleinere Unterprogrammeinheiten bekommen dann ihre Funktion bzw. ggf. ihr Interface kommentiert- und gut ist. Schau mal Deine .define's zum Beispiel. In größeren Programmen kannst Du oft keine feste namensgebundene Register Zuordnung machen wenn diese mehrfach sehr verschiede Verwendung finden sollen. Schön, daß Du eine sachliche Meinung äußerst; die Art der Kommentierung mag in Hochsprache ja gebräuchlich sein. Mit Datenblatt und der Kenntnis der wenigen Dutzend Asm-Instruktionen bewaffnet stellt die Doku in Asm andere Anforderungen bis hin zur bloßen Geschmackssache. Generell gilt für Doku glaub ich keine Mengenbeschränkung. Viel hilft viel (oder manchmal weniger); Absicht (Produktiv, Archiv, Lehre) und Übersicht des Codes spielen dabei die entscheidende Rolle.
Klaus W. schrieb: > Inzwischen nervt es wirklich... Fangen wir doch einfach mal klein an. @Moby hast du schon gelesen? Jörg W. schrieb: > Dazu gehört allerdings noch die Beschreibung der eigentlichen > Funktionalität:
Klaus W. schrieb: > Zu deiner Info, falls es dir immer noch niemand erzählt hat: > Eine LED blinken zu lassen, ist das dämlichste Beispiel, um zu > entscheiden, welche Sprache sinnvoll ist. Zu Deine Info: Ergründe besser erstmal richtig Sinn und Zweck des Programms. Klaus W. schrieb: > Inzwischen nervt es wirklich... ... etwa ASM- Programme nicht lesen zu können ??? Ja. Denn wie soll man sonst viele Punkte pro Asm auch nachvollziehen können (wollen)...
Ralf G. schrieb: > @Moby > hast du schon gelesen? > Jörg W. schrieb: >> Dazu gehört allerdings noch die Beschreibung der eigentlichen >> Funktionalität: @Ralf G. Hast Du schon gelesen?
Also - ich bin jetzt weder C- noch Assembler-Profi. Ich kann von beidem etwas, aber nicht viel. Programmiert habe ich Cobol, PL/1, Pascal und ABAP/4 (nicht gerade technisch :-) ), Basic und Assembler (C64). Ich bin der Meinung, dass die verwendete Programmiersprache der gewünschten Anwendung angepasst sein muss. Ich würde niemals Assembler (habe ich schon gesehen) für eine reine Datenbank-Auswertung in List-Form einsetzen. Genau so wenig ist der Einsatz von Lisp für eine Funkuhr (mir fällt nichts besseres ein) sinnvoll. Je nach ANWENDUNG macht der Einsatz einer Programmiersprache Sinn. Assembler - wer es kann, warum nicht - mit Makro-Einsatz auf dem AVR ist sehr nah an der CPU und vermittelt wahrscheinlich eher ein Gefühl und Verständnis für die Hardware. Schneller ist es möglicherweise auch - in einigen Fällen. Anfangs habe ich damit programmiert - bin aber irgendwann zu C gewechselt, weil es "universeller" - und leichter verständlich (aus meiner sehr eigenen Sicht) ist. Beruflich würde ich den effizientesten - und zwar primär vom Entwicklungsaufwand her - Ansatz wählen. Bei extrem zeitkritischen Anwendungen (damit habe ich aktuell nicht zu tun) würde ich natürlich die Ausführungsgeschwindigkeit in den Vordergrund stellen. Also immer zweckgebunden - und nicht programmatisch ... Gruß Dieter
Moby A. schrieb: > In Asm muss man nicht jede Zeile kommentieren weil schlicht da steht was > los ist. Grad bei 8-Bittern finden sich sehr oft zusammengesetzte Operationen. Und da ist es doch manchmal nützlich, dem Leser das Leben etwas zu erleichtern. Nicht zuletzt bei AVRs, bei denen man manchmal das Gegenteil von dem hinschreibt was man im Sinn hat. Also subtrahiert wo man eigentlich addieren will, weil es den Additionsbefehl nicht gibt.
Moby A. schrieb: > Mit Datenblatt und der Kenntnis > der wenigen Dutzend Asm-Instruktionen bewaffnet stellt die Doku in Asm > andere Anforderungen bis hin zur bloßen Geschmackssache. Das ist aber eigentlich nicht der Sinn einer ordentlichen Dokumentation. Man sollte den Geedanken des Porgrammierers erkennen können ohne lang Befehle und Datenblätter zu studieren.
A. K. schrieb: > Grad bei 8-Bittern finden sich sehr oft zusammengesetzte Operationen. > Und da ist es doch manchmal nützlich, dem Leser das Leben etwas zu > erleichtern. Zum Verstehen ist das Datenblatt und meinetwegen noch das dokumentierte Instruction-Set da. Klar ist dies und jenes mehr oder weniger nützlich- so wie die Ansprüche individuell unterschiedlich sind. Obiges Beispiel hab ich für meine Verhältnisse schon reichhaltigst kommentiert. A. K. schrieb: > Nicht zuletzt bei AVRs, bei denen man manchmal das > Gegenteil von dem hinschreibt was man im Sinn hat. Also subtrahiert wo > man eigentlich addieren will, weil es den Additionsbefehl nicht gibt. Na danke. Da wird man echt nicht fertig. Der ASM Kenner (und dazu gehört im Gegensatz zum C-Universum nicht viel dazu) weiß was gespielt wird. Für jeden anderen spiele ich als Programmierer nicht den Schulungsonkel. Ganz anders bei Code zur Lehre- den didaktischenAnspruch hab ich nicht.
Moby A. schrieb: > Zu Deine Info: Ergründe besser erstmal richtig Sinn und Zweck des > Programms. Genau da liegt das Problem: es macht so gut wie nichts. Das kann man ja sogar diskret aufbauen. Wozu dann noch Assembler? Nur weil man es kann? Mit ein paar Gattern sparst du sogar noch die letzten Byte gegnüber deiner Lösung. Bei Programmen mit einer halbwegs realistischen Komplexität können wir und gerne wieder unterhalten. Ich habe irgendwie keine Lust, nach Jahren immer noch über Taste drücken + oh, es leuchtet was zu philosophieren.
Moby A. schrieb: > Hast Du schon gelesen? Meinst du das, was du hier... Beitrag "Re: C versus Assembler->Performance" ...geschrieben hast? War beim Schreiben meines Posts noch nicht da. Hab' bisschen getrödelt. Oder meinst du...
1 | ;Funktionalität: |
2 | |
3 | ;[A] LED0 = KEY0.state; // an solange Taste gedrückt |
4 | ;[B] LED1.toggle = KEY1.press // wechsel bei jeder Drückflanke |
5 | ;[C] LED2.off = KEY2.press_short; // kurz drücken - aus |
6 | ;[D] LED2.on = KEY2.press_long; // lang drücken - an |
7 | ;alle 3 Tasten entprellt und mit Zeiterfassung(Pressed-Status) |
8 | ;auf bis zu 8 erweiterbar |
... das? Ich dachte, du bist auf dem richtigen Weg. In beiden Fällen hast du leider gezeigt, dass du nicht begriffen hast, worum es überhaupt geht: - Was kann die Funktion/ das Programm? - Welche Parameter muss ich übergeben, welche Werte erhalte ich zurück/ Was muss wo an welchen µC angeschlossen werden Daraus folgt: (1) kann ich nicht verwenden :-( oder (2) Juhu, genau das habe ich gesucht. Das nehme ich. Es geht nicht darum den Code zu entschlüsseln oder zu verstehen.
Tse schrieb: > Man sollte den Geedanken des Porgrammierers erkennen können ohne lang > Befehle und Datenblätter zu studieren. Befehle und Datenblätter sind in Assembler durch nichts, aber auch gar nichts zu ersetzen!
>Zeigt mal, wie sich die Funktionalität in höchstens gleicher C -Codegröße >umsetzen lässt. Zeigt doch mal eine textuelle Beschreibung, oder ein Signalfluss oder Ablaufplan oder sonstwas um zu sagen, was das Programm machen soll. Ich zumindest, habe keine Lust, den asm-Code zurück zu interpretieren, und den Programmablauf zu erraten...
Moby A. schrieb: > Befehle und Datenblätter sind in Assembler durch nichts, aber auch gar > nichts zu ersetzen! Beim Schreiben hast du recht, beim lesen sollte man aber wenigstens den zu Grunde liegenden Algorithmus verstehen können ohne alle paar Zeilen ein Reister/Befehl nachschlagen zu müssen. Oder man macht es sich einfach und gibt zu, dass der Code schlecht dokumentiert ist.
Klaus W. schrieb: > Genau da liegt das Problem: es macht so gut wie nichts. Du verstehst es nicht. Sag es doch so wie es ist ;-) Aber tröste Dich mit dem Gedanken, mit C mag ich auch nichts anfangen. Ein C-Programm für die PC- Kommandozeile hab ich mal verbrochen- dann hatte ich echt genug von diesem sperrigen, umständlichen, langzeiligen, kryptischen Zeug (war mein Empfinden).
Moby A. schrieb: > Na danke. Da wird man echt nicht fertig. Der ASM Kenner (und dazu gehört > im Gegensatz zum C-Universum nicht viel dazu) weiß was gespielt wird. Nun habe ich schon mit recht vielen Assemblern zu tun gehabt, nicht selten praktisch gleichzeitig, und da gibt es die ulkigsten Kombinationen, wie man Dinge schreiben kann. So gibt es in Assembler mal die rechts-nach-links Konvention, also add dest, source und man die links-nach-rechts Konvention add source, dest und manchmal bei der gleichen Maschine beide, je nach Assembler. Besonders originell stellt sich das bei Vergleichsbefehlen dar, weil in cmp x, y bgt l1 nicht sofort klar ist, ob bei x>y oder x<y gesprungen wird. Nicht einmal dann, wenn die Architektur üblicherweise links-nach-rechts vorgibt. Weil es welche gibt, die eben deshalb Vergleichsbefehle nochmal umdrehen, so dass am Ende Vergleichsbefehle genau andersrum arbeiten als die Subtraktionsbefehle. also cmp x,y und sub y,x in den Flags das gleiche Ergebnis hinterlassen. Ähnliche Effekte kriegt man beim Carry-Flag nach der Subtraktion. Manche implementieren es als echtes Borrow. Andere addieren das Einerkomplement, was zu inversem Carry-Flag führt. Wenn man also nicht permanent nur ein einer Architektur drin steckt, oder auch mal jemand anders den Code lesen können soll, dann kann es nicht schaden, bei solchen Feinheiten Tipps zu geben.
Moby A. schrieb: > Entsprechend variabel sind auch die Kommentierungen, die man so sieht. Wenn ich das so richtig verstehe, verbrennst Du im Interrupt die Register r9..r15. Das schließt also in allen anderen Interrupts gleicher Bauart den sei-Befehl aus. Zumindest solche Einschränkungen sollten meiner Meinung nach dokumentiert sein. Ansonsten liegt die Wiederverwertbarkeit Deiner Module bei null. (73 vom Assemblerdilletant)
Matthias L. schrieb: > Zeigt doch mal eine textuelle Beschreibung, oder ein Signalfluss oder > Ablaufplan oder sonstwas um zu sagen, was das Programm machen soll. Na ist denn die umzusetzende Funktionalität nicht eindeutigst beschrieben? Das Ganze bitteschön entprellt, mit mindestens 3 beliebigen IO-Pins und hinterher ausgefülltem Daten-RAM so wie beschrieben. Bin gespannt...
Moby schrieb: > Johann L. schrieb: >> weil deine Code-"Kommentare" vermutlich genauso Sch.... wären. > > Die haben auch nicht den Anspruch jemandem Asm beizubringen. Lass die Nebelkerze mach stecken. C-Kommentare haben auch nicht zum Ziel, jemandem C beizubringen. Dein Code ist echt Hack vom feinsten: Kein Funtionskopf, der erklärt, was die FuUnktion macht, welche Register sie verwendet, zerstört, oder ändert, welche Rückgabewerte sie hat, welche Hardware sie anfasst, etc. Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an Kommentaren und Dokumentation. > Gönne jedem Hochsprachler Woher bitte nimmst du diese Schublade? Ein nicht unwesentlicher Teil der AVR-Entwickler, die sich hier tummeln, verwendet ASSEMBLER-Code aus meiner Feder. > die Genugtuung, auf den Fehler Um den Fehler ging es garnicht, s.o. Mit Verlaub, der Stil von "adu.asm" ist einfach mies. Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein einen 32-Bit Wert kleiner als 1000000 ist?
Moby A. schrieb: > Na ist denn die umzusetzende Funktionalität nicht eindeutigst > beschrieben? > Das Ganze bitteschön entprellt, mit mindestens 3 beliebigen IO-Pins > und hinterher ausgefülltem Daten-RAM so wie beschrieben. Bin gespannt... Was bist du denn für ein Wicht??
Horst S. schrieb: > verbrennst Du im Interrupt die > Register r9..r15. Registerverwendung = Verbrennung, was? Den schnellen, kurzen Sicherungsstandard hab ich in vielen Programmen. Kann man natürlich auch mit langwierigem Push/Pop machen ;-) Horst S. schrieb: > Zumindest solche Einschränkungen sollten meiner Meinung nach > dokumentiert sein. Das zeigt das kurze Programm. Bei längeren darf die Registerverwendung am Anfang dokumentiert sein, da geb ich Dir recht. Horst S. schrieb: > Ansonsten liegt die Wiederverwertbarkeit Deiner > Module bei null. Toll wie Du das in so kurzer Zeit herausgefunden hast. Bin beeindruckt ;-)
Hallo Also ich mach mir jetzt mal nicht die Mühe, alle Artikel durchzulesen... Zu faul bin. Im meinem Gedächtnis finde ich jedoch zum Microsoft Assembler für PC (MASM), da war eine (durchaus sachliche) Werbeaussage der etwa 2 fachen Geschwindigkeit von Assemblerprogrammen gegenüber C(+?). Auch andere Optimierungen wie Echtzeitprogrammierung oder Speicherplatzminimierung sind gut in Assembler möglich. Ich finde auch, alle Betriebssyteme sollten in Assembler geschrieben und optimiert werden, damit der Computer nicht dauernd für C läuft. Gibt es bei C die Verwendung vom Stapel? Das kann man zum Beispiel auch beim Assembler minimieren. Die ganzen neuen Anwendungen wie z.B. digitale Signalverarbeitung sind auch sehr CPU-Takt abhängig. Ich kann aber den längeren Zeitaufwand beim Programmieren (liegt angeblich auch etwa beim Faktor 2) nicht ignorieren und so empfehle ich, zuerst nur zeitlich wichtige Programmteile in Assembler zu programmieren, also Programmteile, die Zeit brauchen. MfG Matthias
Johann L. schrieb: > Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein > (einen) 32-Bit Wert kleiner als 1000000 ist? (Nur mal unter uns, es liest ja keiner mit: Du denkst, daran scheitert er schon?)
Horst S. schrieb: > Wenn ich das so richtig verstehe, verbrennst Du im Interrupt die > Register r9..r15. Das schließt also in allen anderen Interrupts gleicher > Bauart den sei-Befehl aus. Ist bei Assemblerprogrammierung in AVRs nicht unüblich. Man hat genug. Genau da liegt auch ein klarer Vorteil von Assembler gegenüber C bei AVRs. Nur gibts dabei nach oben einen Deckel, das ist nur in kleinem Umfang sinnvoll möglich. > Zumindest solche Einschränkungen sollten meiner Meinung nach > dokumentiert sein. Ansonsten liegt die Wiederverwertbarkeit Deiner > Module bei null. Die Nutzung von Registern sollte bei Assembler generell en detail dokumentiert werden, wenn man keine einheitliche Registerkonvention hat, oder mit global zugewiesenen Registern arbeitet.
Moby A. schrieb: > Du verstehst es nicht. Sag es doch so wie es ist ;-) Wenn es drum geht, möglichst kryptischen Code zu erzeugen, bei dem der geneigte Leser garantiert nicht vom bloßen Draufgucken erkennen kann, was der Code denn eigentlich macht: glaub' uns, Moby, in dieser Wettbewerbskategorie wirst du C kaum schlagen können. :-)) Nur, dass du mal eine Idee bekommst, hier einer der Gewinner des diesjährigen IOCCC:
1 | d=80,e,j;g(){j+=getchar();}main(a,b)char**b;{for(;;){j=0;g();if(j<0)break;g(g());putchar(b[1][j/3*strlen(b[1])>>8]);if(!(++e%d))puts("");}} |
Allerdings ist das nicht die Kategorie, in der irgendjemand eine ernsthafte Arbeit abliefern würde, egal ob Hobby oder Paywork.
:
Bearbeitet durch Moderator
Johann L. schrieb: > Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an > Kommentaren und Dokumentation. Oh das ist mir neu. Johann L. schrieb: > Ein nicht unwesentlicher Teil der AVR-Entwickler, die sich hier tummeln, > verwendet ASSEMBLER-Code aus meiner Feder. Find ich gut. Johann L. schrieb: > Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein > einen 32-Bit Wert kleiner als 1000000 ist? Einen 32-Bit Wert so zu prüfen hat ich in meiner Praxis noch nicht. Ich tät mir spontan die 3 Bytes einzeln vornehmen, kann mir aber gut vorstellen daß Du einen Trick auf Lager hast ;-) Johann L. schrieb: > Mit Verlaub, der Stil von > "adu.asm" ist einfach mies. Mit Verlaub- Deine Meinung. Ralf G. schrieb: > Was bist du denn für ein Wicht?? Wo ist denn Dein Problem?
Könnte auch gehen, aber es steht mir natürlich nicht zu, fremden Code hier modifiziert wiederzugeben. ;-) (Es war übrigens der Eintrag maffiodo2, um dem Autor noch die nötige Ehre zu erweisen.)
Jörg W. schrieb: > Wenn es drum geht, möglichst kryptischen Code zu erzeugen, bei dem > der geneigte Leser garantiert nicht vom bloßen Draufgucken erkennen > kann, was der Code denn eigentlich macht: glaub' uns, Moby, in > dieser Wettbewerbskategorie wirst du C kaum schlagen können. :-)) Hey ich weiß doch, daß komplexe, kryptische Ausdrücke die Stärke von C sind... Deshalb ist Asm ja auch so erfrischend einfach und übersichtlich ;-) So, ich muß mich für heute entschuldigen, ich hoffe irgend jemand überzeugt mich bald in Sachen C-Codegröße, Übersichtlichkeit, Einfachheit, Performance ... Gute Nacht.
Matthias K. schrieb: > Im meinem Gedächtnis finde ich jedoch zum Microsoft Assembler für PC > da war eine (durchaus sachliche) Werbeaussage der etwa 2 fachen > Geschwindigkeit von Assemblerprogrammen gegenüber C(+?). Von wann ist die Aussage? Bei heutigen x86er kann das ebensogut andersrum ausgehen, zumal wenn der Optimizer den relevanten Optimization Guide besser kennt als der Programmierer. Schon mal in ein solches Werk reingesehen? Das sind ziemliche Schwarten. > Ich finde auch, alle Betriebssyteme sollten in Assembler geschrieben und > optimiert werden, damit der Computer nicht dauernd für C läuft. Um das Betriebssystem mit jeder erheblich geänderten Prozessorgeneration neu zu schreiben? Beim Übergang von Pentium Pro/II/III zum Pentium 4 hätte man den Code komplett überarbeiten müssen. > Die ganzen neuen Anwendungen wie z.B. digitale Signalverarbeitung sind > auch sehr CPU-Takt abhängig. Ja, natürlich. Wenn du Echtzeitanforderungen auf den einzelnen Takt runtergebrochen hast, dann geht das nicht anders als direkt.
Habt ihr alle euer Tütü ordentlich angezogen? Dann ist ja gut ...
>Deshalb ist Asm ja auch so erfrischend einfach und übersichtlich
SChnell, ein Blick und Du kannst mir sagen, was das tut:
[asm]
temp1H = r17
temp1L = r16
temp2H = r19
temp2L = r18
faktor = r20
counter = r21
ascii = r22
;------- werte holen
mov r17, adch
mov r16, adcl
;------- temp puffer
movw temp2L, temp1L
;------- teile durch vier
clc ; clear carry flag
ror temp2H
ror temp2L
clc
ror temp2H
ror temp2L
;------- zusammenrechnen
add temp2L, temp1L
adc temp2H, temp1H ; in temp2 steht jetzt 1,25*adc
;------- ausgabe highbyte
mov ascii, -0x30 ; ascii für null
subi temp2H, ascii
UDR = temp2H ; über uart senden
UDR = ',' ; komma senden, warten auf udre einfügen
;------- lowbyte mal zehn,
ldi faktor, 10
ldi counter, 5 ; azahl nachkommastellen
loop:
mul temp2L, faktor
subi r0, ascii
UDR = r0 ; über uart senden, warten auf udre einfügen
mov temp2L, r1
;------ genug stellen ausgegeben?
DEC counter
BRNE loop;
;------- nu fertsch ;-)
[/asm]
Moby A. schrieb: >> Ein nicht unwesentlicher Teil der AVR-Entwickler, die sich hier tummeln, >> verwendet ASSEMBLER-Code aus meiner Feder. > > Find ich gut. Ich dachte, du magst keine Compiler?
Jörg W. schrieb: > kann, was der Code denn eigentlich macht: glaub' uns, Moby, in > dieser Wettbewerbskategorie wirst du C kaum schlagen können. :-)) Er vielleicht nicht, aber gegenüber Perl ist C harmlos. ;-)
Im Anhang mal der komplette Code. Was tut er? Wirst Du ja auf einen Blick sehen. Übrigens scheine ich damals mehr Kommentare geschreieben zu haben, als Du.
Nur mal so am Rande, zum Thema größere Assemblerprogramme: Erinnert sich noch jemand an Frank Ostrowskis GFA-Basic für den Atari ST?
Johann L. schrieb: > Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein > einen 32-Bit Wert kleiner als 1000000 ist? AAhh, verstehe... :-) Aber sowas macht man doch nicht in einem Assemblerprogramm?
Irgendwann stellt sich dann heraus, das der Moby auch nur so ein Kunstprojekt gelangweilter Informatiker ist, um euch so richtig auf die Palme zu bringen.
Ralf G. schrieb: > Johann L. schrieb: >> Mal ne ganz konkrete Frage: Wie testest du in AVR-Assembler, ob ein >> (einen) 32-Bit Wert kleiner als 1000000 ist? > > Nur mal unter uns, es liest ja keiner mit: Du denkst, daran scheitert > er schon? Das werden wir wissen falls er sich nicht um eine konkrete Antwort drückt.
Ralf G. schrieb: > Johann L. schrieb: >> Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein >> (einen) 32-Bit Wert kleiner als 1000000 ist? > > (Nur mal unter uns, es liest ja keiner mit: Du denkst, daran scheitert > er schon?) Interessanter ist doch ob die Antwort 'komplexer' ist als
1 | if(x < 1000000) { ... } |
scelumbro schrieb: > Interessanter ist doch ob die Antwort 'komplexer' ist als Wobei Vergleiche von Multibyte/Multiword-Typen auf AVRs schon deutlich einfacher sind als auf diversen anderen Prozessoren. Atmels sehr hilfeiche Handhabung des Z-Flags bei den CPC/SBC Befehlen kenne ich sonst nur von Zilogs Z8. Auch relativ moderne 8-Bitter wie STM8 kennen diese Methode nicht.
Jörg W. schrieb: > Nur, dass du mal eine Idee bekommst, hier einer der Gewinner des > diesjährigen IOCCC: > d=80,e,j;g(){j+=getchar();}main(a,b)char**b;{for(;;){j=0;g();if(j<0) > break;g(g());putchar(b[1][j/3*strlen(b[1])>>8]);if(!(++e%d))puts("");}} Für Mobys ADC-Code habe ich deutlich länger gebraucht, um ihn zu verstehen. Ernsthaft! Und das, obwohl Mobys Code Kommentare enthält und es vorab bekannt war, wozu er gut ist. Der IOCCC-Code ist zwar schön kurz, aber für IOCCC-Verhältnisse nur mäßig kryptisch. Am schwierigsten fand ich übrigens nicht herauszufinden, was der IOCCC-Code tut, sondern wozu er nützlich sein soll, also das, was bei Mobys Code schon vorab bekannt war. Hätte diese Information bei Moby gefehlt, wäre der Unterschied in der Verständlichkeit noch größer gewesen.
:
Bearbeitet durch Moderator
Johann L. schrieb: > Ralf G. schrieb: >> Johann L. schrieb: >>> Mal ne ganz konkrete Frage: Wie testest du in AVR-Assembler, ob ein >>> (einen) 32-Bit Wert kleiner als 1000000 ist? > Das werden wir wissen falls er sich nicht um eine konkrete Antwort > drückt. Die Frage habe ich doch beantwortet, warte aber noch auf den "Trick" des Fragestellers... Wenn der in der Benutzung eines C-Compilers bestehen soll dann dankeschön ;-) Drückt Euch mal lieber nicht um eine C-Fassung meines simplen kleinen Asm-Progs weiter oben. Ich warte immer noch auf den Beweis der Überlegenheit des C-Compilers... Also, bitte nicht an der Kommentierung festkrallen sondern nur mal eine Lösung. Experten die beides beherrschen sind ja hier offensichtlich genügend versammelt ;-)
Bob schrieb: > Irgendwann stellt sich dann heraus, das der Moby auch nur so ein > Kunstprojekt gelangweilter Informatiker ist, um euch so richtig auf die > Palme zu bringen. Da mach Dir mal keine Sorgen. Bin am Thema schon ernsthaft interessiert und programmiere auch nicht erst seit gestern. Bastler schrieb: > oder um's mal mit Baumann zu sagen: > > schlicht: ein armer Wicht Ja Bastler, Du magst mich auf die Palme bringen... Aber weißt Du, wenn das meiste meiner Werke schön funktioniert, nützlich ist und Freude macht ist das nicht ganz so einfach. Ich weiß ja nicht was Du so zusammenbastelst... Hoffentlich sind das nicht nur beleidigende Floskeln hier ;-(
Moby schrieb: > Die Frage habe ich doch beantwortet, warte aber noch auf den "Trick" des > Fragestellers... Wenn der in der Benutzung eines C-Compilers bestehen > soll dann dankeschön ;-) Moby A. schrieb: >> Ich tät mir spontan die 3 Bytes einzeln vornehmen, > > 4 Stück sinds natürlich ;-) War das deine Antwort? Die Erkenntnis das 32 Bit aus 3 - 4 Bytes bestehen, je nach Uhrzeit und man diese auf einer 8-Bit Maschine einzeln bearbeitet? Ein bisschen konkreter geht es nicht? Hier nochmal die vollständige Implementation dieses Problems in C:
1 | if(x < 1000000) { ... } |
Hmm.... ich habe heute morgen 69 Emails bekommen. Davon der Großteil Benachrichtigungen für diesen Thread, der nur noch darin besteht, einem Unbelehrbaren zu belehren. Dabei ist doch schon an den Assembler-Kommentaren ersichtlich, daß er keinerlei Empathie besitzt, was der Leser erwartet. (Insbesondere der effiziente Leser, der bei einem Text/Quelltext nicht Zeile für Zeile durchgehen will, sondern sich erst einmal den Überblick verschaffen will, ob er überhaupt an der richtigen Stelle sucht.) Das ist Verschwendung. (Tut mir leid Moby, aber so sieht es anhand Deines Quelltextes aus. Deine Schreibweise ist perfekt für jemanden, der niemals Sachen weitergeben will und an seinen Projekten alleine werkelt - aber das ist OK. Nicht jeder hat in jedem Bereich etwas, was er sinnvoll teilen kann.) Dabei sind hier ja durchaus auch noch interessante Fragen offen: - Mein persönliches Interesse: Wo man einen solchen "objektbasiert"-ähnlichen Ansatz für ISRs lernt. - Für den Umbau der obigen ASM-Routinen in C wurde die Struktur des Programms geändert, weil sie der C-Denkweise entgegenkommt. Wäre die diese neue Struktur in ASM sinnvoll implementierbar oder wird das eher unübersichtlich?
:
Bearbeitet durch User
Ralf G. schrieb: > Ich lach' mich tot. Dann verstehst Du womöglich die Antwort nicht ;-) scelumbro schrieb: > War das deine Antwort? Die Erkenntnis das 32 Bit aus 3 - 4 Bytes > bestehen, Nun, 1000000 dezimal sind [0F 42 40] Hex. Einen 32-Bit Wert kann man doch nun Byte für Byte abklappern ob er kleiner ist. Stellt Euch doch nicht so dämlich. Ich würd mich totlachen wenn das in ASM sogar schneller ginge! Wenn nun noch das Argument mit dem bequemer Rechnen in C kommt- Ja. Das ist so. Wie schon ausdrücklich erwähnt. Bei kleineren und mittleren MSR Projekten spielen solche Berechnungen meist eine sehr untergeordnete Rolle. Als Motivation zum Umstieg auf Hochsprache? Keine Chance... Walter T. schrieb: > einem > Unbelehrbaren zu belehren Na ja der Eindruck ist oft gegenseitig. Und die eigentliche Absicht manchen Schreibers zu eindeutig ;-) Walter T. schrieb: > Deine Schreibweise ist > perfekt für jemanden, der niemals Sachen weitergeben will und an seinen > Projekten alleine werkelt Ach was. Wer Asm versteht kann das samt Datenblatt problemlos. Mit der Aufgabe einem C-ler ASM zu erklären beschäftige ich mich nicht. Und lenkt doch nicht ständig mit der Schreibweise, die gerade schön kurz und knapp und gerade nicht so romanfüllend wie Hochsprachencodes daherkommt, vom eigentlichen Problem ab: C ist einfach mehr sprachlicher Aufwand für größere, langsamere Ergebnisse.
Rufus Τ. F. schrieb: > Moby schrieb: >> Also meine liebe 128erMega Haussteuerung läuft bald ein ganzes Jahrzehnt >> :-) > > Wie süß. Nö. Wie nützlich und doch so einfach. Rufus Τ. F. schrieb: > würde es mich > ein müdes Arschrunzeln kosten, mein Programm auf irgendwas anderem > laufen zu lassen, sofern es mindestens 32 Bit breit ist. Ja bitteschön, wenns Spaß macht. Mir wärs den Aufwand nicht wert.
Moby A. schrieb: > Ich würd mich totlachen wenn das in ASM sogar schneller ginge! Keine Sorge, dein Leben ist nicht in Gefahr. Aber auf die konkreten Befehle warten wir immer noch. ;-)
:
Bearbeitet durch User
A. K. schrieb: > Keine Sorge, dein Leben ist nicht in Gefahr. Das glaub ich erst wenn mir jemand sagt, was die entsprechende C-Konstruktion exakt an Takten frisst ;-) 32-Bit Berechnungen sind auf einem 8-Bitter einfach beschwerlich- und werden bei 8-Bit Projekten selten gebraucht... > Aber auf die konkreten Befehle warten wir immer noch. ;-) Glaub ich ehrlich gesagt weniger ;-)
:
Bearbeitet durch User
Wenn du C schon als Hochsprache bezeichnest, was hälst du dann erst von Ada oder gar Rust?
Moby A. schrieb: > Schreibweise, die gerade schön kurz > und knapp und gerade nicht so romanfüllend wie Hochsprachencodes > daherkommt P.S. damit meinte ich den Code aus meinem kleinen LM335 Projekt. Beim weiter oben publizierten hab ich bzgl. Kommentierung fast schon arg übertrieben ;-)
Bob schrieb: > was hälst du dann erst von > Ada oder gar Rust? Für völlig ungeeignet für AVRs und ihre typischen Anwendungen jedenfalls.
Moby A. schrieb: > Das glaub ich erst wenn mir jemand sagt, was die entsprechende > C-Konstruktion exakt an Takten frisst ;-) Basierend auf
1 | void f(long x) |
2 | {
|
3 | if (x < 1000000) |
4 | g(); |
5 | }
|
5-6 Takte für Vergleich+Sprungbefehl. Wenn du weniger brauchst: Wir kondolieren bestimmt alle, versprochen. ;-)
A. K. schrieb: > 5-6 Takte für Vergleich+Sprungbefehl. Na vielleicht auf nem 32-Bitter ... Veralbern kann ich mich allein.
Moby A. schrieb: > Na vielleicht auf nem 32-Bitter ... Nö, beim AVR. Bei einem 32-Bitter wärs oft 0,5 oder so, je nachdem wie man das rechnet.
:
Bearbeitet durch User
Moby A. schrieb: > Und lenkt doch nicht ständig mit der Schreibweise, die gerade schön kurz > und knapp und gerade nicht so romanfüllend wie Hochsprachencodes > daherkommt, vom eigentlichen Problem ab: C ist einfach mehr sprachlicher > Aufwand für größere, langsamere Ergebnisse. Ein Traum... :-) Schreib' doch einfach mal deinen Assemblercode für den Vergleich! Gerne auch als Funktion zur universellen Verwendung.
1 | uint8_t Test_Mio(uint32_t val) |
2 | {
|
3 | return val < 1000000UL; |
4 | };
|
Und das machst du mit weniger Schreibaufwand? Und der Speicherverbrauch ist auch noch geringer? Und die Geschwindigkeit erst!?
Ralf G. schrieb: > Und das machst du mit weniger Schreibaufwand? Und der Speicherverbrauch > ist auch noch geringer? Und die Geschwindigkeit erst!? Falls Du darauf abzielst für solcherlei Berechnungen besser C samt 32Bit-Controller zu verwenden zielst Du jedenfalls nicht auf typische 8-Bit Anwendungen. Da sind solche Berechnungen selten. Soll ichs für Dich noch 10 mal wiederholen?
Moby A. schrieb: > Ausgeschlossen. Falls Du nicht AVR32 meinst. Nö. 8-Bit AVR. Beim Cortex-M3 sind es 4-5, hätte aber in Schleife Luft für Optimierung. Wie schon gesagt, es geht nur um das if(...), nicht um die ganze Funktion oder den Aufruf von g().
Moby A. schrieb: > Ausgeschlossen. :-) In Assembler ist's (als Funktion) möglicherweise sogar länger! Außer du hast die Registerorganistion/ -verwendung vom gcc abgekupfert.
Moby A. schrieb: > Falls Du darauf abzielst für solcherlei Berechnungen besser C samt > 32Bit-Controller zu verwenden zielst Du jedenfalls nicht auf typische > 8-Bit Anwendungen. Zwei typische Beispiele: Bei meinen Anwendungen gibts sehr oft einen Timer-Tick, der eine 32-Bit Variable hochzählt. Ist ganz praktisch für programmierte Wartezeiten und Timeouts. Weniger Bits wär zu wenig. Nicht selten gibts auch Datum/Uhrzeit in 32 Bits. Mal in Unix-Konvention, mal in FAT-Konvention.
Moby A. schrieb: > Falls Du darauf abzielst Nein. > für solcherlei Berechnungen besser C samt > 32Bit-Controller zu verwenden zielst Du jedenfalls nicht auf typische > 8-Bit Anwendungen. Da sind solche Berechnungen selten. Kann schon sein. Nur: wenn's doch mal vorkommt, musst du da gleich die Segel streichen!? >Soll ichs für Dich noch 10 mal wiederholen? Wenn du willst...
A. K. schrieb: > if (x < 1000000) + Sprung ... machst Du in mit C auf einem 8-Bit AVR nicht in 5-6 Takten. Allein ein RJMP nimmt 2... Heute zu Scherzen aufgelegt? Zugegeben, diesen kannte ich noch nicht.
Ralf G. schrieb: > Nur: wenn's doch mal vorkommt, musst du da gleich die > Segel streichen!? Papperlapapp- Dann codiere ich den Vergleich halt.
Moby A. schrieb: > Dann codiere ich den Vergleich halt. Kanst du nicht, kannst du nicht, kannst du nicht... ;-)
A. K. schrieb: > Bei meinen Anwendungen gibts sehr oft einen Timer-Tick, der eine 32-Bit > Variable hochzählt. Ist ganz praktisch für programmierte Wartezeiten und > Timeouts. Weniger Bits wär zu wenig. Kann ich so nicht bestätigen. In typischen 8-Bit Anwendungen langen auch 8-Bit. Für viel mehr noch als nur Timing-Aufgeben... Ein Beispiel geb ich demnächst bei meiner kleinen Tiny-Platine in der Projektesammlung.
Ralf G. schrieb: > Kanst du nicht, kannst du nicht, kannst du nicht... ;-) Moby A. schrieb: > Und die eigentliche Absicht manchen Schreibers zu eindeutig ;-)
Moby A. schrieb: > ... machst Du in mit C auf einem 8-Bit AVR nicht in 5-6 Takten. > Allein ein RJMP nimmt 2... Stimmt, nur ist da aber keiner drin. ;-) Und der bedingte Sprung darin braucht nur 2 wenn er springt. Daher kommt das "5-6".
Tja A.K., du machst mich leider nicht neugierig auf die Lösung...
Moby A. schrieb: > In typischen 8-Bit Anwendungen langen auch 8-Bit. Oder andersrum formuliert: Wenn es mehr als 8 Bits werden, weil die Zeiten mal ein paar Millisekunden und mal einige Sekunden sind, dann schmeisst du den 8-Bitter weg, weil du keine entsprechende Codesequenz gebacken bekommst? ;-) Mir ist das wurscht. Der zählt die Ticks ab Start in 32 Bits hoch. Das gibt (bei meinen(!) Anwendungen) ausreichend Zeit um mich weder mit dem Überlauf rumärgern noch das Verfahren jedesmal anwendungsspezifisch neu überlegen zu müssen. Ist nicht der einzige Weg zur Lösung, sicherlich nicht der effizienteste hinsichtlich Laufzeit, aber dafür recht simpel. Ist mir dann auch egal, ob da ein 8-Bitter drunter steckt oder ein 32-Bitter.
Moby A. schrieb: > Ralf G. schrieb: >> welchen RJMP??????? > > Ein bedingter Sprung im True-Fall auch. Nö, im False-Fall. Im True-Fall ist es nur einer. True 5, False 6.
A. K. schrieb: > Moby A. schrieb: >> In typischen 8-Bit Anwendungen langen auch 8-Bit. > > Oder andersrum formuliert: Wenn es mehr als 8 Bits werden, weil die > Zeiten mal ein paar Millisekunden und mal einige Sekunden sind, dann > schmeisst du den 8-Bitter weg, weil du keine entsprechende Codesequenz > gebacken bekommst? ;-) Oh je oh je. Dann führe ich den Zähler meinetwegen auch 128-bittig aus. Was ist den das für eine Herausforderung... > Mir ist das wurscht. Der zählt die Ticks ab Start in 32 Bits hoch. Das > gibt (bei meinen(!) Anwendungen) ausreichend Zeit um mich weder mit dem > Überlauf rumärgern noch das Verfahren jedesmal anwendungsspezifisch neu > überlegen zu müssen. Ist nicht der einzige Weg zur Lösung, sicherlich > nicht der effizienteste hinsichtlich Laufzeit, aber dafür recht simpel. > Überlaufrumärgern ist mir bislang fremd. Was ist denn das? > Ist mir dann auch egal, ob da ein 8-Bitter drunter steckt oder ein > 32-Bitter. Mir nicht. Ein solider AVR solls schon sein ;-)
Meine Zusammenfassung; C oder Assembler ist klar beantwortet. Das was hier an ASM Code präsentiert macht jeder C- Compiler nicht schlechter. In Sachen Doku ist sogar von C generierter Assembler besser nachvollziehbar. Vor Menschen die ihre Position gegen alle anderen verteidigen habe ich aber Respekt, ist nicht einfach. Sie könnten ja richtig liegen, wenn auch nicht in diesem Fall. Die Masse zählt nicht, nur Argumente. ASM ist für mich ein Tool der letzten Hoffnung. Wenn es um zeitkritisches geht oder man der Meinung ist selber dichteren Code produzieren zu können. Trügerisch da in den Compilern 100e von Mannjahren stecken, man selber aber nur ein Leben hat. Etwas untergegangen ist die Portierbarkeit. Wie man hier sehen kann haben die unterschiedlichsten Leute zum C-Code beigetragen. Code und dessen Funktionen auch ich verstehe obwohl ich den GCC noch nie gesehen habe. Dafür habe ich weder Datenblätter gewälzt noch die Abgründe irgendeiner Maschinensprache reingezogen. Es ist schlicht so zu verstehen. Ansonsten ist ein Tool ein Tool. Es schreibt doch wohl kaum jemand seinen eigenen USB-Stack, weder in C noch in ASM oder sonstwas. Da nehme ich jedenfalls eine lib. Auch ein Bild male ich nicht in C oder ASM sondern mit Pinsel und Farbe oder Gimp, Photshop Paint etc.
Moby A. schrieb: > Tja A.K., du machst mich leider nicht neugierig auf die Lösung... Nein? Klang bisher irgendwie anders. ;-) Aber einfach wärs schon, sie auch ohne mich zu kriegen. Brauchst nur einen AVR-GCC dazu. In Linux trivial. ;-)
A. K. schrieb: > Moby A. schrieb: >> Ralf G. schrieb: >>> welchen RJMP??????? >> >> Ein bedingter Sprung im True-Fall auch. > > Nö, im False-Fall. Im True-Fall ist es nur einer. > True 5, False 6. Irrtum. Der True-Fall braucht zwei... Was sollte aber nun diese Vergleich 1000000-Spinnerei ????
Moby A. schrieb: > Oh je oh je. Dann führe ich den Zähler meinetwegen auch 128-bittig aus. > Was ist den das für eine Herausforderung... Bring erst einmal deine Lösung für 32 Bits, bevor du dich ans 128 Bits ranwagst. ;-) > Überlaufrumärgern ist mir bislang fremd. Ja, den Eindruck kann man kriegen.
Moby A. schrieb: > Irrtum. Der True-Fall braucht zwei... Irrtum. Er springt im False-Fall. Im True-Fall fällt er durch. Da ist bei if() meistens so, es sei denn der Compiler entscheidet, dass es aufgrund der zu erwartenden Werte anders effizienter ist. > Was sollte aber nun diese Vergleich 1000000-Spinnerei ???? Ok, jetzt kommt also die nächste Stufe. Hast du das schon mal in einer mündlichen Prüfung versucht? Also statt der erwarteten Antwort: "Herr Soundso, was soll diese Spinnerei, das muss doch niemand wissen!" ;-)
X4U schrieb: > Meine Zusammenfassung; > > C oder Assembler ist klar beantwortet. Das was hier an ASM Code > präsentiert macht jeder C- Compiler nicht schlechter. w.z.b.w. Dein Beitrag enthält auch sonst nur Punkte, deren Relevanz für typische 8-Bit AVR Projekte hinreichend zweifelhaft ist. Du hast aber Recht, jeder wie er mag. Menschliche Entscheidungen sind so vielschichtig wie individuell. Was die objektiven Vorteile in Asm in keiner Weise schmälert.
@Moby Lass erstmal die Vergleich-1000000-Spinnerei liegen. Es gibt Wichtigeres: Beitrag "LCD Assembler" Da braucht jemand dringend deine Hilfe!
A. K. schrieb: > Moby A. schrieb: >> Irrtum. Der True-Fall braucht zwei... > > Irrtum. Er springt im False-Fall. Im True-Fall fällt er durch. Da ist > bei if() meistens so, es sei denn der Compiler entscheidet, dass es > aufgrund der zu erwartenden Werte anders effizienter ist. Ich merk schon, mit den bedingten ASM-Befehlen hast Du's nicht so ;-) > Ok, jetzt kommt also die nächste Stufe. Oh nein oh nein. Obiges Beispiel bleibt trotzdem eine ebensolche ;-)
Ralf G. schrieb: > @Moby > Lass erstmal die Vergleich-1000000-Spinnerei liegen. Es gibt > Wichtigeres: > Beitrag "LCD Assembler" > > Da braucht jemand dringend deine Hilfe! Dann mal ran, Ralf. Aber ich weiß schon, Dir ist es lieber hier rumzustänkern ;-)
Moby A. schrieb: > Dann mal ran, Ralf. Aber ich weiß schon, Dir ist es lieber hier > rumzustänkern ;-) Da ist was Wahres dran ;-) Ich muss allerdings erstmal weg. Also: übernimmst du mal ausnahmsweise für mich?
Moby A. schrieb: > Nö. Jetzt heißt es: Mahlzeit! Aber das wäre was für dich. Das ist eine deiner typischen AVR-Anwendungen, wo man nicht mehr als ganze Byte braucht.
Nö. Jetzt heißt es: Mahlzeit! A. K. schrieb: > Moby A. schrieb: >> Oh je oh je. Dann führe ich den Zähler meinetwegen auch 128-bittig aus. >> Was ist den das für eine Herausforderung... > > Bring erst einmal deine Lösung für 32 Bits, bevor du dich ans 128 Bits > ranwagst. ;-) Es ist auch sehr gewagt, etwas als "Lösung" zu bezeichnen, was Du im Falle Deines Vergleichs nur hinschreibst, um es von C für Dich übersetzen zu lassen ;-) Ich mag jetzt gar keinen x-bittigen Counter in Asm für Dich hinschreiben weil ich nicht glaube, daß Du damit was anfangen kannst.
:
Bearbeitet durch User
Moby A. schrieb: > Ich merk schon, mit den bedingten ASM-Befehlen hast Du's nicht so ;-) Die Frage dabei ist, worauf man das True/False bezieht. Da hier stets von C Code ausgegangen wird, ist das natürlich die im if(...) genannte Bedingung. Nicht die im bedingten Sprung genannte Bedingung. Weshalb if(cond)block meist so implementiert wird: if cond false goto L1 block L1: Er springt also, wenn die if-Bedingung falsch ist. Du hast das dann im Geist rumgedreht und auf den Sprungbefehl bezogen.
Klaus W. schrieb: > Moby A. schrieb: >> Nö. Jetzt heißt es: Mahlzeit! > > Aber das wäre was für dich. > Das ist eine deiner typischen AVR-Anwendungen, wo man nicht mehr als > ganze Byte braucht. Der lustige Klaus wieder... Völlig untypisch für jemanden der eigentlich permanent genervt ist. Iß auch erst mal was ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Es ist auch sehr gewagt, etwas als "Lösung" zu bezeichnen, was Du im > Falle Deines Vergleichs nur hinschreibst, um es von C für Dich > übersetzen zu lassen ;-) Ich nehme an, dass du in deinem nächsten Urlaub nach Malle schwimmst, statt für die Lösung des Problems "wie komme ich da hin" Werkzeuge anderer Leute zu nutzen.
A. K. schrieb: > Moby A. schrieb: > Du hast das dann im Geist rumgedreht und auf den Sprungbefehl bezogen. Ok A.K., sei es wie es sei, die 5-6 Takte für den Vergleich von einer 32- mit einer 24-Bit Konstante samt Sprung sind für 8-Bit AVR utopisch.
:
Bearbeitet durch User
Moby A. schrieb: > Ok A.K., sei es wie es sei, die 5-6 Takte für den Vergleich von einer > 32- mit einer 24-Bit Konstante samt Sprung sind für 8-Bit AVR utopisch. Nicht utopisch, sondern viel zu viel. Dieser Vergleich braucht 0 Takte, denn den optimiert der Compiler komplett weg. ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Ok A.K., sei es wie es sei, die 5-6 Takte für den Vergleich von einer > 32- mit einer 24-Bit Konstante samt Sprung sind für 8-Bit AVR utopisch. Gibs einfach zu, dass du es in ASM nicht so schnell hinkriegst wie der C-Compiler...
Tse schrieb: > Moby A. schrieb: >> Ok A.K., sei es wie es sei, die 5-6 Takte für den Vergleich von einer >> 32- mit einer 24-Bit Konstante samt Sprung sind für 8-Bit AVR utopisch. > Gibs einfach zu, dass du es in ASM nicht so schnell hinkriegst wie der > C-Compiler... Ich fürchte Dir fehlen da gewisse Kenntnisse, was mit 8-Bit AVR möglich ist und was nicht.
Tse schrieb: > Gibs einfach zu, dass du es in ASM nicht so schnell hinkriegst wie der > C-Compiler... Ich würde es ja liebend gerne mit deiner Asm-Version vergleichen. Deinen erstaunten und ungläubigen Beträgen zufolge scheint die aber wesentlich langsamer zu sein als die C Version.
Moby A. schrieb: > Und die eigentliche Absicht manchen Schreibers zu eindeutig ;-) Stimmt. Ich bin immer noch daran interessiert, "best practices" für Embedded-Programmierung zu lernen. Genau aus dem Grund, weil ich noch nie in ein großes Projekt mit anderen eingebunden war und solche Sachen eben aus irgendwelchen Internet-Threads und -Blogs herauslesen muß, weil es die passenden Bücher nicht gibt. Diese Diskussion um ASM nervt da nur. Zumal sie zu keinem Ergebnis kommen wird. Also: mich nervt sie. Ich gönne euch aber auch euren Spaß.
:
Bearbeitet durch User
Moby A. schrieb: > Ich fürchte Dir fehlen da gewisse Kenntnisse, was mit 8-Bit AVR möglich > ist und was nicht. Dann zeig uns was deiner Meinung nach möglich ist (ASM-Code) und wir vergleichen es mit dem Code des Compilers...
Moby A. schrieb: > Ich fürchte Dir fehlen da gewisse Kenntnisse, was mit 8-Bit AVR möglich > ist und was nicht. Bestimmt. Aber dafür habe ich Kenntnisse, was mit C Compilern möglich ist, und in letzten Fall, also für dein if(const32<const24) reichen die aus, denn das Ergebnis davon ist völlig unabhängig vom Prozessor.
A. K. schrieb: > Ich würde es ja liebend gerne mit deiner Asm-Version vergleichen. Deinen > erstaunten und ungläubigen Beträgen zufolge scheint die aber wesentlich > langsamer zu sein als die C Version. Erstaunt? Ungläubig? Belustigt triffts eher. Da wär ich fast vorsichtig, daß Dir der C-Compiler nicht gleich alles wegoptimiert und Du dann ohne Lösung dastehst.
Moby A. schrieb: > Da wär ich fast vorsichtig, daß Dir der C-Compiler nicht gleich alles > wegoptimiert und Du dann ohne Lösung dastehst. Jau, das ist manchen her im Forum auch schon passiert. Beispielsweise weil sie es nun mit eigenen Delayloops probierten, die auf mysteriöse Art völlig verschwanden, oder sie erst lernen mussten, wozu "volatile" da ist. Aber zwei Konstanten selber miteinander zu vergleichen, statt dafür Code zu erzeugen, ist nun wirklich kein Hexenwerk für einen Compiler. Nur war das nicht die eigentliche Aufgabe, sondern (hoffentlich) bloss eine etwas verunglückte Formulierung von dir.
A. K. schrieb: > Moby A. schrieb: >> Ich fürchte Dir fehlen da gewisse Kenntnisse, was mit 8-Bit AVR möglich >> ist und was nicht. > > Bestimmt. Aber dafür habe ich Kenntnisse, was mit C Compilern möglich > ist, und in letzten Fall, also für dein if(const32<const24) reichen die > aus, denn das Ergebnis davon ist völlig unabhängig vom Prozessor. Vergleich von Konstanten? Was belegt das nun die Überlegenheit von C ? Der Scherz ist ja noch dümmer als ich dachte. Schau mal ich möchte mich hier verzweifelt von den Codesize- und Performance-Vorteilen von C überzeugen lassen !!!! ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Vergleich von Konstanten? Wie soll ich deinen Text ... Moby A. schrieb: > für den Vergleich von einer 32- mit einer 24-Bit Konstante ... denn sonst verstehen? Moby A. schrieb: > Schau mal ich möchte mich hier verzweifelt von den Codesize- und > Performance-Vorteilen von C überzeugen lassen !!!! ;-) Ich umgekehrt auch. Aber dafür fehlt mir deine Asm-Version.
:
Bearbeitet durch User
Vergleich von zwei unsigned 4-Byte-Zahlen A und B mit 8bit-CPU und Sprung falls A > B Die 4 Bytes seien A3,A2,A1,A0 bzw. B3,B2,B1,B0 Methode 1: Teste A3 > B3 Sprung falls A3 > B3 Teste A2 > B2 Sprung falls A2 > B2 Teste A1 > B1 Sprung falls A1 > B1 Teste A0 > B0 Sprung falls A0 > B0 Methode 2: Berechne B0 - A0 mit Carry Berechne B1 - A1 mit Carry Berechne B2 - A2 mit Carry Berechne B3 - A3 mit Carry Sprung falls Carry gesetzt Beide Methoden haben vollig verschiedenes Zeitverhalten. Wenn ich Assembler verwende, habe ich die Kontrolle darüber. Wenn ich Hochsprache verwende, habe ich diese Kontrolle nicht.
Moby A. schrieb: > deren Relevanz für typische > 8-Bit AVR Projekte hinreichend zweifelhaft ist. Heißt das so viel wie dass ein AVR, für Projekte wo man Zahlen >8bit hat eh nicht hergenoimmen wird weil es bessrees git?
Josef G. schrieb: > Beide Methoden haben vollig verschiedenes Zeitverhalten. > Wenn ich Assembler verwende, habe ich die Kontrolle darüber. > Wenn ich Hochsprache verwende, habe ich diese Kontrolle nicht. Korrekt. Wo eine taktgenaue Reproduzierbarkeit des Zeitverhaltens gefordert ist, da ist an dieser Stelle eine Hochsprache nicht zuverlässig einsetzbar (VHDL&Co sind hier wohl nicht gemeint). Glücklicherweise ist das nicht oft der Fall.
Moby A. schrieb: > Schau mal ich möchte mich hier verzweifelt von den Codesize- und > Performance-Vorteilen von C überzeugen lassen !!!! ;-) Ohne dem Augenzwinkern am Ende, hätte ich jetzt gesagt: Hatten wir doch schon. 5-6 Takte. Nur, wieso meinst du das ironisch? Glaubst du nicht dran? Interessiert es dich eigentlich gar nicht, weil du von deinem ASM-Code so überzeugt bist? Willst du die Leute zum ASM-Masochismus erziehen? Schreib' doch einfach die paar Zeilen. Hinterher wirst du auseinandergenommen, weil's viel zu lang ist. Und du kannst sagen, ich mach's trotzdem so. Vielleicht ist der Code aber gar nicht so schlecht und kann mit dem Compiler mithalten. Ja dann..., dann steht's Unentschieden und es geht in die nächste Runde.
Josef G. schrieb: > Beide Methoden haben vollig verschiedenes Zeitverhalten. > Wenn ich Assembler verwende, habe ich die Kontrolle darüber. > Wenn ich Hochsprache verwende, habe ich diese Kontrolle nicht. NB: Oberhalb von relativ einfachen Mikrocontrollern, also bei schnelleren Prozessoren wie x86 oder Cortex-A (RasPi), hast du auch in Assembler keine wirkliche Kontrolle mehr darüber.
Josef G. schrieb: > Methode 1: Würde ich so nicht machen. Besser: > Teste A3 > B3 > Sprung falls A3 > B3 Sprung falls A3 < B3 > Teste A2 > B2 > Sprung falls A2 > B2 Sprung falls A2 < B2 > Teste A1 > B1 > Sprung falls A1 > B1 Sprung falls A1 < B1 > Teste A0 > B0 > Sprung falls A0 > B0
A. K. schrieb: > Würde ich so nicht machen. Was interessiert, ist ja allerdings: Wie macht's Moby? :-)
:
Bearbeitet durch User
Josef G. schrieb: > Berechne B0 - A0 mit Carry ohne Carry (in) > Berechne B1 - A1 mit Carry > Berechne B2 - A2 mit Carry > Berechne B3 - A3 mit Carry > Sprung falls Carry gesetzt je nach Prozessor falls Carry nicht gesetzt
:
Bearbeitet durch User
Ralf G. schrieb: > Was interessiert, ist ja allerdings: Wie macht's Moby? Wenn ich den Thread hier so verfolge: Gar nicht. Denn so eine Fragestellung ergibt sich für ihn nicht, das ist ja auch völlig unrealistisch. Wäre ich nicht so boshaft, wie ich bin, würde ich jetzt nicht den Verdacht äußern, daß er ein Programmieranfänger ist, der für sich das große Feld der Assemblerprogrammierung entdeckt hat ... d.h. er weiß jetzt, wo das Feld ist, und hat sich vorgenommen, es nächste Woche/nächsten Monat/nächstes Jahr ganz sicher auch mal oberflächlich zu erkunden.
Ralf G. schrieb: > Was interessiert, ist ja allerdings: Wie macht's Moby? Mir schwant, er hatte bisher so etwas wie die korrigierte Version von Josefs 1. Variante im Auge und hat nun die bessere und auch vom Compiler genutzte 2. Variante auf dem Tablett serviert bekommen. ;-)
:
Bearbeitet durch User
A. K. schrieb: > Moby A. schrieb: > für den Vergleich von einer 32- mit einer 24-Bit Konstante > > ... denn sonst verstehen? > A. K. schrieb: > Moby A. schrieb: > Vergleich von Konstanten? > > Wie soll ich deinen Text ... > > Moby A. schrieb: > für den Vergleich von einer 32- mit einer 24-Bit Konstante > > ... denn sonst verstehen? > > Moby A. schrieb: > Schau mal ich möchte mich hier verzweifelt von den Codesize- und > Performance-Vorteilen von C überzeugen lassen !!!! ;-) > > Ich umgekehrt auch. Aber dafür fehlt mir deine Asm-Version. Da gibts schon Angebote hier... Man muß sie nur nutzen. Dein Beispiel beweist gar nichts. Ob mit Konstanten oder Variablen ;-)
Ralf G. schrieb: > du von deinem ASM-Code so überzeugt bist? Willst du die Leute zum > ASM-Masochismus erziehen? Ich bin nicht von meinem Code überzeugt sondern kenne die Vorteile von ASM. Wenn Du damit nicht klarkommst (oder nicht damit befassen willst) bleib doch bei C.
Moby schrieb: > Da gibts schon Angebote hier... Klar, mittlerweile von Josef. Hast du da mal die Takte gezählt? > Ich bin nicht von meinem Code überzeugt Wär ich auch nicht, wenn ich keinen hätte.
:
Bearbeitet durch User
Vielleicht überlegt er ja noch angestrengt (Moby, Anm. der Red.), ob er das Ergebnis des heimlich besorgten gcc hier als sein Eigenes präsentiert... Nee, nee. Es kommt noch was. Es soll (diesmal) eben ordentlich werden. So mit Kommentaren und 'Doku'. Wie hier... Beitrag "Re: C versus Assembler->Performance" ... vorgemacht.
Rufus Τ. F. schrieb: > Wäre ich nicht so boshaft, wie ich bin, würde ich jetzt nicht den > Verdacht äußern, daß er ein Programmieranfänger ist, der für sich das > große Feld der Assemblerprogrammierung entdeckt hat ... d.h. er weiß > jetzt, wo das Feld ist, und hat sich vorgenommen, es nächste > Woche/nächsten Monat/nächstes Jahr ganz sicher auch mal oberflächlich zu > erkunden. Da diktiert auch wieder eher eine bestimmte Absicht und Wunschdenken den Text als denn reales Wissen... Bist Du fähig mein obiges Beispiel als gleichlange C-Version zu liefern? Nein? Anfänger. Hauptsache große Klappe.
Moby schrieb: > Wenn Du damit nicht klarkommst (oder nicht damit befassen willst) bleib > doch bei C. Ich bin aus der ASM-Masochisten-Phase raus. Hatte ich aber weiter oben schon geschrieben.
A. K. schrieb: > Moby schrieb: > Da gibts schon Angebote hier... > > Klar, mittlerweile von Josef. Hast du da mal die Takte gezählt? > > Ich bin nicht von meinem Code überzeugt > > Wär ich auch nicht, wenn ich keinen hätte. Und Du hast nur schlechtes Scherze...
Moby schrieb: ...an Rufus... > Anfänger. Hauptsache große Klappe. Guck' an! Der Assembler-Papst! Jetzt wird er auch noch größenwahnsinnig!
Ralf G. schrieb: > Guck' an! Der Assembler-Papst! Jetzt wird er auch noch größenwahnsinnig! Ausser anspruchsloser Provokation bleibt ihm nichts mehr.
Ralf G. schrieb: > Moby schrieb: > ...an Rufus... > Anfänger. Hauptsache große Klappe. > > Guck' an! Der Assembler-Papst! Jetzt wird er auch noch größenwahnsinnig! Am Moderator zweifeln in Größenwahnsinn? Das spräche eher für den Größenwahnsinn der Gegenseite. Hat C-Papst Ralf hier noch was beizutragen um für seine Sprache zu werben. Nimm meinen Code Stück für Stück auseinander. Lass Deinen Compiler beim Optimieren heißlaufen! Doch da Du bei ASM nur Bahnhof verstehst... Schaaaade.
A. K. schrieb: > Ausser anspruchsloser Provokation bleibt ihm nichts mehr. Dir bleibt nichts, die Vorteile von ASM zu bestreiten ;-)
Moby schrieb: > Dir bleibt nichts, die Vorteile von ASM zu bestreiten ;-) Klar hat ASM, wie auch C/C++, Vor- und Nachteile. Ein fähiger Entwickler wird diese abwiegen und für jedes Projekt die am besten geeignete wählen. Mehr gibts zu C(++) vs. ASM eigentlich nicht zu sagen.
Realist schrieb: > für jedes Projekt die am besten geeignete > wählen. Das heißt (zumindest) für viele 8-Bit Projekte: Assembler. Das Werkzeug mit den maximalen Freiheiten und effektivstmöglichen Ergebnissen- mit geringstem bürokratischen Aufwand.
Moby schrieb: > Hat C-Papst Ralf hier noch was beizutragen um für seine Sprache zu > werben. Den Titel hab' ich wirklich nicht verdient! Ich mach' das nur aus Spaß. Aber ich kenne (von Können bin ich weit weg, sag' ich jetzt mal) beides. Bin nur bei C hängengeblieben. Du kannst da gerne drüber lächeln (von mir aus auch lachen), so wie der eine oder andere C-Programmierer vielleicht über BASCOM grinst. Wenn du nach diesem (Beitrag "Re: C versus Assembler->Performance") Post ein Ergebnis präsentiert hättest, wärst du der Chef gewesen. Niemand hätte das erwartet. Alle hätten sich vor dir verneigt. Aber du windest dich wie ein Aal. Tja, warum nur? (Nicht mal jetzt kommt eine Lösung, obwohl feststeht, dass es nur ein Assembler-5-Zeiler ist.)
:
Bearbeitet durch User
Moby schrieb: > Das heißt (zumindest) für viele 8-Bit Projekte: Assembler. Wenn man Entwichlungsaufwand, Wartbarkeit und Portierbarket mal weglässt könntest du recht haben. Zuden ist die schnellst- (Ausführzeit) und kleinstmögliche (RAM, Flash) Lösung oft nicht notwendig und einfach nur overkill.
@Ralf G. Ich mag hier eigentlich über nichts anderes reden als es das Threadthema nahelegt: Wie nah vermag C an die mit ASM möglichen Ergebnisse in Codesize und Performance herankommen? Welchen Aufwand erfordert das? Scherzhaft würde ich die Verhältnisse so beschreiben: Ist wie mit dem Stück Masse (C) daß nur mit immer mehr Energieaufwand hin zur Lichtgeschwindigkeit (ASM) beschleunigen kann und sie doch nie erreicht ;-) Wer irgendwo der Chef ist kannst Du ja gern mit anderen diskutieren.
Moby, es interessiert mich wirklich den von A.K.oben genannten Vergleich von dir zu sehen. Ich lerne gerne dazu und würde mich über eine Lösung von einen ASM-Verfechter freuen. Bitte in übersetzbarer Form schreiben und keinen Pseudocode. Danke dir. Gruß 900ss
Realist schrieb: > einfach nur > overkill. Bei sowas kommen mir immer gleich die dicken C-Bücher und die Konfiguritis der Compiler in den Sinn ;-)
Moby schrieb: > Ist wie mit dem > Stück Masse (C) daß nur mit immer mehr Energieaufwand hin zur > Lichtgeschwindigkeit (ASM) beschleunigen kann und sie doch nie erreicht > ;-) Jetzt verstehe ich: Du hast keinen blassen Schimmer, um was es hier geht! Schade. Die Frage... Ralf G. schrieb: > Johann L. schrieb: >> Mal ne kanz konkrete Frage: Wie testest du in AVR-Assembler, ob ein >> (einen) 32-Bit Wert kleiner als 1000000 ist? > > (Nur mal unter uns, es liest ja keiner mit: Du denkst, daran scheitert > er schon?) ... war eher ironisch gemeint, sollte ein bisschen povozieren. Ich bin fix und fertig. So ein Blender, Schaumschläger... Ich hätte nie gedacht, dass es sooo schlimm steht.
:
Bearbeitet durch User
Moby schrieb: > Realist schrieb: >> einfach nur >> overkill. > > Bei sowas kommen mir immer gleich die dicken C-Bücher <300 Seite C&R für eine universal einsetzbare Sprache vs. 152 Seiten Atmel AVR 8-bit Instruction Set ist jetzt nciht soo dich. > Konfiguritis der Compiler Muss man nicht machen, wenn aber optimierten Code haben will muss man sich -wie in ASM*- "anstrengen". Nur dass es in C nur ein Compilerflag ist. *Und nein, ASM Code ist nicht optimiert nur weil er in ASM geschrieben wurde, man muss ich auch anstrengen.
----------- Das Problem von Horst S. ist gelöst. Der Gegenbeweis wird ausbleiben. Ich würd's wieder nach 'Compiler & IDEs' zurückschieben und ein Schloss dranhängen.
900ss D. schrieb: > Moby, es interessiert mich wirklich den von A.K.oben genannten > Vergleich von dir zu sehen. Das ist ja toll. Wir reden vom Vergleich einer 32-Bit Variablen mit einer Konstanten, ja? Die Lösung (Varbytes nacheinander abklappern) hatte ich schon angedeutet, A.K. hat den Ablauf präzisiert. Ich denke das ist das was maximal möglich ist. Selbst wenn ein Compiler das mit gleicher Codesize umsetzen würde (was ich nicht weiß) hätte das für /mich/ keine Bedeutung, da ich bzw. typische 8-Bit Apps solche hochbittigen Operationen selten benötige(n). Sofern Dein Interesse hier zwischenzeitig nicht noch irgendwo befriedigt wird hole ich das gern später nach. Die von A.K. skizzierte Vergleichsfolge ist nun allerdings alles andere als interessant bzw. von besonderem Genie durchtränkt- aber das Optimum. Ralf G. schrieb: > Ich bin fix und fertig. So ein Blender, Schaumschläger... Ich hätte nie > gedacht, dass es sooo schlimm steht. Wirklich schade das es nur noch zu diesem Niveau reicht... Ist aber auch heiß heute... Rea L. schrieb > Atmel AVR 8-bit Instruction Set Das merkt man sich besser und besser. Sind ja nur vergleichsweise simple Anweidungen. Bei Flagauswirkungen einzelner Befehle schau ich manchmal auch noch rein. > *Und nein, ASM Code ist nicht optimiert nur weil er in ASM geschrieben > wurde, man muss ich auch anstrengen. Absolut. Vom Selbstläufer zum effizienten Werk hat niemand gesprochen. Aber von allen Möglichkeiten dazu.
Ralf G. schrieb: > Ich würd's wieder nach 'Compiler & IDEs' zurückschieben und ein Schloss > dranhängen. Schon klar. Wenn man nichts mehr beizutragen hat ...
Moby schrieb: > Ich mag hier eigentlich über nichts anderes reden als es das Threadthema > nahelegt: Wie nah vermag C an die mit ASM möglichen Ergebnisse in > Codesize und Performance herankommen? BTW: Wo wir jetzt im Offtopic sind. Nach den zig Texten, die Du jetzt hier abgelassen hast: Der Chefarzt nebst Assistent, drei Schwestern und dem Anästesist stehen im OP über 'ner Bypass-Operation gebeugt. Da geht die Schiebetür auf, 'nen Dackel spaziert herein und pisst dem Chefarzt ans Bein. Du, da ist kein Witz dabei und es wird nicht witzig dadurch, dass der Dackel mit dem Schwanz wedelnd rausspaziert oder eine Schwester hysterisch anfängt zu kichern. Es ist ganz einfach: Der Dackel gehört da nicht hin (und ich darf Dich zitieren: Du hast bis auf einen Versuch niemals eine Hochsprache bedient), es stinkt danach erbärmlich nach Pisse (wir landen im OT) und bis auf die Befriedigung des Dackels (Blasenentleerung) hat keiner was von der Geschichte. Kannst Du Dein Geschäft das nächste mal bitte an 'nem Baum erledigen? DANKE
@Horst Der Text spricht für Dich, Kompliment. Ich kenne diesen Ausgang der Geschichte schon: Immer dann wenn die Argumente ausgehen ;-)
Moby A. schrieb: > Immer dann wenn die Argumente ausgehen ;-) Ich brauche keine Argumente. Ich hab als TE um Hilfe gebeten. Du hast sie nicht erbracht. Stattdessen hast Du Dich in das kleine Wort "Assembler" im Titel verkeilt, völlig missverstanden und Dein eigenes Ding gedreht, während sich die Welt im Thread für mich von anderer Seite angestubbst ein Stückchen weiter gedreht hat. Was hast Du gelernt - NIX. Was hast Du mir beigebracht - NIX. Was hab ich gelernt - EINIGES, ABER NICHT VON DIR. Ich wollte was über C wissen, dazu bist Du nicht qualifiziert. Ob Du für Assembler qualifiziert bist? Nach dem Bohei, den Du veranstaltet hast, ist es mir ehrlich gesagt, egal, ICH würde DICH nicht mehr konsultieren.
@TO In einem öffentlichen wie diesem Thread musst Du mit den Antworten leben, die sich wie in diesem Fall um Dein Thema "C vs.Assembler->Performance" drehen- und die sich entwickelnde Diskussion akzeptieren die ich natürlich nicht allein gestalte. Wenn Du mehr Einfluß möchtest, mußt Du Dich auf Gespräche im Bekanntenkreis beschränken. Denen wünsche ich nicht, jemals so übel beleidigt zu werden.
Wollt ihr WIKLICH Fundamantalisten überzeugen? Gibt's keine besseren Wege zum Zeit totschlagen? Z.B. Wind um die Ecke schaufen? Jeder, der halbwegs clevver ist nutz das Werkzeug, dass im Gesamtzusammenhang am ökonomischsten für ihn ist. Der Erfolg gibt einem Recht! Jenseits von Sandkastspielereien trennt sich die Spreu ganz schnell vom Weizen.
Moby A. schrieb: > Ralf G. schrieb: > > Nun, 1000000 dezimal sind [0F 42 40] Hex. Einen 32-Bit Wert kann man > doch nun Byte für Byte abklappern ob er kleiner ist. Stellt Euch doch > nicht so dämlich. Es war lediglich die Frage einen ASM-Experten, welche *kontret* Sequenz er einsetzen würde. Wie man das im Prinzip machen kann weiß hier wohl jeder. Ich war eben nur neugierig auf eine ASM-Moby-Lösung. Aber Moby scheint lieber weitschweifige Prosa zu produzieren als einen 10-Zeiler. > Ach was. Wer Asm versteht kann das samt Datenblatt problemlos. > Mit der Aufgabe einem C-ler ASM zu erklären beschäftige ich mich nicht. > Und lenkt doch nicht ständig mit der Schreibweise, die gerade schön kurz > und knapp und gerade nicht so romanfüllend wie Hochsprachencodes > daherkommt, vom eigentlichen Problem ab: C ist einfach mehr sprachlicher > Aufwand für größere, langsamere Ergebnisse. Okay, ich hab tatsächlich mal den LM335-Code in C dargestellt. Dabei hab ich mir erlaubt, auf magische Zahlen wie $40 oder $e7 zu verzichten:
1 | #include <stdint.h> |
2 | #include <avr/io.h> |
3 | |
4 | #define N_ADCs 4
|
5 | |
6 | uint8_t IC; |
7 | uint16_t ADUC[2 * N_ADCs]; |
8 | |
9 | void adu_init (void) |
10 | {
|
11 | ADMUX = (1 << REFS0); |
12 | ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADSC) | (0b111 << ADPS0); |
13 | }
|
14 | |
15 | void adu (void) |
16 | {
|
17 | uint8_t ic = ++IC; |
18 | uint8_t adc_num = 3 & (ic >> 6); |
19 | |
20 | uint16_t *adc = & ADUC[adc_num]; |
21 | uint16_t sum64 = adc[N_ADCs] += ADC; |
22 | |
23 | if (0 == ic % 64) |
24 | {
|
25 | adc[0] = sum64 >> 6; |
26 | adc[N_ADCs] = 0; |
27 | |
28 | uint8_t refs = (ic & 0x80) |
29 | ? (1 << REFS1) | (1 << REFS0) |
30 | : (1 << REFS0); |
31 | |
32 | ADMUX = refs | adc_num; |
33 | }
|
34 | }
|
== Quelle == C: Das weitschweifige Programm hat 34 Zeilen, von denen allerdings 14 Zeilen keinen Code enthalten und "nur" der Lesbarkeit dienen. Moby-ASM: Ca. 40 Zeilen alleine für "adu". == ASM-Code == avr-gcc: Braucht 40 Instruktionen für "adu", davon sind 5 32-Bit Instruktionen. Moby-ASM: Braucht 40 Instruktionen für "adu" (korrigierte Version), davon sind 7 32-Bit Instruktionen. Moby-ASM: Nach Moby die optimale Lösung. avr-gcc: Hat nicht den Anspruch, die beste Lösung zu liefern, ist aber um 4 Bytes kürzer. Die Registerlast ist höher als bei Moby, was hie allerdings keine Rolle spielt. avr-gcc: Inspektion des erzeugten ASM zeigt, dass der Code tatsächlich suboptimal ist, und mindestens 3 Instruktionen überflüssig sind. Ergo: Wenn Moby seinen optimalen ASM-Code noch optimaler bekommen will, lohnt ein Blick über den Tellerrand.
Johann L. schrieb: > Okay, ich hab tatsächlich mal den LM335-Code in C dargestellt. Danke! Allerdings gefällt mir das Zitat nicht: Johann L. schrieb: > Moby A. schrieb: >> Ralf G. schrieb: >> >> Nun, 1000000 dezimal sind [0F 42 40] Hex. Einen 32-Bit Wert kann man >> doch nun Byte für Byte abklappern ob er kleiner ist. Stellt Euch doch >> nicht so dämlich. Das sieht so aus, als ob ich den Text geschrieben hätte. (Also 1000000 händisch in Bytes zu zerlegen... tsss... Solchen Quatsch mach' ich nicht.)
Johann L. schrieb: > Ergo: Wenn Moby seinen optimalen ASM-Code noch optimaler bekommen will, > lohnt ein Blick über den Tellerrand Mir Deine Übersetzung zu Gemüte zu führen wird noch etwas dauern, aber danke der Bemühung. Allerdings hatte ich meinen ASM Projekt-Codeschnipsel mit wenig aufregender Codesequenz hier gar nicht zur Diskussion gestellt, sondern das angehängte Programm weiter oben. Aber egal. Ein Blick über den Tellerrand ist immer sinnvoll. Welche Erkenntnisse das bringt ist die zweite Frage. Falk B. schrieb: > Jeder, der halbwegs clevver ist nutz das Werkzeug, dass im > Gesamtzusammenhang am ökonomischsten für ihn ist. Der Erfolg gibt einem > Recht! Das ist jetzt inwiefern fundamentalistisch?
Johann L. schrieb: > ist aber um 4 Bytes kürzer Hab ich jetzt was übersehen? Du schreibst, beides ist 40 Byte lang. Was den optimierten ASM Code von Moby immer noch nicht vorne stehen läßt.
Johann L. schrieb: > Ergo: Wenn Moby seinen optimalen ASM-Code noch optimaler bekommen will, > lohnt ein Blick über den Tellerrand. Gib ihm jetzt bloß nicht das Listing. Gib ihm 'ne Anweisung, wie er gcc zu installieren hat, wo er den Code hineinkopieren kann und wie er in das Listing reinschauen kann. MACH JETZT BLOSS KEINEN FEHLER!
Moby A. schrieb: > Die Lösung (Varbytes nacheinander abklappern) hatte ich schon > angedeutet Danke für die Unterstützung Moby. Ich hätte wirklich gerne von dir dazugelernt. Aber die anderen haben oben scheinbar Recht, du schwafelst hier nur rum und kannst nix. Sonst hättest du hier konkret die ASM Anweisungen gepostet. Deine Lösung wäre wirklich interessant gewesen :-(
:
Bearbeitet durch User
Horst S. schrieb: > MACH JETZT BLOSS KEINEN FEHLER! Hat der Herr seinen Humor wiedergefunden? So ernst scheint Dir "Dein" Thread dann auch nicht zu sein... 900ss D. schrieb: > Moby A. schrieb: > Die Lösung (Varbytes nacheinander abklappern) hatte ich schon > angedeutet > > Danke für die Unterstützung Moby. Ich hätte wirklich gerne von dir > dazugelernt. Aber die anderen haben oben scheinbar Recht, du schwafelst > hier nur rum und kannst nix. Sonst hättest du hier konkret die ASM > Anweisungen gepostet. Deine Lösung wäre wirklich interessant gewesen :-( Hatte ich nicht weiter oben geschrieben die bekommst Du noch? Dein letzter Beitrag gibt mir schon arg zu denken wie ernstgemeint Dein Wunsch war ;-(
900ss D. schrieb: > Hab ich jetzt was übersehen? Du schreibst, beides ist 40 Byte lang. 40 Befehle, nicht 40 Bytes.
Horst S. schrieb: > Gib ihm jetzt bloß nicht das Listing. Das wäre nicht so schlimm. Wie du selber gemerkt hast (sogar als C-Neu-Einsteiger??), mit 'C' kannst du ordentlich Struktur reinbringen. Der Assembler macht dann Code draus, der, falls man im Original darauf angewiesen ist, einfach nicht wartbar, nicht übersichtlich, nicht mal so fix erweiterbar ist. Willst du bei einem Assembler-Programm die Übersicht behalten, kostet das eben Ressorcen. Das geht sicher irgenwie (bis zu einer gewissen Größe). Der Compiler braucht sich darum aber nicht zu kümmern. Also: Das Assemblerlisting vom Compiler ist so speziell, will man nur eine Kleinigkeit ändern, kann man's auch neu machen... [leicht übertrieben :-) ]
Moby A. schrieb: > Hatte ich nicht weiter oben geschrieben die bekommst Du noch? Upps, das hatte ich nicht so verstanden. Dann freu ich mich auf eine Lösung von dir. Danke.
Moby A. schrieb: > Hatte ich nicht weiter oben geschrieben die bekommst Du noch? Mundgemalt, auf feinstem Büttenpapier, welches du nächste Woche erst in China persönlich abholst?
Wobei die Compiler - wenn man ihn lässt - zu Lasten von ein paar Befehlen mehr die mit 30 Takten langsame Shift-Schleife ersetzt, also aus:
1 | ldi XL,6 ;Every 320ms: |
2 | adu1: lsr YH ;average out |
3 | ror YL |
4 | dec XL |
5 | brne adu1 |
diesen mit 9 Takten doch wesentlichen schnellern Code produziert:
1 | clr __tmp_reg__ |
2 | lsl r24 |
3 | rol r25 |
4 | rol __tmp_reg__ |
5 | lsl r24 |
6 | rol r25 |
7 | rol __tmp_reg__ |
8 | mov r24,r25 |
9 | mov r25,__tmp_reg__ |
Johann L. schrieb: > avr-gcc: Braucht 40 Instruktionen für "adu", davon sind 5 32-Bit > Instruktionen. Bei welcher Optimierungsstufe?
A. K. schrieb: > zu Lasten von ein paar > Befehlen mehr > diesen mit 9 Takten doch wesentlichen schnellern Code produziert: Vor diesem Szenario steht man auch öfter bei Asm: weniger Platz oder mehr Performance. In diesem Fall hab ich weniger Platzbedarf den Vorzug gegeben.
Johann L. schrieb: > uint16_t *adc = & ADUC[adc_num]; > uint16_t sum64 = adc[N_ADCs] += ADC; Die beiden Zeilen kommen mir total spanisch vor. Liegt sicher nur an meinem niedrigen Niveau. Warum '+='? 16-Bit-Werte aufaddieren... Das passt zum Schluss immer noch in 16 Bit? Ich durchschaue den Trick nicht. (Bitte nicht hauen!) Und dann noch der extra Index am Zeiger. Ich gebe auf...
:
Bearbeitet durch User
Ralf G. schrieb: > Johann L. schrieb: > uint16_t *adc = & ADUC[adc_num]; > uint16_t sum64 = adc[N_ADCs] += ADC; > > Die beiden Zeilen kommen mir total spanisch vor. Liegt sicher nur an > meinem niedrigen Niveau. Warum '+='? 16-Bit-Werte aufaddieren... Das > passt zum Schluss immer noch in 16 Bit? Ich durchschaue den Trick nicht. > (Bitte nicht hauen!) > > Und dann noch der extra Index am Zeiger. Ich gebe auf... Der ADC hat 10 Bit Auflösung, d.h. die 64 aufsummierten Werte haben jeder höchstens 3FFH. An dieser kryptischen Darstellung würd ich auch verzweifeln ;-)
:
Bearbeitet durch User
Moby A. schrieb: > An dieser kryptischen Darstellung würd ich auch verzweifeln Hatte gerade einen kleinen Brown-Out.
Moby A. schrieb: > Falls Du darauf abzielst für solcherlei Berechnungen besser C samt > 32Bit-Controller zu verwenden zielst Du jedenfalls nicht auf typische > 8-Bit Anwendungen. Da sind solche Berechnungen selten. Hast du schon mal was mit den Sensirion Feuchtesensoren gemacht, SHT11 und Verwandte? Ist meiner Ansicht nach eine durchaus typische 8-Bit Anwendung, die auf einem x8er AVR in einem Auto-Sensormodul steckt, das via Bluetooth mit einem Handy kommuniziert (Feuchte, Temperatur und zum Spass noch Luftdruck). Ist fast durchweg 8/16-Bit Code und problemlos auch in Asm umsetzbar. Nur hinter dieser harmlosen letzten Zeile steckt wohl etwas Arbeit:
1 | int v = result(); |
2 | const int32_t C1 = (int32_t)(-4.0 * 100); |
3 | const int32_t C2 = (int32_t)(0.0405 * 100 * (1L<<28)); |
4 | const int32_t C3 = (int32_t)(-2.8e-6 * 100 * (1L<<30)); |
5 | v = (int)((((((C3 * v) >> 2) + C2) >> 11) * v + (1L<<16)) >> 17) + C1; |
Aber wegen dieser Kleinigkeit gleich einen 32-Bitter nehmen?
:
Bearbeitet durch User
A. K. schrieb: > Hast du schon mal Ja hab schon mal. Einen MS5534c in meiner Wetterstation. Gleiche Rechenorgie. Deshalb schrieb ich "selten" . Aber deshalb auf C/32Bit umsteigen? Wenn das täglich vorkommen würde...
:
Bearbeitet durch User
Moby A. schrieb: > Gleiche Rechenorgie. Ergänzung: Streng geheim!! Ich kann nicht mehr. Ich bin weg. :-)
Ralf G. schrieb: > Ergänzung: Streng geheim!! Genau. Deshalb sag ichs ja. Aber kein Grund zur Panik: > Ich kann nicht mehr. Ich bin weg. :-) Oder liegts am C-Code? ;-)
:
Bearbeitet durch User
Ausnahmsweise: Moby A. schrieb: > Ja hab schon mal. Mensch Moby, das war 'ne Steilvorlage!! Falsch. Das war 'n Elfmeter mit doppelter Torbreite, ohne Torwart, mit zwei Versuchen! Und du versemmelst das! Ich fass' es nicht.
Ralf G. schrieb: > Johann L. schrieb: >> uint16_t *adc = & ADUC[adc_num]; >> uint16_t sum64 = adc[N_ADCs] += ADC; > Die beiden Zeilen kommen mir total spanisch vor. > [...] Und dann noch der extra Index am Zeiger. Ich gebe auf... Das liegt an der asm-Vorlage. Die 2 Variablen, die zur "Verwaltung" eines ADC-Kanals gehören, liegen im Speicher verstreut. Ohnehin ist es recht sinnfrei, einen gegebenen Asm-Code genauso umsetzen zu wollen — das zeigen schon die magischen Konstanten wie $40. (Die zu entsorgen freilich auch mit Asm nix kostete. Sie sind der Tribut an einen Hang zur Kryptophilie). * Die Variablen, die man zur "Verwaltung" eines ADC-Kanals brauch, wird man zusammenhalten wollen, z.B. in einer Struktur wie unten. * Der IRQ-Zähler hat eigentlich nix mit dieser Routine zu tun; den wird man von außen reingeben. Falls er doch zum Modul gehören sollte, dann in die gleiche Struktur in der auch die adcs[] leben:
1 | typedef struct |
2 | {
|
3 | struct adc |
4 | {
|
5 | uint16_t result, temp; |
6 | } adcs[4]; |
7 | uint8_t n_irq; |
8 | } aduc_t; |
9 | |
10 | aduc_t ADUC; |
11 | |
12 | void adu (uint8_t n_irq) |
13 | {
|
14 | uint8_t n_adc = 3 & (n_irq >> 6); |
15 | struct adc *adc = & ADUC.adcs[n_adc]; |
16 | |
17 | uint16_t temp = adc->temp += ADC; |
18 | |
19 | if (0 == (n_irq & 0x3f)) |
20 | {
|
21 | adc->result = temp >> 6; |
22 | adc->temp = 0; |
23 | |
24 | uint8_t refs = (n_irq & 0x80) |
25 | ? (1 << REFS1) | (1 << REFS0) |
26 | : (1 << REFS0); |
27 | |
28 | ADMUX = refs | n_adc; |
29 | }
|
30 | }
|
Der Code wird dadurch etwas kleiner — n_irq (vormals IC) würde dann wie gesagt an adäquater stelle (z.B. ISR) verwaltet. Der avr-gcc Code ist immer noch nicht optimal, das Optimierungspotential wird gar noch größer; der Code ist aber immer noch kleiner als Mobys Code. Aber es geht ja schon längst nicht mehr darum, ob der C-Code ein paar poplige Bytes länger oder kürzer ist. Er ist auf der Ebene einfach besser wartbar, z.B. kann ohne Codeänderung die langsame >> 6 Schleife durch linearen Code ersetzt werden, wie Andereas ja bereits anmerkte. Es wäre wesentlich schneller gewesen, eine gescheite Dokumentation zu haben und anhand dieser eine neue Implementation vorzunehmen, anstatt die Bitgepfriemel reverse-engineeren. Moby A. schrieb: > Johann L. schrieb: >> Ergo: Wenn Moby seinen optimalen ASM-Code noch optimaler bekommen >> will, lohnt ein Blick über den Tellerrand > > Mir Deine Übersetzung zu Gemüte zu führen Lass es. Das implementiert man besser komplett neu :-) Hier noch meine Lösung zum Vergleich gegen 1000000, etwa wie in
1 | extern void f (void); |
2 | |
3 | void caller (uint32_t val) |
4 | {
|
5 | if (val < 1000000) |
6 | f(); |
7 | }
|
Lösung:
1 | caller: |
2 | cpi r22,64 |
3 | sbci r23,66 |
4 | sbci r24,15 |
5 | cpc r25,__zero_reg__ |
6 | brsh .L1 |
7 | jmp f |
8 | .L1: |
9 | ret |
10 | .ident "GCC: (GNU) 5.2.1 20150816" |
Es ist meine Lösung, weil: http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.c?r1=179124&r2=179123&pathrev=179124#l3171 Andreas hat sich also doch nicht verzählt... Moby A. schrieb: > Johann L. schrieb: >> Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an >> Kommentaren und Dokumentation. > > Oh das ist mir neu. > > Johann L. schrieb: >> Ein nicht unwesentlicher Teil der AVR-Entwickler, die sich >> hier tummeln, verwendet ASSEMBLER-Code aus meiner Feder. > > Find ich gut. Schön, wusst ich's doch. Der Code wird nämlich von avr-gcc erzeugt :-) > Ein Blick über den Tellerrand ist immer sinnvoll. > Welche Erkenntnisse das bringt ist die zweite Frage. Kein Teller is so groß, als dass es jenseits seines Randes nichts Neues, nicht Interessantes oder nicht Aufregendes zu entdecken gäbe. Inwieweit wird dazu in der Lage sind, ist keine Frage der Weite des Teller, sondern eine Frage der Höhe der Mauern im Kopf, der Weite der Phantasie, der Kühnheit, Eingeschliffenes infrage zu stellen und auf wackligen Beinen neuen Grund zu betreten, des Mutes, dabei zu stolpern und sich dem Gelächter alter Hasen auszusetzen, des Strebens, wirklich gute Lösungen zu finden ohne sich in Perfektionismus zu verhakeln, und der Muße, guten Dingen und dem Lernen die Zeit zuzugestehen, die ihnen gebührt.
:
Bearbeitet durch User
Johann L. schrieb: > cpi r22,64 > sbci r23,66 > sbci r24,15 > cpc r25,__zero_reg__ Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche, sondern so gemischt. (Ist gleich lang, gleich schnell. Sieht nur 'ungewöhnlich' aus.)
Moby schrieb: > Verstehen hier wirklich so wenige noch Asm? Keiner hängt sich das Assembler-Täfelchen so nachdrücklich um den Hals wie du... Moby A. schrieb: > @TO > In einem öffentlichen wie diesem Thread musst Du mit den Antworten leben Nicht unbedingt. Es es sein Thread. Er hat ihn eröffnet und darf ihn zuallererst selber moderieren. Dass ihm Andere seinen Thread entführen und verunstalten gehört nicht zum guten Umgangston. Im realen Leben ist es, wie wenn er eine Besprechung einberufen hat, und einfach jeder sein Zeug bespricht. Das ist zumindest unhöflich...
Schön, daß der Code weiter verbessert wird, obwohl ich immer noch nicht durchsteige... So kann ich leider noch nicht die Gleichwertigkeit mit meinem Code abschätzen. Allerdings hab ich den Eindruck, daß meine Lösung schneller aufs Papier gebracht war, halte Johann L. aber auch die Zeit fürs Reverse Engineering zugute ;-) Ganz sicher ist aber, daß diese Form kryptischer Problemlösung niemals die meine werden wird. Schließlich wollte ich noch die versprochene Lösung für 900ss nachtragen: Der C-Vorgabe > void f (void); > > void caller (uint32_t val) > { > if (val < 1000000) > f(); > } ist die Lösung > Lösung:caller: > cpi r22,64 > sbci r23,66 > sbci r24,15 > cpc r25,__zero_reg__ > brsh .L1 > jmp f > .L1: > ret > .ident "GCC: (GNU) 5.2.1 20150816" nicht ganz äquivalent, weil die Variable verloren geht. Besser und ohne die Konstante in ihre Bytebestandteile zu zerlegen ist ganz unspektakulär
1 | .equ Konstante = 1000000 |
2 | |
3 | cpi r25,byte4(Konstante) |
4 | brlo f1 |
5 | cpi r24,byte3(Konstante) |
6 | brlo f1 |
7 | cpi r23,byte2(Konstante) |
8 | brlo f1 |
9 | cpi r22,byte1(Konstante) |
10 | brsh end |
11 | f1: ... |
12 | |
13 | end: ret |
Das kostet im Maximum 9 Takte. Lothar M. schrieb: > Moby schrieb: >> Verstehen hier wirklich so wenige noch Asm? > Keiner hängt sich das Assembler-Täfelchen so nachdrücklich um den Hals > wie du... ... mit dem 8-Bit AVR in der Hand. Das bleibt eine ideale Kombination. Da ist das letzte Wort hier noch lange nicht gesprochen. > Es es sein Thread. Er hat ihn eröffnet und darf ihn > zuallererst selber moderieren. D Der TO hat sich lebhaft an der Diskussion beteiligt. Einige Moderatoren (mit mir) auch (nicht immer sehr sachlich). Die Beschwerde kam erst in Form einer üblen Beleidigung. Darum solltet Ihr Moderatoren Euch mal zuallererst kümmern. > Im realen Leben sind wir hier nicht. Das schließt Höflichkeit natürlich nicht aus.
Ralf G. schrieb: > Warum nicht nur Subtraktion bzw. Vergleiche, sondern so > gemischt. Mist. Meine Assemblerkenntnisse sind doch ganz schön eingerostet. (Der Vergleich mit Übertrag...)
Moby A. schrieb: > Das kostet im Maximum 9 Takte. Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem Thread anmerken muss. Beispielsweise wenn r25 > byte4(...) aber r24 < byte3(...).
:
Bearbeitet durch User
A. K. schrieb: > Moby A. schrieb: >> Das kostet im Maximum 9 Takte. > > Und ist falsch. Ich fragte mich schon, warum der Johann dem Moby so eine einfache Aufgabe stellt. Um den Moby an seine Grenzen zu führen, muss doch was richtig Knackiges her. Aber offensichtlich war die Aufgabe immer noch zu schwer :( Und bevor wir hier weiterdiskutieren und immer mehr vom Usprungsthema abkommen: Moby, fang doch bitte einen neuen Thread an. Dann beschwert auch keiner darüber, dass du den Thread kaperst.
Moby A. schrieb: > .equ Konstante = 1000000 > > cpi r25,byte4(Konstante) > brlo f1 > cpi r24,byte3(Konstante) > brlo f1 > cpi r23,byte2(Konstante) > brlo f1 > cpi r22,byte1(Konstante) > brsh end > f1: ... > > end: ret Eben, leider falsch, und sicherheitshalber hier mal zitiert, ansonsten verschwindet das wieder, wie weiter oben schon einmal ein Detail.
A. K. schrieb: > Moby A. schrieb: >> Das kostet im Maximum 9 Takte. > > Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem > Thread anmerken muss. Beispielsweise wenn r25 > byte4(...) aber r24 < > byte3(...). Klar, hast recht. So geht das nun nicht. Ist wohl schon zu spät heute geworden ;-) Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein. Dann soll der TO walten wie er will. Obs dann hier noch lange weitergeht?
A. K. schrieb: > Und ist falsch. Ulkig, dass ich dies nun schon zum zweiten Mal in diesem > Thread anmerken muss. Täusche ich mich oder geht es hier immer noch um den Vergleich zweier 4-Byte-Zahlen? Den Fehler hatte ursprünglich ich eingeschleppt: Josef G. schrieb: > Vergleich von zwei unsigned 4-Byte-Zahlen A und B > mit 8bit-CPU und Sprung falls A > B > > Die 4 Bytes seien A3,A2,A1,A0 bzw. B3,B2,B1,B0 > > Methode 1: > > Teste A3 > B3 > Sprung falls A3 > B3 > Teste A2 > B2 > Sprung falls A2 > B2 > Teste A1 > B1 > Sprung falls A1 > B1 > Teste A0 > B0 > Sprung falls A0 > B0 > > Methode 2: > > Berechne B0 - A0 mit Carry > Berechne B1 - A1 mit Carry > Berechne B2 - A2 mit Carry > Berechne B3 - A3 mit Carry > Sprung falls Carry gesetzt Die korrigierte Version von Methode 1 hat A.K. schon angegeben. Ich würde sie so schreiben: Teste A3 > B3 Sprung falls A3 > B3 Abbruch falls nicht A3 = B3 Teste A2 > B2 Sprung falls A2 > B2 Abbruch falls nicht A2 = B2 Teste A1 > B1 Sprung falls A1 > B1 Abbruch falls nicht A1 = B1 Teste A0 > B0 Sprung falls A0 > B0 Dabei ist angenommen, dass der compare-Befehl einen Carry und ein Zero-Flag liefert. Abbruch bedeutet Sprung ans Ende. Bei Methode 2 ist angenommen, dass die CPU bei der Subtraktion den Subtrahenden und den Carry am Addierer invertiert (wie bei 8085) und nicht nur den Subtrahenden invertiert (wie bei 6502), und dass zu Beginn der Carry Null ist.
:
Bearbeitet durch User
Moby A. schrieb: > Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein:
1 | .equ Konstante = 1000000 |
2 | |
3 | cpi r25,byte4(Konstante) |
4 | brlo f1 |
5 | brne end |
6 | cpi r24,byte3(Konstante) |
7 | brlo f1 |
8 | brne end |
9 | cpi r23,byte2(Konstante) |
10 | brlo f1 |
11 | brne end |
12 | cpi r22,byte1(Konstante) |
13 | brsh end |
14 | f1: ... |
15 | |
16 | end: ret |
Also noch BRNE-3 Takte mehr = Max.12 bei zerstörungsfreier Variable. Wiegesagt, selten gebraucht bei 8-Bit AVR! Unbekannt U. schrieb: > Eben, leider falsch, und sicherheitshalber hier mal zitiert, ansonsten > verschwindet das wieder, Du hast ja hier wirklich wichtige Aufgaben desnachts ;-)
Also gut, dann eben zerstörungsfrei:
1 | void g(long); |
2 | void f(long x) |
3 | {
|
4 | if (x < 1000000) |
5 | g(x); |
6 | }
|
Ergebnis vom Compiler:
1 | cpi r22,64 |
2 | ldi r18,66 |
3 | cpc r23,r18 |
4 | ldi r18,15 |
5 | cpc r24,r18 |
6 | cpc r25,__zero_reg__ |
7 | brge .L1 |
Ergebnis von Moby:
1 | cpi r25,byte4(Konstante) |
2 | brlo f1 |
3 | brne end |
4 | cpi r24,byte3(Konstante) |
5 | brlo f1 |
6 | brne end |
7 | cpi r23,byte2(Konstante) |
8 | brlo f1 |
9 | brne end |
10 | cpi r22,byte1(Konstante) |
11 | brsh end |
:
Bearbeitet durch User
A. K. schrieb: > Ergebnis vom Compiler:
1 | cpi r22,64 |
2 | ldi r18,66 |
3 | cpc r23,r18 |
4 | ldi r18,15 |
5 | cpc r24,r18 |
6 | cpc r25,__zero_reg__ |
7 | brge .L1 |
Und der (der Compiler) ist praktisch nur im AVR-Studio auf 'Assembler Help' gegangen, hat das Beispiel zum 'cpc-Befehl' abgekupfert und auf vier Bytes erweitert. ;-)
Ralf G. schrieb: > Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test > gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche, sondern so > gemischt. Für jedes Byte eines Multibyte-Compares wird einzeln die Entscheidung getroffen, welcher Befehl verwendet wird. Fürs erste Byte gibt es CPI, für das letzte das Register mit Inhalt 0. Für die anderen wird nachgesehen, ob die linke Seite überschrieben werden darf. Wenn ja wird SBCI draus, wenn nicht LDI/CPC. Passt so auf beide Versionen des Codes, die vorherige mit SBCI und die jetzige mit LDI/CPC. Siehe Johanns Link oben, das hat er verbrochen. Würde die Entscheidung über die zu verwendenden Methode vorneweg für alle Bytes getroffen, statt für jedes Byte einzeln, wäre hier die Optimierung über das Zero-Register über Bord gefallen. Anders als Assembler-Programmierern ist Compilern die Eleganz des entstehenden Codes gleichgültig. Zu Mobys Fehleinschätzungen gehört wohl die Vorstellung, dass jene Leute, die C verwenden, deshalb keine Ahnung von Asm hätten. Das trifft freilich nicht immer zu.
:
Bearbeitet durch User
A. K. schrieb: > Für jedes Byte eines Multibyte-Compares [...] Ralf G. schrieb: > Mist. Meine Assemblerkenntnisse sind doch ganz schön eingerostet. (Der > Vergleich mit Übertrag...) Wie das funktioneren soll, ist mir schon klar. Ich hatte gedanklich in der Sequenz einen Compare-With-Carry-Befehl drin, der auch Konstanten verarbeitet. Den gibt's aber gar nicht. Und da kommt? ... natürlich die Subtraktion ins Spiel.
Ralf G. schrieb: > der Sequenz einen Compare-With-Carry-Befehl drin, der auch Konstanten > verarbeitet. Den gibt's aber gar nicht. Und da kommt? ... natürlich die > Subtraktion ins Spiel. Ein Compare-With-Carry Befehl ist ohnehin nicht sehr verbreitet. Die meisten Architekturen kennen ihn nicht. Was freilich auch damit zusammenhängt, dass er nur bei Architekturen mit mehreren Rechenregistern im Zusammenspiel mit 2-Register-Befehlen Sinn ergibt. Bei Akkumulator- oder 3-Register-Befehlen ist er sinnlos. Recht clever und ebenfalls selten ist auch die Handhabung des Z-Flags in SBC(I) und CPC, die ein für das Gesamtergebnis gültiges Z-Flag hinterlässt. Bei den meisten Maschinen ist das Z-Flag nur für das letzte Wort gültig und daher beim Multiwort-Vergleich nutzlos.
:
Bearbeitet durch User
A. K. schrieb: > Recht clever ist auch die Handhabung des Z-Flags in SBC(I) und CPC Ja. :) Wie gesagt, ich weiß wo ich nachschlagen muss, da ich mir nicht mehr alle Befehle geläufig sind. Da habe ich dann gesehen, dass es sowas wie 'cpci' gar nicht gibt. Hätte mich dann sicher für sowas... A. K. schrieb: > Ergebnis vom Compiler: > cpi r22,64 > ldi r18,66 > cpc r23,r18 > ldi r18,15 > cpc r24,r18 > cpc r25,__zero_reg__ > brge .L1 ... entschieden. Aber nicht um zu sagen: 'Bei mir existiert die Variable aber noch!', sondern weil ich auf die andere Variante gar nicht gekommen wäre.
Ralf G. schrieb: > sondern weil ich auf die andere Variante gar nicht gekommen wäre. Das ist einfach nur die übliche Variante für zu Fuss programmierte Vergleiche von potentiell längeren Strings, auch bei AVR. Allein schon, weil du bei einem String nicht alle 50 Bytes abklappern willst, wenn es nach den ersten paar Bytes schon klar ist.
Danke Moby, immerhin hast du deinen Code gepostet. Fazit: Auch handgeschriebener ASM-Code ist nicht immer besser als der vom Compiler. Ich verwende wohl weiter den Compiler.... Aber nicht nur deshalb. Alle Vorteile des Compilers wurden ja schon genannt, selbst bei kleinen Projekten ist die Verwendung von ASM-Code nur zweifelhaft von Vorteil. Es gibt Gebiete, wo es sinnvoll ist, ihn einzusetzen (auch schon alles weiter oben erwähnt), genauso wie ein GOTO in 'C'. Warum du Moby, so verbissen an ASM festhälst, wird mir auch ein Rätel bleiben, die von Dir genannten Vorteile sind alle objektiv widerlegt worden. Deine persönliche Begeisterung für ASM-Code ist OK, wenn du mehr Spaß daran hast, dann mach es so. Jedem das was er mag. Allerdings sollte man schon objektiv bleiben und den Tellerrand hat Johann oben ja schon mit gelungenen Worten erwähnt. Neugier: Moby, ist programmieren eher aus Hobby betrieben oder verdienst du dein Geld damit?
Moby A. schrieb: > Ganz sicher ist aber, daß diese Form kryptischer Problemlösung > niemals die meine werden wird. Kryptisch sind beide; kryptisch, weil sie keine oder nur nixnutzige Kommentare enthalten. Johann L. schrieb: > Ob Code Code ist oder Hack, entscheidet sich zu 5% am Code und zu 95% an > Kommentaren und Dokumentation. > Schließlich wollte ich noch die versprochene Lösung für 900ss > nachtragen: > > Der C-Vorgabe > >> void f (void); >> >> void caller (uint32_t val) >> { >> if (val < 1000000) >> f(); >> } > > ist die Lösung > >> Lösung: >>caller: >> cpi r22,64 >> sbci r23,66 >> sbci r24,15 >> cpc r25,__zero_reg__ >> brsh .L1 >> jmp f >> .L1: >> ret >> .ident "GCC: (GNU) 5.2.1 20150816" > > nicht ganz äquivalent, weil die Variable verloren geht. Es ist absolut perfekt 100% äquivalent :-)) Der Wert in R22--R25 wird nämlich nicht mehr benötigt — falls doch, hat Andreas schon eine Lösung gepostet: A. K. schrieb: > Also gut, dann eben zerstörungsfrei:
1 | > void g(long); |
2 | > void f(long x) |
3 | > { |
4 | > if (x < 1000000) |
5 | > g(x); |
6 | > } |
> Ergebnis vom Compiler:
1 | > cpi r22,64 |
2 | > ldi r18,66 |
3 | > cpc r23,r18 |
4 | > ldi r18,15 |
5 | > cpc r24,r18 |
6 | > cpc r25,__zero_reg__ |
7 | > brge .L1 |
> Ergebnis von Moby:
1 | > cpi r25,byte4(Konstante) |
2 | > brlo f1 |
3 | > brne end |
4 | > cpi r24,byte3(Konstante) |
5 | > brlo f1 |
6 | > brne end |
7 | > cpi r23,byte2(Konstante) |
8 | > brlo f1 |
9 | > brne end |
10 | > cpi r22,byte1(Konstante) |
11 | > brsh end |
Doch Vorsich! Der Moby-Vergleich geht NUR für unsigned. Für vorzeichenbehaftete Zahlen muss eine andere Lösung her! > ohne die Konstante in ihre Bytebestandteile zu zerlegen Der von GCC erzeugte Assembler-Code ist selbsterklärend. Ist ja nicht die Aufgabe von GCC, jemand Assembler oder Grundarithmetik beizubringen. Und in Quelle steht "x < 1000000". Da ist nix zerlegt. Yalu X. schrieb: > A. K. schrieb: >> Moby A. schrieb: >>> Das kostet im Maximum 9 Takte. >> >> Und ist falsch. > > Ich fragte mich schon, warum der Johann dem Moby so eine > einfache Aufgabe stellt. Nur aus Interesse. Ehrlich gesagt hatte ich nicht erwartet, dass ein erfahrener Programmierer da strauchelt. Oder zumindest die Haken und Ösen ahnt und 2x nachdenkt bevor er / sie was schreibt. Ich hatte auch nicht erwartet, dass er auf Anhieb die beste Sequenz findet, weil es die eine beste Sequenz nämlich garnicht gibt. > Aber offensichtlich war die Aufgabe immer noch zu schwer :(
Ich bin mir nicht sicher, ob das politisch korrekt ist, wenn ich hier mal (in chronologischer Reihenfolge) was zusammenfasse. (Habe den Beitrag prophylaktisch schon mal selbst gemeldet.) Ich hoffe, die Zitate sind ohne den Zusammenhang noch sinngemäß. ----- Weil eine Hochsprache ein Programm quasi aus Fertigbausteinen zusammensetzt und die Aufgabenstellung damit nur unter Verlusten an Platz und Performance gegenüber der feiner an die Gegebenheiten anpassbaren Asm-Programmierung lösen kann. ----- Hans schrieb: > Wenn du nur 1:1 "übersetztst", dann wird C niemal kleiner als dein ASM > code werden. Kleiner? Wie soll denn das passieren? Da muss sich ein Asm-Programmierer aber schon selten dämlich anstellen :-) ----- Eine uC-Softwarewelt braucht niemand retten, wenn sie mit pure Asm schon im Klartext mit allen seinen Möglichkeiten, Transparenzen und Freiheiten formuliert ist . Immer wieder schön, wenn dann der nächstkleinere Controller genügt ;-) ----- Ich möchte mir von keinem Compiler irgendwas vorschreiben und verschleiern lassen, sondern das Heft des Handelns 100%ig selbst in der Hand behalten. Wo überall geht das heute noch so einfach wie bei den kleinen 8-Bittern? Dazu braucht es nur ein paar Dutzend Asm-Anweisungen und das Datenblatt des Controllers seines Vertrauens. ----- Die wenigen dutzend simplen Asm-Instruktionen bedeuten aber auch, man braucht nicht mehr zu seinem Glück, es vereinfacht und macht die Sache transparent. ----- Vor der Aufgabe, ein gutes Programm zu schreiben stehen Asm- und C- Programmierer gleichermaßen. Asm allein ist nun leider keine Garantie für guten Code [...] ----- X4U schrieb: > Sagt mal, was ist an diesem Codeschnipsel eigentlich lesbar Alles, wenn Du das Datenblatt und die paar Instruktionen kennst. Klartext- und jeder weiß was gespielt wird. ----- Das Ergebnis zählt und ein solches ist natürlich auch in C erreichbar. Das ändert freilich nix an Simplizität und Effizienz von Asm für eine große Klasse von Anwendungen. ----- C ist einfach mehr sprachlicher Aufwand für größere, langsamere Ergebnisse. ----- [ Meine Lieblingsstelle ;-) , Moby an Rufus ] Bist Du fähig mein obiges Beispiel als gleichlange C-Version zu liefern? Nein? Anfänger. Hauptsache große Klappe. ----- Das heißt (zumindest) für viele 8-Bit Projekte: Assembler. Das Werkzeug mit den maximalen Freiheiten und effektivstmöglichen Ergebnissen- mit geringstem bürokratischen Aufwand. ----- Autor: Moby AVR (moby-project) , Sommer 2015 PS: Zählt das eigentlich jetzt schon als Aphorismen
Ralf G. schrieb: > Zählt das eigentlich jetzt schon als Aphorismen Nö. Ein Aphorismus ist ein in sich widersprüchlicher Satz und ohne Kontext verständlich.
A. K. schrieb: > Nö. Ein Aphorismus ist ein in sich widersprüchlicher Satz und ohne > Kontext verständlich. Hmm. Hatte ich jetzt nach... https://de.wikipedia.org/wiki/Aphorismus ... anders interpretiert.
Ralf G. schrieb: > Zählt das eigentlich jetzt schon als Aphorismen Nö, aber man könnte was drauf rappen. Oder so: einfach genialst! https://www.youtube.com/watch?v=9Vg2h_nW0bA
Ralf G. schrieb: > Zählt das eigentlich jetzt schon als Aphorismen Noch nicht ganz. Ich würde es noch eher in die Kategorie der B-Forismen einordnen.
A. K. schrieb: > Nö. Ein Aphorismus ist Johann L. schrieb: > Nö, aber Ich hätte wohl doch ein
1 | ;-) |
hinmachen sollen?
Johann L. schrieb: > Oder so: einfach genialst! > > Youtube-Video "Stoiber On Drums - Jonny König" Sehr schön :-)
Ralf G. schrieb: > Ich hätt's beinahe gegoogelt :-) Vermutlich findet sich dieser Neologismus noch nicht im Duden. Dabei ist die Bedeutung doch ganz einfach: - Bei einem Aphorismus bringt jemand einen Gedanken auf den Punkt. - Bei B-Forismus schreibt jemand in einem Forum immer wieder dasselbe mit anderen Worten. :-)
Ralf G. schrieb: > Johann L. schrieb: >> cpi r22,64 >> sbci r23,66 >> sbci r24,15 >> cpc r25,__zero_reg__ > > Oh, da hab' ich doch noch 'ne Frage, die ich mir schon beim Test > gestellt habe: Warum nicht nur Subtraktion bzw. Vergleiche, > sondern so gemischt. Weil es so einfacher ist im Compiler: Der geht alls Bytes von 0 bis N-1 durchund sucht die beste Möglichkeit für den Byte-Vergleich. o CPI geht weil 22 >=16. o CPC 0 geht immer. o SBCI geht weil 23 >= 16 und das Register danach nicht mehr verwendet wird. o CP/CPC geht immer Wobei hier der Code einfach verbessert werden kann: Anstatt zu testen, ob das 32-Bit Register noch verwendet wird, könnte getestet werden, ob das entsprechende 8-Bit Subregister noch verwendet wird: http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.c?revision=227035&view=markup#l5394
1 | for (i = 0; i < n_bytes; i++) |
2 | {
|
3 | /* We compare byte-wise. */
|
4 | rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i); |
5 | [...]
|
6 | /* Upper registers can compare and subtract-with-carry immediates.
|
7 | Notice that compare instructions do the same as respective subtract
|
8 | instruction; the only difference is that comparisons don't write
|
9 | the result back to the target register. */
|
10 | |
11 | if (ld_reg_p) |
12 | {
|
13 | if (i == 0) |
14 | {
|
15 | avr_asm_len ("cpi %0,%1", xop, plen, 1); |
16 | continue; |
17 | }
|
18 | else if (reg_unused_after (insn, xreg)) |
19 | {
|
20 | avr_asm_len ("sbci %0,%1", xop, plen, 1); |
21 | continue; |
22 | }
|
23 | }
|
Anstatt auf "xreg" wäre also einfach auf "reg8" zu testen. Ein ideales Einstiegsprojekt für jeden, der schon immer mal am Compiler rumschrauben wollte! Testfall:
1 | extern void f (unsigned); |
2 | |
3 | void test (unsigned long x) |
4 | {
|
5 | if (x < 1000000) |
6 | return f (x); |
7 | }
|
Johann L. schrieb: > Weil es so einfacher ist im Compiler: [...] Ich wusste (also, ich ahnte), dass es schwerer ist als Ralf G. schrieb: > Da habe ich dann gesehen, dass es sowas wie > 'cpci' gar nicht gibt. ;-)
> Doch Vorsich! Der Moby-Vergleich geht NUR für unsigned. Für vorzeichenbehaftete Zahlen muss eine andere Lösung her! Das macht nichts. Kleine AVR's brauchen keine Vorzeichen ;-) Moby's Kühlschrankdisplay zeigt die Temperatur eben in Kelvin an, auch wenn man dabei ein Byte verschwenden muß, denn 255K sind recht kalt ;-) Wenn man sich allein die letzten Diskussionen um Georg's Compilerergebnis anschaut. Soll ich diese Entscheidungen, schnell und fehlerfrei, bei jedem Vergleich selber machen, oder hab ich verstanden, wozu es Software gibt. Auch wenn im Fall Software schreiben/Compiler nur ein Problem gelöst wird, das es ohne IT gar nicht gäbe. Die Aufgabe von Software ist nämlich solche Gedankengänge maschinenausführbar gemacht. Man kann natürlich auch zu Fuß ans Ziel kommen. Aktuell machen das manche zwangsweise um von Griechenland nach DE zu kommen. Aber keiner wird bestreiten, daß man auf dieses "Vergnügen" zugunsten eines 2 1/2h Flugs verziechten kann. So geht's auch denen, die mit Software ihre Brötchen verdienen (mich eingeschlossen). Die Blasen im Hirn haben sich Georg, Jörg und viele andere geholt, dem Rest reicht das Ergebnis. Nur ganz wenige verhandeln mit Atmel wegen Rückgabe unbenützter Flash-Zellen gegen finanziellen Ausgleich. Für die wäre dann eine Berufgruppe aus der Gesundheitsbranche zuständig: die Herren mit den weißen Kitteln.
Horst S. schrieb: > Ich bin jetzt nicht unbedingt davon ausgegangen, dass ein (nicht > optimiertes) Assemblerprogramm in C portiert um 10% größer (und damit > auch langsamer) werden muss. Ist das so? Nachdem ich schon in den ersten Beiträgen eigentlich eine eindeutige Antwort auf meine Frage bekommen hatte, möchte ich mich abschließend bei den Leuten, die sich die Mühe gemacht haben, mein Projekt(chen) anzuschauen und mit konstruktiven Beiträgen zu verbessern, noch mal ganz herzlich bedanken. Ich finde, das ist keine Selbstverständlichkeit und verdient zumindest die Anerkennung, den Antwortern bis zum Schluss zuzuhören (man muss nicht jede Idee übernehmen, aber ausprobieren sollte man das schon mal). Für mich scheint das Problem gelöst, wenn Euch nix Krasses mehr auffällt, sehe ich mich als entlassen. Zu den anderen 90% Beiträgen in diesem Threads: Wenn ich noch mal versehentlich Auslöser solch eines Disputs werde, probier' ich mal ganz blauäugig den "Beitrag melden"-Link und hoffe das Beste. Möge ein Moderator mir beistehen, sein Holzbein überstülpen und (Gregory Peck: "verfluchter Wal") da kräftig mit seiner Harpune reinpieken. Hmmm: wer den Film zu Ende geguckt hat, weiss, das hilft auch nicht immer, aber es sieht zumindest so aus, als ob es Wirkung zeigen könnte. In diesem Sinne Gruß Horst
Horst S. schrieb: > Zu den anderen 90% Beiträgen in diesem Threads Ach, nimm's locker, Horst: allein von Johanns Ausführungen über das, was er (*) da so im Compiler treibt, kann man hinreichend viel auch als gestandener Programmierer noch lernen. ;-) (*) Johann ist derjenige, der in den letzten Jahren am AVR-Backend des GCC massiv herumoptimiert hat. Davor war er zwar auch schon brauchbar, aber eben manchmal recht suboptimal (vermutlich eher das, was Moby sich unter einem Compiler vorstellen würde). Dank Johanns Engagement hat er aber nochmal massiv zugelegt, und es dürfte mittlerweile selbst einem gestandenen Assemblerprogrammierer oft schwer fallen, vergleichbar guten Code zu erzeugen.
Jörg W. schrieb: > und es dürfte mittlerweile selbst einem gestandenen > Assemblerprogrammierer oft schwer fallen, vergleichbar guten Code zu > erzeugen. Oh, wecke mal keine schlafenden Hunde ;-)
900ss D. schrieb: > Oh, wecke mal keine schlafenden Hunde ;-) Nu, immerhin hat Moby heute 2 Beiträge geschrieben ohne ein einziges Mal Assembler zu erwähnen. Kann man vielleicht als Fortschritt werten. ;-) Beitrag "Re: Flashplatzbedarf 32Bit zu 8Bit Microcontroller"
:
Bearbeitet durch User
Moby A. schrieb: > Ich liefere aber noch eine korrekte Lösung, soviel Ordnung muß sein. Moby A. schrieb: > .equ Konstante = 1000000 > ... Der interessanteste Benchmark dieser Aufgabe für mich: 1. Moby braucht dafür 1 Stunde und 5 Minuten 2. avr-gcc braucht bedeutend weniger als 1 Sekunde
:
Bearbeitet durch Moderator
Frank M. schrieb: > Der interessanteste Benchmark dieser Aufgabe für mich: > > 1. Moby braucht dafür 1 Stunde und 5 Minuten Johanns Frage: 28.08.2015 23:08 Mobys Antwort: 29.08.2015 23:37 (die falsche) 30.08.2015 02:02 (die richtige)
A. K. schrieb: > Johanns Frage: 28.08.2015 23:08 > Mobys Antwort: 29.08.2015 23:37 (die falsche) > 30.08.2015 02:02 (die richtige) Ich habe lediglich die Differenz der Zeiten aus beiden der oben zitierten Beiträgen gezogen, weil ich annahm, dass sich Moby dieser Aufgabe tatsächlich erst ab 30.08.2015 00:57 mit dem nötigen Ernst annahm. Alles andere davor war einfach so dahingesaut und nicht ernstzunehmen.
:
Bearbeitet durch Moderator
Moby A. schrieb: > Zeigt mal, wie > sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen > lässt. Das würde ja auf mich viel eher Eindruck machen ;-) Welche Funktionalität denn? Nirgends wird beschrieben, was der Code überhaupt machen soll! Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren, die sagen 0,nix über die Gesamtfunktion aus. Zu einer ordentlichen Assemblerprogrammdoku gehört auch erstmal die Beschreibung der Regeln, die Du Dir selbst in Deinem Kopf zurecht gelegt hast, wie RAM-Aufteilung, Parameterübergabe, Registerreservierung (zerstörbar, Parameter, Interrupt, Sonderfunktion), Byteorder usw. Wenn Du denkst, jemand kämpft sich durch Dein Assemblerkauderwelsch, um es dann in eine Funktionsbeschreibung zurück zu übersetzen, dann bist Du schief gewickelt. Du verlangst quasi, den Döner (Assembler) in ne Kuh (Funktionsbeschreibung) zurück zu verwandeln, um dann ne Roulade (C) daraus zu machen. Mache erstmal nen PAP oder beschreibe in Worten, was das Programm machen soll, dann erst kann man das auch in C umsetzen.
:
Bearbeitet durch User
Peter D. schrieb: > Welche Funktionalität denn? > Nirgends wird beschrieben, was der Code überhaupt machen soll! Ja, genau das hab ich vor paar Tagen auch schon vergeblich eingefordert...
Moby schrieb: > Es braucht diesbezüglich kein zeitvernichtendes Hinterherhecheln hinter > den neuesten Technologien und Programmiermethoden Da musste man als C-Progammierer niemals irgendwie hinterherhecheln: C ist viel älter als der AVR. Der AVR wurde sogar von Atmel zusammen mit IAR für C-Compiler optimiert.
1 | Atmel and IAR Systems have worked together since 1995, when we participated |
2 | in the design of the successful AVR 8-bit RISC microcontroller core, and |
3 | delivered a tailor-made C compiler. |
(Quelle https://www.iar.com/iar-embedded-workbench/atmel/) Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur und seinen verbastelten Compiler herumgeärgert hatten. Und wenn es schon einen optimierten Prozessor und dazu einen kostenlosen sehr guten Compiler gibt, dann bin ich fertig. Da fange ich nicht mal mehr für den Tiny9 ein Assemblerprojekt an. BTW: Ich kann mir übrigens vorstellen, warum der Thread inzwischen im Offtopic gelandet ist, obwohl er im ersten Fünftel noch hübsche technische Ansätze hatte...
Lothar M. schrieb: > Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller > Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen > Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur > und seinen verbastelten Compiler herumgeärgert hatten. Der 8051 wurde ein einer Zeit entwickelt, in der man solche Aufgaben nicht in C gelöst hat, sondern meist in Assembler. Und für Aufgaben, die mit 256 Bytes RAM auskommen. Da ist er ziemlich gut. Eine Akku-Architektur ist kein Problem für einen C Compiler. Vorzugsweise mit 16-Bit Akku wie 68x11/12. Auf GCC sollte man dann aber verzichten, der ist auf Register konzipiert.
:
Bearbeitet durch User
Lothar M. schrieb: > Da fange ich nicht mal > mehr für den Tiny9 ein Assemblerprojekt an. Da stimme ich zu. Ein simpler PWM-Controller auf einem ATtiny10: die Hälfte vom Flash für eine PWM-Tabelle und der Rest hat immer noch für's Programm gereicht. Ich bleibe beim Compiler, solange es keinen zwingenden Grund für Assembler gibt.
Moby A. schrieb: > Hab mal meine bereits weiter oben zur Sprache gekommene ASM Lösung aus > einem anderen Hochsprachen-Thread(problem) angehängt. Zeigt mal, wie > sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen > lässt. Das würde ja auf mich viel eher Eindruck machen ;-) Deine beiden Codeschnipsel sind Mini-Programme und damit realitätsfern. Bei realistischen Projekten (erzeugte Codegröße ab ca. 2KB) kann man mit Assembler nicht mehr mithalten. Je größer das Programm, desto größer auch der Speicherplatzgewinn mit C. So gut kann kein Assembler-Programmierer sein, dass er bei mittelgroßen bis großen Projekten so gut optimiert wie die Maschine. Ein Compiler kann hier immer noch den Überblick behalten, während der Assembler-Programmierer diesen so langsam aber sicher verliert.
So Moby, jetzt hab ich mir deinen asm Programm mal angesehen. Da sind einige Dinge drin, die unsauber sind. zB hier:
1 | DATARAM: |
2 | KEY0S: .DB 1 ;Key0 (0/$ff= un/betätigt Status) |
3 | KEY0C: .DB 1 ;Key0 (Betätigungsdauer, Counter) |
4 | KEY1S: .DB 1 ;Key1 (0/$ff= un/betätigt Status) |
5 | KEY1C: .DB 1 ;Key1 (Betätigungsdauer, Counter) |
6 | KEY2S: .DB 1 ;Key2 (0/$ff= un/betätigt Status) |
7 | KEY2C: .DB 1 ;Key2 (Betätigungsdauer, Counter) |
Hier definierst Du sechs Variablen, welche hinternander im Speicher liegen. Ok. Aber hier:
1 | systemint: |
2 | ..ldi ZL,low (KEY0S-2) |
3 | ldi ZH,high(KEY0S-2) |
Hier setzt du den Z-Poiter auf zwei Speicherzellen vor das KEY0S. Das funktioniert zwar, weil Du hier:
1 | keyproc: |
2 | adiw ZH:ZL,2 |
beim Aufruf immer plus zwei rechnest und die Tasten in exakt der Reihenfolge abfragst/aufrufst, in der Du die in DATARAM definiert hast. Aber das ist bei weitem keine ordentliche Lösung. Wie soll ein fremder Programmierer, der (nur) die Funktion keyproc bekommt/sieht/analysiert. wissen, was das soll? Sowas ist kein sauberes Programmieren. Sauberer wäre es, keyproc die "Taste" im DATARAM mitzugeben. Weiter:
1 | systemint: |
2 | ... |
3 | sec ;Entprellung Key1 (PB6) |
4 | sbis PINB,6 |
5 | clc |
6 | rcall keyproc |
Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc aufgerufen wird. Weiter:
1 | keyproc: |
2 | ... |
3 | ldd XL,Z+0 ;8x alle 5ms testen |
4 | rol XL ;= 200% Bulletproof ;-) |
5 | std Z+0,XL |
Das LDD/STD speicher/lädt den Wert KEYxS aus DATARAM. Das ROL schiebt das Carryflag (von der Taste) von rechts rein. Ergebnis: (bleibt) Null, wenn Taste nicht betätigt. Sonst: 0,1,3,7,15,31,63,127,255,255,255,255 bis wieder losgelassen. Weiter:
1 | keyproc: |
2 | ... |
3 | breq keyproc2 |
Wird aufgerufen, wenn obiger Zähler Null ist. Also wenn acht Samples hinternander die Taste nicht gedrückt ist. ...
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Ein maßgeschneiderter C-Compiler? Das ist doch die Erfüllung aller > Entwicklerträume, die sich bis dahin mit dem 8051, dem holprigen > Assembler (dessen bester Befehl der djnz war), seiner Akku-Architektur > und seinen verbastelten Compiler herumgeärgert hatten. Der 8051 hatte noch viele andere geniale Befehle, CJNE, MOVC A,@A+DPTR, JMP @A+DTPR hab ich sehr oft benötigt. Und Bitlogik ging auch sehr einfach mit MOV C,bit, ORL C,(/)bit, MOV bit,C, CPL bit, JBC usw. Ich fands genial, was der Herr Keil da geleistet hat. Meine Assemblerprogramme waren durchweg länger, als später in C geschrieben. Und das Funktionen per default nicht reentrant waren, hat kaum gestört. Die Idee mit dem SRAM-Overlay hätte man nie in Assembler umsetzen können, das kann nur ein Compiler.
Matthias L. schrieb: > Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc > aufgerufen wird. Weiter: > keyproc: > ... > ldd XL,Z+0 ;8x alle 5ms testen > rol XL ;= 200% Bulletproof ;-) > std Z+0,XL Du hättest statt der "..." die entsprechenden Befehle vollständig hinschreiben sollen:
1 | keyproc: adiw ZH:ZL,2 ;Tastenstatus entprellend ermitteln |
2 | in YH,GPIOR0 |
3 | mov YL,YH |
4 | ldd XL,Z+0 ;8x alle 5ms testen |
5 | rol XL ;= 200% Bulletproof ;-) |
Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt, im konkreten Fall mit 0. Somit schiebt ROL in das XL-Register nur Nullen hinein, was den nett gemeinten Programmiertrick völlig versagen lässt. Wir wissen zwar nicht, was Mobys Programm tun soll (er verrät es uns ja nicht), eins kann aber sicher gesagt werden: Es entprellt keine Tasten. Und was lernen wir daraus? 1. Das Carry-Flag ist eigentlich gedacht für das Zusammensetzen von Multibyte- aus mehreren Einzelbytebefehlen (Addition, Shift usw.) und für Vergleiche mit anschließenden bedingten Sprüngen. Dabei wird das Flag in einem Befehl geändert und im direkt darauffolgenden Befehl ausgewertet. Es ist nicht gedacht für den Transport von booleschen Informationen über weite Strecken innerhalb des Programms. Wenn man das trotzdem tut, muss man sehr vorsichtig sein, damit man nicht versehentlich einen Befehl dazwischen einfügt, der das Flag überschreibt. => Wenn man schon Assembler programmiert und dabei auzch noch tief in die Trickkiste greift, sollte man gut ausgeschlafen sein und jede Code-Änderung dreimal mit dem Auge durchgehen und zusätzlich intensiv testen. 2. Ich vermute, Moby hat aus seinem Fundus eine ältere keyproc-Routine übernommen, die zunächst nur für eine einzelne Taste vorgesehen war. Er hat sie auf mehrere Tasten erweitert, musste dazu aber die indirekte Adressierung für das Z-Register und damit verbunden den ADIW-Befehl einführen, was schließlich zu dem Fehler führte. => Wiederverwendbarkeit von Code erfordert eine genaue und vollständige Dokumentation nicht nur der Funktion, sondern auch der Nebeneffekte. Das ist hier offensichtlich nicht geschehen. Da Moby der Assembler-Gott ist, der immer alles richtig macht, hat er auch keinen Bedarf gesehen, die Routine vor ihrer Veröffentlichung wenigstens einmal zu testen ;-) 3. Hochsprachen sind weniger anfällig gegen solche Fehler, da dort Information ausschließlich über Variablen transportiert wird. Wenn eine Variable an einem Punkt geschrieben wird und etliche Anweisungen später wieder gelesen wird, fällt es normalerweise auf, wenn dazwischen eine weitere Zuweisung an die Variable erfolgt. Ausnahme: Die Variable ist global und wird als Nebeneffekt eines Unterprogrammaufrufs überschrieben. Dann ist der Fehler ähnlich schwer zu erkennen wie in Mobys Fall. Das ist aber auch der Grund, warum globale Variablen (vor allem Schreibzugriffe auf dieselben) vermieden werden sollten. Aber selbst diese Fehlerursache lässt sich aus der Welt schaffen, indem man auf der Programmierprachenleiter noch eine Stufe höher steigt (ich sehe schon Mobys entsetzten Gesichtsausdruck vor mir) und eine Funktionalsprache verwendet. Damit gehören solche Fehler (und viele andere auch) endgültig der Vergangenheit an.
Jetzt sind meine Feststellungen ja hier immer noch Thema. Hatte Mod Yalu nicht angemahnt: > Und bevor wir hier weiterdiskutieren und immer mehr vom Usprungsthema > abkommen: > Moby, fang doch bitte einen neuen Thread an. Dann beschwert auch keiner > darüber, dass du den Thread kaperst. Hatte Mod Lothar M. nicht beklagt: > Dass ihm Andere seinen Thread > entführen und verunstalten gehört nicht zum guten Umgangston. Nun erklärte ich mich bereit, dem TO Horst S. wieder das Feld zu überlassen. Was vom TO folgt ist nun aber nur noch > möchte ich mich abschließend ... bedanken. Ja was jetzt? Was willst Du eigentlich? Deine Antworten hast Du also bekommen. Darf nun darüber hinaus nicht mehr diskutiert werden? Mußtest Du diesen Kübel Unrat weiter oben über mich ausgießen? Ich frage mich schon sehr, welche Höflichkeit das nun meinerseits noch wert sein soll... Ich werde sobald möglich noch auf einige in der Zwischenzeit aufgelaufenen Beiträge eingehen. Ein extra Thread dafür ist Blödsinn, weil man sich nicht mehr sinnvoll auf vorhergehende Beiträge beziehen kann. Danke an alle, die sich konstruktiv mit meinen Sourcen auseinandergesetzt haben. Ich hoffe daß ich auch noch was draus lernen kann.
>Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt Das hatte ich sogar noch übersehen. >Es ist nicht gedacht für den Transport von booleschen Informationen >über weite Strecken innerhalb des Programms Dafür würde das SREG das T-Flag bieten. Dieses kann frei verwendet werden und wird nicht bei arithmetischen Ops geändert. Sprungbefehle dafür gibt es aber genauso.
Peter D. schrieb: > Moby A. schrieb: >> Zeigt mal, wie >> sich die Funktionalität in höchstens gleicher C -Codegröße umsetzen >> lässt. Das würde ja auf mich viel eher Eindruck machen ;-) > > Welche Funktionalität denn? > Nirgends wird beschrieben, was der Code überhaupt machen soll! > > Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren, > die sagen 0,nix über die Gesamtfunktion aus. Peter, hast du immer noch nicht verstanden, dass Mobys Code qua Definition selbsterklärend ist? > Nirgends wird beschrieben, was der Code überhaupt machen soll! Ich bezieht mich hier mal auf den Code für den LM335: Mal unabhängig davon, was dieser Asm- oder C- oder In-was-für-einer-Sprache-auch-Immer-Code genau tut, wäre interessant zu wissem, wie der Code einzusetzen ist. Für jeden erzeugten ADC-Wert wird über 64 Werte gemittelt. Warum? Erhöht das die Genauigkeit? Was ist die maximale Aufruffrequenz für die Funktion? Intention ist wohl, die adu-Funktion über eine ADC-ISR aufzurufen, und der ADC liefert beständig neue Werte / IRQs per ADATE (ADC Auto Trigger Enable). Problem: Die adu-Funktion fummelt an der ADC-Konfiguration rum: o Nach Ändern des Input-MUX dauert es recht lange (*), bis wieder brauchbare ADC-Werte verfügbar sind. Die ersten ADC-Werte sind Schrott. o Vermutlich wurde die Mittelung eingeführt, weil sich damit genauere Ergebnisse erzielen lassen; die Mittelung maskiert also nur das MUX-Problem ohne es zu benennen oder zu lösen. Eine Lösung wäre z.B. den 63. ADC-Wert in den 0. zu kopieren. (Falls die MUX-Zeit nicht größer als 2 Wandlungen ist, in welchem Falle noch mehr Werte zu kopieren wären...) o Vermutlich gilt ähnliches für Rumfummeln an REFSx, also Auswahl der Referenzspannung. (*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis: Schrott. Das Datenblatt (ATmega8 oder ATmegax IIRC) gab die Info nicht her, und erst eine Anfrage beim Hersteller ergab Klarheit: Die nach einer MUX-Umschaltung benötigte Zeit ist so hoch, dass ich den Ansatz verwarf und schließlich eine komplett andere Lösung wählte. Irgendwie kann ich mich des Eindrucks nicht erwehren, dass hier eine nerdig-neurotische Fixierung darauf, das letzte Byte aus einer Implementierung zu quetschen, den Blick auf die reale Anwendbarkeit des Codes und deren Einschränkungen verstellt. Natürlich liegt es in der Verantwortung des Anwenders, der Mobys Code anwendet, seine Hardware adäquat zu initialisieren. Jedoch erwähnt Moby in seinem Code diese MUX-Fußangel an keiner Stelle. Da er sich ihrer offenbar nicht bewusst ist, würd ich darauf tippen, dass sein LM335-Code nicht getestet ist — zumindest nicht so, dass man ihn guten Gewissens in einem öffentlichen Forum weitergeben möchte... Natürlich macht der Code Byte für Byte was sein Autor will — inwieweit das überhaupt sinnvoll ist oder Mumputz, steht auf einem anderen Blatt; inzwischen vielleicht sogar im Datenblatt.
:
Bearbeitet durch User
Moby schrieb: > Asm allein ist nun > leider keine Garantie für guten Code, wie man beim TO-Programm schön > sehen kann ;-) Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru, aber einfach abfrühstücken lasse ich mich auch nicht von Dir. Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung.
> Der 8051 wurde ein einer Zeit entwickelt, in der man solche Aufgaben nicht in C gelöst hat, sondern meist in Assembler. Wikipedia: PLM compilers have been made for 8008, 8080, 8085, 8051, 8052, 8096. 80196, 8086, 80186, 286 and 386. Nun ist PLM von der Syntax her kein C, aber sonst C ähnlicher als Assembler. Und wenn man 8008 liest, offenbar ein Zeitgenosse von frühem C anfang der 70er. Von Intel (und seinen Kunden) wurde mit PLM alles gelöst was ging. Ich erinnere mich an eine digitale Regelung um die 4 Farbwerke einer großen Druckmaschine zu synchronisieren (damit die Farben richtig übereinander kommen). Das hatte eine Schweizer Firma 1982 (da war ich Werkstudent in der Druckerei) mit einem 8085-Board in PLM80 gemacht. Auch das 8085-Entwicklungssystem hatte ein OS (ISIS II) in PLM80 geschrieben. Das Konkurrenzprodukt CP/M bestand in Teilen auch aus PLM-Code. (grad gesehen: es gibt die CP/M Sourcen in Netz, dabei auch die F66-Source des Intel PLM80 Compilers. Er soll mit Gnu-FORTRAN übersetzbar sein)(das ist fast wie Oldtimerhefte durchblättern 8-)) Einziger Nachteil an dem Zeug damals: Intel lies es sich vergolden. Und heute haben wir den avr-gcc. 0€, satte Gegenleistung. Ich bekenne: alles Off-Topic, aber das hat in diesem Thread ja Tradition ;-)
:
Bearbeitet durch User
Johann L. schrieb: > (*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein > quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis: > Schrott. Kann ich nicht bestätigen. Ich benutze immer den MUX und habe keinerlei Übersprechen der anderen Eingänge oder falsche Messungen. Z.B. wenn ich 6 Eingänge messen will, lege ich ein Array für die 6 Ergebnisse an. Ein Timerinterrupt liest dann die vorherige Messung ins Array, startet die Messung und schaltet den MUX weiter. Das Main nimmt sich dann den benötigten Wert, ohne auf den ADC warten zu müssen. Nur wenn man die interne Referenz messen will, muß man etwa 8 Meßwerte wegschmeißen, ehe der Wert stimmt. Vermutlich ist da ein hochohmiger Widerstand drin und der Sample-Kondensator braucht dadurch lange zum Umladen. http://www.avrfreaks.net/comment/493872#comment-493872
:
Bearbeitet durch User
>Das hatte eine Schweizer Firma
Ferag AG?
Bobster, oder so. Das ist über 30 Jahre her!
Horst S. schrieb: > Moby schrieb: >> Asm allein ist nun >> leider keine Garantie für guten Code, wie man beim TO-Programm schön >> sehen kann ;-) > > Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent Beispiel:
1 | //Transmitter/Receiver enabled/interrupt enabled |
2 | ldi d0, (1<<TXCIE0) + (1<<RXCIE0) + (1<<TXEN0) + (1<<RXEN0) |
3 | sts UCSR0B, d0 |
Bereis diese 3 Zeilen sind ein Albtraum der Unwartbarkeit und ab weibischer Weitschweifugkeit nicht zu überbieten! Der Kommentar ist überflüssig und lenkt vom Wesentlichem ab, nämlich dem Code. Er verwirrt den Leser, ist redundant und verschwendet wertvolle Bytes in deinem Rechner, auf deiner Festplatte, und in unser aller Birnen! Die nächste Zeile verwändet abermals die Anti-Pattern Byteverschwendung und Zeitverschwendung durch dein Assembler-Programm: Die << und | müssen aufwändigst von deinem Rechner errechnet werden — ein Glück, dass der Assembler, den du verwendest, von erfahrenen Assembler-Experten hochoptimiert programmiert wurde. Nur so ist es möglich, dass es nich Minuten oder gar STunden dauert, bis dein Projekt übersetzt ist! Aber ich schweife ab... "d0" ist ein sehr guten Ansatz, denn es spart 8 wertvolle Bits gegenüber einem "R16" — und das sogar 2× !. Dennoch: Solche symbolischen Namen sind die totale Verfehlung und zeigen die Degeneriertheit deiner Gedankenwelt, ausgelöst durch wiederholten Lesens von Hochsprachen-Code und Kontakt mit Individuen, welche solche Widerlichkeiten ernsthaft in Betracht ziehen oder gar ausüben! Hie noch die selbsterklärende, ultimative Asm-Lösung, die keine Fragen offen lässt!
1 | LDI R16, $db |
2 | STS 132, R16 |
Alles andere ist kindischer Schnickschnack! p.s. ich hab noch eine kürzere Lösung gefunden, die weitere wertvolle Bytes spart!
1 | .word $affe |
2 | .word $dead |
:
Bearbeitet durch User
>Das hatte eine Schweizer Firma
Ferag AG?
Gerade mal Google befragt:
Bobst, machen heute in Verpackungsmaschinen und nicht mehr in
Druckmaschinenausrüstung.
Verdammt, wo soll ich denn dann mit meinen 8GB Ram und 1,3MHz hin? Nur Fickelfilme gucken?
Horst S. schrieb: > Verdammt, wo soll ich denn dann mit meinen 8GB Ram und 1,3MHz hin? Nur > Fickelfilme gucken? Musst die Kiste in Assembler programmieren. Andernfalls ist sie (bei 1,3GHz jedenfalls) für normale Anwendungen viel zu schnell. Nur in Assembler wird es dir gelingen, sie auf vernünftiges Mass zu drosseln. ;-) Aus dem gesparten RAM machst du dann eine RAM Disk. Fürs Swapfile.
:
Bearbeitet durch User
8Gb-RAM und nur 1,3MHz, da kann booten von Windows etwas dauern ;-)
Johann L. schrieb: > Hie noch die selbsterklärende, ultimative Asm-Lösung, die keine Fragen > offen lässt! > LDI R16, $db > STS 132, R16 Das R16 könnte man noch durch die Adresse ersetzen...
Carl D. schrieb: > 8Gb-RAM und nur 1,3MHz, da kann booten von Windows etwas dauern > ;-) Ich boote nicht, ich standbye. (Is'n Notebook.)
Peter D. schrieb: > Johann L. schrieb: >> (*) Seinerzeit hab ich ebenfalls versucht über Zeitscheiben ein >> quasi-paralleles Einlesen mehrerer ADC MUX-Inputs umzusetzen. Ergebnis: >> Schrott. > > Kann ich nicht bestätigen. Ich benutze immer den MUX und habe keinerlei > Übersprechen der anderen Eingänge oder falsche Messungen. > Z.B. wenn ich 6 Eingänge messen will, lege ich ein Array für die 6 > Ergebnisse an. Ein Timerinterrupt liest dann die vorherige Messung ins > Array, startet die Messung und schaltet den MUX weiter. > Das Main nimmt sich dann den benötigten Wert, ohne auf den ADC warten zu > müssen. > > Nur wenn man die interne Referenz messen will, muß man etwa 8 Meßwerte > wegschmeißen, ehe der Wert stimmt. Vermutlich ist da ein hochohmiger > Widerstand drin und der Sample-Kondensator braucht dadurch lange zum > Umladen. > http://www.avrfreaks.net/comment/493872#comment-493872 Ich hab nur noch meine Antwort an den Atmel-Support gefunden, aus der eine Zeit von 125µs hervorgeht:
1 | The device is an ATmega8. However, I assumed that all AVRs are |
2 | equiped with the same input MUX, i.e. you do not taylor input |
3 | MUXs for every AVR derivative. |
4 | |
5 | The ATmega8 manual does not mention these 125µs. |
6 | |
7 | 125µs are *very* long. I would expect transition times in the |
8 | range of ns after a channel selection like in stand alone |
9 | analogue switches / multiplexers. |
Den Datasheets von z.B. ATmega32 und ATtiny26 zufolge betrifft das nur den differentiellen Modus, und den hat nicht jeder AVR. Der ATmega8 hat ihn nicht und da steht es folgerichtig auch nicht drin. "Special care should be taken when changing differential channels. Once a differential channel has been selected, the gain stage may take as much as 125µs to stabilize to the new value. Thus conversions should not be started within the first 125µs after selecting a new differential channel. Alternatively, conversion results obtained within this period should be discarded. The same settling time should be observed for the first differential conversion after changing ADC reference (by changing the REFS1:0 bits in ADMUX)."
:
Bearbeitet durch User
Jörg W. schrieb: > allein von Johanns Ausführungen über das, was er (*) da so im > Compiler treibt, kann man hinreichend viel auch als gestandener > Programmierer noch lernen. ;-) > > (*) Johann ist derjenige, der in den letzten Jahren am AVR-Backend > des GCC massiv herumoptimiert hat. Davor war er zwar auch schon > brauchbar, aber eben manchmal recht suboptimal (vermutlich eher > das, was Moby sich unter einem Compiler vorstellen würde). Ja, ein Compiler arbeitet bestimmt nicht so, wie sich Lieschen Müller das ausmalt. Aber in einem muss ich Moby recht geben: Der erzeugte Code ist nicht optimal. Das Verbesserungspotential würd ich mit 10% oder mehr ansetzen. Aber andererseits ist auch die frage, die weit ein Assemblerprogrammierer vom Optimum (das wir i.d.R nicht kennen) entfernt ist, insbesondere auch wie weit er davon entfernt bleiben will weil er seinen Code nicht kaputt-optimieren mag. Bei Mobys Code könnte man z.B. einiges an Zeit sparen wenn — wie schon erwähnt — auf die Schiebeschleife verzichtet würde und zudem die Funktion inline in der ISR wäre. Dass der Code selbst ein paar Ticks mehr braucht ist dabei garnicht das Problem, aber bei AVRs sind ISRs in der Regel blockierend, und die Latenzzeiten aller anderen ISRs werden höher. > Dank Johanns Engagement hat er aber nochmal massiv zugelegt, Leider geht teilweise viel Zeit drauf, manchen Atmel-Änderungen wie dem Specs-Zeug hinterher zu wischeln. Allein das hat mich mehrere Tage AVR-Zeit gekostet, was in Real Time dann locker Wochen bis Monate sind :-( A. K. schrieb: > Den Datasheets von z.B. ATmega32 und ATtiny26 zufolge betrifft das nur > den differentiellen Modus, und den hat nicht jeder AVR. Der ATmega8 hat > ihn nicht und da steht es folgerichtig auch nicht drin. Ja, es stand / steht nicht im Datenblatt, und es war für ein Device ohne differentiellen Modus. Wenn ich's richtig verstand wurde vom 2nd-LevelSupport nachgemessen, und ich musste einige Tage warten bis die das Ergebnis hatten. Die genaue ADC-Config des ATmega8 hab ich allerdings nicht mehr, eingestampft wie gesagt.
Na da hat sich ja einiges getan, seit ich in diesen Thread das letzte mal reingeschaut habe. Ja, genau so etwas hab ich schon erwartet. Das ist oft der Normalfall, auch in den Programmierforen. Die ärgesten Assembler-Verfechter glänzen da bei Assembler Fragen meistens mit Abwesenheit. Aber das das rückzugsgefechtartige Gestammel von Moby so deutlich ausfallen würde, das hab ich dann doch nicht erwartet. Besonders schön natürlich das Bonmont mit der fehlerhaften Adressierung im BST in der ominösen ADC Routine. Moby, was machst du eigentlich, wenn ich eine andere Verteilung der Referenzspannungen haben will, oder mehr Kanäle, oder nicht 64 Samples sondern weniger? Oder gar, Gott bewahre, mehr? Dann platzt deine ach so tolle handoptimierte Bitpfriemelei wie eine Seifenblase und die Arbeit geht von vorne los. Das alles sind Dinge, die mir in C nur ein Schulterzucken kosten. Einen Zahlenwert ändern und soll sich doch der Compiler was überlegen, wie er das anständig umsetzt. Und sorry. Ich weiss ja nicht, was du für Programme schreibst. Aber die Welt hört beileibe nicht bei 8 Bit Arithmetik auf. Ein bisschen rechnen ist ausserdem keineswegs so selten, wie du das hinstellst. Ganz im Gegenteil: ein paar Werte in ein paar Register schreiben, das ist der eigentlich geringfügigere Teil in einem Programm. Das kann man gut in Assembler machen. Allerdings: Das kriegt der Compiler genau so gut hin. Und wie man gesehen hat, ist der Schwellwert an Komplexität, den du noch überblicken kannst, so gross dann auch wieder nicht. Ich gebe gerne zu, dass ich den 32 Bit Vergleich nicht so elegant hingekriegt hätte. Muss ich auch nicht. Bei mir macht das der Compiler. Mich interessiert es schlicht und ergreifend nicht besonders wie er das macht. Ich kümmere mich lieber darum, welche Bedeutung dieser Vergleich im Kontext meines Programmes hat, warum er da stehen muss, ob es ein kleiner oder doch ein größer sein muss. Die Details der Umsetzung - die macht der Compiler für mich. Und wenn er da ein paar Takte zuviel reinhaut stört das in mehr als 95% aller Fälle nicht die Bohne. Dafür, und diesen Seitenhieb kann ich mir nicht verkneifen, macht der das zum Ausgleich korrekt und braucht nicht anderthalb Stunden dafür. Ich hab mit meiner Zeit wirklich was besseres zu tun, als mich mit Routine-Angelegenheiten rumzuschlagen. So interessant sind die auch wieder nicht. Aber ein ausgefuchster Algorithmus, der kann mich dann auch schon ein paar Stunden oder Tage beschäftigen. Nur - so weit kommst du gar nicht, weil du ihn gar nicht wegen des Umfangs im absehbarer Zeit implementieren kannst. Oder - was noch viel wichtiger ist - du kannst gar nicht Varianten davon genauer studieren, weil du viel zu sehr damit beschäftigt bist, warum das Carry Flag schon wieder mal an einer Stelle nicht den Wert hat, den es haben sollte (jetzt nur mal so zum Beispiel). Kurz und gut: du musst dich auf einer Ebene mit Problemen rumschlagen, die nichts mit der eigentlichen Aufgabenstellung zu tun haben. Die eigentliche Aufgabenstellung mag lauten, anhand einer Uhrzeit ein Temperaturprofil mit einem PID Regler abzufahren. Ob du dabei den X-Pointer oder doch den Z-Pointer zur Indizierung in die Temperaturtabelle benutzt ist dabei völlig nebensächlich. Du musst auch mal in etwas größeren Dimensionen denken als nur "Wenn Taster dann Licht an".
:
Bearbeitet durch User
Karl H. schrieb: > rückzugsgefechtartige Gestammel von Moby Na na nicht so vorschnell. Es soll doch da tatsächlich noch andere Dinge im Leben geben als hier permanent präsent zu sein. Oder etwa nicht? Karl H. schrieb: > Besonders schön natürlich das > Bonmont mit der fehlerhaften Adressierung im BST in der ominösen ADC > Routine. Wir werden doch nun einen Flüchtigkeitsfehler nicht so hoch aufhängen! Daß es hier im Forum unentschuldbar ist, einen Quelltext mit einem solchen zu veröffentlichen, ok, daß muß und werde ich zukünftig berücksichtigen. Karl H. schrieb: > Moby, was machst du eigentlich, wenn ich eine andere Verteilung > der Referenzspannungen haben will, oder mehr Kanäle, oder nicht 64 > Samples sondern weniger? Oder gar, Gott bewahre, mehr? Dann platzt deine > ach so tolle handoptimierte Bitpfriemelei wie eine Seifenblase und die > Arbeit geht von vorne los. Da platzt gar nichts. Oder ist eine entsprechende Umformulierung nun gleich High-Tech? Nein, es ist Kiki. Wenngleich flüchtigkeitsfehleranfällig und damit hier nicht sofort veröffentlichungswürdig. Aber was man schließlich hat das hat man...
Moby A. schrieb: > Da platzt gar nichts. Oder ist eine entsprechende Umformulierung nun > gleich High-Tech? Nein, es ist Kiki. Na Moby... wieder ganz der Alte? ;-(
Karl H. schrieb: > rückzugsgefechtartige Gestammel Da mokieren sich die einen Mods über vaterlandsgefährdende Threadübernahme, die anderen über Rückzug. Da werden beleidigende Kommentare von Forumsteilnehmern kritisiert- und Mods schlagen in die gleiche Kerbe. Diese Forummodlogik für in sich konsistent zu halten würde ich Gestammel nennen... Aber so sind sie, die Menschen. Einer wie der andere. Karl H. schrieb: > Aber die > Welt hört beileibe nicht bei 8 Bit Arithmetik auf. Sicher nicht. Das für Asm wie für 8-Bit AVR nachteilige Thema hatten wir schon. Eine große Klasse von Steuerungs-Anwendungen kommt da ohne aufwendiges 32 Bit aus. Sensoreinlesen, verarbeiten und verschiedene Ausgaben veranlassen (z.B. an seriell angebundene Aktoren/Webinterfaces) haben größere Berechnungen selten am Bein. > Allerdings: Das kriegt der Compiler genau so gut hin. Berechnungen? Sicher doch. Das ist dann aber nur ein Aspekt von vielen und ich erspare mir an dieser Stelle weitere Wiederholungen zu den Vorteilen von Asm. > Mich interessiert es > schlicht und ergreifend nicht besonders wie er das macht. Was man in Asm hat das hat man. Über die Jahre begeisterten Asm-Programmierens kann das eine ganze Menge werden. > braucht nicht anderthalb Stunden dafür. Ja es ist wirklich interessant was sich aus den Zeitdaten veröffentlichter Beiträge so alles ableiten lässt ;-) > ausgefuchster > Algorithmus, der kann mich dann auch schon ein paar Stunden oder Tage > beschäftigen. Nur - so weit kommst du gar nicht, weil du ihn gar nicht > wegen fehlender Notwendigkeit eines solchen ;-) > weil du viel zu sehr damit beschäftigt bist, warum das Carry > Flag schon wieder mal an einer Stelle nicht den Wert hat, den es haben > sollte C-Programmierer haben da andere, gewichtigere Probleme: Den ganzen Zirkus von C-Konstruktionen mitsamt komplexer Ausdrücke und Compileroptionen unter Kontrolle zu behalten... Was ist denn da ein Carry Flag ;-) > in etwas größeren Dimensionen denken > als nur "Wenn Taster dann Licht an". Das Zusammenwirken vieler Sensoren und Aktoren verknüpft über drahtlose Netze stellt durchaus ein paar Anforderungen. Nur eben weniger an Berechnungen.
Ich verweise auf die Universalantworten, auch zu diesem Thema Beitrag "Re: 8bit-Computing mit FPGA" Beitrag "Re: 8bit-Computing mit FPGA" 'Nuff said
Johann L. schrieb: > Das Verbesserungspotential würd ich mit 10% oder mehr ansetzen. Meine Rede. Insbesondere bei kurzen Programmen sind die Chancen dieses Potential zur Geltung zu bekommen hoch. > Aber > andererseits ist auch die frage, die weit ein Assemblerprogrammierer vom > Optimum (das wir i.d.R nicht kennen) entfernt ist, insbesondere auch wie > weit er davon entfernt bleiben will weil er seinen Code nicht > kaputt-optimieren mag. Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich interessiert allein die effiziente,simple Lösung und kein 32bittiges Herumprotzen mit Ressourcen und Vernichtung derer mit Hochsprachen.
Falk B. schrieb: > Ich verweise auf die Universalantworten, auch zu diesem Thema Ja Falk, verweise ruhig was das Zeug hält ;-) Mein Anspruch ist nun aber die praktikable Lösung-und wenn ich mich in der Bude so umschaue- sorry Falk, dann kann ich nicht anders als mich darin total bestätigt zu fühlen ;-) Der Spaß an der Sache ist allerdings auch nicht zu unterschätzen!
Falk B. schrieb: > Ich verweise auf die Universalantworten, Hmm..., jaa..., neee... Da muss es noch was anderes geben. Moby A. schrieb: > Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich > interessiert allein die effiziente,simple Lösung und kein 32bittiges > Herumprotzen mit Ressourcen und Vernichtung derer mit Hochsprachen. Das kommt mir wie 'ne Politikerrede vor. Beeindruckende Wortwahl und nichts dahinter.
Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. Klar: nur dort. Schon bei mittleren nämlich nicht mehr. Schließlich ist auch dein Leben endlich … Was du generell unterschätzt: die, gegen die du hier ankämpfst, sind fast durchweg Leute, die eine solche Sturm-und-Drang-Phase, die du da gerade hast, schon vor ein oder zwei (oder drei) Jahrzehnten durchlaufen haben. Es sind alles Leute, die teilweise wohl viel besser als du wissen, wie ein Assembler funktioniert (und der vom AVR Studio ist in dieser Hinsicht ohnehin nur eine Krücke auf eher unterem Niveau), die teilweise Assembler-Pamphlets von mehreren Dutzend Seiten fabriziert und zumindest zur geplanten Funktion bekommen haben. Im Gegensatz zu dir wissen sie jedoch aus gerade dieser Erfahrung, dass es um die dabei verschwendete Lebenszeit schade war, wenn stattdessen eine Maschine einen durchaus vergleichbar guten Job mittlerweile innerhalb von ein paar Sekunden hinlegt. Moby A. schrieb: > Da werden beleidigende Kommentare von Forumsteilnehmern Nur mal so, weil du das immer wieder anbringst: geh' mal zum Staatsanwalt deines geringsten Misstrauens und befrage ihn, was er als „Beleidigung“ ansieht. Du wirst dich ziemlich wundern, wie hoch die Schwelle dafür liegt. Ein paar flapsige Kommentare eines Forenteilnehmers, dessen Thread du letztlich mit deiner dir üblichen Penetranz gekapert hast (ohne ihm damit auch nur im geringsten zu helfen), fallen da ganz gewiss nicht drunter.
Jörg W. schrieb: > Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. > > Klar: nur dort. Schon bei mittleren nämlich nicht mehr. Schließlich > ist auch dein Leben endlich … Bei mittleren muß man systematischer rangehen. Funktionalität als unabhängiges Modul formulieren das sich von weiteren Nebenabhängigkeiten befreit zum Beispiel flexibel in einem Timerinterrupt aufrufen lässt. So wie die beiden (ADU+Tastenentprell) Beispiele. > Was du generell unterschätzt: die, gegen die du hier ankämpfst, sind > fast durchweg Leute, die eine solche Sturm-und-Drang-Phase, die du da > gerade hast, schon vor ein oder zwei (oder drei) Jahrzehnten durchlaufen > haben. Es sind alles Leute, die teilweise wohl viel besser als du > wissen, wie ein Assembler funktioniert (und der vom AVR Studio ist in > dieser Hinsicht ohnehin nur eine Krücke auf eher unterem Niveau), die > teilweise Assembler-Pamphlets von mehreren Dutzend Seiten fabriziert und > zumindest zur geplanten Funktion bekommen haben. Im Gegensatz zu dir > wissen sie jedoch aus gerade dieser Erfahrung, dass es um die dabei > verschwendete Lebenszeit schade war, wenn stattdessen eine Maschine > einen durchaus vergleichbar guten Job mittlerweile innerhalb von ein > paar Sekunden hinlegt. Ich möchte gegen niemand ankämpfen. Schon gar nicht jemand, der aus vielerlei Gründen (beruflich) Lösungen in Hochsprache undoder 32-bittig umzusetzen hat. Wenn die gleichen Leute dies aber in einer Form verallgemeinern, die Asm und AVR generell in Frage stellen wiederspreche ich vehement. > Nur mal so, weil du das immer wieder anbringst: geh' mal zum > Staatsanwalt deines geringsten Misstrauens und befrage ihn, was er als > „Beleidigung“ ansieht. Da darf ich Dich beruhigen- sooo wichtig ist mir dann das Forum als solches nicht ;-)
:
Bearbeitet durch User
Moby A. schrieb: > umzusetzen hat Du siehst das immer noch durch die falsche Brille: wir müssen das nicht so machen, sondern machen das alle völlig freiwillig so. Weil wir wissen, dass es auf den von dir beschworenen (und dann ja oft doch nichtmal wirklich erreichten) letzten Taktzyklus sowieso nur in 0,001 % der Fälle ankommt. Das vorletzte Mal, dass ich das hatte, war die Diskettenzugriffsroutine meines CP/M-BIOS vor reichlich 25 Jahren. Eine Vierfach-Schleife um die innere Schleife herum (die je 256 Byte einlas) hätte nicht funktioniert, also habe ich sie per Makro im Assembler wirklich viermal eingefügt. (Dummerweise können natürlich auch Compiler sowas, das nennt sich dann loop unrolling, und das machen sie, wenn man sie drängt, auf Geschwindigkeit zu optimieren.)
:
Bearbeitet durch Moderator
A. K. schrieb: > Also gut, dann eben zerstörungsfrei:void g(long); > void f(long x) > { > if (x < 1000000) > g(x); > } > > Ergebnis vom Compiler: > cpi r22,64 > ldi r18,66 > cpc r23,r18 > ldi r18,15 > cpc r24,r18 > cpc r25,__zero_reg__ > brge .L1 Schön. Interessant. Dankeschön. Bei den Takten kommen wir aber auch auf 7...8. Und das wird noch mehr wenn x>16777215.
Wie wärs Moby, könntest du deine Variante noch auf 32 Bits mit Vorzeichen ausdehnen?
Moby A. schrieb: > Und das wird noch mehr wenn x>16777215. Du meintest eventuell 'wenn x mit einer Konstanten größer 16777215' verglichen wird? Da schreibt man die Konstante hin und zack!, hat der Compiler den entsprechenden Code gezaubert.
Jörg W. schrieb: > Du siehst das immer noch durch die falsche Brille: wir müssen das nicht > so machen, sondern machen das alle völlig freiwillig so. Dann bitte auch gern freiwillig. Warum auch nicht? Ich bin doch nicht so verrückt anzunehmen, jeder C-Programmierer sei auf dem Holzweg. Entscheidend ist was hinten rauskommt. Da sehe ich den Asm-Programmierer bei typischen 8-Bit Projekten auf 8-Bit Controllern aber im Vorteil. Erreichbare Performance/Codesize sind auch nur zwei technische Aspekte. Mir fast noch wichtiger sind übersichtliche Programmstruktur (bei sinnvoller Funktionskommentierung) wie überhaupt der Bruchteil notwendiger sprachlicher Mittel, um ans Ziel zu kommen. Direkt. Und daß der unmittelbare Kontakt zum Datenblatt nun wirklich nicht schadet sieht man weiter oben...
Wir sollten anfangen, die Argumente zu nummerieren. Spart Tipparbeit, weil man dann in der hiesigen schon heftig entrollten Argumentationsschleife nur noch die Nummern hinschreiben muss.
A. K. schrieb: > Wie wärs Moby, könntest du deine Variante noch auf 32 Bits mit > Vorzeichen ausdehnen? Nö. Brauch ich nicht. Wozu? Um hier irgendwas zu beweisen? Ist das fertig kommst Du mit dem nächsten um die Ecke ;-) Versuch Du doch umgekehrt mal gegebene Asm-Texte mit C einzudampfen. Weitere Gelegenheiten werde ich noch liefern.
Moby A. schrieb: > Bei den Takten kommen wir aber auch auf 7...8. Und da gibts noch einen Nachteil. Die 7...8 Takte sind bei obiger Compiler-Lösung die Regel, bei meiner schon fast die Ausnahme ;-)
Horst S. schrieb: > Moby schrieb: > Asm allein ist nun > leider keine Garantie für guten Code, wie man beim TO-Programm schön > sehen kann ;-) > > Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so > vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne > großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru, > aber einfach abfrühstücken lasse ich mich auch nicht von Dir. > > Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung. Die Entschuldigung kannst Du Dir sparen. Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das jedenfalls nicht für Deinen Asm-Code. Die lange diesbezügliche Rumbastelei am C-Code im übrigen auch nicht für C.
Moby A. schrieb: > Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das > jedenfalls nicht für Deinen Asm-Code. Allerdings waren die alternativen (und besseren) C-Varianten, die Horst geholfen haben, schon nach wenigen Forums-CPU-Takten verfügbar. Eine alternative Assembler-Variante hast du ihm jedenfalls bis heute noch nicht angeboten. Damit bleiben all deine Argumente reine Theoretisiererei, die vielleicht deinem Ego hilft, aber sonst niemandem. A. K. schrieb: > Wir sollten anfangen, die Argumente zu nummerieren. So, wie die beiden Typen mit den Witzen. Gute Idee. :-)
Johann L. schrieb: > Peter D. schrieb: > Welche Funktionalität denn? > Nirgends wird beschrieben, was der Code überhaupt machen soll! > Die paar wenigen Zeilenkommentare kannst Du Dir an die Backe schmieren, > die sagen 0,nix über die Gesamtfunktion aus. > > Peter, hast du immer noch nicht verstanden, dass Mobys Code qua > Definition selbsterklärend ist? > > Nirgends wird beschrieben, was der Code überhaupt machen soll! > > Ich bezieht mich hier mal auf den Code für den LM335: Asm-Code ist selbsterklärend. Es braucht nämlich nur die Instruktionsbeschreibung und das Datenblatt sowie ein paar funktionserklärende Kommentare. Da es aber zu meiner Überraschung offensichtlich Fragen zum Einsatz und dem Wie&Warum gibt werde ich das in dem entsprechenden Projekte-Beitrag nochmal thematisieren.
Jörg W. schrieb: > deinem Ego hilft Das spielt die letzte Geige, sonst wär durchaus schon eine Menge meiner veröffentlichungsfähigen Entwicklungen in den Projekten. Wenn man das aber trotzdem verstärkt tun sollte dann weil ich natürlich gemerkt habe, daß es diesbezüglich hier einen gewissen Nachhol- bzw. Wissensbedarf gibt und die besten Argumente immer noch überzeugender Code liefert.
900ss D. schrieb: > Danke Moby, immerhin hast du deinen Code gepostet. Fazit: Auch > handgeschriebener ASM-Code ist nicht immer besser als der vom Compiler. Wiegesagt, das C-Ergebnis sollte dann aber erstmal wirklich gleichwertig sein was es so nicht ist. > Warum du Moby, so verbissen an ASM festhälst, wird mir auch ein Rätel > bleiben, die von Dir genannten Vorteile sind alle objektiv widerlegt Das sehe ich anders aber es mag sein, daß es noch ein paar überzeugenderer Beispiele bedarf ;-) > Neugier: Moby, ist programmieren eher aus Hobby betrieben oder verdienst > du dein Geld damit? Mobby Hobby.
:
Bearbeitet durch User
> Und daß der unmittelbare Kontakt zum Datenblatt nun wirklich nicht schadet sieht man weiter oben... Man glaubt zwar kaum, aber auch C-Programmierer dürfen DBs lesen. Und tun das auch. Und was finden sie da: Codefragment in ASM und C. Zum direkten Vergleichen. Ob C nun wirklich mehr oder weniger Schlüsselworte hat, als ein AVR Maschinenbefehle? Auf alle Fälle bringt es beim Anwenden einer Sprache Vorteile, wenn man nicht ständig in Vokabel- und Grammatikheft blättern muß. Ich benutze das DB für die Hardware. Die Sprache kann ich nämlich schon. Und andere (Computer aller Größenklassen) sprechen die auch. Das ist vielleicht der Unterschied zwischen (nur) Hobby und 30 Jahre sich selbst und 20 Jahre noch drei Andere mit Programmieren zu versorgen. Darf aber jeder selber entscheiden, wie er es machen will. JEDER, nicht nur Moby! Und damit verbietet sich die Missionstätigkeit spätesten dann, wenn alle Anderen sagen: "is gut jetzt". Schreibt ein sich fischiger Haßtiraden sicherer, aktuell sehr müder Geselle, der bis gerade für Brötchen in einer von wenigen gekannten, aber von vielen belächelten, auf einer in C und C++ geschriebenen VM ausgeführten Sprache geschrieben hat, deren Vor- und Nachteile er seit 25 Jahren kennt und sinnvoll einsetzt. Der kann sogar die Opcodes der VM im Debugger lesen und zum Glück gibt es für diese keinen Assembler, denn dann bleiben ihm zumindest in dem Umfeld fischige Diskussionen erspart. Mobby Hobby? Wohl eher Moby Hoby!
:
Bearbeitet durch User
Carl D. schrieb: > Auf alle Fälle bringt es beim > Vorteile, wenn man nicht ständig in Vokabel- und > Grammatikheft blättern muß. Ja, die Grammatik gilt es im Gegensatz zu Asm bei C ja noch zusätzlich zu beherrschen. > Und damit > verbietet sich die Missionstätigkeit spätesten dann, wenn alle Anderen > sagen: "is gut jetzt". Die würde sich für mich nur dann verbieten, wenn meine Erfahrungen mit Asm denn schlechte wären. Sind sie aber nicht! Das ist auch kein Wunder, weil Asm alle Voraussetzungen zum effizienten Programmieren mit allen erdenklichen Möglichkeiten, zu minimalem Aufwand bietet. > auf einer in C und C++ geschriebenen VM > ausgeführten Sprache geschrieben hat, deren Vor- und Nachteile er seit > 25 Jahren kennt und sinnvoll einsetzt. Der kann sogar die Opcodes der VM > zum Glück gibt es für diese keinen Assembler, denn > dann bleiben ihm zumindest in dem Umfeld fischige Diskussionen erspart. Warum werde ich bloß nicht müde zu betonen, für welche Zielplattform und für welche Anwendungen ich Asm vorn sehe? Warum fühlt sich jeder Profi bemüßigt, das sogleich auf sein Gebiet- bis hin zur PC Programmierung zu beziehen?
Wannkappierst du eigentlich, daß dein Ges.... keiner mehr hören kann. Soll ich dir ständig runterbeten, womit ich schon gute Erfahrungen gemacht hab? Spätestens nach der Erfahrung, daß andere es nicht mehr hören wollen, würde ich es für mich behalten und mich ganz allein an der glückseeligmachen Erkenntnis laben. Und schon garnicht würde ich einer solchen Gruppe von Ignoranten auch noch demonstrieren, wie rudimentär ich mein Spezialgebiet tatsächlich nur beherrsche. Aber vielleicht wollte ich deshalb auch nie Klassenkasper werden. Oder bekommst du Provision dafür, Threads ins OffTopic zu treiben?
Carl D. schrieb: > der bis gerade für Brötchen in einer von wenigen gekannten, > aber von vielen belächelten, auf einer in C und C++ geschriebenen VM > ausgeführten Sprache geschrieben hat Siehst Du. Viele belächeln diese. Nichtmal auf dem Level ein eindeutiges Urteil. Was sagt uns das? Zuvieles jenseits harter Fakten wird subjektiv erlebt und kann individuell durchaus verschieden bewertet werden. So erklärt sich dann wohl auch manche Vorliebe in der Diskussion C vs. Asm.
Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen > Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. Wenn jemand 18 Jahre lang in Assembler programmiert und damit seine ganze Haussteuerung umgesetzt hat, wird er doch wohl ein paar fehlerfreie Zeilen Quelltext vorweisen können?! > Eine künstliche Distanz einzuhalten ist mir dabei fremd, denn mich > interessiert allein die effiziente,simple Lösung Die interessiert uns auch. Aber es sind ja Sie, welcher behauptet, die "effiziente,simple Lösung" zu haben. Belege dafür bleiben Sie schuldig, unterstellen den Anwesenden aber > 32bittiges Herumprotzen mit Ressourcen und Vernichtung derer mit > Hochsprachen. Das interessiert vermutlich die wenigsten hier -- weder die 32 Bit, noch das Herumprotzen, noch die Vernichtung von Ressourcen. Ich habe auch noch nie jemanden mit so etwas "herumprotzen" sehen. Sie etwa? Johann Lay, Jörg Wunsch und Peter Danegger, die sich an diesem Thread ja mehrmals beteiligt haben, "protzen" jedenfalls nicht mit 32-Bit oder der "Vernichtung von Ressourcen". Diese Leute könnten mit ihrem fehlerlosen Code "protzen", und trotzdem tut es keiner. Deren Code hat übrigens auch keine "Flüchtigkeitsfehler".
Carl D. schrieb: > Wannkappierst du eigentlich, daß dein Ges.... keiner mehr hören > kann. Du musst hier nichts lesen oder gar schreiben. Immerhin ist es Dir ja wert auf mich zu reagieren. Sogar so spät/so früh ;-) Was meinst Du was ich alles nicht mehr hören mag? > Provision dafür, Threads ins OffTopic zu treiben? Tatsächlich sind wir hier nach wie vor bei C vs. Assembler -> Performance und nicht etwa schon beim Kuchenbacken...
:
Bearbeitet durch User
Moby A. schrieb: > Asm-Code ist selbsterklärend. Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei einem "selbsterklärenden Code" passieren?
Sheeva P. schrieb: > Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen > Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. > > Wenn jemand 18 Jahre lang in Assembler programmiert und damit seine > ganze Haussteuerung umgesetzt hat, ... dann wird ja wohl das allermeiste ohne Fehler funktionieren ;-) > Aber es sind ja Sie, welcher behauptet, die > "effiziente,simple Lösung" zu haben. Ich habe nicht die effiziente simple Lösung, sondern sage daß Asm alle nötigen Mittel dafür bietet. > Ich habe auch > noch nie jemanden mit so etwas "herumprotzen" sehen. Sie etwa? In vielen Jahren hier zur Genüge ;-) > Deren Code hat übrigens auch > keine "Flüchtigkeitsfehler". Das bestreite ich jetzt einfach mal so. Wenn sich später in den Projekten auch kaum noch davon was findet. Ich bin weit davon entfernt, wegen Flüchtigkeitsfehlern die Ohren hängenzulassen. Aber in die Projektveröffentlichungen (meine erste und einzige mit Quellcode wohlgemerkt) gehören sie nicht hin. Hatte ich das nicht weiter oben schon gesagt?
Sheeva P. schrieb: > Moby A. schrieb: > Asm-Code ist selbsterklärend. > > Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei > einem "selbsterklärenden Code" passieren? Hatte ich eigentlich auch schon erklärt: Der im Einsatz befindliche Code funktioniert, der für die Projekte leicht veränderte Code (zunächst) nicht. Wirst Du mir daraus jetzt den großen Strick drehen? Bitte bitte nicht, ich flehe um Gnade ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Asm-Code ist selbsterklärend. So wie Josefs Krypto-Asm. Zusammen wärt ihr unschlagbar. ;-)
Moby A. schrieb: > Asm-Code ist selbsterklärend. Auf den Niveau von > die Instruktionsbeschreibung und das Datenblatt ist C das auch, das ist aber nicht der Sinn einer ordentlichen Dokumentation.
Moby A. schrieb: > Sheeva P. schrieb: >> Moby A. schrieb: >> Asm-Code ist selbsterklärend. >> >> Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei >> einem "selbsterklärenden Code" passieren? > > Hatte ich eigentlich auch schon erklärt: Der im Einsatz befindliche Code > funktioniert, der für die Projekte leicht veränderte Code (zunächst) > nicht. > > Wirst Du mir daraus jetzt den großen Strick drehen? > Bitte bitte nicht, ich flehe um Gnade ;-) Wie kann das sein?
Wow, drei Seiten Diskussionstext in ein paar Tagen. Davon gefühlte 99% Ping-Pong mit einem Troll. Bei jedem anderen Thema wären die Herren Moderatoren nicht so zimperlich, aber hier scheints ihnen Spaß zu machen...
Ich habe gerade zwanzig Benachrichtigungsemails zu diesem Thread gelöscht. Die Diskussion geht immer noch um dasselbe Nicht-Thema. Irgendjemand muß sehr, sehr einsam sein.
Moby A. schrieb: > Es soll doch da tatsächlich noch andere Dinge > im Leben geben als hier permanent präsent zu sein. Oder etwa nicht? Gute Idee.
Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen > Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger "Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen - sowohl was Programmier- als auch Prozessoraufwand betrifft. Moby A. schrieb: > Versuch Du doch umgekehrt mal gegebene Asm-Texte mit C einzudampfen. Es gibt nur keine vorn Dir. Und wenn doch, konnte gezeigt werden, dass es mit C kürzer geht - sowohl was Horsts als auch Dein Mini-Progrämmchen betrifft. 2:0.... Damit bist Du ziemlich im Rückstand, Moby. > Weitere Gelegenheiten werde ich noch liefern. Also wenn ich Deine Programmiergeschwindigkeit in ASM hochrechne (einen simplen Vergleich zu programmieren dauert bei Dir über eine Stunde), dürftest Du so in ca. einem Jahr etwas praxisrelevantes abliefern. Du bleibst also weiter bei Deiner Blender-Strategie. (*) Jedenfalls dann, wenn das Compilat die 1KB-Grenze überschreitet, es sich also nicht um einen Codeschnipsel handelt, der für sich allein nicht einsetzbar ist.
:
Bearbeitet durch Moderator
@ Walter Tarpan (nicolas) >gelöscht. Die Diskussion geht immer noch um dasselbe Nicht-Thema. >Irgendjemand muß sehr, sehr einsam sein. Oder ein ZEN-Meister? https://de.wikipedia.org/wiki/Zen#Lehre
Sheeva P. schrieb: > Moby A. schrieb: >> Asm-Code ist selbsterklärend. > > Die "Flüchtigkeitsfehler" sind Dir nicht aufgefallen. Wie kann das bei > einem "selbsterklärenden Code" passieren? Der Code erklärt sich halt nur sich selbst, aber nicht anderen. Zumindest wenn es mehr als ein paar Zeilen sind.
>Der Code erklärt sich halt nur sich selbst, aber nicht anderen. >Zumindest wenn es mehr als ein paar Zeilen sind. WUrde ja bereits gesehen. Der von mir gepostete Asm COde wurde von Moby bisher nicht erklärt. Obwohl es doch selbsterklärend ist.
@Matthias Lipinsky (lippy) >>Der Code erklärt sich halt nur sich selbst, aber nicht anderen. >>Zumindest wenn es mehr als ein paar Zeilen sind. >WUrde ja bereits gesehen. Der von mir gepostete Asm COde wurde von Moby >bisher nicht erklärt. Obwohl es doch selbsterklärend ist. Das erklärt doch alles!
Falk B. schrieb: > Das erklärt doch alles! Jetzt bist du uns aber eine Erklärung schuldig! :) Icke ®. schrieb: > Davon gefühlte 99% Ping-Pong mit einem Troll. Moby ist kein Troll. Der Unterschied ist, dass ein Troll vorsätzlich eine Dikussion stört. Moby stört sie auch, es ist auch Vorsatz dabei, aber ich würde ihm mal nicht unterstellen, dass er sie tatsächlich stören will. Es ist halt nur seine (sehr, sehr penetrant dargelegte) Meinung, dass doch seine Philosophie für alle das beste wäre … Da Horst aber bereits am Anfang des Threads gut und (so ich ihn verstanden habe) ausreichend geholfen worden ist, denke ich, dass es nicht übermäßig stört, hier weiterzudiskutieren. Wenn du dir den ein oder anderen Beitrag mal ansiehst (also eher nicht Mobys, aber beispielsweise Johanns), dann kann man durchaus noch bisschen dabei lernen. OK, von Mobys Beiträgen kann man auch lernen, aber wohl nicht in seinem Sinne. :-))
Moby A. schrieb: > Warum werde ich bloß nicht müde zu betonen, für welche Zielplattform > und für welche Anwendungen ich Asm vorn sehe? Warum fühlt sich jeder > Profi bemüßigt, das sogleich auf sein Gebiet- bis hin zur PC > Programmierung zu beziehen? Weil du dein Assembler Anpreisung auch nicht auf die von dir vorne gesehenen Anwendungen beschränkst. Du kommst mir vor, wie der in Österreich berühmt berüchtigte Flachlandtiroler, der meint nur weil er zu Hause gerade noch so seine 120 Meter hohe Schutthalde raufschnaufen kann, dass er geradezu prädestiniert dazu wäre, andere davon zu überzeugen, dass man die Eiger Nordwand auch mit Sandalen und etwas Bindfaden bezwingen kann.
:
Bearbeitet durch User
Moby A. schrieb: > Asm-Code ist selbsterklärend. Es braucht nämlich nur die > Instruktionsbeschreibung und das Datenblatt sowie ein paar > funktionserklärende Kommentare. Brainfuck, Befunge, Malbolge, FRACTRAN und wie sie alle heißen (https://de.wikipedia.org/wiki/Esoterische_Programmiersprache) sind deiner Definition nach ebenfalls selbsterklärend, denn für jede davon gibt es eine klare Sprachspezifikation, die zudem sogar sehr viel kürzer ausfällt als das AVR Instruction Set Manual. Die allerkürzeste Instruktionsbeschreibung haben diese Prozessoren: https://en.wikipedia.org/wiki/One_instruction_set_computer Deren Assemblersprache müsste für dich somit das Optimum aller Programmiersprachen darstellen, was das Selbsterklärendsein betrifft. Was du bei der Bewertung der Sprachen völlig auser Acht lässt, ist ihre Ausdrucksstärke, d.h. die maximale Komplexität der Problems, das mit einer gegebenen Menge an Code gelöst werden können. Die ist bei den eben erwähnten Sprachen nahezu null, beim AVR-Assembler sehr niedrig, bei C aber schon recht hoch, wie das obige Beispiel des Vergleichs mit einer Konstanten deutlich zeigt: Der aus 9 Zeichen bestehende Term x<1000000 in C ist nicht nur viel kürzer, sondern darüberhinaus auch noch besser lesbar und leichter änderbar als die entsprechende CPI/SBCI-Kette in Assembler. Und wie man gesehen hat, hat selbst ein überzeugter Assembler-Only-Programmierer immense Schwierigkeiten, dieses noch recht einfache Beispiel erst einmal fehlerfrei runterzuprogrammieren und dann auch noch zu optimieren.
Eine sehr schöne Routine, die so nur in C praktikabel ist, ist z.B. der Scheduler: Beitrag "Wartezeiten effektiv (Scheduler)" Die original Idee ist nicht von mir, ich habe sie nur etwas auf den 8051 und den AVR optimiert. Durch die Vorsortierung ist das sehr effizient. Sie läuft unverändert auf jeder anderen CPU und man kann bequem festlegen, ob die Zeitbasis 8, 16, .. 64bittig ist. In Assembler wäre das ein Albtraum und weder anpaßbar noch lesbar oder gar portabel.
Yalu X. schrieb: > Brainfuck, Befunge, Malbolge, FRACTRAN und wie sie alle heißen > (https://de.wikipedia.org/wiki/Esoterische_Programmiersprache) sind > deiner Definition nach ebenfalls selbsterklärend, denn für jede davon > gibt es eine klare Sprachspezifikation Ich kann da nur wieder dieses Beispiel ans Herz legen, was nicht aus einer vorsätzlich irren Programmiersprache stammt. Siehe auch http://fafner.dyndns.org/~vaxman/publications/apl.pdf
Yalu X. schrieb: > Moby A. schrieb: >> Asm-Code ist selbsterklärend. Moby hat einfach nur Schwierigkeiten zu verstehen, dass wir unter 'Code erklären' etwas anderes verstehen als er. Für ihn besteht die 'Erklärung' eines Codes darin, dass er für jeden Assembler Memnonic ein entsprechendes Wort kennt.
1 | ldi r16, 25 |
erklärt er mit
1 | hier wird das Register 16 mit der Konstanten 25 geladen |
Und so 'erklärt' er dann den Code ohne zu begreifen, dass er nichts erklärt, sondern einfach nur vorliest. Alles schön und gut. Nur dass das ganze dann in Summe einen Quicksort ergibt, das entzieht sich seiner Aufmerksamkeit, weil er viel zu sehr mit diesen Low-Level Details beschäftigt ist, bzw. weil sich der eigentliche Zweck eines Codestückes in diesen Details verliert. Wenn Moby C programmieren würde, dann würde er so kommentieren bzw. erklären
1 | i = 5; // i mit 5 laden |
2 | j++; // j um 1 erhöhen |
und das ist genau die Art Kommentierung, die komplett am Sinn einer Kommentierung vorbei geht. Wie ich in einem anderen Thread schon mal sagte: Man kann die Funktionsweise einer Raffinerie nicht dadurch ergründen und erklären, dass man sich alle Schrauben, Muttern und Beilagscheiben ansieht. Klar sind die für die Funktionsweise wichtig, aber auch sind die CAD Programme schon so weit, dass sie Schraubverbindungen selbsttätig dimensionieren und einsetzen. Das CAD, in dem ich zuletzt mitgearbeitet habe, hatte viele derartige Automatismen. Kein Architekt verbringt mehr seine Zeit damit, die Sparren eines Dachstuhls einzeln zu zeichnen. Der zeichnet die Firstlinie, gibt an welches Dach er haben will und das CAD konstuiert den kompletten Dachstuhl anhand des Grundrisses und der sonstigen Angaben für ihn.
:
Bearbeitet durch User
@ Karl Heinz (kbuchegg) (Moderator) >Flachlandtiroler, der meint nur weil er zu Hause gerade noch so seine >120 Meter hohe Schutthalde raufschnaufen kann, dass er geradezu >prädestiniert dazu wäre, andere davon zu überzeigen, dass man die Eiger >Nordwand auch mit Sandalen bezwingen kann. Ein Sandal! ähh, Skandal!
Jörg W. schrieb: > Moby ist kein Troll. Ich kenne Moby und seine Diskussionskultur schon von anderen Threads. Deswegen halte ich mich hier auch raus. > OK, von Mobys Beiträgen kann man auch lernen Ich habe daraus gelernt, daß jeglicher Versuch, Menschen mit derartig zementierten Standpunkten (nannte man früher "Betonköpfe") von ihrem Holzweg abzubringen, selbst unter Zuhilfenahme einleuchtendster Argumente kläglich scheitert. Noch ein klein wenig Topic. Ich programmiere auch gern in ASM, aber ich kenne die Grenzen. Ab einer gewissen Komplexität macht das einfach keinen Sinn mehr. Es ist auch schön, per Pedes durch den Wald zu streifen, den Geräuschen zu lauschen und mit den Füßen direkten Bodenkontakt zu spüren. Und es macht Sinn, die 100m bis zum Bäcker um die Ecke zu laufen. Aber für den Großeinkauf oder die Urlaubsfahrt steig ich dann doch lieber ins Auto.
Karl H. schrieb: > und das ist genau die Art Kommentierung, die komplett am Sinn einer > Kommentierung vorbei geht. In diesem Fall würde ich da eine Ausnahme machen und auch eine Kommentierung der Bedeutung der einzelnen Statements nahelegen: Beitrag "Ein Vorschlag zur Intervall-Arithmetik"
Moby A. schrieb: > Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das > jedenfalls nicht für Deinen Asm-Code. Wenn das Dein einziges Argument ist, gehe ich nicht davon aus, dass Du Dir die Mühe gemacht hast, das Projekt überhaupt zu öffnen. Die reinen Zahlen für die intellektuelle Höchstleistung des numerischen Vergleiches im vierstelligen Bereich (ab der 3. Klasse praktiziert) waren ja im Thread deutlich ablesbar.
Frank M. schrieb: > Moby A. schrieb: > Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch > (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen > Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. > > Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger > "Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen - > sowohl was Programmier- als auch Prozessoraufwand betrifft. Dann bin ich schon sehr gespannt... Wer die realisierte Funktionalität dann kürzer umsetzt gewinnt den Hauptpreis: Moby hält bzgl. Überlegenheit von Asm die Klappe ;-) > 2:0.... Damit bist Du ziemlich im Rückstand, Moby. Geduld, Geduld. Das Spiel läuft noch nicht lange. > Also wenn ich Deine Programmiergeschwindigkeit in ASM hochrechne (einen > simplen Vergleich zu programmieren dauert bei Dir über eine Stunde) ... schließt Du aus den Zeiten meiner Beiträge? Du bist ein Fuchs ;-) Leider mach ich das nicht hauptberuflich und soviel Zeit steht in der Freizeit nun auch nicht gerade zur Verfügung ;-( > Du bleibst also weiter bei Deiner Blender-Strategie Wen meinst Du kann ich hier blenden? Daß Asm eine Menge Potential hat, nun, da bin ich nicht der Einzige der das behauptet- und täglich erlebt ;-)
Moby A. schrieb: > Leider mach ich das nicht hauptberuflich und soviel Zeit steht in der > Freizeit nun auch nicht gerade zur Verfügung Tja, da geht's den Menschen wie den Leuten. Genau sowas ist halt der Grund, warum so ziemlich alle anderen Mitdiskutanten hier, trotz teils guter oder sogar sehr guter Kenntnisse der jeweiligen Assembler-Welt (siehe Johanns Code) ihre Zeit eben nicht damit verplempern wollen, sich nun zu überlegen, ob in der nächsten Zeile ein gesetztes oder ein gelöschtes Carry-Flag ausgewertet werden soll, und ob die Auswertung direkt als bedingter Sprung erfolgen kann oder wegen eines schier unerreichbaren Sprungziels indirekt (also negiert), indem der nächste (lange) Sprungbefehl stattdessen ausgelassen wird. Diesen ganzen aufwändigen Kleinkram beherrscht eine Maschine namens Compiler einfach mal um mehrere Größenordnungen schneller und vor allem weniger fehleranfällig, weil sie ständig inhärent alle Randbedingungen berücksichtigen kann (wie die Länge eines Sprungs oder eben den adressierbaren Bereich einer BST-Anweisung) und auch bei doppelter Verneinung noch keinen Knoten im Gehirn bekommt. Dafür wiederum kann man dann, ganz ohne es hauptberuflich tun zu müssen, auch mal schnell ein paar Zeilen Code nur für eine Antwort im Forum zusammenhacken, um einem Menschen, der um Hilfe bittet, schnell und unbürokratisch zu helfen – nebenbei, neben der ganz normalen Arbeit, Familie, sonstigen Freizeitbeschäftigungen.
Klaus W. schrieb: > Der Code erklärt sich halt nur sich selbst, aber nicht anderen. > Zumindest wenn es mehr als ein paar Zeilen sind. Das gilt für C genauso. Selbsterklärend im Sinne von 'die Sprach-Vorkenntnis überflüssig machend' ist keine von beiden. Direkter Asm-Text sagt aber direkt was nun wirklich Fakt ist und sich bei C nur über Umwege erschließt. Freilich, man muß es oft gar nicht unbedingt 100%ig wissen. Wenn man auf den Effizienzvorteil von Asm verzichten kann und seine einschränkende Hochsprache liebt. Matthias L. schrieb: > Der von mir gepostete Asm COde wurde von Moby > bisher nicht erklärt. Obwohl es doch selbsterklärend ist. Bitte Geduld Matthias. Siehst ja was hier los ist. Danke für Deine Analyse, die ist noch auf meinem Stack geparkt ;-) Falk B. schrieb: > Das erklärt doch alles! Falk und seine schnellen Erklärungen. Hattest Du den AVR nicht schon längst in der Steinzeit verortet? Wie zum Teufel kann der hier heute immer noch so präsent sein? Karl H. schrieb: > Weil du dein Assembler Anpreisung auch nicht auf die von dir vorne > gesehenen Anwendungen beschränkst. In der Tat sehe ich für Asm größeres Potential wenn ein paar andere Randbedingungen erfüllt wären. Das hier zum Thema zu machen wäre aber uferlos. Bleiben wir mal bitteschön beim Thread-aktuellen AVR!
Jörg W. schrieb: > Diesen ganzen aufwändigen Kleinkram Aufwand? Machen wir mal das AVR Instruction Set nicht aufwendiger als es ist. So ein AVR ist schön überschaubar. Und der "Kleinkram" ist ja gerade jenes Kleinteilige was die bessere Anpassbarkeit an die Hardware und damit die bessere Effizienz von Asm ausmacht! > weil sie ständig inhärent alle Randbedingungen > berücksichtigen kann (wie die Länge eines Sprungs oder eben den > adressierbaren Bereich einer BST-Anweisung) und auch bei doppelter > Verneinung noch keinen Knoten im Gehirn bekommt. Das sind gar nicht soviele Randbedingungen. Anders als beim ARM. Daß BST mit einem falschen Operanden unbemängelt assembliert wird muß wirklich nicht sein. Und was den Knoten im Gehirn angeht: Der entsteht mit komplexen C-Ausdrücken sehr viel schneller. Und da reden wir noch nicht vom weitaus abstrakteren OOP wo der Bezug zur Hardware-Wirklichkeit vollends den Bach runter geht.
Moby A. schrieb: >> Diesen ganzen aufwändigen Kleinkram > > Aufwand? Ja. Aufwand. Schließlich hast du dich gerade beklagt, dass dir die Zeit für bestimmte Dinge fehlt. Glaubst du etwa, die anderen Leute hier würden hauptamtlich fürs Forum schreiben, hätten alle keine Familie, keine anderen Hobbys? Moby A. schrieb: > Und was den Knoten im Gehirn angeht: Der entsteht mit komplexen > C-Ausdrücken sehr viel schneller. Ganz gewiss nicht. Hier geht's noch um so einfache Dinge wie
1 | if (i < 1000000) |
wie dir oben bereits ausgiebig demonstriert worden ist. > Und da reden wir noch nicht vom > weitaus abstrakteren OOP wo der Bezug zur Hardware-Wirklichkeit vollends > den Bach runter geht. Ach ja. Das kannst du bestimmt auch mit Code belegen, oder? Moby, du bist einfach mal 50 Jahre zu spät geboren worden. Vor 50 Jahren hättest du dir als "Mel" ja vielleicht noch Respekt erheischt. https://en.wikipedia.org/wiki/The_Story_of_Mel
:
Bearbeitet durch Moderator
Yalu X. schrieb: > Brainfuck, Befunge, Malbolge, FRACTRAN > Die allerkürzeste Instruktionsbeschreibung haben diese Prozessoren Hochsprachen erklären immer mehr oder weniger schlecht was wirklich vor sich geht. Genau diese Wirklichkeit aber adressiert und erklärt Asm. Das ist es was für mich zählt. Andere Prozessoren? Wir wollen doch nun kein neues Faß aufmachen wenn es hier um AVR geht... > Was du bei der Bewertung der Sprachen völlig auser Acht lässt, ist ihre > Ausdrucksstärke, d.h. die maximale Komplexität der Problems, das mit > einer gegebenen Menge an Code gelöst werden können. Da stimme ich Dir sogar zu. Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für maximale Komplexität bekannt, und das ist gut so ;-) Ausdrucksstärke/Flexibilität und mögliche Komplexität sind die zwei Seiten einer Medaille! > hat selbst ein überzeugter Assembler-Only-Programmierer > immense Schwierigkeiten, dieses noch recht einfache Beispiel erst einmal > fehlerfrei runterzuprogrammieren und dann auch noch zu optimieren. Nochmal: 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke. 2. Was man hat das hat man. Für AVR gibts auch genügend fertigen Asm- Beispielcode so denn umfangreichere Berechnungen mal nötig sind. 3. Sind sie ständig nötig ist AVR/ASM die falsche Wahl.
Jörg W. schrieb: > Moby A. schrieb: > Diesen ganzen aufwändigen Kleinkram > > Aufwand? > > Ja. Aufwand. Schließlich hast du dich gerade beklagt, dass dir die > Zeit für bestimmte Dinge fehlt. Glaubst du etwa, die anderen Leute hier > würden hauptamtlich fürs Forum schreiben, hätten alle keine Familie, > keine anderen Hobbys? Oh welche weiten Zusammenhänge man da doch gleich herstellen kann ;-) Das AVR-Instruktion Set ist weniger Aufwand als das bücherfüllende C-Universum. So definier ich das. > Hier geht's noch um so einfache Dinge wie if (i < > 1000000) Und? Das in Asm hinzuschreiben ist nun kein Hexenwerk. Ich bezog mich beim Thema Gehirnknoten auf komplexere Ausdrücke. Beispiele finden sich weiter oben ;-) > Ach ja. Das kannst du bestimmt auch mit Code belegen, oder? Das belegt jeder OOP Code ;-) > Moby, du bist einfach mal 50 Jahre zu spät geboren worden. Meinst Du? Ich hab eher den Eindruck noch gerade richtig, um mit leistungsstarken kleinen simplen AVRs die Chance zu haben, selber wirklich alles in der Hand zu behalten und gestalten zu können!
Moby A. schrieb: > Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für > maximale Komplexität bekannt, und das ist gut so ;-) Warum meinst du, baut Atmel dann AVRs mit 256 KiB und mehr an Flash? > 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke. Hier irrst du bezüglich des AVR gewaltig. Der AVR ist bei der 32-Bit-Arithmetik viel besser als manch anderer 8-Bitter. Selbst die 32-Bit-Gleitkommaarithmetik von AVR-GCC/avr-libc (und auch IAR) ist so rasend schnell, dass du Mühe haben wirst, ihr mit handgefeilter 24-Bit-Ganzzahlarithmetik in deinem Assemblercode das Wasser zu reichen – wobei du dann immer noch die Grenzen des Wertebereichs im Blick behalten musst, während float eben in der Richtung von selbst skaliert. (OK, Turbo-Pascals 48-Bit-Gleitkomma konnte das auch schon vor 30 Jahren auf dem Z80. Nicht ganz so schnell, aber genauso bequem für den Anwender.) > 2. Was man hat das hat man. Für AVR gibts auch genügend fertigen Asm- > Beispielcode so denn umfangreichere Berechnungen mal nötig sind. Ja, und? Für C gibt es mehr Bibliotheken, als du dir auch nur ansatzweise ausmalen kannst. Viele davon laufen durchaus auch auf einem AVR. > 3. Sind sie ständig nötig ist AVR/ASM die falsche Wahl. Trenne mal zwischen AVR und ASM. Die beiden sind nicht miteinander verheiratet (außer in deinem Kopf), und selbst die ältesten Randnotizen von Atmel bezüglich des AVR zeigen, dass Alf Bogen und Vegard Wollan schon vor 20 Jahren deiner Denkweise massiv voraus waren, da sie bereits in der Designphase einen Compilerhersteller (IAR aus Schweden) mit ins Boot genommen haben. Ihnen war klar, dass man den damals fest aufgeteilten Markt an Microcontrollern (zwichen 8051, PIC und MC68) nur dann neu aufrollen kann, wenn bereits die CPU-Architektur möglichst gut auf eine Sprache wie C passt. Dir ist das selbst 15 Jahre später noch nicht klar.
Peter D. schrieb: > Eine sehr schöne Routine, die so nur in C praktikabel ist, ist > z.B. der Scheduler: > Beitrag "Wartezeiten effektiv (Scheduler)" Ohne jetzt den Code im Einzelnen durchgegangen zu sein- fürs "Warten ohne Rechenzeitverschwendung" ist nun wirklich kein C nötig. Meine Controller haben meist einen mehr oder weniger gleichschnellen Timerinterrupt für allgemeine Aufgaben, so auch zur zeitgesteuerten Taskauslösung bzw. Wartezyklen. Das muß nicht zum Albtraum ausarten.
Moby A. schrieb: > Oh welche weiten Zusammenhänge man da doch gleich herstellen kann ;-) Diese Zusammenhänge sind so ziemlich jedem hier klar, nur dir nicht. Aber geben wir's auf, du willst sie ja nicht sehen. > Das AVR-Instruktion Set ist weniger Aufwand als das bücherfüllende > C-Universum. So definier ich das. Definieren kannst du natürlich, was du willst. Der Gültigkeitsbereich der Definition wird dann allerdings auf dein privates Universum beschränkt bleiben. AVR-Befehlssatz: irgendwas um die 150 Seiten C-Sprachbeschreibung (Kapitel 6 im Standard): 135 Seiten > Ich bezog mich > beim Thema Gehirnknoten auf komplexere Ausdrücke. >> Ach ja. Das kannst du bestimmt auch mit Code belegen, oder? > > Das belegt jeder OOP Code ;-) OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und irgendwer hat dir mal gesagt, es sei "komplex".
Jörg W. schrieb: > Warum meinst du, baut Atmel dann AVRs mit 256 KiB und mehr an Flash? Für Daten? Und natürlich für ausschweifende Hochsprachen! > Der AVR ist bei der 32-Bit-Arithmetik viel besser als manch anderer > 8-Bitter. Und? Deshalb ist ein 32Bitter in diesem Fall immer noch sinnvoller. Aber freut mich das hier so festgestellt zu wissen ;-) > Selbst die 32-Bit-Gleitkommaarithmetik von AVR-GCC/avr-libc (und auch > IAR) ist so rasend schnell, dass du Mühe haben wirst, ihr mit > handgefeilter 24-Bit-Ganzzahlarithmetik in deinem Assemblercode das > Wasser zu reichen – wobei du dann immer noch die Grenzen des > Wertebereichs im Blick behalten musst, während float eben in der > Richtung von selbst skaliert. Klasse wenns so ist! Für umfangreichere Arithmetik hätte ich aber auch super Asm Code in der Hinterhand, wenngleich nicht aus meiner Feder. > Ja, und? Für C gibt es mehr Bibliotheken, als du dir auch nur > ansatzweise ausmalen kannst. Viele davon laufen durchaus auch auf einem > AVR. Ja und? Deshalb hab ich wiegesagt damit trotzdem keine Mühe. Das mit den vielen vielen Bibliotheken sehe ich kritisch. Man begibt sich damit in gewisse Abhängigkeiten, nimmt unbekannte Fehlerquellen in Kauf, oft ist eine Funktion schneller selbst geschrieben als irgendwo passend gefunden und verstanden. > wenn bereits die CPU-Architektur möglichst > auf eine Sprache wie C passt. Warum sollte das verwundern wenn sich der potentielle Anwenderkreis damit erweitert? Deshalb bleibt die einfache Architektur weiter einfachem Asm zugänglich. Asm ist da seeehr flexibel ;-)
Karl H. schrieb: > weil er viel zu sehr mit diesen Low-Level > Details beschäftigt ist Nö. Mit der Hardware- Wirklichkeit. Und bestmöglicher programmtechnischer Anpassung an diese. Damit mit der optimalen Chance auf effizienten Code. > Wenn Moby C programmieren würde, dann würde er so kommentieren bzw. > erklären i = 5; // i mit 5 laden > j++; // j um 1 erhöhen So ein Quatsch. Wenn ich sage daß ldi r16,25 selbsterklärend ist (mit Kenntnis der Instruktion) dann würde ich doch in C nicht derart kommentieren ;-) > und das ist genau die Art Kommentierung, die komplett am Sinn einer > Kommentierung vorbei geht. Richtig. Das wäre so. Aber ich sehe schon Du krallst Dich wieder an subjektiven Kommentierungsfragen fest. Wozu ist eigentlich dieses Forum im allgemeinen und die Projekte-Abteilung im speziellen da? Richtig. Zum Fragen. > Man kann die > Funktionsweise einer Raffinerie nicht dadurch ergründen und erklären, > dass man sich alle Schrauben, Muttern und Beilagscheiben ansieht. Es muß langen, Funktionalität und Interfaces zu beschreiben. Mehr Doku- Aufwand treibe ich nicht. Punkt. Alles andere kann erfragt werden. Asm Quellcode bleibt damit herrlich übersichtlich. Von langatmigen Klammerwüsten keine Spur ;-)
Jörg W. schrieb: > OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und > irgendwer hat dir mal gesagt, es sei "komplex". Noch einer schrieb: > Beide Aussagen sprechen von einer Überforderung durch > Informationen und Optionen > Im laufe der Jahrzehnte hat sich die Programmierung komplett geändert. > In die Register eines 8-Bit Controllers, oder auch in ein DOS-Programm > konnte man sich noch vollständig einarbeiten. Heutzutage ist es so > umfangreich - bis man alle Detail durchgearbeitet hat, ist es schon > wieder veraltet. > Es spaltet sich auf - der eine schreibt Python-Libraries für > Raspberry-Peripherie, der andere schreibt damit Web-Oberflächen für > Steuerungen. Pic32 liegt vielleicht noch an der Grenze, wo sich einer > alleine in alles einarbeiten kann. Bei Cortex-A geht das nicht mehr. > > Und dann kommt noch etwas total bescheuertes dazu: > > 20 Entwickler lösen innerhalb eines Programmes 30 gleichartige Probleme > auf 40 verschiedene Arten. C++ ist da am schlimmsten. Man findet in > einem Programm alles von K&R bis Java-Stil; Selbst gebastelte Container > mit obskurer Garbage-Collection neben QList, STL und alten C-Arrays; > Präprozessor-Tricksereinen neben Inline-Funktionen. > > Einfach nur nervtötender Kleinkram. Lässt sich nicht aufräumen - während > man einen Bereich auf eine übersichtliche Lösung umstellt, werden schon > wieder 5 neue Änderungen auf 10 unterschiedliche Arten eingebaut. Soweit zum Thema Komplexität und Kleinkram. Aufgegabelt in "C++ für Mikrocontroller" gleich nebenan ;-)
Icke ®. schrieb: > Ich habe daraus gelernt, daß jeglicher Versuch, Menschen mit derartig > zementierten Standpunkten (nannte man früher "Betonköpfe") von ihrem > Holzweg abzubringen, selbst unter Zuhilfenahme einleuchtendster > Argumente kläglich scheitert. Das höre ich oft als letztes verbleibendes Argument. Immerhin ist das aber noch irgendwo verständlich im Gegensatz zu jenen, die glauben, man müsse nur hinreichend beleidigen. > Noch ein klein wenig Topic. Ich programmiere auch gern in ASM, aber ich > kenne die Grenzen. Ich auch. Nur sind die weit weg. Außer es stehen wirklich mal größerer Berechnungen an ;-) > Es ist auch schön, per Pedes durch den Wald zu streifen, den Geräuschen > zu lauschen und mit den Füßen direkten Bodenkontakt zu spüren. Und es > macht Sinn, die 100m bis zum Bäcker um die Ecke zu laufen. Aber für den > Großeinkauf oder die Urlaubsfahrt steig ich dann doch lieber ins Auto. Ja ja die Vergleiche. Habens wirklich in sich.
Yalu X. schrieb: > Matthias L. schrieb: > Ergebnis: Der Tastenpin befindet sich im Carryflag wenn keyproc > aufgerufen wird. Weiter: > keyproc: > ... > ldd XL,Z+0 ;8x alle 5ms testen > rol XL ;= 200% Bulletproof ;-) > std Z+0,XL > > Du hättest statt der "..." die entsprechenden Befehle vollständig > hinschreiben sollen:keyproc: adiw ZH:ZL,2 ;Tastenstatus entprellend > ermitteln > in YH,GPIOR0 > mov YL,YH > ldd XL,Z+0 ;8x alle 5ms testen > rol XL ;= 200% Bulletproof ;-) > > Der erste Befehl ist nämlich ADIW, das das Carry-Flag überschreibt, im > konkreten Fall mit 0. Somit schiebt ROL in das XL-Register nur Nullen > hinein, was den nett gemeinten Programmiertrick völlig versagen lässt. So. Hab mal drübergeschaut. In der Tat löscht adiw ZH:ZL in jedem Fall das C-Flag. Vermutlich hab ich das später noch hinzugefügt/umgeändert. Abhilfe: Aufruf von keyproc mit T- statt C-Flag und nach mov YL,YH ein brtc zum ldd XL,Z+0 sowie zwischendrin noch ein sec. Also 2 Instruktionen mehr. Es stimmt, das Programm ist noch nicht getestet, sollte aber auch nur im ursprünglichen Thread eine einfache Problemlösung in Asm andeuten. Nach einem Test soll der Main-unabhängige Timerinterrupt-Baustein zur Tastenentprellung und Feststellung der Betätigungsdauer beliebiger IO-Pin Tasten in die Codesammlung. > Wir wissen zwar nicht, was Mobys Programm tun soll Was sollen solche halbgaren Feststellungen? Die beabsichtigte Funktionalität ist doch klar definiert. > Und was lernen wir daraus? > 1. Das Carry-Flag ist eigentlich gedacht Man muß sich nicht unbedingt daran orientieren wofür etwas gedacht ist. Damit geht vielleicht ein höheres Risiko für Fehler (wie hier) einher aber man bewahrt sich alle technischen Möglichkeiten. > Wenn man schon Assembler programmiert und dabei auzch noch tief in > die Trickkiste greift, sollte man gut ausgeschlafen sein und jede > Code-Änderung dreimal mit dem Auge durchgehen und zusätzlich intensiv > testen. Flüchtigkeitsfehler sind wirklich nicht die größten Probleme. Die sind eher systematischer Natur, etwa in Zusammenhang mit unklaren realen Messwerten. > Er hat sie auf mehrere Tasten erweitert, musste dazu aber die > indirekte Adressierung für das Z-Register und damit verbunden den > ADIW-Befehl einführen, was schließlich zu dem Fehler führte. Gut möglich. > => Wiederverwendbarkeit von Code erfordert eine genaue und > vollständige Dokumentation nicht nur der Funktion, sondern auch der > Nebeneffekte. Das ist hier offensichtlich nicht geschehen. Richtig. > Da Moby der Assembler-Gott ist, der immer alles richtig macht, hat er > auch keinen Bedarf gesehen, die Routine vor ihrer Veröffentlichung > wenigstens einmal zu testen ;-) Schön wärs. > 3. Hochsprachen sind weniger anfällig gegen solche Fehler Dafür gegen andere. Also sollte der C-Flag Fehler der Einzige im Programm gewesen sein bin ich schon zufrieden. Das Angebot zum kürzeren Formulieren der beschriebenen Funktionalität in C steht nach wie vor... Dabei muß man sich auch nicht an meiner Programmlogik orientieren.
:
Bearbeitet durch User
Moby A. schrieb: > Jörg W. schrieb: >> OK, Thema abgehakt. Du kennst von OOP offenbar nur den Namen, und >> irgendwer hat dir mal gesagt, es sei "komplex". > > Noch einer schrieb: >> Beide Aussagen sprechen von einer Überforderung durch >> Informationen und Optionen ... >> Einfach nur nervtötender Kleinkram. Lässt sich nicht aufräumen - während >> man einen Bereich auf eine übersichtliche Lösung umstellt, werden schon >> wieder 5 neue Änderungen auf 10 unterschiedliche Arten eingebaut. > > Soweit zum Thema Komplexität und Kleinkram. > Aufgegabelt in "C++ für Mikrocontroller" gleich nebenan ;-) Na und? Du bist halt nicht der einzige, der nicht programmieren kann.
Nö, Moby hat in einer Hinsicht schon recht. Von Assembler zu C zu C++ steigern sich Abstraktion und Komplexität - wobei ich damit nicht die des erzeugten Codes meine. Mit der Länge des Handbuchs ist das nur unzureichend beschrieben. So steht der Assembler-Befehl XXX R0,R1 für eine klare Anweisung, genau an dieser Stelle genau das zu tun, was da steht, und es reicht weitgehend aus, die Beschreibung des Befehls nachzulesen um zu verstehen, was die Zeile genau tut. Man kann aufgrund des vielen Kleinklein zwar das Programm schlechter anhand des Codes erfassen, aber die einzelnen Zeilen sind einfacher. Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt sich die tatsächliche Operation erst aus den Datentypen der Operanden. So ist nicht von vorneherein klar, ob mit oder ohne Vorzeichen verglichen wird, weil das von den exakten Datentypen und dem Typenmodell des Compilers abhängig ist (u16 < i32 => signed, u32 < i32 => unsigned). Dafür aber sieht man gleich, dass es ein Vergleich ist, egal ob dahinter nur ein Maschinenbefehl sitzt, oder hunderte. Die ersten C Compiler waren auch noch auf einer Ebene, der C die Einstufung als glorifizierter Makroassember verdankte. Sie übersetzten ziemlich linear den geschriebenen Code in Maschinencode. Wer Registeroptimierung wollte, der tat das selbst und schrieb "register" hin. Code wurde nicht wegoptimiert, nicht verschoben. Probleme mit in Interrupts verwendeten Daten entstanden erst, als die Compiler besser wurden, weshalb dann "volatile" nachgereicht wurde. Dieses "volatile" sorgt zwar nur für ein paar Zeilen im Handbuch, hat aber fundamentalen Einfluss auf bestimmte Programmierkonzepte, wie viele µC-Programmierer erst lernen müssen. Moby bleibt dies erspart. Mit C++ setzt sich das fort. So kann man sich bei eigentlich per Referenz übergebenen Parametern von dummerweise vom Compiler nur temporär angelegten Daten überraschen lassen, wodurch das Ergebnis im Nirvana entschwindet. Aus dem Quellcode der Zeile geht das nicht hervor, da muss man weit mehr überblicken. Inwieweit das freilich gegen die Programmierung in Hochsprachen spricht muss jeder für sich entscheiden. Komplexität ist nicht grundsätzlich ein Nachteil, weil man oft nur aufgrund der Komplexität der Mittel überhaupt erweiterte Probleme lösen kann. Moby beschränkt sich dann eben auf jene Probleme, die er lösen kann. Die anderen negiert er gerne, weil "braucht man kaum". Das Problem mit Moby ist nicht seine Beschränkung auf Werkzeuge, deren Komplexität er überblicken kann, sondern sein Sendungsbewusstsein, diese persönliche Eigenheit zu Mass der Dinge zu erklären und andere davon überzeugen zu wollen. Ihn schreckt der höhere Abstraktionsgrad höherer Sprachen, andere Leute aber nicht, und das versteht er nicht.
:
Bearbeitet durch User
Moby A. schrieb: > Nun sind AVR und seinen typischen 8-Bit Apps aber nicht gerade für > maximale Komplexität bekannt, und das ist gut so ;-) Du hast gar keine Ahnung, wie "typische 8-Bit-Apps" für AVRs aussehen. Da passt schon jede Menge an Funktionalität rein, von denen Du noch nichtmals zu träumen wagst. Beschränke Dich mal bei Deinen ganzen Behauptungen auf ATTiny mit höchstens 1KB Flash. Da machen Deine Argumente (und damit Assembler) vielleicht noch in einigen Ausnahmefällen überhaupt Sinn. Deine Welt ist klitzeklein, Moby. Du wüsstest noch nichtmals, was Du mit einem ATmega328 anfangen könntest. "Typische AVR-Anwendungen" finden aber eher in diesen Größenordnungen statt.
A. K. schrieb: > So steht der Assembler-Befehl XXX R0,R1 für eine klare Anweisung, ... ... > Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt... So kann man aber nicht sinnvoll vergleichen, es sei denn man misst seine Arbeit in Anzahl Programmzeilen. Es geht ja in der Regel nicht darum, Text zu produzieren, sondern ein Problem zu lösen. Und dann kann man nicht einen C-Ausdruck mit einem Assemblerbefehl vergleichen, sondern müsste den C-Ausdruck mit der entsprechenden Folge von Assemblertext vergleichen, der funktional gleichwertig ist. Und genau dann ist Assembler bei nichttrivialen Problemen eben schon nicht mehr so klar und übersichtlich - wie man an den Fehlern in Mobys ach so klaren, übersichtlichen und selbsterklärenden Programmen sieht. Hier sehe ich den die Crux der ganzen Diskussion (neben dem Missioniergeist, der mit Verblödung regelmäßig einhergeht in jeder Religion): EIN Assemblerbefehl ist übersichtlich, klar. Aber die vielen, die man für ein halbwegs komplexes Problem braucht, sind es nicht mehr. Auch ein typisches C-Programm besteht ja nicht mehr aus einem Vergleich, sondern aus wesentlich mehr. Wenn man dann für jedes Detail etliche Maschinenbefehle erfassen muß, hat man einfach keinen Überblick. Außer man ist so genial wie Moby; ich bin zu doof für sowas.
> ich bin zu doof für sowas.
Viele hier sind zu doof dafür, mich eingeschlossen. Deshalb müssen wir
mit Programmieren unsere Brötchen verdienen. Nur einer macht das als
Hobby, der Mobby! (wie er sich diesen NickName ausgesucht hat. Welch
Weitblick!)
(bin ich froh, daß ich den nicht als Kollegen hab. Obwohl, der ein oder
andere, um den ich einen großen Bogen mache, ist auf einem "guten" Weg)
Klaus W. schrieb: > Und dann kann man nicht einen C-Ausdruck mit einem Assemblerbefehl > vergleichen, Doch, kann man schon. Man kann Programmzeilen vergleichen und man kann Lösungen vergleichen. Ich hatte oben eine Programmzeile verglichen, um den Unterschied der Komplexität dieser Programmzeile hervorzuheben. Dass man für die gleiche Lösung wesentlich mehr Asm-Zeilen benötigt ist unstrittig und eine andere Art von Vergleich. > Aber die vielen, die man für ein halbwegs komplexes Problem braucht, > sind es nicht mehr. Klar. > Außer man ist so genial wie Moby; ich bin zu doof für sowas. Die Grösse eines Programms, das man noch einigermassen überblicken kann ist begrenzt. Weshalb die Lösungen, die man noch alleine stemmen kann, mit der Komplexität des verwendeten Werkzeugs wachsen. Weshalb man in einer geeigneten Hochsprache komplexere Lösungen stemmen kann als in Assembler. Er beschränkt sich auf das, was er überblicken kann, und definiert alles darüber hinaus als "braucht man nicht". ;-)
:
Bearbeitet durch User
A. K. schrieb: > Er beschränkt sich auf das, was er überblicken kann, und definiert alles > darüber hinaus als "braucht man nicht". ;-) Genau dieser Mikrokosmos von Moby ist der Grund für diesen ellenlangen Thread.
Moby A. schrieb: >> Wir wissen zwar nicht, was Mobys Programm tun soll > > Was sollen solche halbgaren Feststellungen? > Die beabsichtigte Funktionalität ist doch klar definiert. Ok, das nehme ich zurück. Ich hatte das mit deinem anderen Code (adu.asm) verwechselt, dem tatsächlich die Beschreibung der Gesamtfunktion fehlt. > Also sollte der C-Flag Fehler der Einzige im Programm gewesen sein bin > ich schon zufrieden. Ich habe das Programm genauso wenig getestet wie du. Der Fehler mit dem Carry-Flag ist mir aufgefallen bei dem Versuch, die Funktion des Codes wenigstens grob zu verstehen. Die meisten Fehler werden aber nicht beim Durchlesen des Codes, sondern erst beim realen Test aufgedeckt. Zum Thema Moby A. schrieb: > Hardware- Wirklichkeit Es ist sicher kein Fehler, wenn ein C-Programmierer auch ein wenig Ahnung von Assembler-Programmierung auf der von ihm eingesetzten Plattform hat, ganz im Gegenteil: Dadurch hat er ein besseres Gefühl dafür, was er mit bestimmten C-Konstrukten der CPU tatsächlich zumutet. Ich behaupte mal, dass C-Programmierer, die auch etwas Assembler können, i.Allg. effizienteren Code schreiben als diejenigen, die nur in Hochsprachen unterwegs sind. Umgekehrt gilt das aber auch: Assembler-Programme von Leuten, die auch regelmäßig in Hochsprachen programmieren, haben i.Allg. eine bessere Struktur. Dazu gehören bspw. die Vermeidung von Nebeneffekten in Unterprogrammen (wo möglich), einheitliche Konventionen für den Transfer der Input- und Outputdaten von Unterprogrammen und die Behandlung zusammengehörender Daten als eine Einheit (Datenstrukturen). Das kostet zwar evtl. ein paar Prozent CPU-Leistung, erleichtet dafür aber die Wiederverwendung von früher geschriebenem Code und reduziert dabei gleichzeitig die Gefahr von Flüchtigkeitsfehlern, wie sie dir bei der Anpassung relativ kurzer Code-Abschnitte jetzt schon zweimal passiert sind. Mein Rat an dich: Bleib bei deinem Assembler, wenn es dir Spaß macht, aber versuche parallel dazu, mehr Einblick in die C-Programmierung zu bekommen. Du wirst dabei immer wieder Aha-Effekte erleben, die dir auch bei der Assembler-Programmierung zugute kommen. Als Nebeneffekt wirst du dann auch bei Assembler-vs-C-Diskussionen wie dieser hier von den anderen ernster genommen :) Moby A. schrieb: > Asm Quellcode bleibt damit herrlich übersichtlich. > Von langatmigen Klammerwüsten keine Spur ;-) Du siehst ein C-Programm als eine langatmige Klammerwüste, weil du von C keine Ahnung hast. Mir geht es ähnlich, wenn ich mir das von A. K. gepostete APL-Beispiel anschaue: A. K. schrieb: > Ich kann da nur wieder dieses Beispiel ans Herz legen Weil ich von APL keine Ahnung habe, stellt sich das Beispiel für mich als Wüste von seltsamen Symbolen dar. Ich käme aber nicht auf die Idee, in einer Diskussion mit APL-Programmierern APL deswegen schlecht zu reden, denn ich weiß genau: - Alle anderen Diskussionsteilnehmer verstehen diesen Code und sehen zwar die Symbole, aber keine Wüste. - Als einziger Ahnungsloser werde ich von den anderen zunächst mitleidig belächelt werden. - Wiederhole ich meine Auffassung, dass APL Käse ist, zu oft, werde ich irgendwann in hohem Bogen aus der Diskussion hinausfliegen. Wenn das Wetter am Wochenende schlecht ist, werde ich mir das APL-Beispiel vielleicht mal genauer anschauen und dann mein erstes Urteil über diese Sprache bilden. Einen Startpunkt habe ich schon gefunden: http://tryapl.org/ :)
Yalu X. schrieb: > Es ist sicher kein Fehler, wenn ein C-Programmierer auch ein wenig > Ahnung von Assembler-Programmierung auf der von ihm eingesetzten > Plattform hat, ganz im Gegenteil: Dadurch hat er ein besseres Gefühl > dafür, was er mit bestimmten C-Konstrukten der CPU tatsächlich zumutet. Das kann ich nur bestätigen. Auch ich habe mal in den 80ern Z80-Assembler gelernt und konnte nach einiger Übung sogar Binär-Programme direkt in HEX-Codes in den Rechner eingeben, ohne einen Assembler bemühen zu müssen - hatte also den Assembler sozusagen eingeatmet :-) Auf jeden Fall ist die Kenntnis einiger Assembler Dialekte (später kam noch 68000 dazu) auch für einen Hochsprachen-Programmierer sehr nützlich. Denn er weiß dann, wie er dem Compiler "Hilfestellung" beim Compilieren/Optimieren geben kann. Als Beispiel sei hier nur das Arbeiten mit Kopien von volatile-Variablen in ISRs genannt. Auch heute schaue ich noch ab und zu in das vom Compiler generierte Assembler-File, einfach weil ich neugierig bin, wie er diese oder jene (kniffligere) Aufgabe gelöst hat und bin manchmal sehr überrascht, wie effizient die Lösung ist. > Ich behaupte mal, dass C-Programmierer, die auch etwas Assembler können, > i.Allg. effizienteren Code schreiben als diejenigen, die nur in > Hochsprachen unterwegs sind. ACK. > Umgekehrt gilt das aber auch: Assembler-Programme von Leuten, die auch > regelmäßig in Hochsprachen programmieren, haben i.Allg. eine bessere > Struktur. Sehe ich genauso. Ich weiß leider nicht, ob Moby aus Deinen Argumenten eine nützliche Lehre ziehen kann, denn manchmal kommt mir sein Horizont ziemlich beschränkt vor.
:
Bearbeitet durch Moderator
Lasst euch nicht auf fundamentale Assembler-Programmierer, die nichts anderes können oder (können) wollen, ein. Sie ziehen euch auf ihr Niveau herunter und besiegen euch mit langjähriger Erfahrung... Yalu X. schrieb: > Weil ich von APL keine Ahnung habe, stellt sich das Beispiel für mich > als Wüste von seltsamen Symbolen dar. Ich würde da auch erst mal nach der Baudrate sehen, wenn sowas über eine serielle Schnittstelle hereinkäme ;-)
:
Bearbeitet durch Moderator
Frank M. schrieb: > Denn er weiß dann, wie er dem Compiler "Hilfestellung" beim > Compilieren/Optimieren geben kann. Das kann allerdings auch in die Hose gehen, wenn man die Maschine wechselt, neue und alte Maschine sich erheblich unterscheiden und man die Regeln der alten Welt im Kopf hat. So verleitet C Programmierung auf 8-Bittern genau diesen Personenkreis dazu, umfänglich mit globalen oder statischen an Stelle lokaler Variablen oder Struct-Parametern zu programmieren. Statisch adressieren können die sehr gut, während sie sich mit Adressierung relativ zu Pointern mitunter deutlich schwerer tun (insbesondere 8051 und PIC). Wechseln man dann auf beispielsweise ARM, dann führt das zu ausgesprochen ineffizienten Programmen, da es bei denen genau umgekehrt ist. Statische Adressierung ist ineffizient, relative Adressierung effizient, und man nimmt dem Compiler die Chance zur Optimierung über Register.
:
Bearbeitet durch User
Wie heisst es schön: Wir leben zwar alle unter dem gleichen Himmel, haben aber nicht alle denselben Horizont.
Moby A. schrieb: > Frank M. schrieb: >> Moby A. schrieb: >> Das Optimum ist bei kurzen AVR Programmen eher zu erkennen und auch >> (fast) erreichbar. Ich hoffe, ich kann das in ein paar zukünftigen >> Projektbeispielen (auch wie viele andere Autoren) unter Beweis stellen. >> >> Da bin ich mal gespannt. Ich wette, jedes Deiner zukünftiger >> "Projektbeispiele"(*) lässt sich in C performanter und kürzer umsetzen - >> sowohl was Programmier- als auch Prozessoraufwand betrifft. > Dann bin ich schon sehr gespannt... > Wer die realisierte Funktionalität Können wir gerne machen. Wir vereinbaren einen Zeitpunkt an dem du und ich Zeit haben. Ein paar Forneteilnehmer denken sich eine Aufgabe aus, irgendjemand (du, ich, wir beide) wählt eine der Aufgaben aus und dann schaun wir mal, wer schneller das Programm stehen hat und wer es fehlerfreier hinkriegt. Ich hab nur eine Bedingung: es darf kein Pipifax Beispiel sein sondern sollte schon was ordentliches sein. Wir müssen uns noch auf eine zu verwendende Hardware einigen. AVR, ein paar Taster und ein 2 oder 4 zeiliges LCD. VOn mir aus kann ich auch noch ein paar Lichtschranken improvisieren. Aber eine CNC Ansteuerung ist zb so für einen Interessenten nicht machbar, denn keiner von uns beiden hat die Hardware da und ohne testen zu können mach ich sowas nicht.
:
Bearbeitet durch User
Lothar M. schrieb: > Ich würde da auch erst mal nach der Baudrate sehen, wenn sowas über eine > serielle Schnittstelle hereinkäme ;-) Ich würde dann aber an deiner Stelle auch am Terminal zweifeln. Zeig mir mal, an welcher Stelle deines 8-Bit Zeichensatzes Symbole wie ⍳, ⌹ oder ⍴ zu finden sind. ;-)
:
Bearbeitet durch User
> AVR, ein paar Taster und ein 2 oder 4 >zeiliges LCD. Vielleicht eine Art Laufschrift, welche beim Starten aus dem EEPROM geladen und dargestellt wird. Mit den Tasten kann man dann in einen Editiermodus gehen und den Text verändern. Dieser würde dann wieder im EEPROM abgelegt... Ich denke, das geht über eine blinkende Led heraus. Aber Tastenentprellung, LCD-Ansteuerung, etwas EEPROM sind ein klar abgesteckter Rahmen. Aber eben etwas mehr als ein >Pipifax Beispiel einer blinkenden LED.
Also wenn ihr das wirklich ernst meint, dann nehmt ein Beispiel, das im Simulator gut getestet werden kann.
:
Bearbeitet durch User
Matthias L. schrieb: >>Pipifax Beispiel > einer blinkenden LED. blinkende LED kann ruhig auch dabei sein. 3 oder 4 Stück, die voneinander unabhängig in einer vom Benutzer eingebbaren Frequenz blinken sollen. Kleine Menüsteuerung noch dazu, mit der man die LED zb auf einen Triggereingang 'verkabeln' kann. Eventuell eine kleine Ablaufsteuerung, damit auch Datenstrukturen ins Spiel kommen. Vielleicht noch ein oder 2 Servos (wenn Moby welche hat) ... Irgendsowas. Ein bunter Mix aus Beherrschung der Hardware, Basistechniken, ein bisschen rechnen, Speicherverwaltung, ..... Aber erst mal muss er den Fehdehandschuh aufgreifen. Mal sehen, obs so kommt wie es immer kommt, wenn ich sowas anbiete :-)
:
Bearbeitet durch User
A. K. schrieb: > Das kann allerdings auch in die Hose gehen, wenn man die Maschine > wechselt, neue und alte Maschine sich erheblich unterscheiden und man > die Regeln der alten Welt im Kopf hat. Ja, natürlich. Wenn man aber nicht nur in der (eingeschränkten) Welt der µCs zuhause ist, sondern zum Beispiel auch für diverseste sehr heterogene UNIX-Umgebungen (beileibe nicht nur x86), programmiert, bekommt man langsam mit der Erfahrung ein "Gefühl" dafür, was unter welcher Plattform sinnvoll ist und was nicht. > Wechseln man dann auf beispielsweise ARM, dann führt das zu > ausgesprochen ineffizienten Programmen, da es bei denen genau umgekehrt > ist. Statische Adressierung ist ineffizient, relative Adressierung > effizient, und man nimmt dem Compiler die Chance zur Optimierung über > Register. Okay. Manchmal muss man dann halt Kompromisse machen - gerade wenn man so portabel programmiert, dass ein- und dasselbe Programm sowohl auf ARM als auch auf AVR und PIC läuft. Wenn ich aber ein Programm erstelle, dass nur auf einem ARM laufen soll, gehe ich da mit ganz anderen Methoden dran. Die hier eher üppigen Ressourcen verleiten mich dazu, den Processor auch als "erwachsene Maschine" auszunutzen. Dazu gehören auch die Methoden zur Adressierung von Speicher bzw. dessen Verwaltung. Das macht wesentlich mehr Spaß als das eher beschränkte Programmieren von 8-Bit-AVRs.
Karl H. schrieb: > blinkende LED kann ruhig auch dabei sein. 3 oder 4 Stück, die > voneinander unabhängig in einer vom Benutzer eingebbaren Frequenz > blinken sollen. Kleine Menüsteuerung noch dazu, mit der man die LED zb > auf einen Triggereingang 'verkabeln' kann. Mein Vorschlag: 8-Kanal Software-UART (nur Eingänge), um 8 verschiedene LEDs mit SW-PWM zu steuern. Hierbei kann dann jeder Teilnehmer Skalierbarkeit seiner Software demonstrieren. Kleines UART-Protokoll dazu: Bn<CR> Helligkeit (Brightness) auf n% Ft,n<CR> Fading innerhalb der Zeit t auf n% Beispiele: B80<CR> Helligkeit (Brightness) auf 80% B00<CR> Ausschalten B100<CR> Brightness auf 100% F10,80<CR> Fading innerhalb von 10 Millisekunden auf 80% F100,00<CR> Fading innerhalb von 100 Millisekunden auf 0% Diese Aufgabe halte ich für sinnvoller, da die Lösung nachher nicht für die Tonne ist, sondern durchaus für das eine oder andere Projekt verwendet werden kann :-)
:
Bearbeitet durch Moderator
A. K. schrieb: > Nö, Moby hat in einer Hinsicht schon recht. Von Assembler zu C zu C++ > steigern sich Abstraktion und Komplexität Die Abstraktion steigt, aber auch die Komplexität? Eher nicht. Es gibt ja schließlich Gründe, warum Spaghetticode wie in Assembler so einen enorm schlechten Ruf hat und warum dringendst von der Verwendung des "goto"-Befehls in C und C++ abgeraten wird: weil das den Code unübersichtlich (vulgo: komplizierter) macht sowie Pflege und Wiederverwendung erschwert. Ja, eine einzelne Assembler-Instruktion ist "einfacher" insoweit als sie nur einen einzigen, winzigen kleinen Teil des Programms ausmacht. Aber das ist nur der eine Teil der Wahrheit, und der andere Teil lautet: eine einzelne Instruktion ist eben nur ein winzig kleiner Teil eines deutlich größeren Programms. Genau da liegen aber die Vorteile einer besseren Strukturierung und Abstraktion durch die Hochsprachen, im Gegensatz zu Spaghetticode, in dem zwischen verschiedenen Sprungmarken und Codeteilen wild hin- und hergesprungen wird. > Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt > sich die tatsächliche Operation erst aus den Datentypen der Operanden. Das ist nicht komplizierter, sondern viel einfacher, weil der Compiler dem Entwickler die Entscheidung, welche Maschineninstruktion(en) zu verwenden sind, ganz einfach abnimmt. Dank der deklarierten Datentypen der Variablen weiß der Compiler nämlich, welche Operation benutzt werden muß, und nimmt automatisch und ohne jedes Zutun die Richtige(tm). Für den Entwickler ist das eine enorme Vereinfachung und Erleichterung seiner Arbeit, und nicht zuletzt deswegen ist die Produktivität eines Entwicklers in Hochsprachen so viel höher als in Assembler. Richtig ist, daß der Entwickler dabei ein wenig von der Kontrolle darüber verliert, was sein Code genau macht. Mehr Kontrolle bedeutet aber immer mehr Arbeit und Komplexität, um die sich der Entwickler kümmern muß.
Sheeva P. schrieb: > Die Abstraktion steigt, aber auch die Komplexität? Eher nicht. In aller Kürze: Bei geeigneten Werkzeugen wird die Lösung eines nicht trivialen Problems durch die Wahl eines komplexeren Werkzeugs oft einfacher, sofern man nicht an der Komplexität des Werkzeugs scheitert. Es ist weitaus schneller, nach Malle zu fliegen als zu schwimmen. Aber man behilft sich dabei eines hochkomplexen Werkzeugs namens "Flugzeug" und überlässt dessen Komplexität andern Leuten und Automaten. Schwimmen ist ein Vorgang von weitaus geringerer Komplexität und ist dabei nicht unmöglich, aber es ist nicht wirklich als Lösungsansatz zu empfehlen. Gäbe es keine Piloten (inkl. Auto-) und man müsste selber ans Steuer des Vogels, dann würde viele Leute wohl den Moby machen und in einfacher erreichbaren heimatlichen Gefilden urlauben. "Komplexität" ist ein weiter Begriff. Ich bezog mich darauf, dass man die Abfolge von Assembler-Befehlen relativ leicht anhand der einzelnen Beschreibungen der Befehle nachvollziehen kann. In einer Hochsprache hingegen gibt es eine Vielzahl an Faktoren, die in die exakte Funktion einer Zeile einfliessen können. Viele dieser Faktoren sind quer über die Sprachbeschreibung gestreut und der Programmierer muss sie im Kopf haben und zum passenden Zeitpunkt mit der Zeile assoziieren. > Ja, eine einzelne Assembler-Instruktion ist "einfacher" insoweit als sie > nur einen einzigen, winzigen kleinen Teil des Programms ausmacht. Weshalb ich ja auch vorhin schon zwischen der Komplexität der Zeile und der Komplexität der Lösung unterschied. >> Im C Statement ist das komplizierter. Im Statement if(a < b)... ergibt >> sich die tatsächliche Operation erst aus den Datentypen der Operanden. > > Das ist nicht komplizierter, sondern viel einfacher, weil der Compiler > dem Entwickler die Entscheidung, welche Maschineninstruktion(en) zu > verwenden sind, ganz einfach abnimmt. Die Codegenerierung ist nur ein Teil der Gesamtproblematik. Ein häufiges Problem unter C Programmieren ergibt sich aus der Kombination vorzeichenfreier und vorzeichenbehafteter Typen. Aus if(a < b)... ergibt sich nicht direkt, ob der Vergleich mit oder ohne Vorzeichen stattfindet. Auch wenn "unsigned a" und "long b" bekannt sind ist das noch nicht klar, denn 16- und 32-Bit Maschinen verhalten sich dann völlig verschieden. Der Programmierer muss also jenseits der Bedeutung des "<" Operators auch die in C üblichen Konvertierungsregeln im Kopf haben und diese in Bezug zur realen Maschine setzen. Es ist diese Art der Komplexität einer Sprache, auf die ich mich beziehe. > muß, und nimmt automatisch und ohne jedes Zutun die Richtige(tm). Er nimmt das, was sich aus den Regeln ergibt. Das ist keineswegs immer die richtige Wahl in Bezug auf die Lösung des Problems. Das "do what I mean, not what I say" Problem ist nach wie vor ungelöst. > Für den Entwickler ist das eine enorme Vereinfachung und > Erleichterung seiner Arbeit, Richtig. Weshalb ich ja diese Form der Komplexität nicht ablehne. Ich weise nur darauf hin, dass es sie gibt.
:
Bearbeitet durch User
A. K. schrieb: > Doch, kann man schon. Man kann Programmzeilen vergleichen und man kann > Lösungen vergleichen. Wenn man die Anzahl von Programmzeilen in Assembler, C und, sagen wir, Ruby vergleicht, wird daraus aber zwangsläufig ein Vergleich von Äpfeln, Bananen, und Rinderhacksteaks, oder anders gesagt: solche Vergleiche hinken und sind weder sinnvoll, noch zielführend. Zumal die Zeilen, die Du vergleichen willst, nicht einmal näherungsweise etwas ähnliches tun. Das ist aber gerade das, was einen Programmierer interessiert: nämlich das, was sein Programm tut, also daß das Programm sein Problem löst. Wie es das Problem dann tatsächlich löst, ist eher nebensächlich. Programmieren ist schließlich kein Selbstzweck, sondern soll praktische Probleme lösen, wie hier im Beispiel den Vergleich zweier Zahlen. > Ich hatte oben eine Programmzeile verglichen, um den Unterschied der > Komplexität dieser Programmzeile hervorzuheben. Dass man für die gleiche > Lösung wesentlich mehr Asm-Zeilen benötigt ist unstrittig und eine > andere Art von Vergleich. Es ist die einzige Art von Vergleich, die einen Sinn ergibt. Aber auch wenn wir bei Deinem Vergleich bleiben, zeigt sich, wie viel komplizerter ASM ist: ein "if(a < b)" versteht sogar jemand, der überhaupt keine Ahnung von der Programmiersprache C oder überhaupt vom Programmieren hat. In Assembler steht da etwas wie "cp r16, r17", "cpc r16, r17" oder "cpi r16, r17", was sich einem Betrachter nur erschließen kann, wenn er weiß, was "cp", "cpc" und "cpi" tun und was die Register "r16" und "r17" sind. Um Dein Assembler-Beispiel aber auch nur halbwegs vergleichbar mit jenem in C zu machen, kommt allerdings noch der Sprungbefehl hinzu, und erst wenn man den hinzunimmt, kommt am Ende etwas heraus, das wenigstens im Ansatz mit dem C-Beispiel äquivalent und vergleichbar ist. Denn das ist schließlich jener Grad an Komplexität, die der Programmierer letztlich behandeln und beherrschen muß. Und dann bekommt die Sache einen Sinn:
1 | if(a < b) mach_dies(); |
ist viel einfacher und lesbarer und sogar für Laien verständlicher als
1 | cp r16, r17 |
2 | brlo mach_dies |
-- und das gilt nur für vorzeichenlose (unsigned) Zahlen in r16 und r17. Wenn die Zahlen vorzeichenbehaftet (signed) sind, heißt die Instruktion nicht mehr "brlo", sondern "brlt"... Das erschließt sich jemandem, der Programmieren kann, aber ein Laie versteht nichtmal, warum es da zwei verschiedene Instruktionen gibt, die (vermeintlich) dasselbe tun. Und weil nur Masochisten und Ideologen sich an solcherlei Kinkerlitzchen aufhalten, reale Programmierer aber praktische Probleme schnell und effizient lösen wollen, wird Assembler heute nurmehr in wenigen Ausnahmefällen benutzt. Für einen, der sie beherrscht, sind C und, wo wir gerade dabei sind, auch C++ sehr viel klarer und einfacher als Assembler.
für unterschiedliche Leute sind halt verschiedene Sachen eine 'Erklärung/Dokumentation'. Hier mal ein klassischer Filmausschnitt: https://www.youtube.com/watch?v=rFz2llnnC1o Es ist ganz klar was dieses Objekt (Zeile Code) tut. Nur das 'wozu' fehlt.
Sheeva P. schrieb: > Wenn man die Anzahl von Programmzeilen in Assembler, C und, sagen wir, > Ruby vergleicht, Wir schreiben aneinander vorbei. Ich beziehe mich stets auf die Komplexität des Werkzeugs und du zählst andauernd Programmzeilen. Wer ein komplexes Werkzeug beherrscht, der hat bei der Lösung eines für dieses Werkzeug geeigneten Problems weniger Arbeit als jemand, der mit einem weitaus einfacheren Werkzeug auskommen muss. Das ändert nichts an der Komplexität des Werkzeugs, sehr wohl aber den Aufwand zur Lösung
:
Bearbeitet durch User
A. K. schrieb: > Wer ein komplexes Werkzeug beherrscht, der hat bei der Lösung eines für > dieses Werkzeug geeigneten Problems weniger Arbeit als jemand, der mit > einem weitaus einfacheren Werkzeug auskommen muss. Das ändert nichts an > der Komplexität des Werkzeugs, sehr wohl aber den _Aufwand zur Lösung_ Akzeptiert und Zustimmung. Ja ich weiss, du wolltest nur diese Feststellung treffen - und da teile ich deine Sichtweise. In diesem Sinne ist Assembler natürlich einfacher, taugt aber trotzdem nicht als tragfähiges Argument. In diesem Sinne ist auch eine Feinsäge und ein Stechbeitel einfacher als eine Tischkreissäge samt entsprechendem Zubehör. Aber dieses Zubehör erlaubt es mir, eine verzinkte Verbindung in windeseile perfekt herzustellen. Etwas wozu ich mich Feinsäge und Stechbeitel viel länger brauchen würde und wo ich schon viel Übung benötigen würde, um ein technisch gleichwertiges Ergebnis hinzukriegen. Dazu kommt noch: Beherrsche ich mein Zubehör, dann wird jede Verzinkung perfekt und ich komme jedesmal in den Genuss der Zeitersparnis. Zum Ausgleich kann ich die gesparte Zeit dann an anderer Stelle in meinem Projekt gut gebrauchen, indem ich mir die Anordnung der SChubladen im Schrank dann eben gut überlege und wenn sich rausstellt, dass das alles nicht so schlau war, dann kann ich ganz schnell neue (verzinkte) Schubladen herstellen. Ich kann vielleicht (abhängig von meinem Werkzeug) nicht jedes beliebige Mass in der Verzinkung erreichen - kann aber mit dieser Einschränkung gut leben. Eine andere Analogie wäre für mich Schach: Die möglichen Züge sind so etwas wie Assembler. Einfach, simpel, schnell zu lernen. Aber Schach ist mehr als nur irgendwelche Züge. Natürlich lässt sich ein Damengambit letzten Endes auch nur auf Züge reduzieren. Aber der Sinn der Sache, die Wirkung, erschliesst sich erst, wenn ich von dieser Zugebene weggehe und mir überlege, wie ich mit einer Zugfolge Druck auf meinen Gegner aufbauen kann. Um eine der banannten Zugfolgen wirklich zu verstehen, muss ich die Gesamtheit des Spielbrettes betrachten und wie sich dort die Kräfte verteilen. Mit Einzelzügen hat das nicht mehr viel zu tun.
:
Bearbeitet durch User
Karl H. schrieb: > Eine andere Analogie wäre für mich Schach: > Die möglichen Züge sind so etwas wie Assembler. Der Vergleich mit Schach stellt aber auch schnell die Aussage 'Wenn der Computer(Compiler) besser ist, dann war der Schachspieler(ASM-Programmierer) nicht gut' stark in Frage. Inzwischen ist die Menge der 'guten' Schachspieler ja schon die leere Menge.
Dumdi D. schrieb: > Inzwischen > ist die Menge der 'guten' Schachspieler ja schon die leere Menge. Ich bin gerne bereit zuzugestehen, dass es für praktische Zwecke nicht akzeptabel ist, dass ein Compiler 20 Minuten an der Übersetzung eines moderaten Codes arbeitet. Würde man ihm die Zeit geben, dann würde er auch die perfekte Lösung finden können. Inklusive rumprobieren, welche Variablen er global in welche Register legt, wie er auf einem AVR das T-Bit für Einzelbitflags sinnvoll nutzen kann, wie er die Pipeline aufs Beste befüllt halten kann. etc. Bruth Force vom Feinsten. Da aber Compiler, anders als die 'großen Schachprogramme', kein Prestigeobjekt sind, wird da nicht so viel investiert.
:
Bearbeitet durch User
Dummerweise wächst der Aufwand extrem mit der Länge und ist daher allenfalls für relativ kleine Schleifen noch praktikabel. Für kurze Sequenzen gibt es ein paar Ansätze: https://en.wikipedia.org/wiki/Superoptimization Karl H. schrieb: > Da aber Compiler, anders als die 'großen Schachprogramme', kein > Prestigeobjekt sind Doch, manchmal schon. Es wurden schon Compilerbauer dabei erwischt, dass sie Benchmarkcode identifizierten und durch handoptimierten Code oder Abkürzungen ersetzten.
:
Bearbeitet durch User
Hach, wer hätte das ausgerechnet bei 14-Bit PICs vermutet? "PIC Microcontroller SuperOptimizer The PIC Microcontroller SuperOptimizer is a program that, given a function, tries to find the shortest sequence of microcontroller instructions that implement that function. It tries every sequence of instructions from a restricted set." http://freecode.com/projects/picsuperoprimizer
:
Bearbeitet durch User
Karl H. schrieb: > Können wir gerne machen. > Wir vereinbaren einen Zeitpunkt an dem du und ich Zeit haben. Ein paar > Forneteilnehmer denken sich eine Aufgabe aus, irgendjemand (du, ich, wir > beide) wählt eine der Aufgaben aus und dann schaun wir mal, wer > schneller das Programm stehen hat und wer es fehlerfreier hinkriegt. > > Ich hab nur eine Bedingung: es darf kein Pipifax Beispiel sein sondern > sollte schon was ordentliches sein. Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem Mega2560? :P
Karl H. schrieb: > Da aber Compiler, anders als die 'großen Schachprogramme', kein > Prestigeobjekt sind, wird da nicht so viel investiert. Der Aufwand, die optimale Lösung zu finden, sollte nicht grösser sein als die Differenz zur suboptimalen leicht ermittelbaren Lösung. Das ist wie beim Informatikern wohlbekannten Problem des Handlungsreisenden. Wenn der erst losfährt, nachdem er seine lange Reiseroute voll durchoptimiert hat, kann es sehr gut sein, dass er insgesamt länger braucht als wenn er einfach so frei Nase losgefahren wäre.
:
Bearbeitet durch User
Kaj G. schrieb: > Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem > Mega2560? :P Da muss ich mich erst mal schlau machen, was das überhaupt ist :-)
Karl H. schrieb: > Kaj G. schrieb: > >> Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem >> Mega2560? :P > > Da muss ich mich erst mal schlau machen, was das überhaupt ist :-)
1 | ccTalk (pronounced see-see-talk) is a serial protocol in widespread use |
2 | throughout the money transaction and point-of-sale industry. Peripherals |
3 | such as the currency detectors for coins and banknotes found in a diverse |
4 | range of automatic payment equipment such as transportation, ticketing, |
5 | payphones, amusement machines, and retail cash management use ccTalk to |
6 | talk to the host controller. |
Wie testen wir die Implementierungen?
Karl H. schrieb: > Karl H. schrieb: >> Kaj G. schrieb: >> >>> Wie waere es mit einer Simulation von 3 ccTalk-Slaves auf einem >>> Mega2560? :P >> >> Da muss ich mich erst mal schlau machen, was das überhaupt ist :-) > ... > Wie testen wir die Implementierungen? Das war ja jetzt erstmal nur ein spontaner Vorschlag von mir, weil ich das in meiner jetzigen Firma schon machen musste. :) Die Implementierung könnte man Testen, in dem Jemand einen Master schreibt, der den Slaves (in einer euch unbekannten reihenfolge) kommandos schickt. Die Reihenfolge muss natürlich für beide Tests gleich sein. Generell müsste man die Aufgabe aber noch etwas spezifizieren. So würde ich zum Beispiel sagen, das es 2 Hopper und 1 Münzprüfer als Slaves sind. Und man müsste nochmal drüber reden ob mit oder ohne Verschlüsselung. Die Spezifikationen zu ccTalk gibt es hier: http://www.cctalk.org/ Auf der rechten Seite: Download Part 1 - 4 Wie gesagt, war jetzt einfach nur ein spontaner Vorschlag :) Das ganze gibt es auch noch mit MDB ( https://de.wikipedia.org/wiki/Multi-Drop_Bus ), davon hab ich aber keine ahnung.
:
Bearbeitet durch User
Könnte man das dann gleich praktisch nutzen? Zb für gratis Bahnfahrten?
Matthias L. schrieb: > Könnte man das dann gleich praktisch nutzen? Zb für gratis Bahnfahrten? Wenn du die Verschlüsselung (wo jeder Hersteller seine eigene haben dürfte, so wie wir) nachbauen/knacken kannst, klar :)
Kaj G. schrieb: > Wenn du die Verschlüsselung (wo jeder Hersteller seine eigene haben > dürfte, so wie wir) nachbauen/knacken kannst, klar :) Nicht ist so verlässlich unsicher, wie selbstgebaute Verschlüsselung. ;-)
A. K. schrieb: > Nicht ist so verlässlich unsicher, wie selbstgebaute Verschlüsselung. Stimmt schon, aber lass dir gesagt sein: Wenn man es wie wir mit organisierter Kriminalität zu tun hat, steckt da sehr viel Zeit, Geld, und auch entsprechende versuche (von sehr kreativen/kompetenten leuten), das ding zu knacken, drin ;) Oder anders gesagt: Selbst wenn du den Algorithmus kennst, kannst du die Verschlüsselung nicht brechen ;) Also "können" schon, dafür muss man dann aber unverhältnis mäßig viel aufwand treiben.
:
Bearbeitet durch User
So, mal zurück zum Thema: Kaj G. schrieb: > Die Implementierung könnte man Testen, in dem Jemand einen Master > schreibt, Das reicht aber nicht, denn wirklich interessant wird es erst, wenn jemand "das Gerät bedient", also z.B. "Geld einwirft und ausgezahlt haben möchte". Geld einwurf könnte man z.B. durch Taster simulieren (10, 20, 50 cent, 1 und 2 euro, je münze ein taster). Ich denke mögliche Aufgaben gibt es genug. Nur wie wird das ganze dann nachher effektiv verglichen, und was ist wann besser? Geht es nur um den Asm-Code, oder auch sachen wie "Lesbarkeit"? geht es um die laufzeit? Was genau will man nachher wie vergleichen? Und wer beurteilt am Ende, was jetzt "besser" ist? Oder geht es nur um "selbstgeschriebenen Asm" vs. "vom Compiler erzeugten Asm"? (Ja ich geb zu, ich hab irgendwo nach 150 Beiträgen auf gehört zu lesen und hab erst jetzt wieder angefangen)
Frank M. schrieb: > Diese Aufgabe halte ich für sinnvoller, da die Lösung nachher nicht für > die Tonne ist, sondern durchaus für das eine oder andere Projekt > verwendet werden kann :-) Sorry, Kay, aber Franks "Anforderung" bezüglich Wiederverwenbarkeit hat was! ;-)
> Ich würde dann aber an deiner Stelle auch am Terminal zweifeln. Zeig mir mal, an
welcher Stelle deines 8-Bit Zeichensatzes Symbole wie ⍳, ⌹ oder ⍴ zu finden sind.
;-)
Es gab zu APL auch spezielle Schablonen, die man auf
MainFrameTerminalTastaturen legte, damit man auch eintippen konte, was
auf dem Display zu sehen war. Das Terminal war dabei im APL-Mode. APL
hab ich zwar nie benutzt, aber an diese komischen Schablonen kann ich
mich erinnern.
Konrad S. schrieb: > Sorry, Kay, aber Franks "Anforderung" bezüglich Wiederverwenbarkeit hat > was! ;-) Ist ja völlig legitim. Ich hatte ja einfach nur was in den Raum/Chat geworfen :-)
Kaj G. schrieb: > Geht es nur um den Asm-Code, oder auch sachen wie "Lesbarkeit"? geht es > um die laufzeit? Zuallererst geht es um die Funktionsfähigkeit. Und zwar fehlerfrei :-) Laufzeit ist ein natürlich ein Thema. Da kann sich Moby was aussuchen. Zeitbedarf in der Erstellung ist ebenfalls ein Thema. Speziell wo doch Moby eh so wenig Zeit für sein Familie hat (Sorry, could not resist) > Was genau will man nachher wie vergleichen? Und wer beurteilt am Ende, > was jetzt "besser" ist? Da hätt ich einen fiesen Ansatz :-) Jeder von uns beiden baut einen Fehler in seine Version ein. Und dann schaun wir mal, welche Fraktion (Assembler oder C) den Fehler schneller findet. :-) Aber kein Sorge. Wenn die Dinge so laufen, wie sie eigentlich immer laufen, wird es nie zu so einem Wettstreit kommen. Ich bin übrigens das Wochenende über unterwegs. Daher nicht wundern, wenn ich (falls doch etwas zu stande kommt), nicht zeitnah antworte. > Oder geht es nur um "selbstgeschriebenen Asm" vs. "vom Compiler > erzeugten Asm"? Es geht darum, die vollmundigen Aussagen endlich mal auf einen Prüfstand zu stellen. Und zwar mit ein bischen mehr als Micky Mouse "Wenn Taster gedrückt, dann LED ein" Programmen (oder Variationen davon). Da Moby kein Profi ist, gestehe ich ihm eine Beschränkung der Komplexität der Aufgabenstellung zu. Aber auch nicht zu trivial.
:
Bearbeitet durch User
Frank M. schrieb: > 8-Kanal Software-UART (nur Eingänge), um 8 verschiedene LEDs mit SW-PWM > zu steuern Oh die Idee klingt gut. Ein Programmierkontest :-) Aber ich steige jetzt schon aus wenn Johann mitmacht. Ich kenne den Source seiner Scopeuhr ;-)
:
Bearbeitet durch User
Karl H. schrieb: > Da Moby kein Profi ist, Also wenn ich die erste Seite dieses Threads richtig verstehe, macht Moby seit 18 Jahren Asm, da sollte man doch schon zu den "Profis" zählen, oder? :)
Kaj G. schrieb: > Karl H. schrieb: >> Da Moby kein Profi ist, > Also wenn ich die erste Seite dieses Threads richtig verstehe, macht > Moby seit 18 Jahren Asm, da sollte man doch schon zu den "Profis" > zählen, oder? :) Hätte ich auch gesagt. Aber auf der anderen Seite wenn ihn ein 32 Bit Vergleich schon vor so unübeerwindliche Hürden stellt. (Den Fehler im ADC Beispiel seh ich so wie er nicht als verzeihlichen Flüchtigkeitsfehler an, sondern der ist schon massiv mittelprächtig schwer und genau von der Sort, vor denen wir Asm-Programmierer immer warnen: du musst dir bei einer Änderung ALLES ansehen. Und ALLES meint auch wirklich alles. Du musst dich um jeden Kleinscheiss selber kümmern: Adressierung, Flags, Registerbenutzung. So gesehen wäre genau dieser Fehler das beste Argument, warum ein Compiler sinnvoll ist. Aber seis drum. Wir alle machen mal Fehler das man sich hinterher nur noch auf den Kopf greift und fragt: Wie konnte das passieren?)
:
Bearbeitet durch User
Moby A. schrieb: > Das Angebot zum kürzeren Formulieren der beschriebenen > Funktionalität in C steht nach wie vor... Dabei muß man > sich auch nicht an meiner Programmlogik orientieren. Du schreibst, du willst den optimalen Code? Warum sparst zu dann auf Teufel-komm-raus 1, 2 läppische Instruktionen anstatt SCHNELLEN Code zu schreiben? Z.B dein Code für den LM335: o Ob der der 2 Byte kürzer oder länger ist, ist sooo egal, egaler geht's nicht. o Der Code läuft in einer ISR. Warum machst du den Code extra lahm, obwohl er in einer ISR laufen soll??? Es ist doch total hirnrissig, paar Bytes zu sparen wenn der Code schnell sein soll! Fangen wir mal mit der Erbsenzählerei an: o RCALL, RET und dein arschlahmer Rechtsschift kosten 2 + 5 = 7 Instruktionen. o Ohne große Verrenkungen macht man den 16-Bit Rechtsshift in 9 Instruktionen OGOTTOGOTT 9 INSTRUKTIONEN HÖLLE!!! o Zieh die 7 Instruktionen für CALL + RET + Schnach-Schift ab, und es bleiben 2 Mehrinstruktionen. o Wenn der Code eh in der ISR laufen soll, wozu dann CALL und RET? Sind doch unnötig wien Kropf! Und jetzte schaust du NICHT auf deinen Codelängenfetisch, sondern schaust dir mal eine SIMULATION an und hälst die SIMULIERTEN BEFEHLE nebeneinander! DAS ist nähmlich, was hier zählt. > 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke. Das ist doch Käse. Assembler ist ein exzellentes Einsatzgebiet für Arithmetik. Und wenn ich solchen Assembler schreibe, dann fuchse ich auch um jedes Byte und jeden Tick. Aber der Code landet dann auch nicht in der Tonne, sondern wird von Tausenden von Compiler-Anwendern eingesetzt.
900ss D. schrieb: > Aber ich steige jetzt schon aus wenn Johann mitmacht. > Ich kenne den Source seiner Scopeuhr ;-) Ja, die Scope-Uhr; Morpheus und Rudi. Ist momentan eingemottet, was aber nicht an Morpheus liegt ("Morpheus" is der Projektname der Software), sondern an Rudi ("Rudi" ist der Projektname für die Handware). Es gab sogar schon Interesse die Uhr zu vermarkten, aber dazu müsste es eine vermarktbare Hardware geben, und mit dem Zeug kenn ich mich nicht aus. Um das professionell und verkaufbar zu machen müsste jemand vom Fach her... Übrigens hab ich "Morpheus" als Name für die Software gewählt, weil ich Gimmiks wie folgendes implementieren wollte: Beitrag "Re: Wie Parametrisierung für Kurve finden?" https://www.mikrocontroller.net/attachment/52470/A-ani.gif https://www.mikrocontroller.net/attachment/52552/AB-ani.gif
Moby A. schrieb: > Das Angebot zum kürzeren Formulieren der beschriebenen Funktionalität > in C steht nach wie vor... Dabei muß man sich auch nicht an meiner > Programmlogik orientieren. "Angebot" angenommen ;-) Es geht doch um deinen Assemblercode in diesem Beitrag: Moby A. schrieb: > Hab mal meine bereits weiter oben zur Sprache gekommene ASM Lösung aus > einem anderen Hochsprachen-Thread(problem) angehängt. Im Anhang findest du den entsprechenden C-Code, der bis auf ein paar Kleinigkeiten die gleiche Funktion wie dein Assemblercode hat. Die Unterschiede: - Die Anzahl der zu verarbeitenden Tasten ist statt auf 8 nur durch die Anzahl der verfügbaren Portpins limitiert. Für jede Taste wird ein zusätzliches RAM-Byte benötigt, dafür bleibt aber das GPIOR0-Register frei. Für die Erweiterung auf mehr als 3 Tasten müssen nur das Makro KEYS auf den entsprechenden Wert gesetzt und zusätzliche Aufrufe von debounce in der Funktion processAllKeys hinzugefügt werden. - Die Anzahl der Abtastwerte lässt sich mit dem Makro DEBOUNCE_SAMPLES leicht ändern. Insbesondere sind auch Werte größer als 8 möglich (für besonders stark prellende Taster). - Es wird nicht nur die Dauer des Tastendrucks, sondern auch die des Loslassens gemessen. Dieses Feature braucht man zwar eher selten, aber wenn doch, dann ist es bereits da und muss nicht mehr implementiert werden. - Die Funktion debounce wird wie bei dir die Routine keyproc für jede Taste aufgerufen, allerdings ist die Aufrufreihenfolge von debounce unwichtig. So kann bspw. die Auswertung einzelner Tasten ausgelassen werden, wenn diese in einer bestimmten Situation gar nicht aktiv sein müssen, was dann etwas CPU-Zeit spart. - In deinem Code muss man bei der Erweiterung der Aktionsroutinen (key<i>pressed und key<i>released) darauf achten, dass darin die Register R27 (XH), R30 (ZL) und R31 (ZH) nicht versehentlich überschrieben werden, da in diesen Informationen zwischen zwei Aufrufen von keyproc aufgehoben werden. Das wird – wie schon beim Carry-Flag geschehen – ganz sicher zur Falle, wenn du deinen Code nach ein paar Monaten wieder herauskramst, um ihn zu erweitern ;-) Beim C-Code besteht diese Gefahr nicht. - Die Entprellung der Tasten und die Ausführung der davon abhängigen Aktionen (key<i>Pressed und key<i>Released) erfolgt bei mir nicht in der Interruptroutine, sondern in der Hauptschleife des Programms (aber trotzdem interruptgetriggert). Dadurch werden – insbesondere bei etwas aufwendigeren Aktionen – weitere Interrupts, die vielleich später hinzukommen – nicht unnötig blockiert. - Zudem erlaubt es diese Ablaufstruktur der CPU, sich während des Nichtstuns zwischen zwei Timer-Interrupts schlafen zu legen und damit Strom zu sparen. Die Entprellroutine ist ganz klassisch, ohne jegliche Tricks und damit für jeden C-Programmierer (hoffentlich) leicht nachvollziehbar mit zwei Zählern (für die eigentliche Entprellung die Gedrücktzeitmessung) realisiert. Man könnte den Code mit Kniffen wie den vertikalen Zählern in Peter Danneggers Routine sicher noch straffen. Peters Routine ließe sich auch relativ problemlos auch auf 8 Abtastwerte erweitern. Allerdings wäre der Code dann nicht mehr so klar verständlich und man müsste Einschränkungen bzgl. der Erweiterbarkeit in Kauf nehmen (maximal 8 Tasten, die alle an denselben I/O-Port angeschlossen sein müssen). Trotz der höheren Flexibilität und der für die meisten sicher leichter verständlichen Programmlogik kann der C-Code größenmäßig gut mit deinem Assemblercode mithalten:
1 | Mobys Asm-Code Yalus C-Code |
2 | ————————————————————————————————————————————————— |
3 | Flash-Verbrauch 266 256 |
4 | RAM-Verbrauch¹ 6 + 1 GPIOR 9 |
5 | Stack-Verbrauch 2 4 |
6 | Quellcodezeilen² 143 91 |
7 | Quellcodezeichen³ 1614 1707 |
8 | ————————————————————————————————————————————————— |
9 | ¹) ohne Stack |
10 | ²) ohne Leer- und Kommentarzeilen |
11 | ³) ohne Kommentare, Leerraum und Zeilenvorschübe |
12 | |
13 | Compiler: GCC 4.7.4 |
14 | Assembler/Linker: Binutils 2.25.1 |
15 | C-Standardbibliothek: AVR-Libc 1.8.1 |
Die 26 Interruptvektoren und die Routine zur Initialisierung des genutzten RAM-Bereichs mit Nullen sind übrigens in den 256 Flash-Bytes enthalten, auch wenn sie nicht explizit im C-Quellcode auftauchen. Da übernimmt die C-Toolchain also netterweise eine weitere lästige Aufgabe. Die versteckte Startroutine initialisiert übrigens auch den Stackpointer und das Statusrgister, was beim ATmega88 nicht unbedingt erforderlich ist. Eine dahingehend optimierte Startroutine würde noch einmal 10 Bytes sparen. Wenn man die Startroutine aber sowieso anpasst, könnte man bei dieser Gelegenheit gleich noch den Aufruf des nie endenen Hauptprogramms optimieren, was weitere 6 Bytes Flash und 2 Bytes Stack spart. Damit läge der Flash-Verbrauch mit 240 Bytes fast 10% unter dem deines Assemblerprogramms. Die Quellcodegröße in Zeichen ist beim C-Code immerhin knapp 6% größer als beim Assemblercode. Mit kürzeren Variablennamen, die dann ähnlich nichtssagend wären wie die Registernamen R18, XL, ZH usw. n deinem Assemblerprogramm könnte auch dieses Manko behoben werden, aber das lasse ich besser bleiben ;-) Abschließende Anmerkungen: Den C-Code habe ich mangels einer Schaltung mit dem ATmega88, den Tastern und den LEDs nicht auf dem Zielsystem laufen lassen. Allerdings habe ich die Funktion debounce mit simulierten Eingaben auf dem PC getestet, so dass ich mit ziemlich sicher bin, dass diese Funktion korrekt ist. Eventuelle Fehler in anderen Programmteilen (Tasten lesen, Ergebnis von debounce abfragen, LEDs schalten usw.) sollten mit minimalen Änderungen und ohne Erhöhung des Flash- und RAM-Verbrauchs korrigiert werden können. Die Initialisierung des Timers habe ich ohne Prüfung von Mobys Code übernommen in der Hoffnung, dass sie fehlerfrei ist.
:
Bearbeitet durch Moderator
900ss D. schrieb: > wenn Johann mitmacht. Ich kenne den Source seiner Scopeuhr ;-) Weiter geht's da: Beitrag "Morpheus + Rudi"
Yalu X. schrieb: > "Angebot" angenommen ;-) Gut gemacht :-) Bin mal gespannt wie groß der Moby's Assemblercode denn wird wenn er all deine Features auch noch implementiert
Kommt, die Sache ist doch schon erledigt. Laut Moby: Moby A. schrieb: > Horst S. schrieb: >> Moby schrieb: >> Asm allein ist nun >> leider keine Garantie für guten Code, wie man beim TO-Programm schön >> sehen kann ;-) >> >> Begründe mir nur diese eine Aussage, sachlich, fachlich kompetent und so >> vollständig, dass ich es aus Deinen Worten verstehen kann (also ohne >> großartige Literatur, die ich nicht habe). Ich bin bestimmt kein Guru, >> aber einfach abfrühstücken lasse ich mich auch nicht von Dir. >> >> Überzeug' mich, dann hast Du eine Chance auf 'ne Entschuldigung. > > Die Entschuldigung kannst Du Dir sparen. > Wenn sich Dein Asm-Code mit C locker unterbieten lässt dann spricht das > jedenfalls nicht für Deinen Asm-Code. Da sich sein Asm-Code auch mit C locker unterbieten lässt, kann er selber laut seiner Argumentation keinen guten Code schreiben.
Johann L. schrieb: >> 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke. > > Das ist doch Käse. Zwar tun sich 32-Bitter damit naturgemäss leichter, aber unten den 8-Bittern schlägt sich AVR dabei ziemlich gut. Register sind dabei deutlich besser als ein Akkumulator.
A. K. schrieb: > Moby beschränkt sich dann eben auf jene > Probleme, die er lösen kann. Die anderen negiert er gerne, weil "braucht > man kaum". Danke A.K. für diesen tiefschürfend analysierenden Beitrag, hab mich köstlich amüsiert. Hast schon recht: Ich beschränke mich. Aber nicht auf die Probleme die ich lösen kann sondern auf die Auswahl dazu hilfreicher Werkzeuge. Da nehm ich nämlich gern das Einfachste ;-) > Ihn schreckt der höhere Abstraktionsgrad höherer > Sprachen, andere Leute aber nicht, und das versteht er nicht. Mich schreckt gar nichts. Ich interessiere mich sogar sehr dafür. Und hab gelernt daß alle ach so vereinfachende Abstraktion und hochsprachliche Seiltänzerei zumindest über dem 8-Bit Hardware-Abgrund eine böse Kehrseite hat. Frank M. schrieb: > Deine Welt ist klitzeklein, Moby. Du wüsstest noch nichtmals, was Du mit > einem ATmega328 anfangen könntest. "Typische AVR-Anwendungen" finden > aber eher in diesen Größenordnungen statt. Du bist ja top informiert ;-) Das war zwar gar nicht der Punkt, aber klar doch kann man mit der Leistung eines AVR eine Menge anstellen. Soviel nämlich, das 8-Bittern noch lange kein Ende beschieden ist. Klaus W. schrieb: > Und genau dann ist Assembler bei nichttrivialen Problemen eben schon > nicht mehr so klar und übersichtlich - wie man an den Fehlern in Mobys > ach so klaren, übersichtlichen und selbsterklärenden Programmen sieht. Da sehe ich keinen Unterschied zu den komplexen Ausdrücken der Hochsprache. Klarheit, Übersichtlichkeit und Selbsterklärnis von ASM-Programmen wird durch Flüchtigkeitsfehler nicht tangiert. A. K. schrieb: > Die Grösse eines Programms, das man noch einigermassen überblicken kann > ist begrenzt. Weshalb die Lösungen, die man noch alleine stemmen kann, > mit der Komplexität des verwendeten Werkzeugs wachsen. Weshalb man in > einer geeigneten Hochsprache komplexere Lösungen stemmen kann als in > Assembler. Interessante These und da mag für höherbittige Universen samt deren Software was dran sein. Notwendig höhere Softwarekomplexität in Asm-Programmen lässt sich aber auch durch ein besonders systematisches Herangehen, Modularisierung und ausgefeilte Schnittstellen erreichen. Alles ohne Sprach-Bimbamborium höherer Sprachen. Frank M. schrieb: > Genau dieser Mikrokosmos von Moby ist der Grund für diesen ellenlangen > Thread. Nun ist ja gut, Frank M. Ich weiß ja, daß Du mit Deinen Programmen das Tor zu höheren Welten aufgestoßen hast. Versichere Dich nur weiter meines arg begrenzten Mikrokosmos- ich merke schon, das tut Dir gut ;-)
Karl H. schrieb: > Aber erst mal muss er den Fehdehandschuh aufgreifen. Mal sehen, obs so > kommt wie es immer kommt, wenn ich sowas anbiete :-) Den greife ich natürlich nicht auf, weil ich für solche Späße keine Zeit investiere. Meine Software die ich veröffentlicht habe und noch zu veröffentlichen gedenke ist nicht so umfangreich, daß ein C-Profi das nicht mal eben schnell kürzer codiert und mich so zum Staunen und Schweigen bringt ;-)
Gerade läuft wieder ein Thread: Verzweifelt keine Anzeige am LCD Es geht um LCD in Assembler. Da wäre eine echte Konifere gefragt. Der Kolege versteht zwar die Befehle, aber nicht, was sie zusammen tun. Aber wie immer: große Klappe, nix tun!
Johann L. schrieb: > Du schreibst, du willst den optimalen Code? Warum sparst zu dann auf > Teufel-komm-raus 1, 2 läppische Instruktionen anstatt SCHNELLEN Code zu > schreiben? Wie schon gesagt steht auch beim Asm-Programmieren öfter die Entscheidung an: Platz oder Speed. Das entscheidet man von Fall zu Fall. Hier geht es aber erst mal drum, welchen Vorsprung Asm zu Hochsprachen hat... Johann L. schrieb: > Z.B dein Code für den LM335: Schön daß Du ihn analysiert und in C codiert hast (bin immer noch nicht durch) aber ich will an dieser Stelle nochmal darauf hinweisen, daß diese relativ langweilige kurze Sequenz gar nicht zur Diskussion stand! Zur Diskussion stand das Entprellprogramm samt Erfassung der Tastenbetätigungsdauer für beliebige IO-Pin Tasten und der beschriebenen Funktionalität... und das steht es immer noch. Zur Diskussion stehen auch alle meine neueren Programme in der Codesammlung. So schwer sind die doch nicht zu verstehen! Johann L. schrieb: >> 1. 32-Bit Arithmetik ist keine AVR/ASM Stärke. > > Das ist doch Käse. Das ist kein Käse weil diese Aussage auf 32-Bit und C gemünzt war.
Carl D. schrieb: > Aber wie immer: große Klappe, nix tun! Och Carl D., war heute auch fleißig. Vielleicht entdeckst Du was Neues von mir in der Codesammlung ??? Wo steckt da eigentlich Dein Name ???
Moby A. schrieb: > Und hab gelernt daß alle ach so vereinfachende Abstraktion und > hochsprachliche Seiltänzerei zumindest über dem 8-Bit Hardware-Abgrund > eine böse Kehrseite hat. Und die böse Kehrseite wäre da welche?
Moby A. schrieb: > Zur Diskussion stand das Entprellprogramm samt Erfassung der > Tastenbetätigungsdauer für beliebige IO-Pin Tasten und der beschriebenen > Funktionalität... und das steht es immer noch. Dann guck doch mal Yalu X's Beitrag von 11:44 an ( Link: Beitrag "Re: C versus Assembler->Performance" ) Wie du siehst ist das C-Programm kürzer und flexibler als dein ASM-Geraffel.
Kaj G. schrieb: > Also wenn ich die erste Seite dieses Threads richtig verstehe, macht > Moby seit 18 Jahren Asm, da sollte man doch schon zu den "Profis" > zählen, oder? :) Den Titel beanspruche ich für mich sicher nicht. Hobby ist Hobby. Der Fokus liegt auf MSR-Lösungen für den Heimbereich. Das Wissen langt, um dort alles Gewünschte umzusetzen. > Und die böse Kehrseite wäre da welche? Intransparenz. Ausdruckskomplexität. Sprachmittelkomplexität. Sprachkonstruktionskomplexität. Compilerkonfiguritis. Um nur mal 5 Details der bösen Kehrseite zu nennen. Verlange nun nur nicht das jetzt nochmal zu erläutern ;-)
Torben H. schrieb: > Dann guck doch mal Yalu X's Beitrag von 11:44 an ( Link: > Beitrag "Re: C versus Assembler->Performance" ) > > Wie du siehst ist das C-Programm kürzer und flexibler als dein > ASM-Geraffel. Sorry- soweit war ich noch gar nicht mit dem Beantworten... Yalu X. schrieb: > "Angebot" angenommen ;-) Danke. Das werde ich mir noch gesondert zu Gemüte führen. Spekuliere nicht damit daß ich der Sache nicht zugrunde gehe ;-)
:
Bearbeitet durch User
Moby A. schrieb: >> Und die böse Kehrseite wäre da welche? > Intransparenz. Wenn man gerne wissen will was da bit für bit vorgeht, hindert einen -auch wenn man in C programmiert- niemand daran das ASM-Listing, den AVR-Instruction Set und die Mikroarchitektur anzusehen > Ausdruckskomplexität. > Sprachmittelkomplexität. > Sprachkonstruktionskomplexität. So komplex wie du immer predigst ist C überhaupt nicht. Wenn du wüstest wovon du redest wäre dir das auch schon lange öaufgefallen. > Compilerkonfiguritis. Ich verstehe schon, dass es einem Angst machen kann wenn ein Compiler mit ein paar Flags besseren Code als du in hochgelobten, handoptimiertem ASM erzeug, deswegen ist es aber noch lange nicht böse.
Rea L. schrieb: > So komplex wie du immer predigst ist C überhaupt nicht. Wenn du wüstest Ja ja ich weiß schon. Verlass Dich drauf. Schon dieser Thread zeigt einige Beispiele. Eigentlich brauche ich mich dazu auch nur an mein erstes und einziges C-Programm für die DOS-Kommandozeile erinnern ;-( Wieviele C-Programmierer die hier klug daherreden können eigentlich Asm? Wissen die Möglichkeiten dort überhaupt einzuschätzen?
Moby A. schrieb: > Wieviele C-Programmierer die hier klug daherreden können eigentlich Asm? > Wissen die Möglichkeiten dort überhaupt einzuschätzen? Alle! Wobei: 'daherreden' ist natürlich abwertend. Also daherreden tut hier keiner von den C-Programmierern.
:
Bearbeitet durch User
Moby A. schrieb: > Ausdruckskomplexität. > Sprachmittelkomplexität. > Sprachkonstruktionskomplexität. Das ist Blödsinn, und das weißt du. C hat ca. 1/3 der Schlüsselwörter von dem AVR-Asm-Instruktionen, und über x86-Asm brauchen wir da mal gar nicht reden. Von Komplexität kann in C nicht wirklich die Rede sein. Natürlich kann man in C unglaublich komplexen Code schreiben, das geht in Asm aber genauso gut. Der Grund, weshalb du Hochsprachen ablehnst, ist der selbe Grund, weshalb sehr viele Leute (besonders hier in Deutschland) "Angst" vor autonomen Fahrzeugen haben: Der Verlust von Kontrolle (die man gar nicht braucht) und das eingestehen, dass jemand anderes (der Compiler bzw. die Compilerbauer bzw. die Technik) besser sind, als man selbst. Dieses "Ich bin der perfekte Autofahrer" ist ein Irrglaube, und das ist bei Dir und Asm nicht anders. Der Kassiererin vertraust du doch auch, das sie deine Ware richtig über die Kasse zieht, oder ziehst du deine Sachen selber über die Kasse? Und ob sie es richtig gemacht hat, kannst du kontrollieren, anhand des Kassenbons, so wie du den Compiler kontrollieren kannst, anhand des Listings. Wo ist dein Problem, zu akzeptieren, das die Compilerbauer besser sind als du? Du hängst dich dann an kleinigkeiten auf, wo der Compiler Deiner Meinung nach, nicht optimialen Code erzeugt hat. Das schöne daran: Es ist deine Meinung. Wenn du was an dem erzeugten Code auszusetzen hast, dann frag doch mal die Compilerbauer, was die sich da gedacht haben und reich einen Patch ein. Die würden sich da bestimmt drüber freuen und dir die Füße küssen. Ebenso wurde bei dir ja auch, wenn es nach der Meinung anderer geht, nicht optimaler Code gefunden... Warum ist das in deiner Welt ok, wenn du das verbrochen hast, es ist aber nicht ok, wenn der Compiler das macht? Oder ist es einfach deine Sturheit, "ich mach schon immer Asm, was anderes braucht ich nicht, was neues lern ich nicht"? Würd mich mal interessieren, ob du überhaupt schon mal versucht hast, eine von deinen Aufgaben in C zu lösen. Und wenn das Ergebnis vom Compiler ja ach so schlecht gewesen sein soll, dann zeig doch mal bitte den entsprechenden C-Code, zusammen mit dem verwendeten Compiler und der Compilerversion usw. Ich bin mir sicher, das würde hier alle beteiligten interessieren... Aber nein, du wirst wieder abwiegel (so wie immer): Ist ja alles nur Hobby, und Hochsprachen haben ja ihre berechtigung, außer im MC bereich, und du wirst Code zeigen, wenn die Zeit gekommen ist, bla bla.
Kaj G. schrieb: > Du hängst dich dann an kleinigkeiten auf, "Ach, der will nur spielen!", wollt' ich gerade sagen... ;-) Das ist nur Schaumschlägerei. Da gibt's einen oben schon mal erwähnten Thread, wo einer ein paar Probleme bei der Ansteuerung eines LCD in Assembler hat. Ursache: Als Anfänger sieht man da einfach nicht durch, was man alles ändern soll, wenn man zur Steuerung mal fix ein paar Pins wechselt. Von Moby keine Spur. Wo ist das Problem, einfach mal zu erklären, was da zu beachten ist? Ich warte einfach mal. Auf meine Hinweise muss der TO dort leider noch ein bisschen warten...
Ralf G. schrieb: > Moby A. schrieb: >> Dir ist es lieber hier >> rumzustänkern ;-) > > Da ist was Wahres dran ;-)
Moby A. schrieb: > Wieviele C-Programmierer die hier klug daherreden können eigentlich Asm? Ich kann beides > Wissen die Möglichkeiten dort überhaupt einzuschätzen? Nicht nur dass, ich weiß auch wann es sinnvoll ist. > Eigentlich brauche ich mich dazu auch nur an mein erstes und einziges > C-Programm für die DOS-Kommandozeile erinnern ;-( Ich kann mich auch noch an mein erstes ASM Programm erinnern: Status-Bits, LDI geht nur für die halben Register, bedingte Sprünge, manuelles PUSH/POP... viel zu kompliziert. Wenn ich nicht weitergemacht hätte wäre das bis heute mein Bild von ASM.
Moby A. schrieb: > Ralf G. schrieb: >> Moby A. schrieb: >>> Dir ist es lieber hier >>> rumzustänkern ;-) >> >> Da ist was Wahres dran ;-) Du hast diesen ';-)' gesehen? Als ich das geschrieben habe, habe ich noch geglaubt, mit etwas Provokation dich wachzurütteln. Ich dachte wirklich, du merkst es mal, dass du dich hier zum Affen machst. Wollte dich nur vor Schlimmerem bewahren. Ich hatte mich geirrt!
Rea L. schrieb: > Nicht nur dass, ich weiß auch wann es sinnvoll ist. Diese Sinnhaftigkeit hängt auch davon ab, über welche Codebasis man verfügt. > Ich kann mich auch noch an mein erstes ASM Programm erinnern: > Status-Bits, LDI geht nur für die halben Register, bedingte Sprünge, > manuelles PUSH/POP... viel zu kompliziert. > Wenn ich nicht weitergemacht hätte wäre das bis heute mein Bild von ASM. Also ist dieses Bild von Asm jetzt positiver. Freut mich. Schau, dieses Werkzeug langt für MC völlig aus. Die Zeit und Mühe zum Beherrschenlernen von C und anderer Weiterentwicklungen kann allein in die eigentlichen Projekte fließen.
Moby A. schrieb: > Also ist dieses Bild von Asm jetzt positiver. Freut mich. Ja, nur schade dass du diese Erfahrung mit C nie machen durftest :-( > Die Zeit und Mühe zum Beherrschenlernen von C war's eindeutig wert. Auf dem PC ist ASM sowieso keine sinnvolle Option und die Zeit habe ich durch den Verzicht auf ASM-Frickelei wenn's nicht notwendig war um ein Vielfaches wieder reingeholt. PS: Wenigstens weiß ich jetzt, dass ich und viele Anderen hier wahrscheinlich auch uns in Sachen C von Mobby nichts sagen lassen müssen.
:
Bearbeitet durch User
Ich finde es interessant, wie/wenn Einer viele Andere an der langen Leine um sich herumtanzen lassen kann. Solche Egozentriker kenne ich auch. Ich meide sie.
Moby A. schrieb: > Die Zeit und Mühe zum Beherrschenlernen von C und anderer > Weiterentwicklungen kann allein in die eigentlichen Projekte fließen. Und nun stell' Dir mal vor, Du müsstest auf eine andere µC-Architektur umsteigen. Aus welchem Grund auch immer. Kein AVR mehr. Stell' Dir also vor, Du müsstest jetzt plötzlich mit MSP430, PIC oder ARM zurechtkommen. In Assembler. Wer C benutzt, und gar einen C-Compiler, der für diverse µC-Architekturen existiert, wie z.B. gcc, der muss sich in so einer Situation natürlich auch umstellen, weil er andere, anders aufgebaute Peripherie ansteuern muss, und weil er möglicherweise Dingen wie der Harvard-Architektur entrinnen kann, und er wird ein anderes Programmiergerät bzw. ein anderes Debuginterface verwenden lernen müssen, aber davon abgesehen kann er seine in das Beherschenlernen von C gesteckte Zeit einfach weiterverwenden. Du hingegen musst zusätzlich auch noch die komplett andere Maschinenarchitektur, den anderen Befehlssatz, die anderen Registersätze, gegebenenfalls die andere Assemblersyntax und die ganzen kleinen ekligen Eigenheiten der neuen µC-Architektur lernen müssen. Und algorithmisch umdenken müssen; MSP430 ist eine 16- und ARM sogar eine 32-Bit-Architektur, wo Dinge komplett anders laufen können. Da ist Dein "selbsterklärender" AVR-Assemblercode vollkommen wertlos. Gut, die Wahrscheinlichkeit, daß Atmel in absehbarer Zeit damit aufhören wird, 8-Bit-AVRs herzustellen, die ist überschaubar; aber es könnte ja auch sein, daß Du aus beruflichen Gründen mit µCs arbeiten musst. Und da wird Dir üblicherweise vom Arbeitgeber vorgegeben, womit Du arbeiten musst. Auch der Umstieg von einem C-Compiler auf einen komplett anderen (gcc zu IAR) ist keine unüberwindbare Hürde -- die Programmiersprache selbst bleibt nämlich die gleiche, nur ein paar Rahmenbedingungen ändern sich.
> Eigentlich brauche ich mich dazu auch nur an mein erstes und einziges
C-Programm für die DOS-Kommandozeile erinnern
Das ist so wie wenn der Papst dir was über Frauen erzählt.
Also nochmal es gibt was, was du nur rudimentär kennst, aber alle
anderen sind zu blöd deine Leuchtkraft zu verstehen.
Ein Fall für die Graukittel!
Carl D. schrieb: > Das ist so wie wenn der Papst dir was über Frauen erzählt. oder der Blinde von der Farbe.
Rufus Τ. F. schrieb: > Und nun stell' Dir mal vor, Du müsstest auf eine andere µC-Architektur > umsteigen. Aus welchem Grund auch immer. Kein AVR mehr. Das Schöne ist: Mein Hobby muß sich tatsächlich nicht an solchen Vorstellungen orientieren ;-) Rufus Τ. F. schrieb: > die ganzen > kleinen ekligen Eigenheiten der neuen µC-Architektur lernen müssen. Und > algorithmisch umdenken müssen; MSP430 ist eine 16- und ARM sogar eine > 32-Bit-Architektur, ... die im Falle von ARM sinnvollerweise nicht mit ASM programmiert wird. MSP430 soll diesbezüglich ja sehr entgegenkommend sein. Leider sind die AVRs für das Meiste aber schon gut genug so daß ein Umstieg vor allem eines wäre: Pure Zeitverschwendung. Rufus Τ. F. schrieb: > aber es könnte ja > auch sein, daß Du aus beruflichen Gründen mit µCs arbeiten musst. Und > da wird Dir üblicherweise vom Arbeitgeber vorgegeben, womit Du > arbeiten musst. Komplett andere Sachlage. Ja, da müsste ich wohl ob konkret sinnvoll oder nicht mit anderen MCs arbeiten- und aus Gründen der dann nötigen Portabilität auch mit Hochsprachen. So aber ist der Hobbyist in einer komfortablen Lage: Er kann das Einfachste nehmen. Und dabei bleiben. Rufus Τ. F. schrieb: > nur ein paar Rahmenbedingungen ändern sich Nur ein paar Rahmenbedingungen? Ja, solche Untertreibungen kenn ich auch aus eigener Entwicklertätigkeit: Meistens ist alles aufwendiger als man erst denkt ;-)
Lothar M. schrieb: > Solche Egozentriker Im Zentrum meiner Beiträge steht was ganz anderes: Keep it simple! Schon bemerkt? Carl D. schrieb: > aber alle > anderen sind zu blöd deine Leuchtkraft zu verstehen. > Ein Fall für die Graukittel! Geht es bei Dir nur noch auf diesem Niveau? Ist Dir das Deine wertvolle Zeit am Sonntag wert? Erstell mal mit Deiner Leuchtkraft, die ich bis jetzt nur Deinen Worten entnehmen darf ein schönes Projekt! Bislang ist Dein Name in der Projekteabteilung nur mit abwertenden Bemerkungen zu anderen Arbeiten vertreten ;-(
Da ich mittlerweile denke, wer hier zuletzt postet, hat gewonnen (Argumente scheinen genug ausgetauscht worden zu sein), fasse ich mich kurz mit: DAGEGEN (Goil, ich kann jetzt sinus auf'm AVR)
Jemand eine Ahnung warum es im Atmel Studio 6.2 zum abgebildeten Compilierfehler kommt, wenn das C-Executable Projekt im Netzwerk (NAS) liegt? Lokal funktionierts.
Hallo Yalu X., hier mal eine allererste Reaktion auf Deine freundlicherweise erstellte Version meiner Tastenauswertung. Durchaus ganz interessant, mal wieder in die C-Welt reinzuschauen, auch wenn sich meine Begeisterung bislang in argen Grenzen hält. Yalu X. schrieb: > - Die Entprellung der Tasten und die Ausführung der davon abhängigen > Aktionen (key<i>Pressed und key<i>Released) erfolgt bei mir nicht in > der Interruptroutine, sondern in der Hauptschleife des Programms (aber > trotzdem interruptgetriggert). Dadurch werden – insbesondere bei etwas > aufwendigeren Aktionen – weitere Interrupts, die vielleich später > hinzukommen – nicht unnötig blockiert. Damit wird eine wesentliche und beabsichtigte Funktion meiner Version nicht erfüllt: Die ganze Tastenauswertung im Hintergrund zu halten. Die ist im Timerinterrupt 1. recht schnell und 2. auch wenig zeit-sensibel gegenüber Verzögerungen durch weitere (i.a. schnelle) Interruptbehandlungen. Die Umsetzung als Hauptprogramm ist natürlich die einfachere Variante- dieses sollte nun aber gerade komplett frei bleiben. Ganz davon abgesehen, daß meine Hauptprogramm-unabhängige Umsetzung schon allein 8 Instruktionen zur Registersicherung verschlingt. Der Timerinterrupt enthält in meinen größeren Programmen viele Service-Aufgaben, die ein Hauptprogramm dann nur noch bedienen/anfordern muß. > - Zudem erlaubt es diese Ablaufstruktur der CPU, sich während des > Nichtstuns zwischen zwei Timer-Interrupts schlafen zu legen und damit > Strom zu sparen. Da im Hauptprogramm gar nix los ist kann "meine" CPU dort genauso schlafen... Macht dann nochmal +3 Instruktionen. > Wenn man > könnte man > Damit läge Bitte keinen Illusionen hingeben: Da hätte ich für mein in zwei Stunden entstandenen Programm auch noch so einige Ideen zum Verkleinern... ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Lothar M. schrieb: >> Solche Egozentriker > Im Zentrum meiner Beiträge qed. > Im Zentrum meiner Beiträge steht was ganz anderes: > Keep it simple! Gerade wegen C kann ich Programmschnipsel unter den 5 Prozessorwelten von 8 bis 32 Bit, in denen ich unterwegs bin, einfach austauschen. Und Code, der z.B. auf einem alten 68332 uC schon seit 20 Jahren läuft, einfach mal kurz auf einem STM32 oder auf einem AVR benchmarken. Das ist für mich simpel...
Moby A. schrieb: > Bitte keinen Illusionen hingeben: Da hätte ich für mein in zwei Stunden > entstandenen Programm auch noch so einige Ideen zum Verkleinern... ;-) Zeigen, nicht schwätzen. Du bist ein Blender - nichts weiter.
Lothar M. schrieb: > Gerade wegen C kann ich Programmschnipsel unter den 5 Prozessorwelten > von 8 bis 32 Bit, in denen ich unterwegs bin, einfach austauschen. Mir fehlt zwar nun jede Vorstellung, welchen Sinn ein solcher Austausch denn haben könnte (doch nicht etwa nur Benchmarking?), aber wenn man den braucht macht es C natürlich simpler. Gar keine Frage. Wenn man seit Jahr und Tag mit einfachen AVRs auskommt sieht die Welt ganz anders aus. Da wird der hier groß beworbene Portabilitäts-Vorteil schlicht eines: Hinfällig! Frank M. schrieb: > Zeigen, nicht schwätzen. Für Dich gilt hier leider bislang nur letzteres ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Lothar M. schrieb: >> Solche Egozentriker > Im Zentrum meiner Beiträge Jetzt handelt es sich auch schon um eine multiple Persönlichkeit. Wenn ich das lese, dann steht da "Horst S.". Man erwirbt kein Eigentum an Beträgen die man sich ungefragt aneignet!
Carl D. schrieb: > Man erwirbt kein Eigentum an Beträgen die man sich ungefragt aneignet! Richtig giftig kann er werden, der Carl D. Wie hoch man doch Eigentumsfragen aufhängen kann ;-) Gibt es nichts Wichtigeres für Dich heut abend?
:
Bearbeitet durch User
Moby A. schrieb: > Mir fehlt zwar nun jede Vorstellung, welchen Sinn ein solcher Austausch > denn haben könnte Meine ersten C Programme entstanden in den 80ern auf VAX, 68000 und DOS-PC (davor waren es andere Sprachen), munter durcheinander. Dann kam Inmos Transputer hinzu, in 16- wie in 32-Version, später diverse anderen x86 Bitbreiten. Um nur die wichtigsten zu nennen. Bei einigen davon war auch Assembler dabei, keine Sorge. Manche C Programme und Programmteile migrierten in den Jahrzehnten durch etliche dieser Systeme und auch durch etliche Betriebssysteme. Mit den Mikrocontrollern waren dann AVR und ARM Original/Thumb/Thumb2 mit dabei, testweise auch mal 8-Bit und 16-Bit PICs. Auch hier ist mir jedoch Assembler durchaus vertraut. Kannst du dir vorstellen, dass Portabilität dabei einen Reiz hat?
:
Bearbeitet durch User
A. K. schrieb: > Kannst du dir vorstellen, dass Portabilität dabei einen Reiz hat? In dieser Gemengelage? Absolut. Da ist Portabilität ja geradezu essentiell... Wenngleich ich mir nicht vorstellen kann daß der über die Jahre mitgeschleifte Code auf verschiedenen Architekturen immer gleichermaßen "frisch" und effizient bleibt. Gerade bei hardwarenaher MC-Programmierung.
:
Bearbeitet durch User
Die krassteste Variante: Diplomarbeit zu Hause auf 68000 (32bit) entwickeln und an der Uni sowohl auf DOS-PC (16bit) als auch Transputer (32bit) zu Ende entwickeln und einsetzen.
Moby A. schrieb: > Gerade bei hardwarenaher MC-Programmierung. Ich habe einen recht guten Sinn dafür, was bei C Code ungefähr hinten rauskommt. Das ergibt sich von selbst, wenn du selber ein Bisschen an Compilern rumgebaut hast. Umgekehrt führt das freilich dazu, dass ich mir die häufiger genutzten Architekturen etwas danach aussuche, wie gut sich C darauf abbilden lässt. Ausreisser wie 8-Bit PIC (schaurig) sind da nur als Spass am Rande beteiligt.
A. K. schrieb: > Die krassteste Variante Verständlich, ja. Nur, was hat das jetzt mit C vs. Asm auf AVR zu tun?
Moby A. schrieb: > Verständlich, ja. Nur, was hat das jetzt mit C vs. Asm auf AVR zu tun? Es ist immer das gleiche C. Aber jedesmal ein anderes Asm. Da hat man dann beispielsweise eine Funktion rprintf() für formatierte Zahl/Stringausgabe, die ein stark eingedampftes printf() darstellt und viel weniger Platz braucht. Auf allen µC-Plattformen der gleiche Code.
:
Bearbeitet durch User
A. K. schrieb: > Umgekehrt führt das freilich dazu, dass ich mir die häufiger genutzten > Architekturen etwas danach aussuche, wie gut sich C darauf abbilden > lässt. Und da kommen sicher auch die AVRs in Frage... A. K. schrieb: > Es ist immer das gleiche C. Aber jedesmal ein anderes Asm. Auf verschiedenen Architekturen. Deren Notwendigkeit für viele Zwecke diskutabel ist.
Moby A. schrieb: > Und da kommen sicher auch die AVRs in Frage... Ja. Nicht ohne Kritik freilich, denn die der Sprache C fremde Adressraumtrennung ging mir angesichts des recht hässlichen Ersatzcodes mächtig auf den Senkel. Erst in neuerer Zeit wurde das besser (dank __flash). Diese in Programmen jenseits der kleinen Tinys unbefriedigende Situation führte mich dann auch zu dem ARM Varianten, ab ARM7/LPC2000. Mit eigenem Startup-Code in Asm um bei Interrupts weniger Zirkus in C zu haben. War ein Projekt dabei, das ich mit 2 kooperierenden µCs implementierte, Mega32 in C und Tiny2313 in Assembler. Asm deshalb, weil ich beides dabei haben wollte. >> Es ist immer das gleiche C. Aber jedesmal ein anderes Asm. > Auf verschiedenen Architekturen. Ja, gleicher Quellcode. > Deren Notwendigkeit für viele Zwecke diskutabel ist. Ich habe keinen Horror vor neuen Architekturen. Ist sogar andersrum - immer die gleiche Basis langweilt mich und als Hobbyist kann ich mir diese Neugierde leisten.
:
Bearbeitet durch User
Moby A. schrieb: > Durchaus ganz interessant, mal wieder in die C-Welt reinzuschauen, > auch wenn sich meine Begeisterung bislang in argen Grenzen hält. Wenn ich ganz ehrlich bin, habe ich auch gar keine Begeisterungsstürme von dir erwartet ;-) > Damit wird eine wesentliche und beabsichtigte Funktion meiner Version > nicht erfüllt: Die ganze Tastenauswertung im Hintergrund zu halten. > Die ist im Timerinterrupt 1. recht schnell und 2. auch wenig > zeit-sensibel gegenüber Verzögerungen durch weitere (i.a. schnelle) > Interruptbehandlungen. Die Tastenentprellung an sich braucht nicht viel Zeit, das ist richtig. Aber die keypress-Funktionen, die du daraus aufrufst, können durchaus etwas aufwendiger werden, wenn sie in einer realen Anwendungen über das bloße Ein- und Ausschalten von ein paar LEDs hinausgehen. Ein sinnvoller Kompromiss wäre, die Entprellung und die Messung der Dauer in der Interruptroutine und den Rest im Vordergrund laufen zu lassen. Aber auch in der vorliegenden Form erfüllt mein Programm eine Vorgaben, die da lauten: Moby A. schrieb: > Das Angebot zum kürzeren Formulieren der beschriebenen Funktionalität > in C steht nach wie vor... Dabei muß man sich auch nicht an meiner > Programmlogik orientieren. Die Funktionalität ist die gleiche wie bei deinem Programm, die Unterschiede liegen nur in der Art und Weise der Implementierung. > Ganz davon abgesehen, daß meine Hauptprogramm-unabhängige Umsetzung > schon allein 8 Instruktionen zur Registersicherung verschlingt. Die Registersicherung ist unnötig, da im Hauptprogramm nach dem Aktivieren des Interrupts nur eine Leerschleife ausgeführt wird. Um wirklich hauptprogrammunabhängig zu sein, genügt es auch nicht, die Register einfach nur in andere Register umzukopieren, da diese ja genauso vom Hauptprogramm überschrieben werden können. Die einzig wirklich unabhängige Registersicherung ist die auf den Stack. Um aber vergleichbare Verhältnisse zu schaffen, darfst du von deinen 266 Bytes die 16 Bytes für die Registersicherung abziehen. Damit liegst jetzt mit 250 zu 256 Bytes wieder knapp vorn. Zufrieden? > Da im Hauptprogramm gar nix los ist kann "meine" CPU dort genauso > schlafen... Macht dann nochmal +3 Instruktionen. Ah, damit musst du natürlich wieder 6 Bytes hinzuaddieren, und es steht jetzt final
1 | 256 : 256 |
also unentschieden. Ich kann mit diesem Ergebnis sehr gut leben, du auch? Und Moby, jetzt mal ganz unter uns: Selbst wenn das C-Programm 300 oder gar 400 Bytes belegen würde, würde ich einen Teufel tun, es in Assembler umschreiben. Denn die 400 Bytes sind gerade einmal lausige 5% des Flash-Speichers des ATmega88. Mit den restlichen 95% kann man in C noch so viele nützliche Dinge erledigen, an die du als Assemblerprogrammierer gar nicht zu denken wagst, weil das deine Arbeitsweise schlicht und ergreifend nicht hergibt. Aber Programme in dieser Größenordnung sind ja deiner Ansicht nach sowieso keine "typischen 8-Bit-Anwendungen" mehr und sollten deswegen gar nicht erst in Erwägung gezogen werden ;-) Und dass man für eine halben Euro mehr einen ATmega168 mit der doppelten und für einen ganzen Euro mehr sogar einen ATmega328 mit der vierfachen Flash-Kapazität bekommt, kann nur auf einen Fehler der Produktmanager bei Atmel zurückzuführen sein. Mach einfach weiter so, wie du es schon immer getan hast, und vermeide es geflissentlich, irgendetwas Neues dazuzulernen, aber versuche bitte, bitte nicht immer wieder, auch andere von dieser Lebensphilosophie zu überzeugen.
:
Bearbeitet durch Moderator
A. K. schrieb: > Ist sogar andersrum - > immer die gleiche Basis langweilt mich und als Hobbyist kann ich mir > diese Neugierde leisten. Genau das allerdings ist absolut legitim. Genau das kann man problemlos akzeptieren. Mein Punkt ist aber ein ganz anderer: Mich interessiert zuerst die simple Lösung. Erst dann die Wege dahin. Fazit: AVR und Asm reichen (noch lange). Da steckt jede Menge Power drin.
A. K. schrieb: >> Und da kommen sicher auch die AVRs in Frage... > > Ja. Nicht ohne Kritik freilich, Atmel nehme ich beispielsweise persönlich übel, dass sie bis heute keinen Befehl für atomare Manipulation des Stackpointers eingebaut haben. Das ist geradezu Sabotage an C, wenn man nicht grad IAR heisst und Var-Stack und Return-Stack trennt.
Moby A. schrieb: > Lothar M. schrieb: >> Gerade wegen C kann ich Programmschnipsel unter den 5 Prozessorwelten >> von 8 bis 32 Bit, in denen ich unterwegs bin, einfach austauschen. > Mir fehlt zwar nun jede Vorstellung, welchen Sinn ein solcher Austausch > denn haben könnte Entwicklung und Test auf dem PC und anschließender Einsatz auf einem 68332 uC ist sinnvoll. Es gibt eben mitnichten nur 1 uC Familie und wenn man eine portable Programmiersprache kennt, dann traut man sich eher mal einen Wechsel auf einen, der optimale Ressourcen mitbringt. Und zwängt sich und sein Design nicht unbedingt in die einzige uC Familie deren Assembler man gerade kennt...
Yalu X. schrieb: > genügt es auch nicht, die > Register einfach nur in andere Register umzukopieren, da diese ja > genauso vom Hauptprogramm überschrieben werden können. Das ist eine Frage der Konvention. R10-R15 sind für schnelle Interruptbehandlung reserviert. Und ich habe diese "minderwertigeren" Register auch noch nicht vermisst. Stacksicherung kostet Flash, RAM und dauert. > Ein sinnvoller Kompromiss wäre, die Entprellung und die Messung der > Dauer in der Interruptroutine und den Rest im Vordergrund laufen zu > lassen. Du mußt die von mir angestrebte totale Unabhängigkeit von solchen "Serviceaufgaben" etwas weiter gefaßt sehen. Als Konzept, was Aufgaben trennt, Nebenwirkungen beseitigt, Übersichtlichkeit schafft. Was weniger auf Ressourcensparung denn aufs Möglichmachen komplexerer Programme abzielt. > Ich kann mit diesem Ergebnis sehr gut leben, du auch? Natürlich nicht, weil da noch eine Menge drin ist. Ich möchte allerdings Deine Zeit auch nicht unnötig in Beschlag nehmen. Eine weiter optimierte Version kommt auf alle Fälle noch in die Projekte und Dein Programm wird auf Herz und Nieren geprüft. Die einzige C-Kreatur, die je meine AVR Flash-Speicher bevölkerte ;-) > Mit den restlichen 95% kann man in C noch > so viele nützliche Dinge erledigen, an die du als Assemblerprogrammierer > gar nicht zu denken wagst, weil das deine Arbeitsweise schlicht und > ergreifend nicht hergibt. Sinn und Zweck des Programmierens ist nicht, 100% vollzucodieren, sondern mit Asm viel Platz für a) Erweiterungen und b) Daten aller Art zu haben oder vielleicht mit einem kleinen Tiny statt Mega auszukommen... > Aber Programme in dieser Größenordnung sind ja deiner Ansicht nach > sowieso keine "typischen 8-Bit-Anwendungen" mehr und sollten deswegen > gar nicht erst in Erwägung gezogen werden ;-) Wo hast Du die Größenbeschränkung typischer 8-Bit Anwendungen aufgeschnappt? Meine größte hat 18KB optimierten Reincode und leistet eine Menge. Das ist längst noch nicht vollendet bzw. problemlos erweiterbar. > auch andere von dieser Lebensphilosophie zu > überzeugen. Hier gehts nicht um Lebensphilosophie sondern Fakten, Fakten, Fakten.
:
Bearbeitet durch User
>Hier gehts nicht um Lebensphilosophie sondern Fakten, Fakten, Fakten. Nein Moby. Die ignorierst Du. >Sinn und Zweck des Programmierens ist nicht, 100% vollzucodieren, >sondern mit Asm viel Platz für a) Erweiterungen und b) Daten aller Art >zu haben oder vielleicht mit einem kleinen Tiny statt Mega >auszukommen... Cleverer aus Deiner Sicht wäre es gewesen, mindestens das "mit Asm" wegzulassen. Aber trotzdem. Diese Aussage war sehr interessant. Wenn ein µC eine bestimmte Funktion übernehmen soll, geht es dir als Ziel darum ASM zu nutzen. Ok. Allen anderen hier geht es darum, diese Funktion mit möglichst geringem zeitlichen Aufwand umzusetzen. Das ist der Unterschied und deshalb wirst du die Vorteile von Hochsprachen (egal welche) nie verstehen. Du hast ja zugegeben, das du deine Zeit damit verplemperst, Schleifen in asm selbst zu bauen, anstatt einfach for(...) hinzuschreiben und zu wissen, das funktioniert. Das erklärt auch diese Aussage: >> Ich kann mit diesem Ergebnis sehr gut leben, du auch? >Natürlich nicht, weil da noch eine Menge drin ist. >Ich möchte allerdings Deine Zeit auch nicht unnötig in Beschlag nehmen. >Eine weiter optimierte Version kommt auf alle Fälle noch in die Projekte Welchen sinnvollen Grund gäbe es, da noch weiter rumzufrickeln? Das Programm tut was es soll, es passt in den Flash und fertig. Wenn jetzt zwei Bytes weniger vom Flash verwendet wurden... wen interessierts?
A. K. schrieb: > die der Sprache C fremde Adressraumtrennung Witzigerweise gab es die PDP-11 ja auch mit "Split I&D", was damals den effektiven Adressraum (pro Task) verdoppelt hat. So fremd ist das also eigentlich für C gar nicht … Problem beim AVR ist ja nur, dass konstante Daten auf diese Weise sowohl Platz im RAM als auch Flash brauchen würden. Das war bei der PDP-11 nicht so das Thema, denn an welcher Stelle der Platte nun die vorzuladenden Konstanten liegen, ist da ziemlich schnuppe.
Jörg W. schrieb: > Witzigerweise gab es die PDP-11 ja auch mit "Split I&D", was damals > den effektiven Adressraum (pro Task) verdoppelt hat. Konnte man auf der PDP-11 explizit Daten im I-Space adressieren? Denn nur dann wäre das vergleichbar. Andernfalls hat man damit nur das normale und unproblematische AVR Datenmodell, bei dem alle Daten im RAM liegen und ggf. vom Startupcode aus dem Flash ins RAM kopiert werden. Oder eben vom Loader des Betriebssystem aus dem Exe-File in den D-Space. Trennung von Funktions- und Datenadressen war nie ein Problem. Mehrere getrennte Datenadressräume aber schon.
:
Bearbeitet durch User
A. K. schrieb: > Konnte man auf der PDP-11 explizit Daten im I-Space adressieren? Meiner Erinnerung nach gab es ein "move from previous instruction space" oder dergleichen … yep: https://en.wikipedia.org/wiki/PDP-11_architecture
1 | 0065 MFPI Move from previous I space: −(SP) = src |
2 | 1065 MFPD Move from previous D space: −(SP) = src |
3 | 0066 MTPI Move to previous I space: dest = (SP)+ |
4 | 1066 MTPD Move to previous D space: dest = (SP)+ |
Ja, schon klar, das Problem beim AVR entsteht ja nur dadurch, dass alle Konstanten naturgemäß in einem der beiden Adressräume liegen müssen (im Flash), und dass es daher wünschenswert ist, sie gleich in diesem Adressraum als Daten ansprechen zu können. Trotzdem ist es natürlich allemal kurios, dass C eigentlich auf einer Harvard-Maschine gewachsen ist, sie uns (aufgrund der Randbedingungen) dennoch beim AVR dann so viele Bauchschmerzen bereitet.
:
Bearbeitet durch Moderator
Jörg W. schrieb: > Meiner Erinnerung nach gab es ein "move from previous instruction > space" oder dergleichen … yep: Nur sind diese Befehle eigentlich dafür gedacht, den Useradressraum durch Kernelcode ansprechen zu können. Ausserdem lese ich in einem Handbuch von 1979: "When MFPI is executed and both previous mode and current mode are User, the instruction functions as though it were MFPD.". MFPI ist demzufolge nicht geeignet, um in User-Programmen auf den eigenen I-Space zuzugreifen.
:
Bearbeitet durch User
A. K. schrieb: > MFPI ist demzufolge nicht geeignet, um in User-Programmen auf den > eigenen I-Space zuzugreifen. Ah, OK. Solche Details waren mir nicht mehr bewusst. Damit ist natürlich klar, dass für ein normales User-Programm in der Tat beide Adressräume völlig getrennt waren.
Jörg W. schrieb: > Trotzdem ist es natürlich allemal kurios, dass C eigentlich auf einer > Harvard-Maschine gewachsen ist, sie uns (aufgrund der Randbedingungen) > dennoch beim AVR dann so viele Bauchschmerzen bereitet. Das Problem ist ja weniger die Harvard-Architektur an sich, sondern beim AVR die Harvard-Architektur in Kombination mit der Verwendung des Programmspeichers als alleinigen nichtvolatilen Speicher (neben dem EEPROM, das sich aber ebensowenig für direkte Datenzugriffe eignet). Bei einem klassischen Computer sind beide Adressräume mit RAM belegt, und die nichtvolatilen Daten werden von einem externen Massenspeicher geladen. Damit belegen die Const-Daten in den CPU-Adressräumen nur einmal Platz. Dass diese Daten zusätzlich auch noch Platz auf dem Massenspeicher brauchen, stört nicht so sehr.
Moby A. schrieb: > Karl H. schrieb: >> Aber erst mal muss er den Fehdehandschuh aufgreifen. Mal sehen, obs so >> kommt wie es immer kommt, wenn ich sowas anbiete :-) > > Den greife ich natürlich nicht auf, weil ich für solche Späße keine Zeit > investiere. Schade. Mit handfesten konkreten Argumenten hätte ich mich überzeugen lassen :-) Aber eigentlich hab ich auch nichts anderes erwartet. > Ja, da müsste ich wohl ob konkret sinnvoll oder nicht mit anderen > MCs arbeiten- und aus Gründen der dann nötigen Portabilität auch > mit Hochsprachen. So aber ist der Hobbyist in einer komfortablen Lage: > Er kann das Einfachste nehmen. Und dabei bleiben. Nur ist aber gerade für eine Hobbyisten Assembler nicht "das Einfachste". Es gibt viel zu viele Fallstricke, in denen er sich stunden- oder tagelang verfangen kann, und die ihm ein Compiler locker und problemlos abnehmen kann. Du widersprichst dir ständig selbst und merkst es noch nicht einmal. Du du gefragt hast, wer hier aller Assembler kann: So ziemlich die meisten der regelmässig hier Helfenden. Meiner einer inklusive. Ist zwar schon teilweise lange her, aber Z80, IBM360, VAX, 68000 und (no, na) AVR Assembler ist keineswegs wie du zu denken scheinst, ein Buch mit 7 Siegeln. Die meisten, die heute Hochsprachen einsetzen können passabel bis gut Assembler. Und gerade weil sie das oft und lange genug gemacht haben, benutzen sie heute eine "Hochsprache". Wobei man diskutieren kann, an welcher Stelle der Skala "Assembler -> Hochsprache" C tatsächlich anzusiedeln ist. Ist schon lustig: auf der einen Seite lehnst du jegliche Demonstration der vermeintlichen Vorteile ab, weil du die Zeit dafür nicht hast. Und auf der anderen Seite lehnst du alle Hilfen ab, die dir massiv Zeit in der Entwicklung einsparen könnten ohne dass du etwas dafür bekommst. Ich hab hier im Forum schon so manchem sein Programm mehr oder weniger brennfertig geschrieben. Das geht, weil ich das zwischen ein paar Compilerläufe in meiner eigentlichen Arbeit einschieben kann. In Assembler würde ich das nie machen, weil das (wie du richtig sagst) viel zu zeitaufwändig und auch viel zu fehleranfällig wäre. Und da gehst noch nicht mal darum, irgendeine Behauptung mit Fakten zu stützen oder zu beweisen, sondern rein um den Spass an der Freude. Komisch: die C Programmierer können das, die Assembler Programmierer anscheinend nicht. Zumindest hat sich noch nie ein militanter Assembler-über-alles Verfechter auf einen derartigen Wettstreit eingelassen. Ob uns das was sagen sollte?
:
Bearbeitet durch User
Karl H. schrieb: > Komisch: die C Programmierer können das, die Assembler Programmierer > anscheinend nicht. Weils einfach viel zu viel Arbeit ist, sich in ein ellenlanges (fremdes) Assembler-Programm einzulesen, um es zu verstehen, den Fehler zu finden und es darüber hinaus auch noch zu fixen. > Zumindest hat sich noch nie ein militanter > Assembler-über-alles Verfechter auf einen derartigen Wettstreit > eingelassen. Ob uns das was sagen sollte? Er weiß genau, dass er verliert.
Frank M. schrieb: > Er weiß genau, dass er verliert. Gewonnen hat zuallererst eins: Die funktionierende Lösung. An den Vorteilen von Asm gibts nichts zu deuteln. Karl H. schrieb: > Schade. Mit handfesten konkreten Argumenten hätte ich mich überzeugen > lassen :-) Wie scheinheilig ;-) Du hast nämlich auch so die Möglichkeit das Gegenteil zu beweisen. Da war ein anderer Mod hier aber ehrlicher. > Aber eigentlich hab ich auch nichts anderes erwartet. Nun, ich auch nicht. > Nur ist aber gerade für eine Hobbyisten Assembler nicht "das > Einfachste". Es gibt viel zu viele Fallstricke, in denen er sich > stunden- oder tagelang verfangen kann, und die ihm ein Compiler locker > und problemlos abnehmen kann. Also ich hab mehr Overhead in Gestalt von Compilern und und den vielen Hochsprachelementen in der AVR-Entwicklung nie vermisst. > Du du gefragt hast, wer hier aller Assembler kann: > So ziemlich die meisten der regelmässig hier Helfenden. Meiner einer > inklusive. Dann auf gehts Karl Heinz. In der Codersammlung wartet schon mein nächstes Projekt. Das ist eine wirklich ganz ganz einfache Ausgabe eines seriellen Datenstroms. Mach das kürzer. Mach es schneller. So hocheffizient und zeitsparend die C-Entwicklung ja sein soll- dann ist das doch schnell erledigt! > Ist schon lustig: auf der einen Seite lehnst du jegliche Demonstration > der vermeintlichen Vorteile ab, weil du die Zeit dafür nicht hast. Diese Deine Demonstration lehne ich gewiss nicht ab und auch Mod Yalus Programm ist mir eine genaue Analyse wert. > Zumindest hat sich noch nie ein militanter > Assembler-über-alles Verfechter auf einen derartigen Wettstreit > eingelassen. Ob uns das was sagen sollte? Also erstens bin ich nicht militant sondern ein äußerst friedfertiger Mensch. Zum anderen läuft Dein großspuriger Wettstreit auf die bloße Demo von Zeitersparnis und ggf. noch ein paar Asm-Rechenschwächen hinaus. Daß die Demonstration von Codeersparnis und mehr Speed idealerweise zugunsten von Asm ausfallen muß wirst auch Du wissen. Ggf. spekulierst Du aber noch mit ein paar meiner Flüchtigkeitsfehler ;-)
Moby A. schrieb: > In der Codersammlung wartet schon mein nächstes Projekt. > Das ist eine wirklich ganz ganz einfache Ausgabe eines seriellen > Datenstroms. Mach das kürzer. Mach es schneller. Sag mal, willst Du uns verarschen? Was hast Du an Nicht-Blink-LED-Level nicht verstanden? Kanst Du nur solche Micky-Maus-Programme, die keiner braucht?
Frank M. schrieb: > Sag mal, willst Du uns verarschen? Was hast Du an Nicht-Blink-LED-Level > nicht verstanden? > > Kanst Du nur solche Micky-Maus-Programme, die keiner braucht? Ich merk schon auf dieses Deine Niveau und diese Deine Absichten ist es nicht weiter wert einzugehen. Vermutlich ist Dir Dein IRMP zu Kopf gestiegen... Warte mal auf mein nächstes Projekt. Da wird gezeigt wie eine simple IR-Ausgabe ausschauen kann ;-)
>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >zugunsten von Asm ausfallen muß wirst auch Du wissen Das hat auch nie jemand hier bestritten. >Mach das kürzer. Mach es schneller. Das ist in Hochsprachen ganz einfach. Wärend da einfach
1 | uint16_t u16Loop = 0; |
2 | while ( u16Loop < 12345 ) |
3 | {
|
4 | ..
|
5 | u16Loop++; |
6 | }
|
in zehn Sekunden hingeschrieben ist, benötigst Du wielange dafür? Ein Testen der reinen Schleife ist auch nicht nötig. Sie funktioniert dank Compiler immer, egal wie das Konstrukt "Schleife" beschaffen ist. Du in ASM musst viel Zeit investieren, um die Infrastruktur (die Schleife) erstmal zu erzeugen und zum laufen zu bekommen. GEschweige denn, das was in der Schleife geschehen soll. "höhere" Hochsprachen wie C#/C++ gehen ja noch weiter und bieten ein
1 | for each ( arrray... ) |
2 | {}
|
wo über ein komplettes Array iteriert werden kann. Egal wie das Array beschaffen ist. Schaffst Du das auch in ASM in zwei Sekunden hinzuschreiben, was über jedes beliebige Array läuft, egal welchen Typs/Länge das Array hat?
Moby A. schrieb: > Daß die Demonstration von Codeersparnis und mehr Speed idealerweise > zugunsten von Asm ausfallen muß wirst auch Du wissen. ??? Kapier ich nicht, das ist doch hier jetzt des öfteren widerlegt worden. Langsam wirst du albern.
Moby A. schrieb: > Warte mal auf mein nächstes Projekt. Da wird gezeigt wie > eine simple IR-Ausgabe ausschauen kann ;-) Ich hoffe, Du verstehst unter einer "simplen IR-Ausgabe" nicht, dass Du nun eine IR-LED statt einer normalen LED blinken lässt. Das wäre nicht witzig, sondern eher ein Witz. Also: Korrekte Modulation und ein echter IR-Code (z.B. NEC), mit dem man ein real existierendes Gerät schalten kann? Das ist schon interessanter.
Muss mich hier im Augenblick wieder verabschieden... Nicht gleich als Rückzug missverstehen Karl Heinz ;-) Melde mich später wieder und gehe auf weitere Beiträge ein. Der Diskussionsbedarf scheint endlos ;-(
Moby A. schrieb: > Warte mal auf mein nächstes Projekt. Nö, Moby. Wir warten nicht, sondern machen inzwischen lieber an unseren eigenen, nicht-simplen Projekten weiter. Vielleicht finde ich ja endlich mal Zeit, die Bediensteuerung meiner PTS250 zu Ende zu bekommen. Die Backends (Ansteuerung eines VFD, Ansteuerung einer kleinen Matrixtastatur, Ansteuerung der PTS250 selbst über speicheradressierte parallele Schieberegister) sind alle schon da, aber die Bedienerführung braucht noch ein bisschen Gehirnschmalz, bevor man überhaupt ans Programmieren gehen kann.
900ss D. schrieb: > Moby A. schrieb: >> Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >> zugunsten von Asm ausfallen muß wirst auch Du wissen. > > ??? Kapier ich nicht, das ist doch hier jetzt des öfteren widerlegt > worden. Langsam wirst du albern. Matthias L. schrieb: >>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >>zugunsten von Asm ausfallen muß wirst auch Du wissen > > Das hat auch nie jemand hier bestritten. So, das musste noch sein ;-)
Moby A. schrieb: > Matthias L. schrieb: >>>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >>>zugunsten von Asm ausfallen muß wirst auch Du wissen >> >> Das hat auch nie jemand hier bestritten. > > So, das musste noch sein ;-) Und den Rest ignorierst Du mal wieder?
Matthias L. schrieb: > Und den Rest ignorierst Du mal wieder? Er liest nur das, was er lesen will. Die Rosinen - auch wenn sie stinken wie die Pest - reichen ihm.
Matthias L. schrieb: >>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >>zugunsten von Asm ausfallen muß wirst auch Du wissen > > Das hat auch nie jemand hier bestritten. Verstehe ich nicht Matthias. Ist doch hier bewiesen worden, dass C-Code sogar kürzer sein kann. Nur in den aufgeführten Beispielen, kann man natürlich nicht für alle Fälle annehmen. Moby A. schrieb: > So, das musste noch sein ;-) Ja der Widerspruch ist natürlich ein gefundenes Fressen für dich. Ist irgendwie billig, aber gönn ich dir. :-) Trotzdem ist eine pauschale Aussage bzgl. Codegröße einfach quatsch. Aber ich will da mal lieber nicht näher drauf eingehen Moby, du siehst nur, was du sehen willst. Machst dir aber sicher das Programmier-Leben schwer, was du natürlich nicht weißt, weil du die "anderen" Seite nicht kennst und deshalb nicht beurteilen kannst. Dass du C nicht verstehst und du deshalb ASM bevorzugst, weil du auch keine Zeit investieren willst, C zu verstehen, ok ist deine Entschweidung. Aber deine Mission hier ist deshalb auch wirklich über und dir fehlt dafür die Kompetenz. Nimm das Beispiel von Yalu oben und arbeite es durch. Du wirst viel lernen und vielleicht bringt es dich dahin, das C auch für deine Projekte durchaus eine gute Wahl sein könnte. Nein, wir hier brauchen ASM nicht lernen, wie schon beschrieben, können es die meisten ausreichend gut (ich auch).
Jörg W. schrieb: > sondern machen inzwischen lieber an unseren eigenen, nicht-simplen > Projekten weiter. Ich mache aber auch kurz mal zwischendurch ein simples Programm... ;-) Moby A. schrieb: > Daß die Demonstration von Codeersparnis und mehr Speed idealerweise > zugunsten von Asm ausfallen muß wirst auch Du wissen. Und wenn dieses Ideal vom Assemblerprogrammierer nicht erreicht wird, weil der Assemblerprogrammierer schon nicht ideal programmieren kann? Oder wenn mehr Speed bedeutet, einen Tag/Woche/Monat früher und damit rechtzeitig fertig zu sein? > Daß die Demonstration von Codeersparnis und mehr Speed idealerweise > zugunsten von Asm ausfallen muß wirst auch Du wissen. Klar stimmt das, weil sogar das optimalste C Programm, das sogar besser ist als das beste vom Assemblerprogrammierer programmierte Assemblerprogramm, leicht in Assembler überführt werden kann. Und damit wäre für diesen überoptimalen C-Compiler bestenfalls Gleichstand erreichbar, weil es ja immer ein gleich gutes Assemblerprogramm gibt. Ergo: dieses Argument ist unsinnig.
Lothar M. schrieb: > Ergo: dieses Argument ist unsinnig. Yep. Man muss die Frage etwas anders formulieren: Nicht ob in C kürzere Programme erstellt werden können als in Asm, sondern ob C-Programmierer kürzere oder schnellere Programme zustande bringen als Asm-Programmierer. Also Asm-Programmierer, die nicht klammheimlich Code vom Compiler abschreiben. ;-)
:
Bearbeitet durch User
A. K. schrieb: > Yep. Man muss die Frage etwas anders formulieren: Nicht ob in C kürzere > Programme erstellt werden können als in Asm ... Ich würde in diese Frage unbedingt einschließen, wer schneller fertig ist, und ob jemand anders den geschriebenen Code nachvollziehen und ändern/anpassen/ergänzen/erweitern kann. Denn darum geht es im richtigen Leben. Was bringt mir der optimalste Code, wenn das Programm erst nach Markteinführung fertig ist, oder wenn ich nach dem Weggang des Programmierers das Programm neu schreiben muss?
:
Bearbeitet durch Moderator
Matthias L. schrieb: >>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >>zugunsten von Asm ausfallen muß wirst auch Du wissen > > Das hat auch nie jemand hier bestritten. Ja das Potential hat ASM freilich, aber zu welchen Preis? Das man mit ASM nicht automatisch das bessere oder gar das beste Ergebnis erzielt, hat dieser Thread eindeutig bewiesen. Nein, dazu braucht man Erfahrung, leider kann bei ASM gelerntes Wissen nicht einfach so auf andere Architekturen Übertragen, und man muss eine Menge Arbeit hineinstecken. Für mich persönlich stimmt da einfach nicht mehr das Kosten/Nutzen Verhältnis, auch als Hobbyist der die Zeit hätte. Mit C bin ich schneller fertig und der Frustfaktor ist geringer. Mit dem Compiler kann ich ohnehin kaum mithalten. ASM wird erst wieder interessant, wenn ich wirklich alles aus der Maschine rausholen muss. Wie z.B. wenn der AVR ein BAS Signal generieren muss (Zeitkritisch, Takte zählen!) oder wenn der x86 Bootloader noch in die 420 Byte des ersten Sektors (FAT32) passen muss. Das hat seinen Reiz. Aber wenn es darum geht ein paar Cent für den nächst größeren µC zu sparen ist mir das einfach zu blöd (wenn Hochsprache gleich größerer Ressourcenverbrauch überhaupt gelten würde). Früher dachte ich immer Moby wäre ein Experte in Sachen ASM und arbeitet an anspruchsvollen Projekten, wo jedes Byte und jeder Takt zählt. Denn dann wäre seine Einstellungen noch irgendwo nachvollziehbar, auch wenn er eine Menge Unsinn über Hochsprachen behauptet. Doch dann lässt er sich bei dem 32-Bit Vergleich vom Compiler locker schlagen und sagt sowas wie "Überlaufrumärgern ist mir bislang fremd." etc. . Da kommt mir der Eindruck, dass die Komplexität seiner Programme gegen Null konvergiert. Das endet dann in völliger Unverständnis, wenn man sich ansieht, was er die letzten Jahre hier alles so für Aussagen und Behauptungen abgelassen hat. Er verlangt immer Fakten, doch schafft er selbst keine, höchstens welche die gegen ihn sprechen.
Über die Code-Geschwindigkeit kann man in Ausnahmefällen ja noch streiten, aber über die Codegröße? In meinen Programmen macht der eigendliche Code vielleicht 30% aus, der Rest sind Texte, Fonts, Graphiken, etc. Ob der Code dann am Ende 25% oder 35% ausmacht, ist sowas von irrelevant. Was die Wiederverwertbarkeit angeht: wenn ich eine Graphik-Lib für ein 128*64-LCD habe und dieses auf ein320*240-LCD portieren will, dann ändere ich in C den Index von uint8_t auf uint16_t. In Asm darf ich im besten Fall die komplette Lib neu schreiben. Im schlechtesten nicht, weil mein Chef mich vorher entlässt. Als ich vor ca. 15 Jahren von Asm auf C umgestiegen bin, da war das eine Erleuchtung. Die Rate der schweren Fehler ist schlagartig um 90% gesunken, und die Produktivität ist extrem gestiegen. Daß das nicht nur mir so geht, kann man selbst in diesem Thread sehen, siehe Mobys Asm-Beispiel. Sehr merkwürdig finde ich immer wieder, daß nur noch Hobby-Programmierer die Asm-Fahne hochhalten. Wenn ich alle Monate einen Chip brauche, dann ist es mir egal, ob ich den xxx8kbyte oder den yyy16kbyte für 0.25€ mehr einkaufe. In der Industrie, wo es oft um hohe Stückbzahlen geht, würde dagegen niemand im Traum auf die Idee kommen, in Asm zu schreiben, um damit <vielleicht> kleineren Code zu produzieren. Gruß, Stefan
Christopher C. schrieb: > Er verlangt immer Fakten, doch schafft er selbst keine, höchstens welche > die gegen ihn sprechen. Dabei wäre es ja ein Leichtes gewesen, passend zum Thema des Threads Horst mit einem optimierten Assemblerprogramm zu helfen, für das es ja immerhin schon eine Vorlage gab. :) Aber nein, stattdessen lässt er sich die Butter vom Brot nehmen, indem Horst bereits nach 5 Stunden eine C-Version seines Codes hat, die 10 % unter seiner alten Assemblerversion im Codeverbrauch liegt …
Das frustrierende an Asm ist doch: Kleine Programme bekommt man wirklich sehr gut hinoptimiert. In einigen Fällen sogar heute noch besser als mancher C-Compiler. Werden die Programme richtig komplex, dann verliert man schnell den Überblick: welche Register zerstört die Funktion xyz? In welchen Registern wird welcher Wert übergeben? Wird der Stack vor dem Funktionsende wieder korrekt freigeräumt? Im Ergebnis sinkt die mögliche Optimierung bei Asm mit größer werdendem Programm immer mehr. Der C-Compiler optimiert dagegen immer gleich gut. Gruß, Stefan
Moby A. schrieb: > Warte mal auf mein nächstes Projekt. Da wird gezeigt wie > eine simple IR-Ausgabe ausschauen kann ;-) Formuliere doch schon mal die Anforderungen für Dein nächstes Projekt, zum Beispiel so: Aufgabe: Senden eines IR-NEC-Frames Plattform: AVR-µC: ATTiny25/45/85 PWM-Pin: PB0, also OC0A Modulation: 38kHz IR-Protokoll: NEC, IR-Adresse 0xFF, Kommando-Code 0xA0
Stefan K. schrieb: > Werden die Programme richtig komplex, dann verliert man schnell den > Überblick: welche Register zerstört die Funktion xyz? In welchen > Registern wird welcher Wert übergeben? Wird der Stack vor dem > Funktionsende wieder korrekt freigeräumt? Wobei man sich das in einem Assemblerprojekt genauso definieren könnte, wie es ein C-Compiler halt machen muss. Ich habe auch schon größere Assemblerprojekte hier gesehen, vor deren Komplexität ich durchaus den Hut ziehe (Heizungs-Thermostat-Steuerung), aber irgendwo verkriecht sich halt da drin noch eine kleine Wanze oder zwei, aber die zu suchen gleicht einer Suche nach der Nadel im Heuhaufen.
Jörg W. schrieb: > Wobei man sich das in einem Assemblerprojekt genauso definieren > könnte, wie es ein C-Compiler halt machen muss. Klar, wobei z.B. eine Funktionsdefinition in C selbsterklärend ist. In Asm musst Du in der Doku nachsehen, daß R15 der X-Index und R14 der Y-Index ist, und R13/R12 von der Funktion zerstört werden. Sprich: Asm ohne Kommentare geht gar nicht, gut geschriebenes C kommt an den meisten Stellen auch ohne Kommentare aus. Um Asm sicher zu coden, musst Du einfach viel mehr Aufwand treiben. Und gerade den sehe ich bei vielen Asm-Propheten leider gar nicht. Viele Grüße, Stefan
:
Bearbeitet durch User
Stefan K. schrieb: > Asm musst Du in der Doku nachsehen, daß R15 der X-Index und R14 der > Y-Index ist, In einem guten Assembler kannst du wahlweise global oder innerhalb der Asm-Funktion Registern auch Namen geben.
Wenn du R15 jetzt "X_Index" taufst, musst du aber trotzdem noch wissen, daß du R15 nicht einfach für etwas anders nehmen solltest :-) Um in einem großen Programm so etwas im Griff zu haben, muss man schon Profi sein, und da gibt es hier nur einen!
Klaus W. schrieb: > Wenn du R15 jetzt "X_Index" taufst, musst du aber trotzdem noch wissen, > daß du R15 nicht einfach für etwas anders nehmen solltest :-) Wenn man das macht, dann sollte man für den Bereich der benannten Register keine Originalregisterbezeichnung verwenden. Entweder man verwendet darin konsequent logische Namen, oder direkt die Register. Dieser Bereich ergibt sich per Konvention. Ohnehin blickt man bei grösseren Programmen nur noch durch, wenn man klarstellt, welche Register überhaupt von Unterprogrammen verändert werden dürfen, da passt das gut mit hinein. Natürlich ist der Umfang an Detaildoku in Asm wichtiger. Aber man kann auch Asm-Programmierung mit geeigneten Werkzeugen deutlich erleichtern, sowohl in Form eines geeigneten Assemblers wie auch durch Knowhow. Wobei Atmel verständlicherweise nicht sehr viel Aufwand in den Assembler investiert. Der wird von der Systemphilosophie her nur für kleine Programme benötigt. Umgekehrt stellt die Notwendigkeit zu systematischem und übersichtlichem Vorgehen eine Chance des Compilers dar. Der hat diese Zwänge nicht in gleichem Masse und kann strunzschaurigen aber effizienten Code generieren, solange er funktioniert. Ein Asm-Programmierer, der später noch durchblicken will, der wird das eher vermeiden wollen.
:
Bearbeitet durch User
Jörg W. schrieb: > Klaus W. schrieb: >> und da gibt es hier nur einen! > > Lass mich raten: den GCC. :-) ok, dann gibt es doch 2
A. K. schrieb: > Klaus W. schrieb: >> Wenn du R15 jetzt "X_Index" taufst, musst du aber trotzdem noch wissen, >> daß du R15 nicht einfach für etwas anders nehmen solltest :-) > > Wenn man das macht, dann sollte man für den Bereich der benannten > Register keine Originalregisterbezeichnung verwenden. Entweder man > verwendet darin konsequent logische Namen, oder direkt die Register. Kann man machen. Dann landest du aber bei nicht-kleinen Programmen auch recht schnell in der Situation, dass die Register nicht mehr reichen. Solange man Programmgrößen hat, in denen alles in sein jeweils eigenes Register passt und noch ein paar zur freien Verwendung übrig bleiben, geht das ja noch. Nur ist das Ende dieser Fahnenstange recht schnell erreicht. Mir scheint Moby hatte noch nie den Fall, mal etwas Größeres zu programmieren.
Karl H. schrieb: > Mir scheint Moby hatte noch nie den Fall, mal etwas Größeres zu > programmieren. Tja, ist halt nicht nötig bei "typischen" Anwendungen :-) Falls doch, hast du halt nur die falschen Probleme!
Karl H. schrieb: > Mir scheint Moby hatte noch nie den Fall, mal etwas Größeres zu > programmieren. Deshalb schrieb ich ja: Mobys Mikrokosmos. Da ist die Welt noch einfach. Eine Ameise schleppt Blätter auf den eigenen Schultern. Wofür braucht man da einen Schubkarre oder gar einen LKW? Sie könnte damit auch gar nichts anfangen.
Karl H. schrieb: > Dann landest du aber bei nicht-kleinen Programmen auch recht schnell in > der Situation, dass die Register nicht mehr reichen. Kannst das auch mit Variablen auf dem Stack so halten, wenn zu wenig Register. Aber auch hier ist der Compiler im Vorteil, weil er die Registerverwendung innerhalb einer Funktion variieren kann. Also für verschiedene Variablen das gleiche Register verwenden kann, je nachdem wie häufig die Var an welcher Stelle der Funktion genutzt wird. Bei Asm-Programmierung läuft man dann in Gefahr, den Überblick zu verlieren.
Jörg W. schrieb: > Moby A. schrieb: > Warte mal auf mein nächstes Projekt. > > Nö, Moby. Wir warten nicht, Du warst doch gar nicht angesprochen. > sondern machen inzwischen lieber an unseren > eigenen, nicht-simplen Projekten weiter. Vielleicht finde ich ja > endlich mal Zeit, die Bediensteuerung Natürlich. Da sollte und muß man Prioritäten haben. Deshalb lasse ich mich auch nicht auf irgendeinen Wettkampfquatsch ein wenn konkrete Angebote längst auf dem Tisch liegen. > braucht noch ein bisschen Gehirnschmalz, bevor man überhaupt ans > Programmieren gehen kann. Ein ganz wichtiger Gesichtspunkt: Die Sache bis zum Ende durchdenken bevor es ans Programmieren geht. 900ss D. schrieb: > Ja der Widerspruch ist natürlich ein gefundenes Fressen für dich. Ist > irgendwie billig, aber gönn ich dir. :-) Das ist nicht billig sondern ganz symptomatisch für eine Diskussion, die die Vorteile von Asm auf Teufel komm raus und mit allen Mitteln abzustreiten sucht. Spätestens beim nächsten Experten, der lange Erfahrung (wobei auch immer) als Argument an sich angibt, allerspätestens aber wenn es nur noch zu abwertenden Bemerkungen (unter der Gürtellinie) langt, dann kann das jeden, der erfolgreich mit Asm unterwegs ist, eigentlich nur nachdrücklichst bestätigen ;-)
Moby A. schrieb: > Dann auf gehts Karl Heinz. > In der Codersammlung wartet schon mein nächstes Projekt. > Das ist eine wirklich ganz ganz einfache Ausgabe eines seriellen > Datenstroms. Du meinst das hier
1 | systemint6: sbrc SIC,0 |
2 | rjmp systemint8 ;Clock H->L |
3 | |
4 | lsl A2HO3 ;DATABIT-OUTPUT |
5 | rol A2LO2 |
6 | rol A1LO1 |
7 | brcs systemint7 |
8 | cbi PORTB,0 |
9 | rjmp systemint8 |
10 | systemint7: sbi PORTB,0 |
11 | |
12 | systemint8: sbi PINB,2 ;Clock generation |
13 | systemint9: inc SIC |
14 | |
15 | ireturn: reti |
Ja, hast du schön gemacht. > Mach das kürzer. Mach es schneller. :-) Das gesteh ich dir gerne zu, dass das so nicht geht. Aber jetzt mach du mal dasselbe mit einer Ausgabe von 40 Bytes. Und wenn wir schon dabei sind: ich hätte gerne 32 Samples pro Mittelungs-Durchgang und nicht 8 na wie schnell hast du die Änderung gemacht? > So hocheffizient und zeitsparend die C-Entwicklung ja sein soll- dann > ist das doch schnell erledigt! Ist hier doch gar nicht notwendig. Ob das Ding ein paar Takte mehr oder weniger braucht, interessiert doch keinen. Ist doch sowieso Timer gesteuert.
A. K. schrieb: > Aber auch hier ist der Compiler im Vorteil, weil er die > Registerverwendung innerhalb einer Funktion variieren kann. Also für > verschiedene Variablen das gleiche Register verwenden kann, je nachdem > wie häufig die Var an welcher Stelle der Funktion genutzt wird. Das kann man mit Asm genauso. Im Übrigen hat ein AVR ausreichend Register, um auch einen gewissen Reservierungsumfang zu ermöglichen. > Bei > Asm-Programmierung läuft man dann in Gefahr, den Überblick zu verlieren. Läuft man mit einer gewissen Systematik eben nicht. Dazu ist die AVR-Architektur zu einfach ;-)
Moby A. schrieb: >> Bei >> Asm-Programmierung läuft man dann in Gefahr, den Überblick zu verlieren. > > Läuft man mit einer gewissen Systematik eben nicht. > Dazu ist die AVR-Architektur zu einfach ;-) Ach Moby. Wir reden doch nicht von der Architektur. Wir reden von Programmen, die vom Umfang her nicht mehr in die Kategorie Micky Mouse fallen. Eben das, was bei uns täglich anfällt. Programme, bei denen du deine 8 Variablen Größen nicht mehr in Registern halten kannst. Programme, in denen auch mal eine Datenstruktur vorkommt. Programme, die auch mal ein wenig flexibel anpassbar sein müssen - und das ohne großen Aufwand. Wie vorhin schon geschrieben: Ändere dein Programm mal um auf eine andere Anzahl an Samples. Die Hälfte deiner Tricks in diesem Assembler Programm bricht dann sofort zusammen. Mach mehr als 2 ADC Kanäle und schon wieder hast du massive Änderungen.
:
Bearbeitet durch User
Karl H. schrieb: > Das gesteh ich dir gerne zu, dass das so nicht geht. Prima. > Aber jetzt mach du mal dasselbe mit einer Ausgabe von 40 Bytes. > Und wenn wir schon dabei sind: ich hätte gerne 32 Samples pro > Mittelungs-Durchgang und nicht 8 > > na wie schnell hast du die Änderung gemacht? Langsamer als in C. Deshalb gilt es die Anforderungen vorher zu durchdenken. Die Flexibilität von C wird nun aber gerade mit der Tatsache erkauft, daß der Code nicht so effizient an die Hardware angepasst ist und damit größer ist / langsamer läuft als nötig. Klar- dieser Nachteil muß nicht in jedem Projekt entscheidend sein. Aber er ist vorhanden und darum geht es mir hier. Von meiner (subjektiven) Abneigung gegen sprachgewaltige, komplex ausgedrückte abstrakte Programmiererbevormundung mal ganz abgesehen. > Ist hier doch gar nicht notwendig. Ob das Ding ein paar Takte mehr oder > weniger braucht, interessiert doch keinen. Ist doch sowieso Timer > gesteuert. Das interessiert erstens durchaus, wenn noch mehr Funktionalität hinzukommen soll und ich vielleicht bei meinen 128kHz Takt bleiben möchte. Und zweitens steht für Erweiterungen mehr Platz zur Verfügung. Hochsprache initiiert: Man nehme einfach meht MHz... Man nehme einfach einen größeren Flash... Man wechsele einfach auf 32-Bit! Ist doch so schön einfach...
Moby A. schrieb: >> na wie schnell hast du die Änderung gemacht? > > Langsamer als in C. Siehst du. Genau darum gehts im wirklichen Leben. > Deshalb gilt es die Anforderungen vorher zu durchdenken. Da helfen dir die Anforderungen nicht viel. Dieses Programm ist so spezifisch auf genau diese Aufgabenstellung zugeschnitten, dass du bei der kleinsten Änderung alles wegwerfen kannst. > Die > Flexibilität von C wird nun aber gerade mit der Tatsache erkauft, daß > der Code nicht so effizient Noch mal. Die Effizenz interessiert keinen, solange es schnell genug ist. Du hast nichts davon, wenn der µC 2 Takte früher mit der ISR fertig ist. > er ist vorhanden und darum geht es mir hier. Von meiner (subjektiven) > Abneigung gegen sprachgewaltige, komplex ausgedrückte abstrakte > Programmiererbevormundung mal ganz abgesehen. Es tut mir leid Moby. Aber die meisten Programme sind nun mal nicht in der Kategorie, die du hier immer wieder zum besten gibst. Die sind deutlich komplexer. > Das interessiert erstens durchaus, wenn noch mehr Funktionalität > hinzukommen soll wenn mehr Funktionalität hinzukommen soll, dann wirds aber mit deinen Registern schnell ganz eng. Und das bedeutet: du musst umbauen.
Moby A. schrieb: > Das interessiert erstens durchaus, wenn noch mehr Funktionalität > hinzukommen soll Sei Dir gewiss: Bei Dir kommt nicht mehr Funktionalität dazu. > Und zweitens steht für Erweiterungen mehr Platz zur Verfügung. Welche Erweiterungen? Dann wirds doch viel zu komplex für Dich... > Hochsprache initiiert: > Man nehme einfach meht MHz... > Man nehme einfach einen größeren Flash... > Man wechsele einfach auf 32-Bit! Das ist nur in Deinem kleinen Köpfchen so! Weißt Du eigentlich, dass es auch ATmegas und nicht nur ATTinys mit 1KB Flash gibt? > Ist doch so schön einfach... In Newsgroups würde man Dich nun merkbefreit nennen. Seufz.
Karl H. schrieb: > Kategorie > Micky Mouse ist eben nur in Asm realisierbar ;-) Und mit etwas Systematik sehr viel mehr. Das beste Pferd im Stall heißt hierfür AVR. Karl H. schrieb: > Eben das, was bei uns täglich anfällt. > Programme, bei denen du deine 8 Variablen Größen nicht mehr in Registern > halten kannst. Programme, in denen auch mal eine Datenstruktur vorkommt. > Programme, die auch mal ein wenig flexibel anpassbar sein müssen. Ja, flexibel sollte alles sein. Genau das verursacht aber auch Aufwand und macht die Dinge komplizierter. Deshalb: Anforderungen der konkreten App analysieren und erst dann über die Umsetzung befinden.
Moby A. schrieb: > Hochsprache initiiert: > Man nehme einfach meht MHz... > Man nehme einfach einen größeren Flash... > Man wechsele einfach auf 32-Bit! > Ist doch so schön einfach... Genau das bedeutet es eben nicht. Auch nicht auf einem AVR Nur weil man eine Hochsprache benutzt bedeutet das nicht, dass man hirnlos an die Sache rangeht. Aber es bedeutet, dass ich mich nicht um jeden Kleinkram selber kümmern muss. Das kostet manchmal ein wenig Leistung, aber selten mehr als 5%. Und sobald die Programme größer werden dreht sich das Verhätlnis oft sogar um. Denn dann kannst du als Assembler Programmierer gar nicht mehr alles so ausnutzen (zumindest nicht im überschaubaren Kostenrahmen), weil du in mehr als 20 Codeseiten nicht mehr überblicken kannst, welche Register du an welcher Stelle gefahrlos benutzen kannst und welche du wo pushen und popen musst. Mit dem Effekt, dass du in Basisfunktionen immer alle temporären Register pushen und popen wirst. Und genau dasselbe macht ein Compiler auch. Du bist in einer Programmgröße unterwegs, wo du noch alles getrennt und sauber in Register unterbringst. Das geht und das ist auch gut so. Aber es bringt dir nichts, weil es niemanden interessiert, ob da ein paar Takte mehr oder weniger drauf gehen.
Moby A. schrieb: > Karl H. schrieb: >> Kategorie >> Micky Mouse > > ist eben nur in Asm realisierbar ;-) Micky Mouse geht auch in C. In einem Bruchteil der Zeit, die ein ASM-Programmierer dafür braucht. > Und mit etwas Systematik sehr viel mehr. Zeig doch mal endlich! Zeig doch mal endlich ein Programm, dessen Binärgröße über 1k bis 2k geht! Hast Du nicht, kannst Du nicht. > Genau das verursacht aber auch Aufwand und macht die Dinge > komplizierter. Deshalb: Anforderungen der konkreten App analysieren und > erst dann über die Umsetzung befinden. Es gibt Leute, die verschwenden bei Deinen kleinen Progrämmchen noch nichtmals einen Gedanken für die Umsetzung. Was Du bereits "Projekt" nennst, ist für andere C-Programmierer ein laues Lüftchen.
Moby A. schrieb: > Karl H. schrieb: >> Kategorie >> Micky Mouse > > ist eben nur in Asm realisierbar ;-) > Und mit etwas Systematik sehr viel mehr. > Das beste Pferd im Stall heißt hierfür AVR. > > Karl H. schrieb: >> Eben das, was bei uns täglich anfällt. >> Programme, bei denen du deine 8 Variablen Größen nicht mehr in Registern >> halten kannst. Programme, in denen auch mal eine Datenstruktur vorkommt. >> Programme, die auch mal ein wenig flexibel anpassbar sein müssen. > > Ja, flexibel sollte alles sein. > Genau das verursacht aber auch *Aufwand* Es verursacht eben nicht Aufwand Wenn ich in deinem Programm in C geschrieben ein
1 | #define NR_SAMPLES 8
|
gegen ein
1 | #define NR_SAMPLES 12
|
austausche, dann verursacht das eben keinen wirklichen Aufwand. Der Compiler sucht sich bei
1 | ADCSumme /= NR_SAMPLES; |
dann schon die richtige Methode raus, um das sauber umzusetzen. Da braucht niemand ein
1 | lsr A1H ;AINP1SUM/8 |
2 | ror A1LO1 |
3 | lsr A1H |
4 | ror A1LO1 |
5 | lsr A1H |
6 | ror A1LO1 |
schreiben. Hab ich NR_SAMPLES auf 8 gesetzt, dann wird der Compiler mit einer ähnlichen Lösung kommen. Ist sie 12, dann benutzt er eine andere Variante. Je nach Zahlenwert hat er Strategien mit, wie er die Division umsetzt. Und zwar so, dass mich als Programmierer das überhaupt nicht kümmern muss > und macht die Dinge > komplizierter. Auch nicht Deine Systematik, mit der du in SIC einzelne Bits dazu benutzt um festzustellen, in welcher Phase des Programmlaufs du dich gerade befindest, das ist komplex und schwer zu warten. Wie gesagt: nimm 2 weitere ADC dazu und dein Programm bricht zusammen wie ein Kartenhaus. Alles wegwerfen und neu anfangen lautet dann die Devise.
:
Bearbeitet durch User
Karl H. schrieb: > wenn mehr Funktionalität hinzukommen soll, dann wirds aber mit deinen > Registern schnell ganz eng. Und das bedeutet: du musst umbauen. Unfug. Du hast das unabhängige Bausteinprinzip noch nicht ganz verstanden. Oder willst das nicht zur Kenntnis nehmen. Was glaubst Du was man im noch gar nicht existenten Hauptprogramm so alles anstellen könnte? Das läuft nämlich dann bewußt und wunderbar entkoppelt von der schon vorhandenen Funktionaliät.
Mittlerweile sollten wir alle verstanden haben, das es sinnlos ist. Moby ist in seiner Welt gefangen und kann nur innerhalb dieser argumentieren.
Moby A. schrieb: > Karl H. schrieb: >> wenn mehr Funktionalität hinzukommen soll, dann wirds aber mit deinen >> Registern schnell ganz eng. Und das bedeutet: du musst umbauen. > > Unfug. Du hast das unabhängige Bausteinprinzip noch nicht ganz > verstanden. Ui. So wie du programmierst, solltest du das Wort 'Baustein' lieber nicht in den Mund nehmen. > Oder willst das nicht zur Kenntnis nehmen. Was glaubst Du > was man im noch gar nicht existenten Hauptprogramm so alles anstellen > könnte? Das läuft nämlich dann bewußt und wunderbar entkoppelt von der > schon vorhandenen Funktionaliät. SO. Dann zeig mal. Mach eine Tabelle rein, in der Uhrzeiten stehen und je nach Uhrzeit wird eine von 2 Sets von ADC gesampelt. Von 6:00 Uhr bis 9:30 will ich den ADC0 und den ADC3, von 9:30:01 bis 14:05:20 soll es ADC1 und ADC0 sein, von 14:05:21 bis Mitternacht den ADC4 und den ADC5. Ich mach es dir einfach und sage mal, es soll über den Tag verteilt 25 Zeiträume geben.
Karl H. schrieb: > SO. > Dann zeig mal. > Mach eine Tabelle rein, in der Uhrzeiten stehen und je nach Uhrzeit wird > eine von 2 Sets von ADC gesampelt. Von 6:00 Uhr bis 9:30 will ich den > ADC0 und den ADC3, von 9:30:01 bis 14:05:20 soll es ADC1 und ADC0 sein, > von 14:05:21 bis Mitternacht den ADC4 und den ADC5. Ich mach es dir > einfach und sage mal, es soll über den Tag verteilt 25 Zeiträume geben. Und weils so schön ist, soll mit gleicher Zeittabelle (zusätzlicher Eintrag) auch noch ein Ventil angesteuert werden. Moby, wir alle haben schon Assembler programmiert. Durchwegs größere Programme als so etwas. Und wir alle haben gesehen, dass man als Programmierer mit seinen Fähigkeiten dann ganz schnell am Ende ist. Was bei einem 200 Zeilen Programm noch funktioniert, geht bei 20000 Zeilen dann eben nicht mehr. Das überblickt kein Mensch mehr in der Art und Weise wie du das suggerierst: nämlich dass er jeden einzelnen überflüssigen Taktzyklus herausoptimieren könnte. Ganz im Gegenteil, ganz im Gegenteil. Compiler leisten da einen viel besseren Job als es ein Mensch je könnte.
Matthias L. schrieb: > Moby ist in seiner Welt gefangen und kann nur innerhalb dieser > argumentieren. Alles andere ist, per definitionem, „unnütz groß, 32 bit, Verschwendung“. :-) Dabei hat er immer noch nicht kapiert, dass der Thread damit begann, dass innerhalb von gerade mal 5 Stunden das C-Programm 10 % kleiner war als Horsts ursprüngliches Assemblerprogramm (welches er gewiss nicht mit Absicht so schlecht geschrieben haben wird). Kein Moby war da, etwas Vergleichbares mit dem Assemblercode zu tun um zu zeigen, dass es in Assembler wirklich kleiner oder schneller geworden wäre.
Matthias L. schrieb: > Mittlerweile sollten wir alle verstanden haben, das es sinnlos > ist ... die offensichtlichen Vorteile von Asm in typischen 8-Bit Apps zu bestreiten. Ganz richtig Matthias. > Moby ist in seiner Welt gefangen und kann nur innerhalb dieser > argumentieren. Wenn Du die Fokussierung auf die tatsächlichen Bedürfnisse solcher Apps auf AVRs kleine Welt nennen willst dann mach das. Karl H. schrieb: > Dann zeig mal. > Mach eine Tabelle rein, in der Uhrzeiten stehen und je nach Uhrzeit wird > eine von 2 Sets von ADC gesampelt. Von 6:00 Uhr bis 9:30 will ich den > ADC0 und den ADC3, von 9:30:01 bis 14:05:20 soll es ADC1 und ADC0 sein, > von 14:05:21 bis Mitternacht den ADC4 und den ADC5. Ich mach es dir > einfach und sage mal, es soll über den Tag verteilt 25 Zeiträume geben. Für dieses Projekt sind schon hardwaremäßig nur 2 ADCs vorgesehen und damit basta. Eine Softwareuhr zu implementieren ist jedenfalls kein Problem. Je nach Uhrzeit bestimmte Dinge zu erledigen auch nicht. Du kannst jetzt die Anforderungen so hoch schrauben wie es Dir passt, um Deine hochgelobte Flexibilität unter Beweis zu stellen. Aber dazu noch was: Wer diese Flexibilität wirklich braucht hat die eigentliche Aufgabe vorab nicht gründlich genug auf ihre Anforderungen hin durchdacht ;-)
Jörg W. schrieb: > Kein Moby war da, ... um anderer Leute Arbeit zu erledigen? Die C-Programmierer waren gefragt. Und sie haben herausgefunden daß dieses Asm-Programm grottig programmiert sein muß ;-)
Moby A. schrieb: > Für dieses Projekt sind schon hardwaremäßig nur 2 ADCs vorgesehen und > damit basta. Ah ja. Na wenn du das sagst. Da sind noch ein paar Dinge drinnen
1 | SYSTEMINT: mov r18,SIC |
2 | mov r17,SIC |
3 | andi r17,$30 |
4 | brne systemint6 |
die $30 funktionieren nur, weil du genau 3 Bytes raustaktest. Wenn ich auf mehr als 2 ADC bestehe, dann bricht auch der Teil der Steuerung ob gemessen oder ausgegeben werden soll, in sich zusammen. > Eine Softwareuhr zu implementieren ist jedenfalls kein Problem. Je nach > Uhrzeit bestimmte Dinge zu erledigen auch nicht. Na dann mach. 4 verschiedene ADC, unterschiedliche Eingänge, Zeittabelle. Das eine bringt dich in das Problem, das dir die Register ausgehen. Das andere bringt dich in das Problem, dass deine ausgeknobelte Logik den Bach runter geht. Das allerdings muss ich dir lassen: die Logik in der ISR ist schon ausgeknobelt. > Du kannst jetzt die > Anforderungen so hoch schrauben wie es Dir passt, um Deine hochgelobte > Flexibilität unter Beweis zu stellen. Tja. Profis müssen ihre Programme eben auch wartbar halten. Wenn auf eine Änderung der Anforderungen ein 'und damit basta' kommt, dann bist du deinen Job los. > Aber dazu noch was: Wer diese Flexibilität wirklich braucht hat die > eigentliche Aufgabe vorab nicht gründlich genug auf ihre Anforderungen > hin durchdacht ;-) Ich hab meine Anforderungen gründlich durchdacht. Und das hat zum Ergebnis gebracht, dass ich 4 ADC Eingänge brauche und eine Zeitsteuerung dazu. Da dein ASM-Programm ja so wunderbar funktioniert, dachte ich eigentlich ich könnte das als Basis benutzen. Schliesslich ist das ja der Sinn der Codesammlung, dass man dort Programme findet, die obwohl sie nicht 100% auf die eigene konkrete Anforderung passen, dann doch als Basis dienen können und leicht auf diese anpassbar sind. Das funktioniert eigentlich mit fast allen Programmen. Nur scheinbar mit deinen nicht. Wer nicht 100% dieselben Anforderungen hat wie du, der steht dann im Regen. Oder wie? Ich würde eher sagen, das ist dann ein wenig sinnlos. Denn wann hat schon jemand genau diese Anforderungen, dass er 2 ADC plus 2 Eingänge hat, die er dann auch noch codiert in 3 Bytes getaktet übertragen muss. Und zwar GENAU so und nicht anders. Jede kleinste Abweichung davon - Pech gehabt. Dann stehen massive Analysen und Änderungen an.
:
Bearbeitet durch User
Karl H. schrieb: > Moby, wir alle haben schon Assembler programmiert. Durchwegs größere > Programme als so etwas. Größere Programme. Tatsächlich? Gibts sowas? > Und wir alle haben gesehen, dass man als > Programmierer mit seinen Fähigkeiten dann ganz schnell am Ende ist. Merkwürdig. Für alle typischen MSR Aufgaben die bei einer Haussteuerung so anfallen langte mir bisher ein kleiner AVR mit Asm. Ob das auch damit zusammenhängt, daß man viele ihrer Funktionen dezentral realisiert?
Moby A. schrieb: > Merkwürdig. Für alle typischen MSR Aufgaben die bei einer > Haussteuerung so anfallen langte mir bisher ein kleiner AVR mit Asm. Tja. Och weiss ja nicht, was du unter Haussteuerung verstehst.
Moby A. schrieb: > das auch damit zusammenhängt, daß man viele ihrer Funktionen dezentral > realisiert? Wie willst du denn zb eine Heizungssteuerung, die auf * Aussentemperatur * Innentemperatur * Vorlauftemperatur * Uhrzeit * Wochentag * Temperaturprofile je nach Wochentag und Uhrzeit aufbaut, samt Menüsteuerung, dezentralisieren?
:
Bearbeitet durch User
Karl H. schrieb: > Moby A. schrieb: > >> das auch damit zusammenhängt, daß man viele ihrer Funktionen dezentral >> realisiert? > > Wie willst du denn zb eine Heizungssteuerung, die auf > * Aussentemperatur > * Innentemperatur > * Vorlauftemperatur > * Uhrzeit > * Wochentag > * Temperaturprofile je nach Wochentag und Uhrzeit > aufbaut, samt Menüsteuerung, dezentralisieren? Edit: genau dafür könnte ich deine Sensorplatine gut brauchen. Aussentemperatur, Innentemperatur, Vorlauftemperatur und Helligkeit draussen per ADC messen und für die digitalen Inputs fällt mir auch noch was ein :-) Aber leider, leider. Geht ja nicht. Die Software ist dazu zu unflexibel. Aber dafür ist sie schnell. Kein Taktzyklus wird verschwendet. Hilft mir nur nichts. Werd ich mir doch in 10 Minuten ein C Programm dafür schreiben müssen. Das verbraucht zwar pro ISR Aufruf 10 Takte mehr, aber dafür kann ich mit 3 Tastendrücken noch einen 5ten ADC mit dazunehmen und in 2 Jahren den Windsensor vom noch zu bauenden Wintergarten auch noch anschliessen.
:
Bearbeitet durch User
Karl H. schrieb: > die $30 funktionieren nur, weil du genau 3 Bytes raustaktest. > > Wenn ich auf mehr als 2 ADC bestehe, dann bricht auch der Teil der > Steuerung ob gemessen oder ausgegeben werden soll, in sich zusammen. Da bricht gar nichts zusammen weil das genau so beabsichtigt ist. > Eine Softwareuhr zu implementieren ist jedenfalls kein Problem. Je nach > Uhrzeit bestimmte Dinge zu erledigen auch nicht. > > Na dann mach. Die wird hier nicht gebraucht (und wäre ohnehin umständlich zu stellen). > 4 verschiedene ADC, unterschiedliche Eingänge Hier gibt es: 2 ADU und 2 Digital-Eingänge. Nix anderes. > Das eine bringt dich in das Problem, das dir die Register ausgehen. Da geht höchstens irgendwann mal Flash und RAM aus. > andere bringt dich in das Problem, dass deine ausgeknobelte Logik den > Bach runter geht. Bitte versteh doch: Hard-und Software ist von Anfang an auf EIN Ziel fokussiert. Ist das so schwierig? Deine Flexibilität erübrigt sich damit. Meine Flexibilität besteht darin, im Rahmen dieser Gegebenheiten weitere Funktionalität hinzuzufügen. Punkt und Aus und kein Problem. > Tja. Profis müssen ihre Programme eben auch wartbar halten. Wenn auf > eine Änderung der Anforderungen ein 'und damit basta' kommt, dann bist > du deinen Job los. Ja ja ist schon in Ordnung. Ich verzichte aber im Rahmen typischer 8-Bit Apps auf Hochsprache. Die muß hier ganz objektiv nicht sein. Damit nehme ich deren Nachteile nicht in Kauf- und die Zeitersparnis relativiert sich durch Erfahrung und eine große Codebasis. > Ich hab meine Anforderungen gründlich durchdacht. Und das hat zum > Ergebnis gebracht, dass ich 4 ADC Eingänge brauche und eine > Zeitsteuerung dazu. Da dein ASM-Programm ja so wunderbar funktioniert, > dachte ich eigentlich ich könnte das als Basis benutzen. Nein kannst Du nicht. Die ist für genau dieses Projekt und für nix anderes (außer sich vielleicht was abzuschauen). > Wer nicht 100% dieselben Anforderungen hat wie du, der > steht dann im Regen. Oder wie? Ach was. Je zwei 10-Bit ADC und Digitaleingänge seriell über eine längere Leitung zur Verfügung gestellt lassen sich doch vielseitig nutzen. Wenn ich mehr brauche denke ich daran vor dem Projekt-Design ;-)
:
Bearbeitet durch User
> Wie willst du denn zb eine Heizungssteuerung, die auf > * Aussentemperatur > * Innentemperatur > * Vorlauftemperatur > * Uhrzeit > * Wochentag > * Temperaturprofile je nach Wochentag und Uhrzeit > aufbaut, samt Menüsteuerung, dezentralisieren? > > Edit: genau dafür könnte ich deine Sensorplatine gut brauchen. Nö. Dafür ist sie aber nicht gedacht und gemacht. Meine Güte. Dafür tut sie das wofür sie gut ist optimal und einfach. > und in 2 Jahren den Windsensor vom noch zu bauenden Wintergarten auch > noch anschliessen. Man merkt Dir an diesen Gedanken Deinen Jahrgang an. Entschuldige wenn ich das so sage. Das ist ja noch das alte Mainframe-Denken mit Zentral-CPU, um die sich alle Sensorik und Aktoren zu scharen haben ;-)
:
Bearbeitet durch User
Moby A. schrieb: > Hier gibt es: > 2 ADU und 2 Digital-Eingänge. Nix anderes. Dann ist das Programm für 99,9% der typischen Anwender sinnlos. Damit erfüllt es weder den Anspruch einer Weiterverwendung, noch hat es etwas in der Codesammlung zu suchen, da für die Allgemeinheit unbrauchbar. Ich plädiere daher dafür, dass ein Mod es aus der Codesammlung verschiebt. Und das witzigste daran: Es ist damit auch kein typisches AVR-Programm, worauf Moby immer so pocht. Ein unbrauchbares Programm ist lediglich ein Moby-Programm, aber keinesfalls eine typische AVR-Anwendung. Das ist einfach nur unverwertbarer Schrott.
:
Bearbeitet durch Moderator
Moby A. schrieb: > Wenn ich mehr brauche denke ich daran vor dem Projekt-Design ;-) Schön. Und andere denken eben in der Design Phase schon darüber nach, wie sie eine im Rahmen bleibende Variationsmöglichkeit einbauen können, wenn sie das zu moderaten Kosten bekommen können.
Frank M. schrieb: > Das ist einfach nur unverwertbarer Schrott. Darf ich dann mein "grottiges" Programm in die Codesammlung als "universeller Betrachter von PS2-Mausprotokollen auf'm PC" einstellen? Und wenn ja, mach ich das dann in C oder in Assembler?
Moby A. schrieb: > Hier gibt es: > 2 ADU und 2 Digital-Eingänge. Nix anderes. Und Mittelwert über 8 Samples. Hast du vergessen. Ist ebenfalls ein integraler Bestandteil im Code, der nicht so einfach tauschbar ist. Die ganze Taktung in der ISR baut darauf auf.
Frank M. schrieb: > Das ist einfach nur unverwertbarer Schrott. Da denke ich eher an solche unterirdischen Beiträge ;-( Karl H. schrieb: > Und andere denken eben in der Design Phase schon darüber nach, wie sie > eine im Rahmen bleibende Variationsmöglichkeit einbauen können, wenn sie > das zu moderaten Kosten bekommen können. Einverstanden. Karl H. schrieb: > Und Mittelwert über 8 Samples. > > Hast du vergessen. Ist ebenfalls ein integraler Bestandteil im Code, der > nicht so einfach tauschbar ist. Die ganze Taktung in der ISR baut darauf > auf. Das ist richtig. Und langt aus!
Moby A. schrieb: > Jörg W. schrieb: >> Kein Moby war da, > > ... um anderer Leute Arbeit zu erledigen? Du hättest zumindest mal deine immer wieder proklamierten Vorzüge der Assemblerprogrammierung unter Beweis stellen können. > Die C-Programmierer waren gefragt. Die waren im Gegensatz zu dir ja auch da. Ach so, nicht ganz korrekt: du warst ja dann auch da, aber nur, um die Vorzüge zu proklamieren. Nicht etwa, um wirklich was beizutragen, was Horst geholfen hätte. > Und sie haben herausgefunden daß dieses Asm-Programm grottig > programmiert sein muß ;-) Dummerweise haben sie ganz nebenbei auch noch rausgefunden, dass deine ach so tollen Codeschnipsel, die du uns bislang präsentiert hast, mindestens genauso grottig programmiert sind.
:
Bearbeitet durch Moderator
Horst S. schrieb: > Darf ich dann mein "grottiges" Programm in die Codesammlung als > "universeller Betrachter von PS2-Mausprotokollen auf'm PC" einstellen? Wenn der Schwerpunkt auf "universell" liegt, warum nicht? > Und wenn ja, mach ich das dann in C oder in Assembler? Wenn beide Versionen laufen, kannst Du auf jeden Fall beide Versionen einstellen. Dann hat jeder was davon. Aber Programme, wo die Hardware-Anforderungen ans beschränkte Programm - nur um total genial auszusehen - angepasst werden und nicht umgekehrt, sind für die Allgemeinheit sinnlos und haben in der Codesammlung nichts zu suchen. Was nützt mir ein Taschenrechner, der nur 2 und 2 addieren kann, weil man das total abgefahren in Assembler programmieren kann? Nichts.
Horst S. schrieb: > Darf ich dann mein "grottiges" Programm in die Codesammlung als > "universeller Betrachter von PS2-Mausprotokollen auf'm PC" einstellen? > Und wenn ja, mach ich das dann in C oder in Assembler? Nicht Dein Programm als solches ist schlecht sondern die Asm-Version. Bewusst falschverstanden? Natürlich stellst Du nun die verbesserte C-Version in die Codesammlung.
Moby A. schrieb: > Frank M. schrieb: >> Das ist einfach nur unverwertbarer Schrott. > > Da denke ich eher an solche unterirdischen Beiträge ;-( Sieh der Wahrheit einfach ins Auge: Ein nicht wiederverwendbares bzw. nicht erweiterbares Programm ist nur für eine konkrete Konstellation gedacht, die keine typische Anwendung ist. Damit ist es unbrauchbar.
Moby A. schrieb: > Aber dazu noch was: Wer diese Flexibilität wirklich braucht hat die > eigentliche Aufgabe vorab nicht gründlich genug auf ihre Anforderungen > hin durchdacht ;-) Das kannst Du in Deinem Hobby zuhause sagen. Kunden, die Entwicklungen in Auftrag geben, denken nicht so genau. Und wenn den dann einfällt, Moby A. schrieb: > Hier gibt es: > 2 ADU und 2 Digital-Eingänge. Nix anderes. Doch noch drei weitere ACUs und Digitaleingänge ergänzt werden müssen... Was dann? Alles neu Schreiben, wo bei C einfach die Arraygröße erhöht wird...
Frank M. schrieb: > Sieh der Wahrheit einfach ins Auge: Ein nicht wiederverwendbares bzw. > nicht erweiterbares Programm ist nur für eine konkrete Konstellation > gedacht, die keine typische Anwendung ist. Damit ist es unbrauchbar. Ergänzung: .... unbrauchbar für die Allgemeinheit. Und der Rest. Nun ja, sowas
1 | ldi r16,8 ;SYSTEMINT-Init (TIMER 0 Compare INT) |
2 | out OCR0A,r16 ;ca.115 kHz / (SYSINT-Teiler 8+1 |
3 | ldi r16,2 ; * Vorteiler 64)= ca.200Hz |
4 | out TCCR0A,r16 |
5 | ldi r16,3 |
6 | out TCCR0B,r16 |
7 | ldi r16,4 |
8 | out TIMSK0,r16 ;Enable Timer0 Compare-INT (SYSINT) |
9 | |
10 | ldi r16,$22 ;PB5,PB1-> PULLUP! |
11 | out PORTB,r16 |
12 | ldi r16,$5 |
13 | out DDRB,r16 ;PB0,2-> OUTPUT! |
14 | |
15 | ldi r16,$18 ;Init ADU |
16 | out DIDR0,r16 |
17 | ldi r16,2 |
18 | subi r16,AINP1REF |
19 | out ADMUX,r16 |
20 | ldi r16,$e0 |
21 | out ADCSRA,r16 |
22 | |
23 | ldi r16,$20 |
24 | out MCUCR,r16 ;SLEEP Mode Enable |
ist ein Beispiel dafür, wie man es nicht macht. Ich wollte nichts sagen, denn sonst heisst es wieder ich lenke auf 'Kleinigkeiten' ab. Und im übrigen hat Moby ja klar gemacht, dass seine Programme so zu nehmen sind wie sie sind und davon wird keinen Millimeter abgewichen.
:
Bearbeitet durch User
Moby A. schrieb: > Nicht Dein Programm als solches ist schlecht sondern die Asm-Version. Was genau ist an der Assembler-Version schlecht?
Horst S. schrieb: > Moby A. schrieb: >> Nicht Dein Programm als solches ist schlecht sondern die Asm-Version. > > Was genau ist an der Assembler-Version schlecht? Du verbrauchst vier CPU-Takte und drei Bytes RAM mehr als Mobys perfekte Lösung.
Jörg W. schrieb: > Du hättest zumindest mal deine immer wieder proklamierten Vorzüge der > Assemblerprogrammierung unter Beweis stellen können. Die sind viel schneller und effektiver an den kleinen Sachen demonstriert. > Die waren im Gegensatz zu dir ja auch da. ... weil nicht sein kann was nicht sein darf? Nein- im Ernst, mir fällt kein Zacken aus der Krone die vielen Hilfswilligen einschließlich der Mods hier auch mal zu loben. > Dummerweise haben sie ganz nebenbei auch noch rausgefunden, dass deine > ach so tollen Codeschnipsel, die du uns bislang präsentiert hast, > mindestens genauso grottig programmiert sind. Nun ja, ich kenne ja die zugrundeliegenden Kriterien: Flexibilität und Wartbarkeit ;-) Danke.
Horst S. schrieb: > Moby A. schrieb: >> Nicht Dein Programm als solches ist schlecht sondern die Asm-Version. > > Was genau ist an der Assembler-Version schlecht? Dass es größer als das C-Programm ist. Damit fällt es durch Mobys Qualitätsprüfung. Da braucht er sich das Programm noch nichtmals anzuschauen. Kein Wunder, das wäre ja Arbeit - jedenfalls was Assembler betrifft. Kein Mensch will sich die Lektüre eines größeren ASM-Codes antun, wenn er auch noch von einem anderen Menschen programmiert wurde. Da braucht man fürs sinnentnehmende Lesen und Verstehen ja genauso lange wie fürs Programmieren. Genau aus diesem Grunde sind ASM-Programme, die über Mobys 3-Zeiler hinausgehen, nicht mehr wartbar durch Dritte.
Moby A. schrieb: > Jörg W. schrieb: >> Du hättest zumindest mal deine immer wieder proklamierten Vorzüge der >> Assemblerprogrammierung unter Beweis stellen können. > > Die sind viel schneller und effektiver an den kleinen Sachen > demonstriert. Aber eben leider auch nur dort. Ein Papierflieger ist technologisch auch viel einfacher als eine Cessna. Wobei zugegebenermassen der Zielbereich von AVR Assembler schon recht weit reicht. > Nun ja, ich kenne ja die zugrundeliegenden Kriterien: Flexibilität und > Wartbarkeit ;-) Danke. Einen hast du vergessen: Schnelligkeit in der Entwicklung.
:
Bearbeitet durch User
Frank M. schrieb: > Da braucht man fürs sinnentnehmende Lesen und Verstehen ja genauso lange > wie fürs Programmieren. Ich behaupte mal: länger Ich gebs zu, ich hab fast 20 Minuten an
1 | SYSTEMINT: mov r18,SIC |
2 | mov r17,SIC |
3 | andi r17,$30 |
4 | brne systemint6 |
gebrütet, bis ich raus hatte, warum $30, ob das korrekt ist oder nicht und welche Konsequenzen es für den Rest des Codes hat.
:
Bearbeitet durch User
Karl H. schrieb: > wie man es nicht macht. Gut. Ich machs trotzdem so und bekomme maximale Funktionalität in den Controller ;-) > davon wird keinen Millimeter abgewichen So schauts aus. Im Übrigen kann jeder den Quelltext nach Herzenslust erweitern ;-) Karl H. schrieb: > unbrauchbar sind Dinge, die nicht funktionieren. Meine Zwecke erfüllt die Sensorplatine hervorragend!
:
Bearbeitet durch User
Karl H. schrieb: > Einen hast du vergessen: > Schnelligkeit in der Entwicklung Den hatte ich schon relativiert ;-)
Ich hätte dich ja gerne eingeladen, etwas sinnvolles zu tun und am Assembler Tutorial mitzuarbeiten. Themen gäbe es ja noch genug. Abere solange du nicht verstehst, was an
1 | ldi r16,$22 ;PB5,PB1-> PULLUP! |
2 | out PORTB,r16 |
schlecht ist, und warum
1 | ldi r16, (1<<PB5) | (1<<PB1) |
2 | out PORTB, r16 |
besser ist UND VOR ALLEN DINGEN, warum deine Technik bei
1 | ldi r16,$e0 |
2 | out ADCSRA,r16 |
ganz schlecht ist, spar ich mir die Einladung.
Moby A. schrieb: > Im Übrigen kann jeder den Quelltext nach Herzenslust erweitern ;-) Hast Du es immer noch nicht kapiert? Dein Quelltext ist nicht erweiterbar. Er funktioniert nur für die von Dir beschriebene Konstellation. Da kommt mir der Verdacht hoch, Du passt die Hardware-Konstellation an Deine Programme an und nicht umgekehrt. "Ich kann nur 2 ADCs, also benutze ich nur 2". Das ist für Dritte nicht erweiterbar und deshalb unbrauchbar. Daher hat es nichts in der Codesammlung zu suchen.
Moby A. schrieb: > Karl H. schrieb: >> Einen hast du vergessen: >> Schnelligkeit in der Entwicklung > > Den hatte ich schon relativiert ;-) Ach so?` Bis jetzt hast du dich immer gesträubt, mal etwas anspruchsvollere Aufgaben in Angriff zu nehmen.
So, jetzt hab ich zwei Flapps-Antworten und Mobys Meinung zu meinem Assembler-Projekt immer noch nicht. Nochmal, Moby: Was ist schlecht an meinem Assembler-Projekt?
Karl H. schrieb: > Bis jetzt hast du dich immer gesträubt, mal etwas anspruchsvollere > Aufgaben in Angriff zu nehmen. Du meinst für Deinen Test? Das ist doch ausführlich begründet. Auch wenn mir eine Codebasis helfen mag bedeutet das noch lange keine Mühen ;-) Zeitmangel fürs Hobby ist freilich der Hauptgrund. Da bist Du als Mod und hauptberuflicher MC Entwickler ganz sicher in einer besseren Lage ;-)
Moby A. schrieb: > Karl H. schrieb: >> Ich gebs zu, ich > > ... brüte an obigen C-Texten auch noch ;-) Ich weiss nicht, welche C Texte du meinst. Aber nur mal so Der Anfang deines Sensorprogramms würde (in deiner SChreibweise) so aussehen
1 | int main(void) |
2 | {
|
3 | OCR0A = 8; |
4 | TCCR0A = 2; |
5 | TCCR0B = 3; |
6 | |
7 | TIMSK0 = 4; |
8 | |
9 | PORTB = 0x22; |
10 | DDRB = 5; |
11 | DIDR0 = 0x18; |
12 | |
13 | ADMUX = 2 + AINP1REF; |
14 | ADCSRA = 0xE0; |
15 | |
16 | MCUCR = 0x20; |
17 | SIC = 0; |
18 | |
19 | sei(); |
20 | |
21 | while(1) |
22 | {
|
23 | }
|
24 | }
|
Das ist doch nicht sonderlich schwer. Links vom Zuweisungs-= steht, wo etwas hin soll, rechts davon was dort hin soll.
1 | OCR0A = 8; |
ist vollkommen äquivalent zu
1 | ldi r16,8 |
2 | out OCR0A,r16 |
und wird vom Compiler auch genau dazu umgesetzt (mit dem einen kleinen Unterschied, dass es mich in der C Version nicht interessiert, welches Register der Compiler nimmt um die Konstante zu laden). Der Endeffekt ist derselbe: das Bitmuster für 8 landet im Register OCR0A. Das ist der entscheidende Punkt und nicht welches Register zum Transfer benutzt wird. In der C Version sehe ich das auch nicht. Da sehe ich nur das, was tatsächlich relevant ist: nämlich dass die 8 ins OCR0A bugsiert wird. Wie, das ist Sache des Compilers - ein Detail dass mir völlig wurscht ist. Und wenn das OCR0A auf einem Prozessor nicht mittels OUT erreichbar ist, dann ist mir das ebenfalls wurscht - Sache des Compilers die Operation mit einem STS in die Wege zu leiten. In diesem Sinne hilft mir der Compiler mich auf das Wesentliche zu konzentrieren: warum 8, wo kommen die her, kann ich die Konsante so formulieren, dass da nicht 8 als Zahlenwert steht sondern für alle nachvollziehbar dort steht wie sich die 8 berechnen? Das sind die Dinge um die ich mich kümmere und nicht welche Register da benutzt werden. Ich gebe zu, dass die ISR nach deinem Prinzip nicht so elegant formulierbar ist, weil du natürlich ein paar Dinge heftig ausnutzt. Unter anderem dass du die Bits aus einem Register ins nächste schieben kannst und dann das dabei ins Carry fallende Bit für einen bedingten Sprung benutzen kannst, während sich die Register dabei gleichzeitig wieder auf 0 setzen. Klar, das geht so in C nicht.
:
Bearbeitet durch User
Horst S. schrieb: > Nochmal, Moby: Was ist schlecht an meinem Assembler-Projekt? Nein nicht nochmal Moby. Meine Antwort hast Du bereits. Im übrigen habe ich gar keinen Grund zu weiteren höflichen Antworten Dir gegenüber.
Karl H. schrieb: > Ich gebe zu, dass die ISR nach deinem Prinzip nicht so elegant > formulierbar ist, weil du natürlich ein paar Dinge heftig ausnutzt. > Klar, das geht so in C nicht. Wenigstens ein paar Leute hier die versuchen, meinen Aussagen auf den technischen Grund zu gehen. Danke.
Moby A. schrieb: > Wenigstens ein paar Leute hier die versuchen, meinen Aussagen auf den > technischen Grund zu gehen. Danke. Och, das können praktisch alle hier. Schon vergessen? Die meisten haben einen durchaus respektablen Assembler Background. Nur ist es eben vergleichsweise mühsam in 4 oder 5 aufeinanderfolgenden Assembler-Anweisungen alle Abläufe und Nebenbedingungen herauszulesen, die da tatsächlich ablaufen und für das Programm relevant sind. Um wieviel einfacher ist da C. Ein
1 | ADC1OH <<= 1; |
hat genau die eine Aufgabe, die Bits um 1 Stelle nach links zu verschieben. Nicht mehr und nicht weniger. Die verschobenen Bits werden zwar an anderer Stelle etwas bedeuten, aber es gibt in der abstrakten C Maschine keine derartigen impliziten Bedeutungsübertragungen von einer Anweisung zur nächsten. Und das ist viel leichter zu verfolgen. Überhaupt wenn der Code länger wird. Wenn es möglich ist, Nebeneffekte von einer Anweisung zur nächsten 'mitzunehmen', dann können die Compiler das schon. Dafür kann ich aber die Operation auch auf zb Portregister anwenden, wenn ich das will
1 | PORTB <<= 1; |
ohne mich darum kümmern zu müssen, erst mal ein Register frei haben zu müssen, dort dann mittels IN den aktuellen Portwert einzulesen, die Bits zu verschieben und mit einem OUT wieder alles auf den Port zu schreiben. Gleiches Prinzip: Ich kümmere mich um die höhere Ebene, dass die Bits verschoben werden müssen. Wie das auf Prozessorebene umzusetzen ist, ist Sache des Compilers. Ich will mich nicht darum kümmern müssen.
:
Bearbeitet durch User
Moby A. schrieb: > Frank M. schrieb: >> Er weiß genau, dass er verliert. > > Gewonnen hat zuallererst eins: Die funktionierende Lösung. > An den Vorteilen von Asm gibts nichts zu deuteln. Welche Vorteile sollten denn das sein? Das Programm vom TO war bereits nach kurzer Zeit in C kürzer und lesbarer als seine Assembler-Lösung, Dein erstes Assembler-Programm hatte trotz seiner extrem überschaubaren Größe einen ziemlich dicken Fehler. Dein zweites Programm, obwohl erkennbar mit der Intention entworfen, es einem Compiler (oder dem, was Du Dir darunter vorstellst) so schwer wie möglich zu machen, hat Yalu mit einem kürzeren C-Code mit besser Funktionalität widerlegt, woraufhin Du plötzlich neue, vorher unbekannte Anforderungen aus dem Hut zaubern mußtest. Bei dem 32-Bit-Vergleich war der Code, den der Compiler generiert hat, ebenfalls besser als das, was Du produziert hast. Ich stelle also fest: trotz Deines angeblichen Genies und der angeblichen Vorteile von Assembler hast Du es nicht geschafft, auch nur einen einzigen der Diskutanten von Deinen kruden Ansichten zu überzeugen. Deine ständige Wiederholung der angeblichen Vorteile von Assembler können keine Argumente ersetzen, an größere Aufgabenstellungen als ein paar Taster und blinkende LEDs traust Du Dich offensichtlich nicht heran, und der Code, den Du uns bislang präsentiert hast, war kaputt, unelegant, stilistisch schlecht und in keinem Fall wirklich besser als das, was der C-Compiler generiert hat. Von den angeblichen Vorteilen von Assembler, die Du behauptest, hast Du kein einziges beweisen können. Im Gegenteil haben alle Beteiligten hier gesehen, daß man in C schneller zum Ziel kommt, und der C-Code les- und wartbarer, erweiterbarer, fehlerärmer und die damit erzeugten Resultate meist sogar kleiner und performanter als Dein Assembler sind. Assembler hat heute überhaupt keine Vorteile mehr gegenüber C, außer in einer einzigen, winzig kleinen Nische: nämlich, wenn es um taktgenaues Timig geht. Daß Assembler ansonsten nur Nachteile gegenüber C hat, dafür aber unübersichtlich, kompliziert zu schreiben, zu lesen, und zu warten ist, das hast nicht nur Du hier mehrmals bewiesen, sondern das erkennen sogar die Anfänger hier, die deswegen mehrheitlich zu C neigen. Das Einzige, was Du jetzt noch ins Feld führen kannst, ist Dein eigener Unwille, Dich mit C und seinen enormen Vorteilen zu beschäftigen, weil Du vor 18 Jahren an einem C-Programm für die DOS-Kommandozeile gescheitert bist. Das ist aber Dein ganz ureigenes, höchstpersönliches Problem, und für andere Menschen auf der Welt kein Maßstab. Und es ist sicher keine Rechtfertigung dafür, daß Du hier ständig Threads zu Sprachen kaperst, obwohl die Dich angeblich gar nicht interessieren, und sie mit Deinem penetranten, halt- und hirnlosen Gesülze vollschmierst. Zu den Assembler-Threads dieses Forums, beispielsweise den beiden, in denen zwei Assembler-Programmierer dringend Hilfe bei der Ansteuerung von LCD-Displays gesucht haben, hast Du übrigens auch nichts beitragen können. Daß Du angesichts Deiner miserablen und blamablen Performance immer noch wagst, von den "Vorteilen von Assembler" zu schwadronieren, nötigt mir zwar einen gewissen Respekt vor Deiner Chuzpe ab, zeugt aber am Ende doch nur von Ignoranz und Realitätsverlust oder einer armseligen Befriedigung daran, anderen den Spaß an diesem Forum zu verderben. Laß' es gut sein, Ritter von der traurigen Gestalt. Die Windmühlen haben gewonnen, und Sancho Pansa zeigt Dir den Weg zu Deiner Dulcinea. :-)
Karl H. schrieb: > Nur ist es eben vergleichsweise mühsam in 4 oder 5 aufeinanderfolgenden > Assembler-Anweisungen alle Abläufe und Nebenbedingungen herauszulesen, > die da tatsächlich ablaufen und für das Programm relevant sind. Oder anders ausgedrückt: Warum soll ich mich 20 Minuten da durchquälen, um alle Nebeneffekte dieser paar Anweisungen im Kontext des Programms herauszufinden, wenn ich in C das komplette Programm in 10 Minuten neu schreiben kann? Auch dieses Programm wird funktionieren und seine Aufgabe perfekt erfüllen, möglicherweise einen Tick langsamer und mit einem Tick mehr Flash Verbrauch (*), die aber hauptsächlich dem geringen Umfang der Problemstellung geschuldet sind. Mit dem Bonus, dass dann auch 4 ADC keinerlei Probleme mehr aufwerfen sondern nur im Ändern eines Zahlenwertes bestehen? (*) was aber in der Praxis kein wirkliches Problem darstellt. Denn für nicht verbrauchtes Flash krieg ich kein Geld zurück. Dafür spar ich mir aber Zeit in der Entwicklung, die ich für sinnvolleres als dem Suchen nach dem letzten Register Trick benutzen kann, der mir dann sowieso bei einer möglichen Erweiterung erst recht wieder auf den Schädel fällt.
:
Bearbeitet durch User
Moby A. schrieb: > Matthias L. schrieb: >> Moby A. schrieb: >>>Daß die Demonstration von Codeersparnis und mehr Speed idealerweise >>>zugunsten von Asm ausfallen muß wirst auch Du wissen >> >> Das hat auch nie jemand hier bestritten. > > So, das musste noch sein ;-) Das mag zwar idealerweise so sein, praxisch gibt es aber weder eine "Codeersparnis" noch "mehr Speed". q.e.d. Nimm es hin, gegen die Maschine hast Du keine Chance. Ein Kran kann mehr heben, ein Bestückungsautomat besser bestücken, und ein Compiler besser optimieren als Du. Einfache, monotone Tätigkeiten können Maschinen nun einmal besser als Menschen, und genau deswegen gewinnen Schachcomputer regelmäßig gegen die besten Schachspieler der Welt.
Jörg W. schrieb: > Klaus W. schrieb: >> und da gibt es hier nur einen! > > Lass mich raten: den GCC. :-) Ich hätte da eher an Johann und Dich gedacht. Ehre, wem Ehre gebührt. ;-)
Moby A. schrieb: > Nein nicht nochmal Moby. Meine Antwort hast Du bereits. Im übrigen habe > ich gar keinen Grund zu weiteren höflichen Antworten Dir gegenüber. Doch, den hast Du. Moby A. schrieb: > Ich kenne diesen Ausgang der Geschichte schon: > Immer dann wenn die Argumente ausgehen ;-) DEINE WORTE (Dazu sag ich mal nur: Wer gegen den Wind pisst, darf sich nicht wundern, wenn er nass wird)
Sheeva P. schrieb: > Laß' es gut sein, Ritter von der traurigen Gestalt. Die Windmühlen haben > gewonnen, und Sancho Pansa zeigt Dir den Weg zu Deiner Dulcinea. :-) Ich war erst versucht, Deinen wunschdenkenden Beitrag falschen Satz für falschen Satz auseinanderzunehmen. Verschiedene Dinge sind so gar nicht in Dein Bewußtsein gedrungen oder ganz blockiert. Da aber nun auch die Absicht sooo eindeutig formuliert ist überlasse ich Dich besser Deiner immerhin schönen, blühenden Phantasie ;-)
Karl H. schrieb: > Denn wann hat schon jemand genau diese Anforderungen, > dass er 2 ADC plus 2 Eingänge hat, die er dann auch noch codiert in 3 > Bytes getaktet übertragen muss. Und zwar GENAU so und nicht anders. Jede > kleinste Abweichung davon - Pech gehabt. Dann stehen massive Analysen > und Änderungen an. Wie würde das Programm eigentlich aussehen, wenn Mobys Sensorplatinchen an das Programm "SerialComInstruments" (Beitrag "Projekt: Virtuelle Instrumente an serielle Schnittstelle") angebunden werden soll, welches Moby so toll findet...?
Karl H. schrieb: > [...] für die digitalen Inputs fällt mir auch noch was ein :-) Reed-Kontakte für Fenster?
Moby A. schrieb: > Karl H. schrieb: >> Moby A. schrieb >>> Eine Softwareuhr zu implementieren ist jedenfalls kein Problem. Je nach >>> Uhrzeit bestimmte Dinge zu erledigen auch nicht. >> >> Na dann mach. > > Die wird hier nicht gebraucht (und wäre ohnehin umständlich zu stellen). In C wäre die nicht umständlich zu erstellen, sondern ganz einfach. Siehst Du die Vorteile des großartigen C gegenüber dem unflexiblen, komplizierten und unleserlichen Assembler?
Sheeva P. schrieb: > Wie würde das Programm eigentlich aussehen, wenn Mobys Sensorplatinchen > an das Programm "SerialComInstruments" > (Beitrag "Projekt: Virtuelle Instrumente an serielle Schnittstelle") angebunden werden soll, > welches Moby so toll findet...? Wahrscheinlich würde ein weiteres Platinchen mit einem Tiny13 dazu kommen, welches das Originalprotokoll auseinandernimmt, die 4 Inforamtionseinheiten wieder extrahiert und per UART auf den Weg schickt. Nur bloss nichts ändern.
Sheeva P. schrieb: > Moby A. schrieb: >> Karl H. schrieb: >>> Moby A. schrieb >>>> Eine Softwareuhr zu implementieren ist jedenfalls kein Problem. Je nach >>>> Uhrzeit bestimmte Dinge zu erledigen auch nicht. >>> >>> Na dann mach. >> >> Die wird hier nicht gebraucht (und wäre ohnehin umständlich zu stellen). > > In C wäre die nicht umständlich zu erstellen der Fairness halber: er schrub 'stellen' und nicht 'erstellen'. Spielt aber keine wirkliche Rolle. Denn wenn die Aufgabenstellung erfordert, dass ein Zeitprofil abgearbeitet werden muss, dann gibts da nichts zu diskutieren. Dann eignet sich seine Vorlage eben nicht dazu, diese "Sensorplatine mit erweiterter Funktionalität" daraus zu entwickeln. Fangen wir eben wieder bei 0 an. Das ist eben die Krux an 'optimalen' Lösungen (so wie Moby sie versteht). Sie sind für genau einen Zweck und nur für diesen einen Zweck optimal. Kleine Abweichungen sind nicht drinn. Ganz krass ist natürlich, wenn diese kleinen Abweichungen nicht nur das Optimalitätskriterium verletzten sondern schlicht ohne massiven Aufwand nicht machbar sind.
:
Bearbeitet durch User
Karl H. schrieb: > per UART auf den Weg schickt. UART? Seit wann hat ein ATtiny13 sowas? Der hat doch nichtmal eine USI … Daher kann sich Moby ja auch so schöne eigene Protokolle ausdenken, mit einer 2-Bit-Prüfsumme und so. Klar, das schlägt kein C-Programmierer, der würde zur Datensicherung wohl eher zu einer ordentlichen CRC greifen (schon deshalb, weil's dafür ja ein passendes Headerfile gibt :).
Sheeva P. schrieb: > Wie würde das Programm eigentlich aussehen, wenn Mobys Sensorplatinchen > an das Programm "SerialComInstruments" > (Beitrag "Projekt: Virtuelle Instrumente an serielle Schnittstelle") angebunden werden soll, > welches Moby so toll findet...? Die Platine muss nicht angebunden werden. Die Aufgabenstellung war vorher klar definiert, eine Anbindung war nicht vorgesehen. Ihr C-ler immer mit eurer "Flexibikität", die im Hobby doch eh nicht notwendig ist. Macht euch halt vorher mal Gedanken was ihr in eurem Projekt braucht... Hachja, nach 5-monatiger MC.net Abstinenz fühl ich mich gleich wieder wie zu Hause. Köstliche Unterhaltung mit den bekannten Gesichtern. Nur eines hat sich geändert: damals sah ich Moby als penetrante Nervensäge, die aber fachlich was drauf hat. Immerhin arbeitet er seit zig Jahren mit Assembler. Nun aber, tut mir Leid, ist "Witzfigur" die einzig treffende Bezeichnung. Fachlich ne Niete (sorry, deine Programme sind lächerlich), noch schlimmer aber in Punkto Sozialkompetenz. Hauptsache zum x-ten Mal die Floskel der "typischen 8 Bit Anwendungen " bemüht... Oder auf "bockig" umgeschaltet (gibts nicht, Basta!) Ich glaub langsam echt, wenn die Register nicht reichen wird lieber ein neuer Tiny drangepappt bevor man sich über Stack etc. Gedanken machen müsste...
Karl H. schrieb: > der Fairness halber: er schrub 'stellen' und nicht 'erstellen'. Lass mal, das ist doch egal. Er versteht sowieso alles wie er es braucht ;-) Karl H. schrieb: >> Wenigstens ein paar Leute hier die versuchen, meinen Aussagen auf den >> technischen Grund zu gehen. Danke. > > Och, das können praktisch alle hier Wie man wohl zu diesem Eindruck gelangen kann? Karl H. schrieb: > OCR0A = 8; > ist vollkommen äquivalent zu ldi r16,8 > out OCR0A,r16 > und wird vom Compiler auch genau dazu umgesetzt (mit dem einen kleinen > Unterschied, dass es mich in der C Version nicht interessiert, welches > Register der Compiler nimmt um die Konstante zu laden). Tja nur dumm daß man 'OCR0A' in C genauso kennen muß. Mit Asm wird der eigentliche Vorgang des Ladens zudem transparenter dargestellt. Welches Register das nun nach Lust und Laune erledigt ist wurscht solange LDI darauf angewendet werden kann. > Und wenn das OCR0A auf einem Prozessor nicht mittels OUT erreichbar > ist, dann ist mir das ebenfalls wurscht - Sache des Compilers die > Operation mit einem STS in die Wege zu leiten. Bei der überschaubaren AVR Typenpalette kennt man seine Schäfchen. Und wenn nicht probiert man einfach OUT: Der Assembler meckert dann schon! > warum 8, wo > kommen die her, kann ich die Konsante so formulieren, dass da nicht 8 > als Zahlenwert steht sondern für alle nachvollziehbar dort steht wie > sich die 8 berechnen? Das ist dem Blick ins Datenblatt überlassen. Das bläht Quellcode nur auf. Aber wenn eine Info aus irgendeinem anderen Zusammenhang für das Verständnis der Funktion wirklich wichtig sein sollte- ja dann mach ich halt einen Kommentar dazu.
le x. schrieb: > Ich glaub langsam echt, wenn die Register nicht reichen wird lieber ein > neuer Tiny drangepappt Die haben noch immer gereicht! Aufrüsten tut eher der C-ler ;-)
Jörg W. schrieb: > mit einer 2-Bit-Prüfsumme Nun Jörg, dafür langte der Platz noch und die ist nicht nur besser als nix sondern auch ausreichend. Ist natürlich nichts für Sicherheitsfanatiker, das geb ich unumwunden zu ;-)
Moby A. schrieb: > Karl H. schrieb: >> OCR0A = 8; >> ist vollkommen äquivalent zu ldi r16,8 >> out OCR0A,r16 >> und wird vom Compiler auch genau dazu umgesetzt (mit dem einen kleinen >> Unterschied, dass es mich in der C Version nicht interessiert, welches >> Register der Compiler nimmt um die Konstante zu laden). > > Tja nur dumm daß man 'OCR0A' in C genauso kennen muß. Hab ich was anderes behauptet? Ich denke das hat hier noch nie irgendwer anders behauptet. Nur weil du C programmierst, bedeutet das nicht, dass die entsprechenden "Register Summary" Abschnitte im Datenblatt zum Altpapier wandern. > Mit Asm wird der eigentliche Vorgang des Ladens zudem transparenter > dargestellt. Welches Register das nun nach Lust und Laune erledigt ist > wurscht solange LDI darauf angewendet werden kann. Das wars. Mir reichts. Du bist unbelehrbar. Ich versuch dir eine Brücke zu bauen und du nimmst nichts an. Gar nichts. Du bist wie ein sturer Esel. Aber ich warne dich: bei der nächsten 'Nimm doch Assembler' Meldung in einem C Thread, wird gelöscht.
:
Bearbeitet durch User
Karl H. schrieb: > Dann eignet sich seine Vorlage eben nicht dazu, > diese "Sensorplatine mit erweiterter Funktionalität" daraus zu > entwickeln. Fangen wir eben wieder bei 0 an. Dann fängt man besser zuvor gar nicht erst mit meinem Projekt an... Nennt sich Vorüberlegung. Oder steht der Anspruch auf Nutzungsmöglichkeit in beliebigen Projekten etwa in den Forenregeln ? ;-) Karl H. schrieb: > Sie sind für genau einen Zweck und nur für diesen einen Zweck > optimal. Genau! Wobei das Funktions- Prinzip durchaus auch anderswo Verwendung finden kann. Eine optimale- oder sagen wir besser dem Optimum angenäherte Umsetzung und die Flexibilität von C- das beißt sich. le x. schrieb: > Oder auf "bockig" umgeschaltet (gibts nicht, Basta!) Hardware-Tatsachen sind so wie sie sind. Basta! ;-)
Moby A. schrieb: > Die haben noch immer gereicht! > Aufrüsten tut eher der C-ler ;-) Echt jetzt? In deinen zig-Jahren Assembler- und Avr -Entwicklung haben dir immer die Register gereicht?! Ist ja auch schön für dich und in Ordnung. Wirklich. Aber dann erzähl doch bitte keine Weisheiten übers Programmieren. Ich erzähl dir ja auch nix übers imkern...
Moby A. schrieb: > Das ist dem Blick ins Datenblatt überlassen. Ah, der zwangsneurotische Sprachcomputer hat per Zufallsgenerator wieder das Schlagwort "Blick ins Datenblatt" ausgewählt. TASK WEITERPLAPPERN - 100% Was ist jetzt mit meinem "schlechten" Assemblerprojekt?
Moby A. schrieb: > Tja nur dumm daß man 'OCR0A' in C genauso kennen muß. > Mit Asm wird der eigentliche Vorgang des Ladens zudem transparenter > dargestellt. Welches Register das nun nach Lust und Laune erledigt ist > wurscht solange LDI darauf angewendet werden kann. > Das ist dem Blick ins Datenblatt überlassen. > Das bläht Quellcode nur auf. Selten so einen Stuss gehört. Am besten wir hören auf.
Horst S. schrieb: > Was ist jetzt mit meinem "schlechten" Assemblerprojekt? Das hättest du auf vier ATtiny13 aufteilen müssen. :)
@ Karl Heinz (kbuchegg) (Moderator) >Das wars. >Mir reichts. Du bist unbelehrbar. Ich versuch dir eine Brücke zu bauen >und du nimmst nichts an. Gar nichts. Du bist wie ein sturer Esel. Mensch Karl Heinz, du hast aber auch eine VERDAMMT lange Leitung! Ausdauer und Grundschullehrergeduld sind schön und gut, man sollte aber dennoch keine Perlen vor die Säue werfen. >Aber ich warne dich: bei der nächsten 'Nimm doch Assembler' Meldung in >einem C Thread, wird gelöscht. ;-)
Karl H. schrieb: > Du bist wie ein sturer Esel. Sollte man auf diese Bezeichnung zurückgreifen wenn man nicht mehr weiter weiß ? Welchen Wert haben Brücken zu suboptimalen, aufwendigeren Lösungen? Warum sollten eigentlich mir manch C-ler hier nicht wie ein sturer Esel erscheinen? Karl H. schrieb: > Aber ich warne dich: bei der nächsten 'Nimm doch Assembler' Meldung in > einem C Thread, wird gelöscht. Schade. Klingt schon wieder wie eine Kapitulationserklärung. Asm vs. C wird in entsprechendem Zusammenhang immer ein Thema bleiben. Matthias L. schrieb: > Selten so einen Stuss gehört. Am besten wir hören auf. Du mußt Dich zu "Stuss" ja nicht äußern ;-)
le x. schrieb: > Echt jetzt? Ja, echt jetzt. Aber könnte sein daß es ohne Erfahrung nicht so einfach ist ;-)
Moby A. schrieb: > Asm vs. C wird in entsprechendem Zusammenhang immer ein Thema bleiben. Bitte aber in deinen eigenen Threads. Allein dieser Thread zeigt, dass deine Diskussionskultur keinerlei Nutzen für den TE hat(te). Wenn du nicht gewillt bist, wirklich jemandem zu helfen, dann halt' dich bitte aus fremden Threads fern. Nein, ein pauschales „in Assembler geht das sowieso alles besser“ ist keine Hilfe.
Moby A. schrieb: > Mit Asm wird der eigentliche Vorgang des Ladens zudem transparenter > dargestellt. Was interessiert es dich wie die 8 ins OCR0A kommt? Wichtig ist ja nur, dass sie drin steht. Wenn es hingegen wirklich wichtig ist, dass das in einer genauen Anzahl Instruktionszyklen passiere, wäre ASM angebracht. > Welches Register das nun nach Lust und Laune erledigt ist > wurscht solange LDI darauf angewendet werden kann. Genau deswegen kann man das auswählen auch dem Compiler überlassen. Vllt. findet er auch noch eines wo "zufällig" seit 20 Zeilen schon eine 8 drinsteht. Moby A. schrieb: > Warum sollten eigentlich mir manch C-ler hier nicht wie ein > sturer Esel erscheinen? Vielleicht weil viele "C-ler", im Gegensatz zu dir, auch die andere Seite (ASM) kennen und fundierte Entscheidungen treffen können. Du erinnerst mich irgendwie an einen ex-Schulkollegen der keinen Fisch mag, er hatte ihn zwar noch nie probiert, er weiß es einfach... Wie kommt es eigentlich, dass deine Aussagen kaum Unterstützung finden? Sind so gut wie alle hier auf dem Irrweg, oder vielleicht doch du?
Stefan K. schrieb: > Sprich: Asm > ohne Kommentare geht gar nicht, gut geschriebenes C kommt an den meisten > Stellen auch ohne Kommentare aus. Du meinst wenn Funktionen aussagekräftige Namen haben? Das geht in Asm genauso. asm ist zunächst mal eines: Schlicht. Eindeutig. Transparent. Keine ausschweifende Klammerwüste mit x Ebenen und komplexen Ausdrücken in denen x Sprachelemente verwurstet sind ;-) Rea L. schrieb: > Wie kommt es eigentlich, dass deine Aussagen kaum Unterstützung finden? Nun, C mag durchaus von der Mehrheit angewendet werden. Viele können wohl nur noch Hochsprache. Ist dann wohl irgendwie schmerzlich mit einer effizienteren Programmierweise konfrontiert zu werden? Bei soviel Emotion hier hat man ja fast das Gefühl, man läßt Welten zusammenstürzen ;-) > Sind so gut wie alle hier auf dem Irrweg, oder vielleicht doch du? Hatten wir das nicht schon? Wer eine funktionierende Lösung vorzeigt ist nicht auf dem Irrweg. Hier geht es aber eher um technische Feinheiten (mit hochemotionaler Begleitmusik allerdings).
Jörg W. schrieb: > Nein, ein pauschales „in Assembler geht das sowieso alles besser“ ist > keine Hilfe. Daß alles besser geht hat auch niemand behauptet. Berechnungen zum Beispiel. In Asm sind größere Sachen im Prinzip aufwendiger. Wenn MSR-Projekte größere Berechnungen nicht ständig benötigen fehlt dieses Motiv zum Umstieg aber.
Moby A. schrieb: > Berechnungen zum Beispiel. Komisch, mein Rechner ist zum rechnen da, nicht nur zum Daten schieben, sonst wär's ja 'nen Schieber. Was macht mein "schlechtes" Assemblerprogramm? Auswertung schon fertig?
Moby A. schrieb: > Viele können wohl nur noch Hochsprache. Du solltest eigentlich mittlerweile gemerkt haben, dass das für viele bis alle hier nicht zutrifft. > Ist dann wohl irgendwie schmerzlich mit einer > effizienteren Programmierweise konfrontiert zu werden? Meine Form einer effizienten Programmierung hat einmal darin bestanden, mir für ein Projekt auf Z80 Basis einen sehr einfachen Compiler zu stricken. Eigentlich eher ein Mix aus einer eigenen simplen Sprache und Assembler. Damit das Programm besser les- und wartbar ist. Ist schon etwas älter, brauchbares C für Z80 gab es nicht. Der plz.y Quelltext hat übrigens 2 Compiler zwischen sich und dem Programm, nämlich vorneweg einen Parser-Generator der C Quelltext erzeugt: Beitrag "Re: Gibt es eine Programmiersprache mit diesem Schleifentyp?"
:
Bearbeitet durch User
Moby A. schrieb: > Nun, C mag durchaus von der Mehrheit angewendet werden. Viele können > wohl nur noch Hochsprache. Moby, es ist dir mehrere Male klipp und klar gesagt (und auch mit Codebeispielen gezeigt) worden: hier irrst du gewaltig. So gut wie alle, denen du hier mehr oder weniger Unfähigkeit oder Faulheit unterstellst, haben teils bessere Assemblerkenntnisse als du, haben oft auch weit mehr Architekturen und Assembler benutzen dürfen, als du dir auch nur ansatzweise vorstellen kannst. Trotzdem (oder gerade deshalb) sehen sie darin kein Allheilmittel, für das sie andere evangelisieren müssten. Nochmal: wir werden eine derartige Vereinnahmung beliebiger Threads durch dich in Zukunft nicht mehr dulden. Wenn du denkst, dass du andere davon überzeugen musst, wieviel besser es ist, mit reinem Assembler zum Ziel zu kommen, dann veröffentliche deine eigenen Projekte oder eröffne anderweitig deine eigenen Threads. Für diesen Thread ist alles gesagt worden, was zu sagen war. Horst hatte nach wenigen Stunden ausreichend Hilfe, um selbst gegenüber seiner ursprünglichen Lösung sich gut verbessern zu können. Damit betrachtet er das Thema des Threads als abgeschlossen.
Jörg W. schrieb: > abgeschlossen Schade, ich fand den Thread heute noch einmal richtig unterhaltsam, wobei mir immerhin eines klar geworden ist: Moby A. schrieb: > Zeitmangel fürs Hobby ist freilich der Hauptgrund. Man zähle einfach mal seine Beiträge allein in diesem Thread. Da ist es nicht verwunderlich, dass für die Assemblerprogrammierung kaum Zeit bleibt :)