假设我通过像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
。请帮助。
答案 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。