我有一个 C 函数,它应该将调用者的 lr 寄存器的值放入一个局部变量中。
我试过以下代码:
volatile long lr;
asm(
"str %0, [sp, #4]\n" :
"=r", (lr)
);
然而,这并没有改变任何东西。并不是我得到了错误的值,只是 lr 局部变量的值根本没有改变(包含垃圾)。
有任何想法吗?
谢谢!
要直接回答这个问题,有两种解决方案。
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
.
您的代码将获得地址处的值SP+4
。该位置是否包含初始LR
值取决于编译器、优化设置、特定函数或放置此代码的函数中的位置。简而言之,它可能只是偶然地起作用。
编辑:您的代码甚至没有读取任何相关内容,它只是在堆栈上存储了一个未初始化变量的值(提示:命名您的变量lr
不会让它神奇地获取寄存器 LR
的值)。在最好的情况下它不会做任何事情,在最坏的情况下你会覆盖一些重要的东西并且它会崩溃。
我假设您实际上想要获取函数的返回地址,而不是 LR。存在特定于编译器的选项。
GCC 提供了__builtin_return_address()
返回当前函数的返回地址的内在函数(如果用 0 调用),或者可能是调用堆栈中的其他函数(尽管我不依赖后者)。
Visual C++ 有_ReturnAddress()
甚至_AddressOfReturnAddress()
内在函数。
我建议使用上述方法之一(假设您使用的是 GCC 或 VC)并且不要依赖可能随时停止工作的技巧。