caller和callee的区别

本文深入探讨了JavaScript中的caller与callee属性的作用及使用方法,包括它们如何在函数内部相互引用,以及如何通过这些属性进行函数调用的追踪与分析。

caller返回一个函数的引用,这个函数调用了当前的函数;callee放回正在执行的函数本身的引用,它是arguments的一个属性

caller
caller返回一个函数的引用,这个函数调用了当前的函数。
使用这个属性要注意:
1 这个属性只有当函数在执行时才有用
2 如果在javascript程序中,函数是由顶层调用的,则返回null

functionName.caller: functionName是当前正在执行的函数。

var a = function() { 
alert(a.caller); 
} 
var b = function() { 
a(); 
} 
b();

上面的代码中,b调用了a,那么a.caller返回的是b的引用,结果如下:

var b = function() { 
a(); 
} 
如果直接调用a(即a在任何函数中被调用,也就是顶层调用),返回null:

var a = function() { 
alert(a.caller); 
} 
var b = function() { 
a(); 
} 
//b(); 
a();
输出结果:

null

callee
callee放回正在执行的函数本身的引用,它是arguments的一个属性
使用callee时要注意:
1 这个属性只有在函数执行时才有效
2 它有一个length属性,可以用来获得形参的个数,因此可以用来比较形参和实参个数是否一致,即比较arguments.length是否等于arguments.callee.length
3 它可以用来递归匿名函数。

var a = function() { 
alert(arguments.callee); 
} 
var b = function() { 
a(); 
} 
b();
a在b中被调用,但是它返回了a本身的引用,结果如下:
var a = function() { 
alert(arguments.callee); 
} 


<think>嗯,用户想了解Cortex-M架构中callercallee的寄存器的保存与恢复机制。我需要先回忆一下相关的知识,可能涉及到AAPCS标准,也就是ARM架构的过程调用标准。 首先,Cortex-M处理器使用的是ARM的Thumb指令集,寄存器包括R0-R15,其中R13是堆栈指针SP,R14是链接寄存器LR,R15是程序计数器PC。根据AAPCS,寄存器分为caller-savedcallee-saved两类。Caller-saved寄存器在函数调用时可能会被callee修改,所以调用者(caller)需要在调用前保存这些寄存器的值,如果之后还需要使用的话。而callee-saved寄存器则是由被调用者(callee)负责保存恢复,这样调用者可以放心使用这些寄存器,无需自己保存。 比如,引用中的内容提到v8-v15(可能是指浮点寄存器?)必须由callee保存,而其他如v0-v7由caller处理。不过在Cortex-M中,通常讨论的是通用寄存器R0-R12。根据引用[3],编写汇编函数需要遵循AAPCS,手动管理寄存器栈。可能R0-R3用于参数传递结果返回,属于caller-saved,而R4-R11可能需要callee保存,如果它们会被修改的话。 另外,链接寄存器LR在函数调用时会被自动更新为返回地址,但如果在函数中再次调用其他函数,LR的值会被覆盖,所以通常函数开头会将LR保存到栈中。例如,使用PUSH {LR},然后在返回前POP {PC},这样就能正确返回。 用户可能想知道具体的哪些寄存器由谁保存,以及在实际编程中如何操作。需要结合AAPCS标准,说明哪些寄存器是caller保存,哪些是callee保存,并给出示例代码,说明如何保存恢复。同时,可能需要提到堆栈的使用,例如在进入函数时保存必要寄存器到栈,退出前恢复。 还要注意,引用[1]提到LR的作用是硬件自动保存返回地址,这样程序员不需要手动传递返回地址,简化了函数调用。而引用[2]中的寄存器规则可能与浮点寄存器相关,但Cortex-M可能没有浮点单元,具体要看型号。需要确认Cortex-M的寄存器分类,可能通用寄存器的规则与浮点不同。 总结回答的结构应该是:先介绍callercallee的概念,然后分点说明寄存器分类,保存恢复机制,结合示例代码引用中的信息,最后给出常见问题。需要确保引用正确,比如引用[3]提到手动管理寄存器栈,遵循AAPCS,所以在回答中要强调这点,并给出示例。</think>### Cortex-M架构中Caller/Callee寄存器机制解析 Cortex-M架构的寄存器保存机制遵循AAPCS标准(ARM架构过程调用标准)[^3],核心设计目标是保证函数调用时寄存器的正确性可预测性。以下分步骤说明其实现细节: #### 一、寄存器分类与职责划分 1. **Caller-saved寄存器(易失性寄存器)** - 范围:R0-R3, R12 - 特性:调用者(caller)需主动保存这些寄存器值(若后续需要继续使用) - 场景:函数参数传递(R0-R3)、临时计算结果存储 ```asm ; Caller示例:调用函数前保存R0-R3 PUSH {R0-R3} ; 保存寄存器 BL target_function POP {R0-R3} ; 恢复寄存器 ``` 2. **Callee-saved寄存器(非易失性寄存器)** - 范围:R4-R11, LR(特殊处理) - 特性:被调用函数(callee)若需修改这些寄存器,必须自行保存恢复 ```asm ; Callee示例:函数入口保存寄存器 my_function: PUSH {R4-R6, LR} ; 保存非易失性寄存器及返回地址 ... ; 函数逻辑 POP {R4-R6, PC} ; 恢复寄存器并返回(PC←LR) ``` #### 二、关键寄存器LR的特殊处理 - **LR(R14)的作用**:硬件自动存储返回地址(如`BL指令`自动设置LR=PC+4)[^1] - **嵌套调用时的处理**:若callee内部再次调用其他函数,需手动保存LR到栈中 ```asm nested_call: PUSH {LR} ; 保存当前返回地址 BL another_func POP {PC} ; 直接恢复PC实现返回 ``` #### 三、栈空间管理原则 - **栈对齐要求**:Cortex-M通常要求8字节栈对齐(硬件自动检测) - **动态栈分配**:通过修改SP寄存器实现局部变量存储 ```asm func_with_stack: SUB SP, SP, #16 ; 分配16字节栈空间 ... ; 使用栈空间 ADD SP, SP, #16 ; 释放栈空间 ``` #### 四、混合编程注意事项(C与汇编交互) 1. **参数传递规则**:前4个参数通过R0-R3传递,返回值使用R0 2. **浮点寄存器处理**:若使用FPU(如Cortex-M4F),需额外保存S16-S31寄存器[^2] #### 五、典型错误场景 - **LR未保存**:未在callee中保存LR导致返回地址丢失 - **栈溢出**:递归调用过深或局部变量过大导致SP越界 - **寄存器覆盖**:误用caller-saved寄存器而未保存
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值