get the caller's lr from subroutine into C variable - arm
arm, assembly
Solution
To answer the question directly, there are two solutions.
long lr;
asm(" mov %0,lr\n" :: "=r" (lr));
This will put the `lr` value in the lr variable. You may wish to do this to analyse something. If you are assuming that the `lr` contains a return address, then this is untrue as Igor explains. In a non-leaf function, the compiler may use the `lr` as a temporary when computing a function argument as it is going to be clobbered.
register long lr asm("lr");
This form allows you to reference the variable lr anywhere and the compiler will use the live `lr` value. The value may change through-out the function. For instance, when you call another function, it will usually be set to the return point in the currently active function.
As Igor explains whether getting the `lr` may not give you exactly what you expect. And the mechanism's we are using are gcc specific. You can not do this in a portable way; but accessing an `lr` is intrinsically non-portable.
See: ARM link register and frame pointer question for a little more on the use of `lr`.
Problem
I've got a C function that's supposed to get the value of the caller's lr register into a local variable. I've tried the following code: ``` volatile long lr; asm( "str %0, [sp, #4]\n" : "=r", (lr) ); ``` However, this doesn't change anything. It's not that I get the wrong value, it's just that the value of the lr local variable doesn't change at all ( contains garbage ). Any ideas? Thanks!