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);
}
อย่างที่คาดไว้ fun1 นั้นเป็น ints ทั้งหมดดังนั้น 16 บิตคณิตศาสตร์
00000000 <fun1>:
0: 86 0f add r24, r22
2: 97 1f adc r25, r23
4: 08 95 ret
แม้ว่าเทคนิคจะไม่ถูกต้องเนื่องจากเป็นการเพิ่ม 16 บิตที่เรียกใช้โดยรหัสถึงแม้จะเพิ่มประสิทธิภาพคอมไพเลอร์นี้เอา adc ออกเนื่องจากขนาดผลลัพธ์
00000006 <fun2>:
6: 86 0f add r24, r22
8: 08 95 ret
ไม่แปลกใจจริงๆที่นี่การโปรโมตเกิดขึ้นคอมไพเลอร์ไม่เคยทำเช่นนี้ไม่แน่ใจว่าเวอร์ชันนี้ทำให้เกิดการเริ่มต้นวิ่งเข้ามาในช่วงต้น ๆ ในอาชีพการงานของฉันและแม้คอมไพเลอร์ที่ส่งเสริมการสั่ง บอกให้ทำคณิตศาสตร์ยูชาร์ไม่แปลกใจ
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
และอุดมคติฉันรู้ว่ามันคือ 8 บิตต้องการผลลัพธ์ 8 บิตดังนั้นฉันก็บอกให้ทำ 8 บิตตลอดทาง
0000001a <fun4>:
1a: 86 0f add r24, r22
1c: 08 95 ret
ดังนั้นโดยทั่วไปจะดีกว่าที่จะตั้งเป้าหมายขนาด register ซึ่งเป็นขนาดที่เหมาะสม (u) int สำหรับ 8 บิต mcu เช่นนี้ผู้เขียนคอมไพเลอร์ต้องประนีประนอม ... จุดที่ไม่ทำให้เป็นนิสัย การใช้ uchar สำหรับคณิตศาสตร์ที่คุณรู้ว่าไม่จำเป็นต้องมากกว่า 8 บิตเหมือนเมื่อคุณย้ายรหัสนั้นหรือเขียนรหัสใหม่เช่นนั้นบนโปรเซสเซอร์ที่มีการลงทะเบียนมากขึ้นตอนนี้คอมไพเลอร์ต้องเริ่มปิดบังและขยายเครื่องหมายซึ่งบางคำสั่ง และคนอื่น ๆ ไม่
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 บิตมีค่าใช้จ่ายมากขึ้น ฉันโกงเล็ก ๆ น้อย ๆ / ต้องการตัวอย่างที่ซับซ้อนมากขึ้นเล็กน้อยเพื่อดูสิ่งนี้มากขึ้นอย่างเป็นธรรม
แก้ไขตามการอภิปรายแสดงความคิดเห็น
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
ไม่แปลกใจ แม้ว่าทำไมออพติไมเซอร์ถึงออกคำสั่งพิเศษนั้น แต่คุณไม่สามารถใช้ ldi บน r19 ได้หรือไม่? (ฉันรู้คำตอบเมื่อฉันถาม)
EDIT2
สำหรับ 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.
เพื่อหลีกเลี่ยงนิสัยที่ไม่ดีหรือไม่เปรียบเทียบ 8 บิต
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.
การเพิ่มประสิทธิภาพอย่างชัดเจนนั้นใช้เวลาเพียงไม่กี่วินาทีในการลองใช้คอมไพเลอร์ของคุณเองเพื่อดูว่ามันเปรียบเทียบกับผลลัพธ์ของฉันได้อย่างไร แต่อย่างไรก็ตาม:
whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o
และใช่การใช้ไบต์สำหรับตัวแปรขนาดไบต์แน่นอนบน avr, pic ฯลฯ จะช่วยให้คุณประหยัดหน่วยความจำและคุณต้องการที่จะพยายามอนุรักษ์มันจริงๆ ... ถ้าคุณใช้มันจริง ๆ แต่เท่าที่จะทำได้ จะอยู่ในหน่วยความจำมากที่สุดเท่าที่จะเป็นไปได้ดังนั้นการประหยัดแฟลชจึงมาจากการไม่มีตัวแปรเพิ่มเติมการประหยัด RAM อาจหรืออาจไม่จริง ..