iOSObjective-C汇编

更新时间:2023-07-09 00:39:21 阅读: 评论:0

iOSObjective-C汇编
转:/industry/20130624/6463_2.html
汽车保养用品Objective -C 汇编
到现在为止,我们涉及到的函数都是用C语言来写的。Objective-C在C语言的基础上稍微增加了一点复杂度。下面我们就来看看用Objective-C代码编译出来的汇编指令。打开ViewController.m文件,然后将下面的方法添加到类的实现中:
骑缝章英文1. - (int)addValue:(int)a toValue:(int)b {
2.    int c = a + b;
3.    return c;
4. }
同样,通过这样的步骤来查看汇编代码:Product\Generate Output\Asmbly File。记得将output类型设置为Archiving,然后搜索addValue:toValue: ,你会发现类似如下的汇编代码:
1. "-[ViewController addValue:toValue:]":
2.    adds    r0, r3, r2
who是什么意思3.    bx  lr
首先看到的是一个标签(label)名称——”-[ViewController addValue:toValue:]“,这个名称包含类名和完整的Objective-C方法名称。
把上面的汇编代码与之前的addFunction相关汇编代码进行比较,你会发现这里是将r2和r3进行加法运算,而不是r0与r1相加——这意味着传递给addValue:toValue:方法的参数使用了r2和r3寄存器(没有使用r0和r1),这是为什么呢?
这是因为:在调用Objective-C方法时,除了传递明确指定的参数外,还会在明确参数之前传递两个隐含的参数(implicit parameter)。addValue:toValue:方法跟下面的C函数是等价的:
1. int ViewController_addValue_toValue(id lf, SEL _cmd, int a, int b) {
2.    int c = a + b;
3.    return c;
4. }
这就是为什么a和b两个参数分别存储到r2和r3的原因。可能你之前已经听说过前两个参数了(经常使用lf吧)。
提醒:lf和_cmd占用了r0和r1寄存器。
可能之前你还没有见过_cmd。其实跟lf一样,在Objective-C函数中,_cmd是可以直接使用的,它存储着当前执行方法的lector。一般来说,你并不需要使用_cmd(这也可能是为什么你从来没有听说过_cmd的原因)。
为了观察Objective-C方法是如何被调用的,现在将如下方法添加到ViewController中:
1. - (void)foo {
2.    int add = [lf addValue:12 toValue:34];
3.    NSLog(@"add = %i", add);
4. }
重新生成汇编文件,然后寻找“-[ViewController foo]“:,应该能看到类似如下的代码:
1. "-[ViewController foo]":
2. @ 1:月光爱人英文版
3.    push    {r7, lr}
哈佛大学录取条件4. @ 2:
5.    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
6.    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC1_0+4))
7. LPC1_0:
8.    add r1, pc
9. @ 3:
10.    ldr r1, [r1]
11. @ 4:
12.    movs    r2, #12
13.    movs    r3, #34
14. @ 5:
15.    mov r7, sp
16. @ 6:
17.    blx _objc_msgSend
18. @ 7:
19.    mov r1, r0
20. @ 8:
21.    movw    r0, :lower16:(L__unnamed_cfstring_-(LPC1_1+4))
22.    movt    r0, :upper16:(L__unnamed_cfstring_-(LPC1_1+4))
23. LPC1_1:
24.    add r0, pc
25. @ 9:
26.    blx _NSLog
27. @ 10:
28.    pop {r7, pc}
北京游戏培训
同样,这与之前C语言产生的汇编代码非常相似,我们也来看看具体都做了些什么:
1、将r7和lr push到栈中。
2、利用pc(program counter)将标签L_OBJC_SELECTOR_REFERENCES_对应的值装载到r1寄存器中。这个标签引用到一个lector。实际上lector就是一个字符串,并且存储在数据段中(data gment)。
3、如果在汇编文件中搜索L_OBJC_SELECTOR_REFERENCES_,会看到如下内容:
1. L_OBJC_SELECTOR_REFERENCES_:?    .long  L_OBJC_METH_VAR_NAME_
r1会指向这里(L_OBJC_SELECTOR_REFERENCES_),这个标签包含了另外一个标签:
L_OBJC_METH_VAR_NAME_。在文件中查找这个标签(L_OBJC_METH_VAR_NAME_),会找到这样的字符串:addValue:toValue:。
而指令ldr r1, [r1]的作用:对r1中存储的地址进行解引用(dereferencing),然后将得到的值放到r1中。如果用C伪代码看起来应该是这样的:r1 = *r1。仔细想想的话,可能你应该知道r1将会存储着指向字符串addValue:toValue: 的指针。
4、将常量装载到r2和r3中。
5、将sp保持到r7寄存器中。
6、这是一个分支(branch),以带链接跳转和根据情况切换指令集的模式来调用objc_msgSend方法。这是Objective-C runtime中非常重要的一个方法——它根据传递的参数找到并调用相关的函数。
该方法使用到了4个参数(r0-r3)。因此,在上面的代码中,将lector装载到r1中,另外两个参数(12和34)装载到r2和r3中。注意:在此并没有明确的装载r0,因为r0已经存储着lf变量了。
7、调用addValue:toValue:的返回值被存放在r0中。这里的指令将这个结果值保持到r1中。在接下来调用NSLog函数时会用到这个值。
8、将NSLog用到的第一个字符串参数装载到r0中。这跟之前介绍的用C函数里面调用printf一样。
9、这是一个分支(branch),以带链接跳转和根据情况切换指令集的模式来调用NSLog方法。
10、从栈中pop出两个值,并放入r7和pc寄存器中。这跟之前一样,从foo方法中返回。
如上所见,由C和Objective-C代码生成汇编指令,区别不是太大。只不过在Objective-C生成的汇编指令中,会隐示的给方法传递两个参数,以及使用到的lector以字符串的形式存放在数据段中(data gment)。
Obj-C 消息发给了谁
上面我们看到了objc_msgSend方法。可能你在crash log中已经看到过这个方法。该方法是Objective-C runtime中的一个核心方法。runtime包含了内存管理以及类的相关处理。
每次调用Objective-C方法时,都由objc_msgSend方法(这是一个C方法)处理消息的派送(dispatching)。该方法根据传递的消息类型在类的方法列表中查找被调用方法的实现。objc_msgSend方法的签名(signature)看起来是这样的:
1. id objc_msgSend(id lf, SEL _cmd, ...)
在方法执行期间,第一个参数是lf。在方法中写的一些代码,例如lf.someProperty,其中lf就是来自自
objc_msgSend方法中的lf参数。
第二个参数很少人会知道,这也是一个被隐藏的参数(hidden parameter)。如果在Objective-C方法中,写这类似这样的代码:NSLog(@”%@”, NSStringFromSelector(_cmd)); ,会看到控制台输出了当前的lector。
剩下的参数一般就是开发者传递给该方法的参数了。所以如果一个方法携带两个参数,例如上面的
addValue:toValue:,那么还会携带额外的两个参数。因此,我们也可以用下面的代码来代替通过Objective-C方式的调用:
1. - (void)foo {
一般现在时表将来
2.    int add = (int)objc_msgSend(lf, NSSelectorFromString(@"addValue:toValue:", 12, 34);
3.    NSLog(@"add = %i", add);
4. }
注意:虽然objc_msgSend的返回值类型是id,不过在上面的代码中将其转换为int类型了。因为它们的size是相同的,所以转换为int不会有问题。如果该方法返回的是不同的size,那么实际上是别的函数被调用了,更多内容请看这里:here。同样,如果返回的是一个floating指针,那么则是objc_msgSend的另一个变种被调用了,更多内容请看这里:here。
当一个Objective-C方法被编译的时候,上面用C写的等效方法签名应该是这样的:
1. int ViewController_addValue_toValue(id lf, SEL _cmd, int a, int b)
对此为什么会这样,现在应该不会感觉到奇怪——这样的签名是为了与objc_msgSend相匹配!也就是说当
objc_msgSend在查找并跳转到对应方法时,所有的这些参数都应该在正确的地方。
这里可以看到更多关于objc_msgSend相关内容:文章1,文章2。
你现在可以进行逆向工程了
根据上面对ARM汇编的介绍,你应该可以能够知道为什么有些代码被breaking、crashing或者没有正确的执行。
通过观察相关的汇编代码,可以更加清楚的获知到引起bug的详细步骤。
有时候,你可能无法查看源代码——例如,你遇到的bug是发生在第三方库或者系统的framework中。此时,通过汇编指令进行分析可以帮助你迅速的找到问题。下面的目录存放着iOS SDK中所有的framework:工程项目质量管理
<Path_to_Xcode>/Contents/Developer/Platforms/iPhoneOS.platform/Developer/
SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks
我建议使用HopperApp对这些库进行分析。该软件能够对二进制文件进行反汇编——这样你就可以看库中的内容了——这样做是没有问题的!!!例如,打开UIKit,就可以看到每个方法都做了什么。如下图所示:
上图中的汇编代码是[UINavigationController shouldAutorotateToInterfaceOrientation] 方法相关的。结合之前介绍的ARM汇编知识,相信上面的汇编代码具体做了些什么你应该能看出来。
首先是将一个lector引用装载到ri寄存器中,以供后续调用objc_msgSend使用。然后可以看到,别的寄存器并没有做任何改动,所以我们可以知道传递给objc_msgSend方法的lf指针(存储在r0中),跟传递给shouldAutorotateToInterfaceOrientation方法的lf是同一个。
同理,我们可以知道被调用方法携带一个参数(代码中有一列是用来显示相关名称的)。由于r2寄存器没有改动过,所以这个参数就是从shouldAutorotateToInterfaceOrientation方法传入的。
最后,函数调用之后,r0没有改动过,所以被调用函数的返回值就是调用函数的返回值。
这样一来,就可以推断出这个方法的实现应该是这样的了:
1. - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
2.    return [lf _doesTopViewControllerSupportInterfaceOrientation:interfaceOrientation];
3. }
cool!很容易吧!虽然大多数方法都比上面的这个要复杂,不过你可以根据汇编指令拼凑出一些代码,进而快速的确定这些代码做了些什么。
foggy何去何从
这篇关于iOS汇编的教程向你介绍了一些运行在iOS设备中的ARM汇编指令核心概念。你应该学习到了C和Objective-C相关的一些调用约定。
udf通过本文介绍的知识,当你的程序在使用系统库crash时,你可以对所有能看到的随机代码进行分析。当然,你也可以通过汇编指令来准确的分析你自己写的方法。
如果你希望更加深入的了解ARM,请看这里:Raspberry Pi。这里的涉及到的小型设备都拥有ARM处理器,跟iOS
设备非常相似,同时也有许多教程可以教你如何对这些设备进行编程。
另外,NEON也值得去学习了解。这是另外扩展的一套指令集,自iPhone 3GS以来设备中的所有处理器,都支持NEON指令集。该指令集提供了SIMD(单指令,多数据——Single Instruction Multiple Data)指令,对数据的处理非常高效,例如,图片的处理。如果你需要对数据进行高效的处理,那么最好学习一下如何直接写NEON指令,并结合使用内联汇编(inline asmbly)。这个指令集非常的先进!

本文发布于:2023-07-09 00:39:21,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/1086392.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:方法   汇编   代码   参数
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图