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


von Martin (Gast)


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
1
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
1
class test1
2
{
3
  public:
4
    void Init( void );
5
    void Cyclic( void );
6
    int  GetResult( void );
7
    
8
  private:
9
    int  data;
10
    
11
};
12
13
void test1::Init( void )
14
{
15
  data = 17;
16
}
17
void test1::Cyclic( void )
18
{
19
  if( data & 1 )
20
  {
21
    data = (data >> 1) | 0x1000;
22
  } else 
23
  {
24
    data = (data >> 1);
25
  }
26
}  
27
int   test1::GetResult( void )
28
{
29
  return data;
30
}


Assembler-Code für Init-Routine:
1
Optimierung -O3:
2
void test1::Init( void )
3
{
4
    data = 17;
5
 8000d30:   2300        movs    r3, #0
6
 8000d32:   2211        movs    r2, #17
7
 8000d34:   7002        strb    r2, [r0, #0]   <-- hier werden 4 Byte eines int einzeln gespeichert !!!
8
 8000d36:   7043        strb    r3, [r0, #1]
9
 8000d38:   7083        strb    r3, [r0, #2]
10
 8000d3a:   70c3        strb    r3, [r0, #3]
11
}
12
 8000d3c:   4770        bx  lr
13
 8000d3e:   bf00        nop
14
 
15
Optimierung -Os:
16
void test1::Init( void )
17
{
18
    data = 17;
19
 80009b0:   2300        movs    r3, #0
20
 80009b2:   2211        movs    r2, #17
21
 80009b4:   7002        strb    r2, [r0, #0]   <-- hier werden 4 Byte eines int einzeln gespeichert !!!
22
 80009b6:   7043        strb    r3, [r0, #1]
23
 80009b8:   7083        strb    r3, [r0, #2]
24
 80009ba:   70c3        strb    r3, [r0, #3]
25
}
26
 80009bc:   4770        bx  lr

von Peter II (Gast)


Lesenswert?

sinnvoller dürfte das sein:
1
void test1::Init( void )
2
:  data(17)
3
{
4
}

schaum mal ob sich da etwas ändert.

von Martin (Gast)


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.

von ich (Gast)


Lesenswert?

Hallo,

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

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

von Martin (Gast)


Lesenswert?

So einfach ist das also -- und schon sieht der Assembler-Code vernünftig 
aus!

Danke!!!

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.