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);
}
seperti yang diharapkan fun1 adalah semua ints begitu juga matematika 16 bit
00000000 <fun1>:
0: 86 0f add r24, r22
2: 97 1f adc r25, r23
4: 08 95 ret
Meskipun secara teknis salah karena merupakan tambahan 16 bit yang dipanggil oleh kode, bahkan tidak dioptimalkan kompiler ini menghapus adc karena ukuran hasil.
00000006 <fun2>:
6: 86 0f add r24, r22
8: 08 95 ret
tidak benar-benar terkejut di sini promosi terjadi, kompiler tidak terbiasa melakukan ini tidak yakin versi apa yang membuat ini mulai terjadi, berlari ke awal ini dalam karir saya dan meskipun kompiler mempromosikan rusak (seperti di atas), melakukan promosi meskipun saya menyuruhnya melakukan matematika uchar, tidak terkejut.
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
dan yang ideal, saya tahu itu 8 bit, ingin hasil 8 bit jadi saya hanya menyuruhnya melakukan 8 bit sepanjang jalan.
0000001a <fun4>:
1a: 86 0f add r24, r22
1c: 08 95 ret
Jadi secara umum lebih baik untuk bertujuan untuk ukuran register, yang idealnya ukuran int (u), untuk 8 bit mcu seperti ini penulis kompiler harus membuat kompromi ... Intinya jangan membuat kebiasaan menggunakan uchar untuk matematika yang Anda tahu tidak perlu lebih dari 8 bit seperti ketika Anda memindahkan kode itu atau menulis kode baru seperti itu pada prosesor dengan register yang lebih besar sekarang kompiler harus mulai menutupi dan menandatangani perluasan, yang beberapa lakukan secara asli dalam beberapa instruksi, dan yang lainnya tidak.
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
memaksa 8 bit lebih mahal. Saya curang sedikit / banyak, akan membutuhkan contoh yang sedikit lebih rumit untuk melihat lebih banyak tentang ini secara adil.
EDIT berdasarkan diskusi komentar
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
tidak ada kejutan. Meskipun mengapa pengoptimal meninggalkan instruksi tambahan itu, bisakah Anda tidak menggunakan ldi pada r19? (Saya tahu jawabannya ketika saya menanyakannya).
EDIT2
untuk avr
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.
untuk menghindari kebiasaan buruk atau tidak perbandingan 8 bit
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.
jelas optimisasi hanya membutuhkan waktu satu detik untuk mencoba dengan kompiler Anda sendiri untuk melihat bagaimana perbandingannya dengan output saya, tetapi bagaimanapun:
whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o
Dan ya menggunakan byte untuk variabel ukuran byte, tentu saja pada avr, pic, dll, akan menghemat memori Anda dan Anda ingin benar-benar mencoba untuk melestarikannya ... jika Anda benar-benar menggunakannya, tetapi seperti yang ditunjukkan di sini sesedikit mungkin adalah akan berada dalam memori, sebanyak mungkin dalam register, sehingga penghematan flash datang dengan tidak memiliki variabel tambahan, penghematan ram mungkin atau mungkin tidak nyata ..