我编写了一个示例程序来测试我的AVR库。这是命令行:
avr-gcc -g -Wall -mcall-prologues -fshort-enums -Os -ffreestanding -I./include -I./ -DF_CPU=8000000L -Wl,-gc-sections -Wl,-relax -mmcu=attiny1634 *.cpp -o main
检查生成的汇编代码我发现以下内容:
000001c6 <_GLOBAL__sub_I___vector_16>:
template<class driver> cqueue uart<driver>::rxq __attribute__ ((section (".noinit")));
1c6: 20 91 09 01 lds r18, 0x0109 ; 0x800109 <guard variable for uart<drv::uart0>::rxq>
1ca: 30 91 0a 01 lds r19, 0x010A ; 0x80010a <guard variable for uart<drv::uart0>::rxq+0x1>
1ce: 40 91 0b 01 lds r20, 0x010B ; 0x80010b <guard variable for uart<drv::uart0>::rxq+0x2>
1d2: 50 91 0c 01 lds r21, 0x010C ; 0x80010c <guard variable for uart<drv::uart0>::rxq+0x3>
1d6: 60 91 0d 01 lds r22, 0x010D ; 0x80010d <guard variable for uart<drv::uart0>::rxq+0x4>
1da: 70 91 0e 01 lds r23, 0x010E ; 0x80010e <guard variable for uart<drv::uart0>::rxq+0x5>
1de: 80 91 0f 01 lds r24, 0x010F ; 0x80010f <guard variable for uart<drv::uart0>::rxq+0x6>
1e2: 90 91 10 01 lds r25, 0x0110 ; 0x800110 <guard variable for uart<drv::uart0>::rxq+0x7>
1e6: a1 e0 ldi r26, 0x01 ; 1
1e8: 32 d0 rcall .+100 ; 0x24e <__adddi3_s8>
1ea: 20 93 09 01 sts 0x0109, r18 ; 0x800109 <guard variable for uart<drv::uart0>::rxq>
1ee: 30 93 0a 01 sts 0x010A, r19 ; 0x80010a <guard variable for uart<drv::uart0>::rxq+0x1>
1f2: 40 93 0b 01 sts 0x010B, r20 ; 0x80010b <guard variable for uart<drv::uart0>::rxq+0x2>
1f6: 50 93 0c 01 sts 0x010C, r21 ; 0x80010c <guard variable for uart<drv::uart0>::rxq+0x3>
1fa: 60 93 0d 01 sts 0x010D, r22 ; 0x80010d <guard variable for uart<drv::uart0>::rxq+0x4>
1fe: 70 93 0e 01 sts 0x010E, r23 ; 0x80010e <guard variable for uart<drv::uart0>::rxq+0x5>
202: 80 93 0f 01 sts 0x010F, r24 ; 0x80010f <guard variable for uart<drv::uart0>::rxq+0x6>
206: 90 93 10 01 sts 0x0110, r25 ; 0x800110 <guard variable for uart<drv::uart0>::rxq+0x7>
20a: 20 91 01 01 lds r18, 0x0101 ; 0x800101 <guard variable for uart<drv::uart1>::rxq>
20e: 30 91 02 01 lds r19, 0x0102 ; 0x800102 <guard variable for uart<drv::uart1>::rxq+0x1>
212: 40 91 03 01 lds r20, 0x0103 ; 0x800103 <guard variable for uart<drv::uart1>::rxq+0x2>
216: 50 91 04 01 lds r21, 0x0104 ; 0x800104 <guard variable for uart<drv::uart1>::rxq+0x3>
21a: 60 91 05 01 lds r22, 0x0105 ; 0x800105 <guard variable for uart<drv::uart1>::rxq+0x4>
21e: 70 91 06 01 lds r23, 0x0106 ; 0x800106 <guard variable for uart<drv::uart1>::rxq+0x5>
222: 80 91 07 01 lds r24, 0x0107 ; 0x800107 <guard variable for uart<drv::uart1>::rxq+0x6>
226: 90 91 08 01 lds r25, 0x0108 ; 0x800108 <guard variable for uart<drv::uart1>::rxq+0x7>
22a: 11 d0 rcall .+34 ; 0x24e <__adddi3_s8>
22c: 20 93 01 01 sts 0x0101, r18 ; 0x800101 <guard variable for uart<drv::uart1>::rxq>
230: 30 93 02 01 sts 0x0102, r19 ; 0x800102 <guard variable for uart<drv::uart1>::rxq+0x1>
234: 40 93 03 01 sts 0x0103, r20 ; 0x800103 <guard variable for uart<drv::uart1>::rxq+0x2>
238: 50 93 04 01 sts 0x0104, r21 ; 0x800104 <guard variable for uart<drv::uart1>::rxq+0x3>
23c: 60 93 05 01 sts 0x0105, r22 ; 0x800105 <guard variable for uart<drv::uart1>::rxq+0x4>
240: 70 93 06 01 sts 0x0106, r23 ; 0x800106 <guard variable for uart<drv::uart1>::rxq+0x5>
244: 80 93 07 01 sts 0x0107, r24 ; 0x800107 <guard variable for uart<drv::uart1>::rxq+0x6>
248: 90 93 08 01 sts 0x0108, r25 ; 0x800108 <guard variable for uart<drv::uart1>::rxq+0x7>
24c: 08 95 ret
0000024e <__adddi3_s8>:
24e: 00 24 eor r0, r0
250: a7 fd sbrc r26, 7
252: 00 94 com r0
254: 2a 0f add r18, r26
256: 30 1d adc r19, r0
258: 40 1d adc r20, r0
25a: 50 1d adc r21, r0
25c: 60 1d adc r22, r0
25e: 70 1d adc r23, r0
260: 80 1d adc r24, r0
262: 90 1d adc r25, r0
264: 08 95 ret
00000266 <__tablejump2__>:
266: ee 0f add r30, r30
268: ff 1f adc r31, r31
26a: 05 90 lpm r0, Z+
26c: f4 91 lpm r31, Z
26e: e0 2d mov r30, r0
270: 09 94 ijmp
变量uart<drv::uart0>::rxq>
定义如下(uart<drv::uart0>::rxq>
具有相似的定义):
namespace drv {
struct uart0
{
static void putchar(char c) { UDR0 = c; }
};
} /* namespace drv */
class uart0 : uart<drv::uart0>
{
...
};
template <class driver>
class uart : public driver
{
protected:
static cqueue rxq;
public:
static char getchar() { ... }
};
template<class driver>
cqueue uart<driver>::rxq __attribute__ ((section (".noinit")));
在上面,cqueue
是循环缓冲类:
class cqueue
{
protected:
typedef union {
struct {
uint8_t head: 4;
uint8_t tail: 4;
};
uint8_t nibbles;
} nibbles_t;
// Indices and data initialized with zeroes
volatile nibbles_t ptr;
qchar data[ 1 << 4 ];
public:
bool is_empty() const { return ptr.head == ptr.tail; }
void reset() { ptr.head = ptr.tail = 0; }
uint8_t available() const { ... }
bool put(qchar) { ... }
qchar get() { ... }
};
循环缓冲区意味着未初始化,因此我不明白为什么以及守卫代码在那里做什么。尽管添加.noinit
部分代码仍然存在并且正在咀嚼闪存的一部分(几乎 200字节,只是为了控制 32 !)我'而宁愿保持。
从程序开头调用保护代码:
00000124 <__do_global_ctors>:
124: 10 e0 ldi r17, 0x00 ; 0
126: c4 e8 ldi r28, 0x84 ; 132
128: d0 e0 ldi r29, 0x00 ; 0
12a: 03 c0 rjmp .+6 ; 0x132 <__do_global_ctors+0xe>
12c: 21 97 sbiw r28, 0x01 ; 1
12e: fe 01 movw r30, r28
130: 9a d0 rcall .+308 ; 0x266 <__tablejump2__>
132: c3 38 cpi r28, 0x83 ; 131
134: d1 07 cpc r29, r17
136: d1 f7 brne .-12 ; 0x12c <__do_global_ctors+0x8>
如何告诉编译器不要添加该保护代码?