unsigned int fun1 ( unsigned int a, unsigned int b )
{
return(a+b);
}
unsigned char fun2 ( unsigned int a, unsigned int b )
{
return(a+b);
}
unsigned int fun3 ( unsigned char a, unsigned char b )
{
return(a+b);
}
unsigned char fun4 ( unsigned char a, unsigned char b )
{
return(a+b);
}
beklendiği gibi fun1 tüm ints olduğu gibi 16 bit matematik
00000000 <fun1>:
0: 86 0f add r24, r22
2: 97 1f adc r25, r23
4: 08 95 ret
Teknik olarak yanlış olmasına rağmen, kod tarafından çağrılan 16 bitlik bir eklenti olsa da, bu derleyicinin optimize edilmemesi bile sonuç boyutu nedeniyle adc'yi kaldırdı.
00000006 <fun2>:
6: 86 0f add r24, r22
8: 08 95 ret
Burada gerçekten şaşırmadım, derleyiciler bunu yapmazdı, bu sürümün başlamasına neden olan bu emin değilim, kariyerimin başlarında bu işe girdi ve derleyiciler sıra dışı tanıtım yapmasına rağmen (tıpkı yukarıdaki gibi), tanıtım yapıyorum. söyledi uchar matematik yapmak, sürpriz değil.
0000000a <fun3>:
a: 70 e0 ldi r23, 0x00 ; 0
c: 26 2f mov r18, r22
e: 37 2f mov r19, r23
10: 28 0f add r18, r24
12: 31 1d adc r19, r1
14: 82 2f mov r24, r18
16: 93 2f mov r25, r19
18: 08 95 ret
ve ideal, 8 bit olduğunu biliyorum, 8 bit sonuç istiyorum, bu yüzden sonuna kadar 8 bit yapmasını söyledim.
0000001a <fun4>:
1a: 86 0f add r24, r22
1c: 08 95 ret
Bu yüzden genel olarak, ideal bir (u) int büyüklüğü olan kayıt boyutunu hedeflemek daha iyidir, bunun gibi 8 bitlik bir mcu için derleyici yazarları bir uzlaşma yapmak zorundaydı ... Nokta olmak alışkanlık yapma bu kodu taşıdığınızda veya daha büyük kayıtlara sahip bir işlemcide böyle yeni bir kod yazarken, derleyicinin maskelemeye başlaması ve genişlemesi imzalaması gerektiği gibi bildiğiniz matematik için uchar'ı kullanmak 8 bitten fazlasına ihtiyaç duymaz, ve diğerleri değil.
00000000 <fun1>:
0: e0800001 add r0, r0, r1
4: e12fff1e bx lr
00000008 <fun2>:
8: e0800001 add r0, r0, r1
c: e20000ff and r0, r0, #255 ; 0xff
10: e12fff1e bx lr
8 bit daha fazla maliyet zorlama. Biraz / lot aldattım, daha adil bir şekilde görmek için biraz daha karmaşık örneklere ihtiyacım olacaktı.
Yorum tartışmasına dayalı EDIT
unsigned int fun ( unsigned char a, unsigned char b )
{
unsigned int c;
c = (a<<8)|b;
return(c);
}
00000000 <fun>:
0: 70 e0 ldi r23, 0x00 ; 0
2: 26 2f mov r18, r22
4: 37 2f mov r19, r23
6: 38 2b or r19, r24
8: 82 2f mov r24, r18
a: 93 2f mov r25, r19
c: 08 95 ret
00000000 <fun>:
0: e1810400 orr r0, r1, r0, lsl #8
4: e12fff1e bx lr
sürpriz değil. Optimizer neden bu ekstra talimatı bıraksa da, r19'da ldi'yi kullanamazsınız? (Ben sorduğumda cevabı biliyordum).
EDIT2
avr için
avr-gcc --version
avr-gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Kötü alışkanlığı önlemek veya 8 bit karşılaştırmasını önlemek için
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
açıkça optimizasyon sadece benim çıktı ile karşılaştırmak için kendi derleyici ile denemek için bir saniye sürer, ama yine de:
whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o
Ve evet, bayt büyüklüğünde değişkenler için bayt kullanmak, kesinlikle bir avr, pic, vb. mümkün olduğunca kayıtlarda bellekte olacak, bu yüzden flaş tasarrufları ekstra değişkenler olmadan gelir, koç tasarrufları gerçek olabilir veya olmayabilir.