从子程序得到调用者的lr到C变量 - arm

时间:2013-08-16 09:59:30

标签: assembly arm

我有一个C函数,它应该将调用者的lr寄存器的值转换为局部变量。

我尝试过以下代码:

volatile long lr;
asm(
    "str %0, [sp, #4]\n" :
    "=r", (lr)
);

然而,这并没有改变任何事情。这不是我得到错误的值,只是lr局部变量的值根本不会改变(包含垃圾)。

有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

要直接回答这个问题,有两种解决方案。

    long lr;
    asm(" mov %0,lr\n" :: "=r" (lr));

这会将lr值放在 lr变量中。你可能希望这样做来分析一些东西。如果您假设lr包含返回地址,那么这是不正确的,因为Igor解释。在非叶函数中,编译器在计算函数参数时可能会使用lr作为临时函数,因为它将被破坏。

    register long lr asm("lr");

此表单允许您在任何地方引用变量 lr ,编译器将使用实时lr值。该值可能会在整个函数中发生变化。例如,当您调用另一个函数时,它通常会被设置为当前活动函数的返回点。

正如Igor解释,获取lr是否可能无法满足您的期望。我们使用的机制是 gcc 特定的。您无法以便携式方式执行此操作;但访问lr本质上是不可移植的。

有关使用lr的更多信息,请参阅:ARM link register and frame pointer

答案 1 :(得分:3)

您的代码将获取地址SP+4的值。该位置是否包含初始LR取决于编译器,优化设置,特定函数或放置此代码的函数中的位置。简而言之,它可能只会偶然发挥作用。

编辑:您的代码甚至没有读取任何相关内容,它只是在堆栈中存储未初始化变量的值(提示:命名变量lr不会让它神奇地取寄存器的值 LR)。在最好的情况下,它不会做任何事情,在最糟糕的情况下,你会覆盖重要的东西,它会崩溃。

我假设您确实想要获取函数的返回地址,而不是LR。存在特定于编译器的选项。

  1. GCC提供__builtin_return_address()内在函数,它返回当前函数的返回地址(如果用0调用),或者可能是调用堆栈中的其他函数(尽管我不会依赖后者) )。

  2. Visual C ++有_ReturnAddress()甚至_AddressOfReturnAddress()内在函数。

  3. 我建议使用上述之一(假设您正在使用GCC或VC)并且不依赖可能随时停止工作的技巧。