2015-05-10 24 views
6

Bu kod (kol) bağlı olarak farklı bir kod oluşturur:GCC dizi endeks değeri

void blinkRed(void) 
{ 
    for(;;) 
    { 
     bb[0x0008646B] ^= 1; 
     sys.Delay_ms(14); 
    } 
} 

... asm-kod folowing derlenmiş:

08000470: ldr r4, [pc, #20]  ; (0x8000488 <blinkRed()+24>) // r4 = 0x422191ac 
08000472: ldr r6, [pc, #24]  ; (0x800048c <blinkRed()+28>) 
08000474: movs r5, #14 
08000476: ldr r3, [r4, #0] 
08000478: eor.w r3, r3, #1 
0800047c: str r3, [r4, #0] 
0800047e: mov r0, r6 
08000480: mov r1, r5 
08000482: bl 0x80001ac <CSTM32F100C6::Delay_ms(unsigned int)> 
08000486: b.n 0x8000476 <blinkRed()+6> 

It is ok. Sadece dizi indeksi (-0x400) değiştirirseniz

Ama ....

void blinkRed(void) 
{ 
    for(;;) 
    { 
     bb[0x0008606B] ^= 1; 
     sys.Delay_ms(14); 
    } 
} 

... bende bu yüzden optimize edilmemiş kod:

08000470: ldr r4, [pc, #24]  ; (0x800048c <blinkRed()+28>) // r4 = 0x42218000 
08000472: ldr r6, [pc, #28]  ; (0x8000490 <blinkRed()+32>) 
08000474: movs r5, #14 
08000476: ldr.w r3, [r4, #428] ; 0x1ac 
0800047a: eor.w r3, r3, #1 
0800047e: str.w r3, [r4, #428] ; 0x1ac 
08000482: mov r0, r6 
08000484: mov r1, r5 
08000486: bl 0x80001ac <CSTM32F100C6::Delay_ms(unsigned int)> 
0800048a: b.n 0x8000476 <blinkRed()+6> 

fark içinde olmasıdır ilk durumda r4 hedef adresi ile hemen yüklenir (0x422191ac) ve daha sonra bellek 2 bayt yönergeleri ile gerçekleştirilir, ancak ikinci durumda r4 bazı ara adresi ile yüklenir (0x42218000) ve ardından belleğe erişim, hedef adresi (0x422181ac) ile ofset (+0x1ac) ile 4 baytlık komutla gerçekleştirilir.

Neden derleyici böyle yapar?

kullanmak: arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -g2 -Wall -O1 -std=gnu++14 -fno-exceptions -fno-use-cxa-atexit -fstrict-volatile-bitfields -c -DSTM32F100C6T6B -DSTM32F10X_LD_VL

bb olup: içinde MEMORY bölüm:

BITBAND(rwx): ORIGIN = 0x42000000, LENGTH = 0x02000000 

SECTIONS bölümünde: .ld olarak

__attribute__ ((section(".bitband"))) volatile u32 bb[0x00800000]; 

bu gibi tanımlanmıştır

.bitband (NOLOAD) : 
SUBALIGN(0x02000000) 
{ 
    KEEP(*(.bitband)) 
} > BITBAND 
+1

Ummm ... bunun ilgili olup olmadığından emin değilsiniz, ancak ... optimize edilmiş sürüm de işe yarayacak mı? Belki daha hızlı yük için bazı önkoşullar vardır.Bu bilgi, optimize edicinin problemi mi, yoksa mimariyle mi ilgili olduğunu gösterir. – luk32

+0

Her iki sürüm de çalışır. Bir örnekte mevcut olan ve diğerlerinde mevcut olmayan herhangi bir önkoşul hayal edemiyorum. İndeks adım adım değiştirdim ve dizi endeksi 0x00086020 - 0x000863FF arasındaysa ikinci sürümün derlendiğini öğrendim. Dizi dizini bu aralığın dışındaysa, ilk (en iyileştirilmiş) sürüm derlenir. – Woodoo

+0

Ne tür ARM? Muhtemelen bir bellek hizalama sorunu. – Unimportant

cevap

1

Bunu -O1 bir artefact/eksik optimizasyon fırsatı olarak düşünürdüm.

biz bb[...] yüklemek için -O- oluşturulan kodun bakarsak Daha ayrıntılı olarak anlaşılabilir:

İlk durumda:

movw r2, #:lower16:bb 
movt r2, #:upper16:bb 
movw r3, #37292 
movt r3, 33 
adds r3, r2, r3 
ldr r3, [r3, #0] 

İkinci vaka:

movw r3, #:lower16:bb 
movt r3, #:upper16:bb 
add r3, r3, #2195456  ; 0x218000 = 4*0x86000 
add r3, r3, #428 
ldr r3, [r3, #0] 

İkinci durumda kod daha iyidir ve bu şekilde yapılabilir, çünkü sabit iki ekleme komutuyla eklenebilir (bu, endeksin 0x0008646B olması durumunda geçerli değildir).

-O1 yalnızca zaman alıcı olmayan optimizasyonları yapar. Görünüşe göre, eklentiyi ve ldr'yi erkenden birleştirir, böylece daha sonra, tüm adresi bir bilgisayar göreli ldr ile yükleme fırsatını kaçırır.

-O2 (veya -fgcse) ile derleyin ve kod beklenen gibi görünüyor.