arm - 为什么ARM将返回地址保存在链接寄存器而不是堆栈中?
问题描述
我一直在寻找这个答案一个多星期,但没有运气。到目前为止,我已经了解到堆栈会在函数嵌套或中断发生时保存返回地址,但最近我了解到现代处理器使用链接寄存器来实现相同的目标。经过一番研究,我知道堆栈确实被用于在旧处理器中保存返回地址。但是,为什么现代处理器在旧实现工作时使用整个单独的寄存器( LR )来保存返回地址对我来说没有意义?与基于堆栈的实现相比,LR 有什么好处?
提前致谢!!!
解决方案
RISC 架构往往具有较少的特殊指令或行为 - 而是使用标准指令进行堆栈管理。这通常意味着程序更大,CPU 本身更简单,并且编译器预计会更难优化
考虑:
int bar(int a)
{
return a * a;
}
void foo()
{
bar(22);
}
foo();
这里bar()
是一个叶函数——它不会继续进行进一步的函数调用。因此,返回地址LR
永远不会被覆盖。因此,根本不需要将其写入堆栈。这将保存和加载并从/存储到内存。
foo()
另一方面会发生变异LR
,因为它会进行函数调用,因此需要将调用者的返回地址存储在堆栈中。
将此与在其中进行函数调用自动将返回地址推送到堆栈的体系结构进行对比——这种优化是不可能的。
ARM 过程调用标准的所有版本都定义了被调用者保存函数调用的寄存器 - 调用者可以期望在函数调用中维护的寄存器。如果该函数是微不足道的,它再次导致没有内存访问。
在中断中,时序通常更为关键。ARM CPU 有一组影子寄存器,它们只能在中断状态下访问。这意味着可以编写不需要内存访问的普通中断处理程序。
推荐阅读
- bash - 检查文件是否打开 bash
- kubernetes - 在 pod 故障 Kubernetes 上运行容器
- qt - 对于这个提议的 UI,我应该使用哪些 Qt 快速控件?
- awk - 如果模式符合以下条件,则 awk 打印文本
- angularjs - 使用控制器作为语法访问子控制器中的继承范围
- r - 注释未正确映射到 R 闪亮的绘图热图中
- r - 缺失数据的网格图
- c++ - 如何自定义 Google 测试失败消息?
- aws-lambda - Redshift:如何修复由并发 MERGE 操作引起的可序列化隔离违规(1023)?
- mysql - MySQL innoDB 页面会在硬盘内碎片化吗?还是 InnoDB 防止这种情况发生以加快查询速度?