www.mikrocontroller.net

Forum: GCC GCC ARM Cortex-M3: Merkwürdiger Assembler Code von C++-Routinen


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Martin (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

ich habe gerade ein kleines C++-Test-Programm geschrieben und wundere 
mich, warum der compilierte Code so merkwürdig aussieht. Offensichtlich 
wird in der Init()-Routine der Zugriff auf data in 4 einzelnen 
Byte-Zugriffen geschrieben, obwohl die Daten Word-aligned im Speicher 
liegen und der Cortex-M3 den str-Befehl auch auf unaligned-Adressen 
anwenden könnte.

Hier der C++-Code und der Disassembler-Code (einmal mit -Os und einmal 
mit -O3 compiliert). Das zieht sich so durch den ganzen Code durch! Hat 
jemand eine Ahnung, wie man dem GCC diese Ineffizienz abgewöhnen kann? 
Eigentlich sollte doch ein einziges
str    r2, [r0, #0] 
ausreichen, oder sehe ich das falsch?

Vielen Dank für Hinweise.
Martin


Compiler-Aufruf (ich verwende Sourcery G++ Lite):
arm-none-eabi-gcc -o test1.o -c -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER 
-Wall -mcpu=cortex-m3 -mthumb -g3 -gdwarf-2 -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -fno-inline 
-ffunction-sections -fdata-sections  -fno-rtti -fno-exceptions test1.cc
class test1
{
  public:
    void Init( void );
    void Cyclic( void );
    int  GetResult( void );
    
  private:
    int  data;
    
};

void test1::Init( void )
{
  data = 17;
}
void test1::Cyclic( void )
{
  if( data & 1 )
  {
    data = (data >> 1) | 0x1000;
  } else 
  {
    data = (data >> 1);
  }
}  
int   test1::GetResult( void )
{
  return data;
}



Assembler-Code für Init-Routine:
Optimierung -O3:
void test1::Init( void )
{
    data = 17;
 8000d30:   2300        movs    r3, #0
 8000d32:   2211        movs    r2, #17
 8000d34:   7002        strb    r2, [r0, #0]   <-- hier werden 4 Byte eines int einzeln gespeichert !!!
 8000d36:   7043        strb    r3, [r0, #1]
 8000d38:   7083        strb    r3, [r0, #2]
 8000d3a:   70c3        strb    r3, [r0, #3]
}
 8000d3c:   4770        bx  lr
 8000d3e:   bf00        nop
 
Optimierung -Os:
void test1::Init( void )
{
    data = 17;
 80009b0:   2300        movs    r3, #0
 80009b2:   2211        movs    r2, #17
 80009b4:   7002        strb    r2, [r0, #0]   <-- hier werden 4 Byte eines int einzeln gespeichert !!!
 80009b6:   7043        strb    r3, [r0, #1]
 80009b8:   7083        strb    r3, [r0, #2]
 80009ba:   70c3        strb    r3, [r0, #3]
}
 80009bc:   4770        bx  lr

Autor: Peter II (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
sinnvoller dürfte das sein:
void test1::Init( void )
:  data(17)
{
}

schaum mal ob sich da etwas ändert.

Autor: Martin (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Das geht nicht, da Init() kein Constructor ist.

Init() war hier auch nur als einfaches Beispiel gedacht -- alle 
Word-Zugriffe werden als 4 einzelne Byte-Zugriffe übersetzt, was einfach 
ineffizient ist.

Autor: ich (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

ohne -fpack-struct wird daraus bei mir (Sourcery gcc version 4.6.1):
movs  r3, #17
str  r3, [r0, #0]

mit -fpack-struct erhalte ich das selbe Ergebniss wie du.

Autor: Martin (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
So einfach ist das also -- und schon sieht der Assembler-Code vernünftig 
aus!

Danke!!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net