Reputation: 7360
Consider the following Objective C interface definition
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@property NSObject* myprop;
@end
The assembly generated for ARMv7 by Xcode 5 for [MyClass myprop]
looks like
.code 16 @ @"\01-[MyClass myprop]"
.thumb_func "-[MyClass myprop]"
"-[MyClass myprop]":
Lfunc_begin0:
.cfi_startproc
@ BB#0:
sub sp, #8
@DEBUG_VALUE: -[MyClass myprop]:self <- undef
@DEBUG_VALUE: -[MyClass myprop]:_cmd <- undef
str r0, [sp, #4]
str r1, [sp]
ldr r0, [sp, #4]
movw r2, :lower16:(_OBJC_IVAR_$_MyClass.myprop-(LPC0_0+4))
movt r2, :upper16:(_OBJC_IVAR_$_MyClass.myprop-(LPC0_0+4))
LPC0_0:
add r2, pc
ldr r2, [r2]
movs r3, #1
add sp, #8
b.w _objc_getProperty
Ltmp0:
Lfunc_end0:
.cfi_endproc
I want to understand the resulting assembly and have the following questions about it:
1) The last instruction (b.w _objc_getProperty
) sets the PC to the address of the label _objc_getProperty
. But how does this procedure know where to jump back? Does it assume that the method is invoked with bl
, and therefore the link register contains the target address?
2) What do the 3 lines below the second @DEBUG_VALUE do?
If I understand it correctly, the content of r0 is stored at stack offset 4, r1 is stored at the current stack (offset 0), and r0 is filled with stack offset 4. But why does the last instruction changes anything? Doesn't it just mean that r0 is filled with what it already contained? What are the values used for? _obj_getProperty
?
3) Why is r3 set to 1 at the end? (movs r3, #1
)?
Upvotes: 0
Views: 368
Reputation: 18493
In C code the function would probably look like this:
resulttype Lfunc_begin0(type1 arg1, type2 arg2)
{
return _objc_getProperty(arg1, arg2, Myclass_myprop, 1);
}
First let's look at the following example:
int func(void)
{
a();
b();
return c();
}
It would now be possible to do the function call to "c()" the following way:
save_lr
bl a
bl b
bl c
restore_original_lr
bx lr
Alternatively it would be possible to perform the following code:
save_lr
bl a
bl b
restore_original_lr
b c
In this case the "bx lr" instruction at the end of "c()" will directly jump to the function that called ourself and we do not have to do the "bx lr".
Because some function calls in the C code may destroy the content of R0 and R1 unoptimized C code will save these registers to the stack just for the case that their value is needed later. Well-optimized C code would check this and remove the three instructions after the "@DEBUG" lines. Even the "add SP," and "sub SP," lines could be optimized away!
The _obj_getProperty function obviously takes four arguments. R0 and R1 are simply passed (as shown in the C code above) while R2 and R3 are the additional arguments for that function.
What the 4th argument (R3=1) really means cannot be seen from the assembler code shown here.
Upvotes: 1