Hallo
ich lese hier schon seit längerem mit und habe auch schon so manches
Problem lösen können durch die Beiträge anderer User. Heute hab ich auch
mal ein Problem was ich noch nicht lösen konnte.
Ich nutze folgende Funktion um die Parität eines Zeichens zu berechnen
und übergebe dann die 9 Bit an die Hardware-UART. Bei der Compoilierung
werden die beiden Zeilen, die um 1 bzw. 2 Bit shiften einfach
wegoptimiert, alle anderen bleiben bestehen.
Wie kann das sein? Wie kann ich das verhindern?
Silvio
Kein Name schrieb:> Der Backslash maskiert das Newline?
Oh, ja. Der Programmier-Fehler ist wirklich fies.
INteressant ist, dass auch die Forensoftware das hinkriegt, dass die
beiden Zeilen auskommentiert sind, weil sie mit dem \ alle zu einer
Zeile zusammengezogen wurden und daher alles nach dem \\ in der ersten
Zeile als Kommentar gewertet wird. Hätte ich jetzt nicht gedacht, dass
die das schafft.
bist du dir sicher, dass die Paritätsberechnung mit einem nicht näher
bekannten Wert von bit9 beginnen soll?
Alles in allem ist deine Paritätsberechnung mit den vielen
Schiebeoperationen alles andere als µC-schonend implementiert. Hoffen
wir mal, dass der Optimizer des Compilers erkennt, dass er das jeweilige
Ergebnis der Stufe davor weiterverwenden kann.
Hallo
auf diese Idee mit dem fortsetzen der Zeile bin ich noch gar nicht
gekommen. Ich dachte imme nach // ist alles Kommentar bis zum Zeilenende
also auch ein \. Habe aber jetzt im Disassambly Listing gesehen daß auch
an anderen Stellen was als Kommentar angesehen wurde was eigentlich Code
sein sollte. Hat aber bisher keine Auswirkungen gehabt weil in der
Initialisierung und nur bei Werten die ich auch so setze wie sie nach
einem Reset automatisch sind.
Mit dem Startwert für bit9 ist geändert. Die Berechnung in Assambler
erfolgt folgendermaßen:
bit9 testen
Ergebnis in temporäre Speicherstelle
Zeichen laden
Zeichen shiften
Zeichen Bit 0 testen
Ergebnis in Arbeitsregister
XOR von Arbeitsregister und temporärer Speicherstelle
Ergebnis in Arbeitsregister
Arbeitsregister Bit 0 testen
Ergebnis in Bit9 speichern
Ist für alle 8 Bit gleich bis auf die Anzahl der Stellen beim Shift.
Sollte also passen. Für die Berechnung werden etwa 200 Assambler-Befehle
gebraucht.
Vielen dank für die Hilfe, ohne euch hätte ich den Fehler garantiert
nicht gefunden.
Silvio
Hallo
ich habe jetzt vor der Berechnung bit9 auf 0 gesetzt. Damit kann der
Code so bleiben.
Die ASM-Variante ist zwar schön kurz und auch schnell, aber da ich weder
mit dem Platz (8k Befehle, 4k genutzt) noch der Ausführungszeit (ca.
40µs) Probleme habe werde ich das erstmal so lassen.
Der ASM-Code der erzeugt wird ist im Anhang.
Silvio
Silvio G. schrieb:> Die ASM-Variante ist zwar schön kurz und auch schnell
Sorry. Das würde ich weder kurz noch schnell nennen.
Probier mal diese Variante, ob die schneller geht bzw. weniger Code
produziert
1
unsignedcharParity(unsignedchari)
2
{
3
staticconstunsignedcharnibbleParity[]=// die Parität für jeweils 4 Bit
Silvio G. schrieb:> Hallo>> auf diese Idee mit dem fortsetzen der Zeile bin ich noch gar nicht> gekommen. Ich dachte imme nach // ist alles Kommentar bis zum Zeilenende> also auch ein \.
Die Reihenfolge in der der Präprozessor arbeitet ist:
Zuerst Line Continuations zusammenziehen
dann Kommentare durch 1 Leerzeichen ersetzen
Hallo
mit dem schnell und kurz meinte ich aus dem Post vor mit das
swap...
Meine Version sind ca. 300 Befehlszyklen bei ca. 200 Befehlen.
Die Funtion Parity ergibt 74 Befehle mit ca. 130 Befehlszyklen (ASM im
Anhang).
Silvio
Silvio G. schrieb:> Die Funtion Parity ergibt 74 Befehle mit ca. 130 Befehlszyklen (ASM im> Anhang).
Zähl nochmal nach und lass dabei jene Daten weg, die nicht dazu gehören.
Von der Tabelle sind nur die ersten 16 relevant, der Rest sind
irgendwelche Strings.
Silvio G. schrieb:> Die Funtion Parity ergibt 74 Befehle mit ca. 130 Befehlszyklen (ASM im> Anhang).
Autsch.
Wenn der Compiler ein static Array so einbaut, dass er es jedesmal beim
Betreten der Funktion wieder neu erzeugt, würde ich ganz schnell den
Compiler wechseln.
Karl Heinz Buchegger schrieb:> Wenn der Compiler ein static Array so einbaut, dass er es jedesmal beim> Betreten der Funktion wieder neu erzeugt, würde ich ganz schnell den> Compiler wechseln.
Wie kommst du darauf?
Karl Heinz Buchegger schrieb:> Silvio G. schrieb:>>>> Die Funtion Parity ergibt 74 Befehle mit ca. 130 Befehlszyklen (ASM im>> Anhang).>>> Autsch.> Wenn der Compiler ein static Array so einbaut, dass er es jedesmal beim> Betreten der Funktion wieder neu erzeugt, würde ich ganz schnell den> Compiler wechseln.
Edit:
Was treibt der Compiler da? Da ist noch mehr in der Funktion als nur die
Tabelle.
Hast du den Optimizer eingeschaltet?
Oder die Generierung von Debug-Information aktiviert?
@ A. K.
leider nicht, da es für den Compiler 3 Varianten gibt. Die besseren
beiden kosten Geld, die schlechteste ist frei. Die beste Variante soll
um 40% kleineren Code erzeugen.
Silvio
A. K. schrieb:> Karl Heinz Buchegger schrieb:>> Wenn der Compiler ein static Array so einbaut, dass er es jedesmal beim>> Betreten der Funktion wieder neu erzeugt, würde ich ganz schnell den>> Compiler wechseln.>> Wie kommst du darauf?
OK. Ich bin nicht 100% sicher. Aber das hier
1
653:unsignedcharParity(unsignedchari)
2
654:{
3
655:staticconstunsignedcharnibbleParity[]=// die Parität für jeweils 4 Bit
Karl Heinz Buchegger schrieb:> Oder die Generierung von Debug-Information aktiviert?
Da sind beim Disassembleren irgendwelche Strings mit zugerordnet worden,
die nicht zu diesem Teil des Codes zählen aber keine Symbole haben.
Silvio G. schrieb:> leider nicht, da es für den Compiler 3 Varianten gibt. Die besseren> beiden kosten Geld, die schlechteste ist frei. Die beste Variante soll> um 40% kleineren Code erzeugen.
Gratuliere. Der erzeugte Code der ersten Variante ist selbst für einen
nicht optimierenden Compiler geradezu abschrenkend schlecht.
A. K. schrieb:> Karl Heinz Buchegger schrieb:>> Oder die Generierung von Debug-Information aktiviert?>> Da sind beim Disassembleren irgendwelche Strings mit zugerordnet worden,> die nicht zu diesem Teil des Codes zählen aber keine Symbole haben.
Sieht wohl so aus. Mal rückübersetzen
1
0273 3420 RETLW 0x20 ' '
2
0274 3450 RETLW 0x50 'P'
3
0275 3461 RETLW 0x61 'a'
4
0276 3472 RETLW 0x72 'r'
5
0277 3469 RETLW 0x69 'i'
6
0278 3474 RETLW 0x74 't'
7
0279 3461 RETLW 0x61 'a'
8
027A 3465 RETLW 0x65 'e'
9
027B 3474 RETLW 0x74 't'
10
027C 3420 RETLW 0x20 ' '
11
027D 3400 RETLW 0
12
027E 3430 RETLW 0x30 '0'
13
027F 3431 RETLW 0x31 '1'
14
0280 3432 RETLW 0x32 '2'
15
0281 3433 RETLW 0x33 '3'
16
0282 3434 RETLW 0x34 '4'
17
0283 3435 RETLW 0x35 '5'
18
0284 3436 RETLW 0x36 '6'
19
0285 3437 RETLW 0x37 '7'
20
0286 3438 RETLW 0x38 '8'
21
0287 3439 RETLW 0x39 '9'
22
0288 3400 RETLW 0
23
0289 3420 RETLW 0x20 ' '
24
028A 3457 RETLW 0x57 'W'
25
028B 3465 RETLW 0x65 'e'
26
028C 3472 RETLW 0x72 'r'
27
028D 3474 RETLW 0x74 't'
28
028E 3420 RETLW 0x20 ' '
29
028F 3400 RETLW 0
30
0290 344E RETLW 0x4e 'N'
31
0291 3472 RETLW 0x72 'r'
32
0292 342E RETLW 0x2e '.'
33
0293 3420 RETLW 0x20 ' '
34
0294 3400 RETLW 0
35
0295 3430 RETLW 0x30 '0'
36
0296 3431 RETLW 0x31 '1'
37
0297 3400 RETLW 0
Jep. Das sind wohl Strings von woanders aus dem Programm, die nur
zufällig hier beim Disassemblieren mitgekommen sind. Die eigentliche
Funktion ist das hier