我使用的是基于ARM cortex-A8 的S5PV210
当我声明这样的中断例程时:
void isr_routine(void) __attribute__ ((interrupt ("IRQ")));
像这样编译
arm-linux-gcc -c -march=armv7-a -fpie -fno-builtin $< -o $@
我知道gcc会通过推送一些寄存器来为我切换上下文。在我意识到这一点之前,我是手动完成的。所以我很好奇gcc是怎么做到的。拆解后,我发现了类似以下的代码
PUSH {r0-r4,r11,r12,lr}
这违背了我关于如何切换上下文的概念。在Arm cortex-A8官方文档中,明确表示r0-r12由用户模式和IRQ模式共享。然而,用户模式中的lr独立于IRQ模式。所以,我曾经像这个一样切换上下文
PUSH {r0-r12}
可以吗?为什么gcc推lr寄存器,为什么gcc不推r5-r10 rigsters?
r4-r11作为ARM ABI的一部分在函数调用之间保留,因此中断例程不需要保存它们,除非函数本身将对它们进行破坏。如果中断例程调用的另一个函数想要修改这些寄存器,它已经有义务将它们作为正常ABI的一部分进行保存和恢复。在这个集合中,编译器似乎只想使用r4和r11(没有使用r5-r10)。
维基百科的文章虽然不具有权威性,但阅读起来很容易,可能会有所帮助:http://en.wikipedia.org/wiki/Calling_convention#ARM
r5-r10是ARM中被调用的保存寄存器,因此如果它们在isr_routine中使用,gcc将推送它们。如果不使用它们(如果可能的话,它会尽量不使用它们),就不会麻烦保存/恢复它们的值,因为这是不必要的。我猜你的isr_routine足够简单,不需要它们(所有东西都适合r0-r4或r11-r12)