寄存器内容是否会被调用者覆盖

本文介绍了IA32架构中寄存器的使用惯例,特别是%rdi寄存器在过程调用中的作用。通过具体示例展示了如何在调用过程中避免寄存器值被覆盖,并解释了为何需要使用栈来保存寄存器值。

IA32(俗称x86)采用了一组统一的寄存器使用惯例., 所有的过程调用都必须遵守, 包括程序库中的过程.
看例子:

yoo: 
   …    
   movq $15213, **%rdx**    
   call who    a
   ddq **%rdx**, %rax …    
   ret
who:
   … 
   subq $18213, **%rdx** 
   …    
   ret

深入了解计算机系统P173说得很清楚。
P里边的保存x使用的寄存器%rdi,在调用Q的时候也要使用,所以为了不覆盖,我们可以继续使用%rdi,但是必须要把%rdi里边的值,先放到一个空间,所以我们push,即保存这个值进入栈里边,这个时候有了备份,就可以修改这个寄存器了。同时,在调用函数结束的时候,要把这个值pop出来。

### 函数调用过程中寄存器的使用规则和行为(基于STM32架构) 在STM32架构下,函数调用过程中涉及多个寄存器的协作,以确保程序流程控制、数据传递和状态保存的正确性。该架构基于ARM Cortex-M系列内核,其寄存器使用规则遵循ARM AAPCS(Procedure Call Standard for the ARM Architecture)标准。 #### 参数传递与返回值 在函数调用时,前四个整型或指针参数通过R0至R3寄存器进行传递。如果参数数量超过四个,则多余的参数会被压入栈中[^2]。返回值通常通过R0寄存器返回,对于64位的数据类型(如`long long`),则会使用R0和R1两个寄存器组合表示。 #### 调用者保存与被调用者保存寄存器 调用者保存(Caller-saved)寄存器包括R0-R3和R12(IP),这些寄存器在函数调用后内容可能会被修改,因此调用方如果希望保留其值,需要在调用前将其压栈,并在调用后恢复。而被调用者保存(Callee-saved)寄存器包括R4-R11,函数在使用这些寄存器时必须先将它们的值保存到栈中,并在函数返回前恢复。 #### 栈指针(SP)与链接寄存器(LR) 栈指针寄存器R13(SP)用于管理当前栈的位置,在函数调用过程中负责栈的增长和收缩。链接寄存器R14(LR)保存函数调用的返回地址。当执行BL(Branch with Link)指令调用子函数时,LR会自动保存当前PC(程序计数器)的返回地址。如果函数内部再次发生嵌套调用,LR的内容需要被手动压栈以防止被覆盖。 #### 程序计数器(PC) 程序计数器R15(PC)始终指向当前正在执行的指令地址加8(由于流水线特性)。在函数调用时,CALL指令(如BL)会将返回地址写入LR,然后跳转到目标函数入口地址执行。 #### 栈帧的构建与销毁 虽然STM32默认不强制使用基址指针(如x86中的EBP),但某些编译器优化选项下仍可能使用R11作为帧指针(FP)。在函数入口处,通常会调整SP以分配局部变量空间,并可选地将FP压栈并设置为当前SP值。函数退出时,需恢复FP、SP以及被保存的寄存器内容。 以下是一个简单的函数调用示例: ```c void delay(volatile uint32_t count) { while(count--) { // 延时循环 } } int main(void) { delay(100000); // 调用延迟函数 } ``` 在汇编层面,`delay`函数的调用可能表现为: ```armasm main: LDR R0, =100000 ; 将参数加载到R0 BL delay ; 调用函数,LR保存返回地址 ``` 其中`BL`指令将PC+4写入LR,然后跳转到`delay`函数入口。 #### 中断与异常处理中的寄存器行为 在中断服务函数(ISR)中,硬件自动将部分寄存器(如R0-R3, R12, LR, PC, xPSR)压入栈中。其余寄存器由软件手动保存。此外,进入ISR时LR的值会被特殊编码(EXC_RETURN),用于指示异常返回的行为。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值