从c的伪代码到汇编-动手实现objc-msgsend.docxVIP

从c的伪代码到汇编-动手实现objc-msgsend.docx

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
从C的伪代码到汇编,动手实现objc_msgSend objc_msgSend 函数支撑了我们使用 Objective-C 实现的一切。Gwynne Raskind , Friday QA 的读者,建议我谈谈 objc_msgSe nd的内部实现。要理解某件事还有比自己动 手实现一次更好的方法吗?咱们来自己动手实现一个 objc_msgSend。 Tramapoli ne! Trampopoli ne!( 蹦床) 当你写了一个发送 Objective-C 消息的方法: [obj message] 编译器会生成一个 objc_msgSend调用: objc_msgSend(obj, @selector (message)); 之后objc_msgSe nd会负责转发这个消息。 它都做了什么?它会查找合适的函数指针或者 IMP,然后调用,最后跳转。任何传给 objc_msgSend的参数,最终都会成为IMP的参数。IMP的返回值成为了最开始被调用的 方法的返回值。 因为objcmsgSend只是负责接收参数,找到合适的函数指针,然后跳转,有时管这种 叫做trampoline (译注:[蹦床]((computing)).更通用的来说,任何一段负责把一段代 码转发到另一处的代码,都可以被叫做 trampoli ne 。 这种转发的行为使 objc_msgSend变得特殊起来。因为它只是简单的查找合适的代 码,然后直接跳转过去,这相当的通用。传入任何参数组合都可以,因为它只是把这些参 数留给IMP去读取。返回值有些棘手,但最终都可以看成 objc_msgSend的不同变种。 不幸的是,这些转发行为都不能用纯 C实现。因为没有方法可以将传入 C函数的泛 参(gen eric parameters )传给另一个函数。 你可以使用变参,但是变参和普通参数的传 递方法不同,而且慢,所以这不适合普通的 C参数。 如果要用C来实现objc_msgSend,基本样子应该像这样: id objc_msgSend(id self, SEL _cmd, ...) { Class c = object_getClass(self); IMP imp = class_getMethodImplementation(c, _cmd); return imp(self, _cmd, ...); } 这有点过于简单。事实上会有一个方法缓存来提升查找速度,像这样: id objc_msgSend(id self, SEL _cmd,…) { Class c = object_getClass(self); IMP imp = cache_lookup(c, _cmd); if(!imp) imp = class_getMethodlmplementation(c, _cmd); return imp(self, _cmd, ...); } 通常为了速度,cache_lookup 使用in li ne 函数实现。 汇编 在Apple版的run time 中,为了最大化速度,整个函数是使用汇编实现的。在 Objective-C 中每次发送消息都会调用 objc_msgSend,在一个应用中最简单的动作都会有 成千或者上百万的消息。 为了让事情更简单,我自己的实现中会尽可能少的使用汇编,使用独立的 C函数抽象 复杂度。汇编代码会实现下面的功能: id objc_msgSend(id self, SEL _cmd, ...) { IMP imp = GetImplementation(self, _cmd); imp(self, _cmd, ...); } 6. 7. GetImplementation 可以用更可读的方式工作。 汇编代码需要: 把所有潜在的参数存储在安全的地方,确保 GetImplementation 不会覆盖它们。 调用 GetImplementation 。 把返回值保存在某处。 恢复所有的参数值。 让我们开始吧! 这里我会尝试使用 X86-64 汇编,这样可以很方便的在 Mac上工作。这些概念也可以 应用于i386 或者ARM 这个函数会保存在独立的文件中,叫做 msgsend-asm.s。这个文件可以像源文件那样 传递给编译器,然后会被编译并链接到程序中。 第一件事要做的是声明全局的符号( global symbol )。因为一些无聊的历史原因, C 函数的global symbol 会在名字前有个下划线: .globl _objc_msgSend _objc_msgSend: 编译器会很高兴的链接最近可使用的 (n earest available) objc_msgSe nd 。简单的链 接这个到一个测试 app已经可以让[obj messag

文档评论(0)

yuxiufeng + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档