Forum: Compiler & IDEs Unsigned Char vergleich beim AVR GCC


von Clemens H. (sum)


Lesenswert?

Hallo Leute,

ich habe jetzt schon diverse stellen gefunden, die der GCC einfach mal
miserabel löst. Hier die für mich bedeutenste:
1
  44:dcf77.c       ****     if ((unsigned char)((unsigned
2
char)dcf77_State & (unsigned char)DCF77_StateMask) != (unsigned
3
char)DCF77_StateSense) return;
4
 147                 .LM5:
5
 148 0016 8091 0000     lds r24,dcf77_State
6
 149 001a 9927          clr r25
7
 150 001c 8C70          andi r24,lo8(12)
8
 151 001e 9070          andi r25,hi8(12)
9
 152 0020 0C97          sbiw r24,12
10
 153 0022 41F4          brne .L2

Es ist alles nach (unsigned char) gecastet und dennoch macht der gcc
daraus eine Integer operation (16 Bit). Erst wenn ich eine Register
variable definiere, die den berechneten Wert erhält, wird der Vergleich
ein simpler 8-Bit-Vergleich:
1
  43:dcf77.c       ****   register unsigned char temp = (dcf77_State &
2
DCF77_StateMask);
3
 146                 .LM5:
4
 147 0014 8091 0000     lds r24,dcf77_State
5
 148 0018 8C70          andi r24,lo8(12)
6
  45:dcf77.c       ****   if (temp != DCF77_StateSense) return;
7
 150                 .LM6:
8
 151 001a 8C30          cpi r24,lo8(12)
9
 152 001c 41F4          brne .L2

Wieso bekommt er das nicht auch schon beim casten hin oder merkt es gar
selber, dass nur 8-bit-Werte beteiligt sind?

Irgendwie hat Assembler schon so seine Vorteile.

Schöne Grüße, Clemens

von A.K. (Gast)


Lesenswert?

Wenn die avr-libc nicht benötigt wird, wirkt -mint8 bisweilen Wunder.

von Clemens H. (sum)


Lesenswert?

Hi,

ja, das geht wohl. Allerdings werden dann meine unsigned short
variablen auch alle nur  bit lang :(.

Also kein Ausweg bisher.

danke schonmal und schöne Grüße, Clemens

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

kurz:
Der C-Standard verlangt das so.

lang:
Forensuche.

Matthias

von A.K. (Gast)


Lesenswert?

Wenn man im eigenen Programm konsequent die Typen aus stdint.h
verwendet, ist -mint8 nur dann Problem, wenn man 32bit braucht und
nicht ersatzweise mit 64bit leben kann. Oder wenn man printf() und
ähnliche aus der libc benötigt.

Der C Standard verlangt zwar, dass int >= 16bit und dass alle Rechnung
so ausgeführt wird, als ob alles kleinere zu 16bit konvertiert wird.
Aber er verlangt natürlich nur, dass das Ergebnis diesem Verfahren
entspricht. Wenn sich das exakt gleiche Ergebnis wie hier mit reiner
8bit-Rechnung ermitteln lässt - warum nicht?

Es gibt schon so ein paar Ecken im Compiler, die einen erstaunen
können. So neigt er bei manchen 2-er-Potenz Bitmasken dazu, den
Operanden erst umständlichst nach rechts zu schieben um dann Bit 0
testen zu können, statt gleich auf's gewünschte Bit loszugehen. Nobody
is perfect, auch gcc/avr nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Wenn sich das exakt gleiche Ergebnis wie hier mit reiner
> 8bit-Rechnung ermitteln lässt - warum nicht?

Klar, es müsste ihm ,,nur'' jemand beibiegen.  Da alle
Architekturen,
für die am GCC ,hauptberuflich' gebaut wird, dieses Problem aber
nicht
haben (deren Register sind eh' alle 32 bits breit), muss sich da wohl
jemand aus der Microcontroller-Ecke drum kümmern, dass derartige
Optimierungen eingebaut werden.

von A.K. (Gast)


Lesenswert?

Das ist ja das ulkige daran, die Optimierungen sind schon drin. Meist
macht er es auch richtig, nur manchmal nicht, dann aber ist jeder Cast
wirkungslos. Eine Logik dahinter konnte ich noch nicht erkennen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.