Forum: Compiler & IDEs avr-gcc verwendet sbiw um einen 8-Bit Rueckgabewert zu vergleichen.


von Tobias Schneider (Gast)


Lesenswert?

Hi,

mein avr-gcc hat mit unter Ubuntu 13.04 mit -O2 folgendes produziert:
1
  
2
3
    void bar(void)
4
    {
5
        if( foo() == 1 )
6
      94:   0e 94 53 00     call    0xa6    ; 0xa6 <foo>
7
      98:   01 97           sbiw    r24, 0x01       ; 1
8
      9a:   11 f0           breq    .+4             ; 0xa0 <bar+0xc>
9
            return 1;
10
        uint8_t a = foo();
11
      9c:   0c 94 53 00     jmp     0xa6    ; 0xa6 <foo>
12
      a0:   08 95           ret
13
     
14
    000000a2 <main>:
15
        return 2;
16
    }
17
     
18
    void main(void)
19
    {
20
        bar();
21
      a2:   0c 94 4a 00     jmp     0x94    ; 0x94 <bar>
22
     
23
    000000a6 <foo>:
24
    #include <stdint.h>
25
    uint8_t foo(void)
26
    {
27
        return 1;
28
    }
29
      a6:   81 e0           ldi     r24, 0x01       ; 1
30
      a8:   08 95           ret

Wie zu sehen ist, gibt foo() einen 8-Bit grossen Wert in r24 zurueck. 
Danach testet der Compiler das Ergebnis mit sbiw, welched r24:r25 
anschaut. Das ganze hat mir in einem komplexeren Programm schon Probleme 
bereitet. Wenn ich die if-Abfrage durch
1
uint8_t baz=foo(); if( baz == 1 ) {...}
ersetzte, wird cpi zum Vergleichen genommen und das Ergebnis ist wie 
erwartet.

Bug im Compiler oder nur mein Tunnelblick?

Gruss,
Tobias

von Marius W. (mw1987)


Lesenswert?

War da nicht was mit Integer-Promotion? Probier mal
1
if( foo() == (uint8_t)1 )

Gruß
Marius

EDIT: siehe 
http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Logische_Operatoren_werden_auf_int-Gr.C3.B6.C3.9Fe_erweitert

von Karl H. (kbuchegg)


Lesenswert?

Tobias Schneider schrieb:

> Wie zu sehen ist, gibt foo() einen 8-Bit grossen Wert in r24 zurueck.
> Danach testet der Compiler das Ergebnis mit sbiw, welched r24:r25
> anschaut. Das ganze hat mir in einem komplexeren Programm schon Probleme
> bereitet.

Da würde ich doch glatt mal schätzen, dass du es mit Funktionsprototypen 
nicht so genau nimmst (bzw. die entsprechenden Compilerwarnungen 
ignorierst) und du so den Compiler zu der Standard-Annahme zwingst, dass 
jede Funktion von der er nichts genaueres weiß einen 16-Bit int zurück 
liefert, den er dann natürlich auch einem 16-Bit Vergleich unterziehen 
muss.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Welche Compilerversion ist das?

Wie ist der Code für foo?

Was ist das Problem mit SBIW?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hast du für foo einen Prototyp definiert vor dem Aufruf?

von Tobias Schneider (Gast)


Lesenswert?

Gna, Ihr habt absolut recht.

Hatte das urspruenglich in nem groesseren Programm, den Header nicht 
eingebunden und die eine Warnung uebersehen...

Ja, der Compiler hat dann als Rueckgabetyp int(?) eingesetzt und den 
16-Bit Vergleich durchgefuehrt.

Zu mindest ich hab jetzt meine Lektion gelernt ;)

Danke fuer die Hinweise.

Gruss,
Tobias

von Malte S. (maltest)


Lesenswert?

1:0 für -Werror
Ja, es gibt gcc-Warnungen, die sind eher lästig und im konkreten Fall 
total überflüssig. Sind aber i.d.R. nicht viele und durch einen Satz 
Klammern o.ä. behoben.
In viel viel mehr Fällen sind die Warnungen sehr berechtigt. Da hilft 
-Werror gegen das Übersehen.

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.