gpt4 book ai didi

c - ARM:链接寄存器和帧指针

转载 作者:太空狗 更新时间:2023-10-29 16:22:58 25 4
gpt4 key购买 nike

我试图了解链接寄存器和帧指针在ARM中的工作方式。我去过几个站点,我想确认自己的理解。

假设我有以下代码:

int foo(void)
{
// ..
bar();
// (A)
// ..
}

int bar(void)
{
// (B)
int b1;
// ..
// (C)
baz();
// (D)
}

int baz(void)
{
// (E)
int a;
int b;
// (F)
}

然后我叫foo()。链接寄存器是否将包含代码在(A)点的地址,而帧指针将包含在代码在(B)点的地址?在所有本地变量都声明之后,堆栈指针可能在bar()内的任何位置?

最佳答案

某些寄存器调用约定取决于ABI(应用程序二进制接口(interface))。 APCS 标准中需要FP,而不是较新的 AAPCS (2003)中需要。对于 AAPCS (GCC 5.0+),FP没有使用,但可以使用。带有堆栈和帧指针的debug info is annotated用于与 AAPCS 一起进行堆栈跟踪和展开代码。如果函数是static,则编译器实际上不必遵守任何约定。

通常,所有ARM寄存器都是通用的。 lr(链接寄存器,也为R14)和pc(程序计数器也为R15)是特殊的,并包含在指令集中。您是正确的,lr将指向 A pclr是相关的。一个是“你在哪里”,另一个是“你在哪里”。它们是函数的代码方面。

通常,我们有sp(堆栈指针R13)和fp(frame pointer R11)。这两个也是相关的。这个
Microsoft layout很好地描述了事物。堆栈用于存储函数中的临时数据或本地数据。 foo()bar()中的任何变量都存储在此处,堆栈中或可用的寄存器中。 fp跟踪函数之间的变量。它是该功能在堆栈上的框架或图片窗口。 ABI定义了此框架的布局。通常,编译器会将lr和其他寄存器以及fp的先前值保存在幕后。这将形成堆栈框架的链接列表,如果需要,可以一直追溯到main()。根是fp,它指向一个堆栈帧(如struct),struct中的一个变量是前一个fp。您可以遍历列表,直到最终的fp(通常为NULL)。

因此,sp是堆栈所在的位置,fp是堆栈所在的位置,非常类似于pclr。每个旧的lr(链接寄存器)都存储在旧的fp(帧指针)中。 spfp是函数的数据方面。

您的点 B 是 Activity 的pcsp。点 实际上是fplr;除非调用另一个函数,否则编译器可能已准备就绪,可以设置fp指向 B 中的数据。

以下是一些ARM汇编程序,可能会演示这一切如何工作。取决于编译器的优化方式,这会有所不同,但是应该给出一个主意,

; Prologue - setup
mov ip, sp ; get a copy of sp.
stmdb sp!, {fp, ip, lr, pc} ; Save the frame on the stack. See Addendum
sub fp, ip, #4 ; Set the new frame pointer.
...
; Maybe other functions called here.

; Older caller return lr stored in stack frame.
bl baz
...
; Epilogue - return
ldm sp, {fp, sp, lr} ; restore stack, frame pointer and old link.
... ; maybe more stuff here.
bx lr ; return.
这就是 foo()的样子。如果您不调用 bar(),那么编译器将进行叶优化,并且不需要保存框架;只需要 bx lr。这很可能就是为什么您对网络示例感到困惑的原因。它并不总是相同的。

外卖应该是
  • pclr是相关的代码寄存器。一个是“您在哪里”,另一个是“您在哪里”。
  • spfp是相关的本地数据寄存器。一个是“本地数据在哪里”,另一个是“最后一个本地数据在哪里”。
  • parameter passing一起创建功能机制。
  • 很难描述一般情况,因为我们希望编译器尽可能快地实现的快速发展,以便他们使用所有可能的技巧。

  • 这些概念对于所有CPU和编译语言都是通用的,尽管细节可能有所不同。链接寄存器,帧指针的使用是 function prologue和结尾的一部分,如果您理解了所有内容,便知道堆栈溢出如何在ARM上工作。

    另请参阅: ARM calling convention
    MSDN ARM stack article
    University of Cambridge APCS overview
    ARM stack trace blog
    Apple ABI link

    基本框架布局是
  • fp [-0]保存了pc,我们将其存储在此处。
  • fp [-1]保存了lr,此函数的返回地址。
  • fp [-2]上一个sp,此函数占用堆栈之前。
  • fp [-3]上一个fp,最后一个堆栈帧。
  • 许多可选寄存器...

  • ABI 可以使用其他值,但是以上是大多数设置的典型值。上面的索引适用于32位值,因为所有ARM寄存器均为32位。如果您是以字节为中心的,请乘以四。帧也至少对齐四个字节。

    附录:这在汇编程序中不是错误;这是正常的。 ARM generated prologs问题中有一个解释。

    关于c - ARM:链接寄存器和帧指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752188/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com