为什么gcc在arm FIQ中断处理程序中保存r4?
考虑以下C代码:为什么gcc在arm FIQ中断处理程序中保存r4?,arm,interrupt-handling,Arm,Interrupt Handling,考虑以下C代码: extern void dummy(void); void foo1(void) __attribute__(( interrupt("IRQ") )); void foo2(void) __attribute__(( interrupt("FIQ") )); void foo1() { dummy(); return; } void foo2() { dummy(); return; } arm gnueabi gcc生成的代码基本上如下所示: foo1
extern void dummy(void);
void foo1(void) __attribute__(( interrupt("IRQ") ));
void foo2(void) __attribute__(( interrupt("FIQ") ));
void foo1() {
dummy();
return;
}
void foo2() {
dummy();
return;
}
arm gnueabi gcc生成的代码基本上如下所示:
foo1:
sub lr, lr, #4
stmfd sp!, {r0, r1, r2, r3, ip, lr}
bl dummy
ldmfd sp!, {r0, r1, r2, r3, ip, pc}^
foo2:
sub lr, lr, #4
stmfd sp!, {r0, r1, r2, r3, r4, lr}
bl dummy
ldmfd sp!, {r0, r1, r2, r3, r4, pc}^
foo1的代码并不包含任何惊喜r0-r3
和ip
被保存,因为对dummy的调用可能会更改它们的值。另外,在更正了lr后,它最终被推入并弹出到pc中。这是相当标准的
然而,foo2的代码令人惊讶。不需要保存ip
的值,因为它是存盘寄存器。但gcc保存的r4
令人惊讶
那么gcc为什么要保存r4呢?我看不出有任何理由这样做,因为对dummy的调用不会损坏这个寄存器。我怀疑这样做是为了确保EABI所需的8字节堆栈对齐。实际使用的寄存器并不重要,它可以是r12或其他任何东西-它只是用于额外的4字节调整。仅供参考