2014-12-02 91 views
0

考虑以下目标C的接口定义的ARM组件试图了解iOS应用

#import <Foundation/Foundation.h> 

@interface MyClass : NSObject 

    @property NSObject* myprop; 

@end 

对ARMv7通过Xcode的5为[MyClass myprop]生成的组件看起来像

.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 

我想了解所得并且有关于它的以下问题:

1)最后一条指令(b.w _objc_getProperty)将PC设置为标签_objc_getProperty。但是这个程序怎么知道要跳回去?它是否假定该方法是用bl调用的,因此链接寄存器包含目标地址?

2)第二个@DEBUG_VALUE下面的3行是做什么的?

如果我理解正确,r0的内容存储在堆栈偏移量4,r1存储在当前堆栈(偏移量0),r0堆栈偏移量4填充。但为什么最后一条指令改变了什么?这不仅仅意味着r0充满了它已经包含的内容吗?用于什么值? _obj_getProperty

3)为什么r3在最后设置为1? (movs r3, #1)?

+0

编译器在关闭优化的情况下看起来非常愚蠢,并且将所有参数保存到堆栈而不触及它们,然后将它们重新加载到-O0的完全相同的寄存器气味。试图推理-O0输出可能是相当无用的; -O1可能是一个更好的选择。这看起来像一个蹦床,它增加了两个额外的参数来标识特定的属性,然后转发到通用的“get”例程,但我真的不知道Objective-C的内部及其调用约定。 – Notlikethat 2014-12-02 11:40:12

回答

1

在C代码的功能很可能是这样的:

resulttype Lfunc_begin0(type1 arg1, type2 arg2) 
{ 
    return _objc_getProperty(arg1, arg2, Myclass_myprop, 1); 
} 

首先让我们来看看下面的例子:

int func(void) 
{ 
    a(); 
    b(); 
    return c(); 
} 

现在将有可能做的函数调用为“c ()“以下方式:

save_lr 
bl a 
bl b 
bl c 
restore_original_lr 
bx lr 

或者,可以执行以下操作ING代码:

save_lr 
bl a 
bl b 
restore_original_lr 
b c 

在这种情况下,在最后的“BX LR”指令“C()”将直接跳转到调用我们自己的功能和我们没有做“BX LR”。

由于C代码中的某些函数调用可能会破坏R0和R1的内容,未优化的C代码会将这些寄存器保存到堆栈中,只是为了稍后需要它们的值。经过优化的C代码会检查这个并在“@DEBUG”行之后删除三条指令。即使是“添加SP”和“子SP”线条也可以进行优化!

_obj_getProperty函数显然需要四个参数。简单地传递R0和R1(如上面的C代码所示),而R2和R3是该函数的附加参数。

第4个参数(R3 = 1)的真正含义不能从这里显示的汇编代码中看到。