4

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

我试过以下代码:

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

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

有任何想法吗?

谢谢!

4

2 回答 2

6

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

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

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

    register long lr asm("lr");

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

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

请参阅:ARM 链接寄存器和帧指针问题,了解更多关于lr.

于 2013-08-16T12:47:47.233 回答
4

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

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

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

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

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

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

于 2013-08-16T11:52:07.413 回答