【问题标题】:get the caller's lr from subroutine into C variable - arm将调用者的 lr 从子程序中获取到 C 变量 - arm
【发布时间】:2013-08-16 09:59:29
【问题描述】:

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

我试过以下代码:

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

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

有什么想法吗?

谢谢!

【问题讨论】:

    标签: assembly arm


    【解决方案1】:

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

        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 本质上是不可移植的。

    请参阅:ARM link register and frame pointer 问题以了解更多有关使用 lr 的信息。

    【讨论】:

    • 当您尝试访问 APCS 的 stack frame's 保存的lr 时,我想您真正想要的是__built_in_return_address();在这种情况下,您最好使用fp,因为它始终处于活动状态。 sp 将针对局部变量进行调整,并且永远不会正确设置以获取保存的 lr。如果您使用__built_in_return_address(),则根本不必了解这一点。
    • 此外,较新的 AAPCS 不要求设置帧指针,因此您需要使用 ELF/目标文件中的辅助表来执行调用树遍历(以及对象清理)。最好让__built_in_return_address() 为你做这件事。请参阅可能影响 lr 使用的 -mabi 值。
    【解决方案2】:

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

    编辑:您的代码甚至没有读取任何相关内容,它只是在堆栈上存储了一个未初始化变量的值(提示:将变量命名为 lr 不会' t 让它神奇地获取 register LR) 的值。在最好的情况下它不会做任何事情,在最坏的情况下你会覆盖一些重要的东西并且它会崩溃。

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

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

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

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

    【讨论】:

    • "你的代码会得到地址SP+4处的值"会吗? OP 正在执行 STR,而不是 LDR
    • 糟糕,确实如此。那就更没用了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2013-06-07
    • 1970-01-01
    • 2012-05-23
    相关资源
    最近更新 更多