Hallo zusammen.
Na M1.R, da hast du ja was grauenvoll teuflisches entdeckt
.
Ich habe mal alle Varianten zu folgendem ausprobiert mit Optimizermode "-Os" (Größe): (Versionen: avr-gcc (GCC) 4.1.2 (WinAVR 20070525))
-- Als Variable
int8_t a=0;
char a=0;
-- Als Funktion
usart_put_int (a);
usart_put_int ((int8_t) a);
usart_put_int8_t (a);
-- Als Rechnung
a=a+1;
a+=1;
a++;
Es gibt nur genau eine Funktion, die zu jeder Variablen/Rechnungs-Kombination das richtige Ergebnis liefert.
==> Das ist die Funktion usart_put_int8_t() mit dem Parametertyp int8_t
- Das casten hatte nichts gebracht und lieferte beim a++ genau das gleiche falsche Ergebnis.
- Zu jeder anderen Variablen/Funktions-Kombination, also eigentlich mit falschem Parametertyp, hatte es keinerlei Warning vom Compiler gegeben. Auch dann nicht, wenn alle Funktionen als Prototypen angegeben waren.
- In allen Fällen wurde die Variable a als 16-Bit-Zahl immer in 2 Registern gehalten.
Hier der kommentierte Output vom Compiler im Fehlerfall mit a++:
Code:
Variante 03: int8_t a++;
int8_t a=0;
158: c0 e0 ldi r28, 0x00 ; 0 <<== Byte 1 für a
15a: d0 e0 ldi r29, 0x00 ; 0 <<== Byte 2 für a
usart_put_int (a);
15c: ce 01 movw r24, r28 <<== Ein WORT wird bewegt
15e: c6 df rcall .-116 ; 0xec <usart_put_int>
a++;
166: 21 96 adiw r28, 0x01 ; 1 <<== Ein WORT wird in a addiert
Hier der kommentierte Output vom Compiler im zufällig funktionierenden Fall mit a=a+1:
Code:
Variante 01: int8_t a=a+1
int8_t a=0;
158: c0 e0 ldi r28, 0x00 ; 0 <<== Byte 1 für a
15a: d0 e0 ldi r29, 0x00 ; 0 <<== Byte 2 für a
usart_put_int (a);
15c: 8c 2f mov r24, r28 <<== EIN Byte von a für Parameter
15e: 99 27 eor r25, r25 <<== Vorbelegung Byte 2 für Parameter
160: 87 fd sbrc r24, 7 <<== Vorzeichen Low-Byte a prüfen
162: 90 95 com r25 <<== Vorzeichen vom Parameter auf - setzen
164: c3 df rcall .-122 ; 0xec <usart_put_int>
a=a+1;
16c: 21 96 adiw r28, 0x01 ; 1 <<== Ein WORT wird in a addiert
Weiterer Versuch mit:
volatile int8_t a=0;
Nur jetzt wird die Variable als ein Byte im Speicher gehalten. Das 2.te Byte zum Aufrufen der INT-Parameter-Funktion wird immer mit korrektem Vorzeichen erzeugt.
- Soll heissen: Es kommt immer das richtige Ergebnis zustande.
Es bleibt: Parameter müssen passen.
Es verwundert: Kein Warning vom Compiler.
Es staunt, grüßt und trinkt nun ein Bier:
Sternthaler
P.S.: Ein Versuch, so wie von Radbruch, dass alle Varianten in einem Programm getestet werden, hat vollkommen andere Verhältnisse gebracht.
Selbst mehrere Variablen mit unterschiedlichen Startwerten konnte den Optimierer meistens nicht dazu bewegen nicht doch nur immer eine Variable zu erzeugen.
Bei Radbruch wird die "falsche" Variable b wegoptimiert.
Und dann wäre da noch die "fähige" Funktion:
void usart_put_int8_t (int8_t wert)
{
usart_put_int ((int)wert);
}
Lesezeichen