为什么在ARM ABI的函数调用期间不保存CPSR寄存器?

时间:2016-08-30 11:56:07

标签: assembly arm abi

假设我通过像SUBS R0, R0, #1这样的指令改变调用者函数中的CPSR寄存器,其中R0正好等于1,然后使用beq cpsr_test调用函数。在被调用函数中,Z的{​​{1}}标志仍然设置,对吗?然后被调用函数的行为受调用者的影响,那么为什么所有程序在函数调用期间都不保存CPSR(甚至是上下文切换)?

来电者/被叫者示例:

CPSR

内核空间上下文切换示例(不保存cpsr):

caller  mov     r0, #1
        subs    r0, r0, #1 // Z flag set 
        b       callee

callee  mov     r2, #3
        // something here that have not update cpsr
        beq     label_1    // caller's Z flag is set
        b       label_2

label_1
label_2

我看到了这篇帖子:how to understand the function of “__swtich_ to” for contex-switch in the ARM linux,我知道/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */ FUNCTION(arm_context_switch) /* save non callee trashed supervisor registers */ /* spsr and user mode registers are saved and restored in the iframe by exceptions.S */ push { r4-r11, lr } /* save old sp */ str sp, [r0] /* load new regs */ mov sp, r1 pop { r4-r11, lr } bx lr 因为争用而无需保存已保存,但仍无法保存R0-R3。请帮助。

1 个答案:

答案 0 :(得分:1)

在ARM上运行的程序通常遵循ARM calling convention

  

通过在调用子例程之前将参数值放入寄存器R0到R3来传递参数,子例程通过在返回之前将其放入R0来返回值。 [...]我们在进入子程序之前将任何其他参数放在堆栈上(前面的参数最后被推到堆栈上,这样第五个参数就在堆栈的顶部(由SP引用)。

     

允许每个子程序按照自己的意愿改变R0到R3;但如果它使用R4到R12,它必须将它们恢复到以前的值。它还必须恢复堆栈指针R13,有效地从堆栈中删除所有内容。它可以改变链接指针R14。

请注意,没有提到标志寄存器:CPSR 即使像ARM-THUMB Procedure Call Standard这样更正式的文件也没有 暗示在函数调用之间不保存标志。

进行上下文切换时,CPSR会被保存as can be seen in the ARM documentation