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);
}
như mong đợi fun1 là tất cả các ints, toán 16 bit cũng vậy
00000000 <fun1>:
0: 86 0f add r24, r22
2: 97 1f adc r25, r23
4: 08 95 ret
Mặc dù về mặt kỹ thuật không chính xác vì đây là một bổ sung 16 bit được gọi ra bởi mã, ngay cả trình biên dịch không được tối ưu hóa này đã loại bỏ adc do kích thước kết quả.
00000006 <fun2>:
6: 86 0f add r24, r22
8: 08 95 ret
Không thực sự ngạc nhiên ở đây chương trình khuyến mãi xảy ra, các trình biên dịch đã không sử dụng để làm điều này không chắc chắn phiên bản nào đã bắt đầu xảy ra, đã chạy vào đầu sự nghiệp của tôi và mặc dù các trình biên dịch quảng bá không theo thứ tự (giống như ở trên), thực hiện quảng cáo mặc dù tôi bảo nó làm toán uchar, không ngạc nhiên.
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
và lý tưởng, tôi biết nó là 8 bit, muốn có kết quả 8 bit nên tôi chỉ đơn giản bảo nó làm 8 bit cho đến hết.
0000001a <fun4>:
1a: 86 0f add r24, r22
1c: 08 95 ret
Vì vậy, nói chung, tốt hơn là nhắm vào kích thước thanh ghi, lý tưởng nhất là kích thước của một (u) int, đối với một mcu 8 bit như thế này, các tác giả trình biên dịch đã phải thỏa hiệp ... Điểm không được tạo thành thói quen sử dụng uchar cho toán học mà bạn biết không cần nhiều hơn 8 bit như khi bạn di chuyển mã đó hoặc viết mã mới như thế trên bộ xử lý với các thanh ghi lớn hơn bây giờ trình biên dịch phải bắt đầu che dấu và mở rộng, một số thực hiện theo một số hướng dẫn, và những người khác thì không.
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
buộc 8 bit chi phí nhiều hơn. Tôi đã lừa dối một chút / rất nhiều, sẽ cần những ví dụ phức tạp hơn một chút để thấy nhiều hơn về điều này một cách công bằng.
EDIT dựa trên thảo luận ý kiến
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
Không bất ngờ. Mặc dù tại sao trình tối ưu hóa lại bỏ hướng dẫn thêm đó, bạn không thể sử dụng ldi trên r19? (Tôi biết câu trả lời khi tôi hỏi nó).
EDIT2
cho 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.
để tránh thói quen xấu hay không so sánh 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.
tối ưu hóa rõ ràng chỉ mất một giây để thử với trình biên dịch của riêng bạn để xem nó so sánh với đầu ra của tôi như thế nào, nhưng dù sao:
whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o
Và có, sử dụng byte cho các biến có kích thước byte, chắc chắn trên avr, pic, v.v., sẽ giúp bạn tiết kiệm bộ nhớ và bạn muốn thực sự cố gắng bảo tồn nó ... nếu bạn thực sự đang sử dụng nó, nhưng như thể hiện ở đây càng ít càng tốt sẽ có trong bộ nhớ, càng nhiều trong các thanh ghi càng tốt, vì vậy tiết kiệm flash xuất hiện bằng cách không có thêm biến, tiết kiệm ram có thể hoặc không thể là thật ..