【发布时间】:2014-05-29 21:15:10
【问题描述】:
我为 atmega328 编写了一个非常简单的中断服务例程 (ISR),并使用 AVR studio 用 avrgcc(使用 -Os)编译。
ISR (TIMER0_OVF_vect) {
txofcnt++; //count overflows and store in uint16_t
}
如果您注意到生成的程序集(如下),它使用 r24、r25 来完成增加 volatile uint16_t txofcnt 的作业,但它也无需读取它们就 push-write-pop r1、r28、r29。它还有一个额外的 r0 推送/弹出,而无需在两者之间使用它。
我完全不明白为什么 r1 被推送、清除然后最终弹出。 但也是为什么 gcc 觉得需要将 EIMSK 和 GPIOR0 加载到寄存器中然后不使用它们。如果您能告诉我 GPIOR0 的用途,则可以加分,数据表说它存在但没有描述。
00000258 <__vector_16>:
ISR (TIMER0_OVF_vect) {
258: 1f 92 push r1
25a: 0f 92 push r0
25c: 00 90 5f 00 lds r0, 0x005F
260: 0f 92 push r0
262: 11 24 eor r1, r1
264: 8f 93 push r24
266: 9f 93 push r25
268: cf 93 push r28
26a: df 93 push r29
26c: cd b7 in r28, 0x3d ; 61 reads register EIMSK
26e: de b7 in r29, 0x3e ; 62 reads register GPIOR0
txofcnt++;
270: 80 91 0a 01 lds r24, 0x010A
274: 90 91 0b 01 lds r25, 0x010B
278: 01 96 adiw r24, 0x01 ; 1
27a: 90 93 0b 01 sts 0x010B, r25
27e: 80 93 0a 01 sts 0x010A, r24
}
282: df 91 pop r29
284: cf 91 pop r28
286: 9f 91 pop r25
288: 8f 91 pop r24
28a: 0f 90 pop r0
28c: 00 92 5f 00 sts 0x005F, r0
290: 0f 90 pop r0
292: 1f 90 pop r1
294: 18 95 reti
【问题讨论】:
-
您的目标是什么设备?在某些 AVR 上,寄存器 0x3d 和 0x3e 是堆栈指针寄存器。 ISR序言可能被“硬编码”以将堆栈指针存储在被调用者保存的寄存器
r28和r29中,以防ISR代码交换到中断堆栈?但我只是猜测。 -
正如我上面所说的 MEGA328
-
我很惊讶为什么 gcc 这样做(我知道,'固定/临时寄存器,等等等等')以及为什么,十多年来仍然没有任何好的答案,当人们想知道为什么时,他们只是被告知要“裸”或在汇编中编写 ISR。让 gcc 跟踪和消除这里的冗余代码真的有多难?