返回

objc_msgSend底层汇编解析,揭秘iOS消息发送机制

IOS

前言

在上一篇文章中,我们探讨了 Runtime 的基础知识,以及与 Runtime 交互的三种方式。我们还总结道:方法的本质实际上是消息发送的过程。本文将继续深入探讨 objc_msgSend 的汇编实现,揭开 iOS 消息发送机制的神秘面纱。

汇编实现剖析

objc_msgSend 是 Objective-C 中用于发送消息的核心函数。它是一个汇编函数,它的实现可以在 iOS 系统的 objc-runtime.h 头文件中找到。其原型如下:

id objc_msgSend(id self, SEL op, ...);

其中:

  • self:要向其发送消息的对象。
  • op:要发送的消息选择器。
  • ...:要传递给消息处理程序的可选参数。

objc_msgSend 函数的汇编实现可以分解为以下步骤:

  1. 查找方法实现:

    • 从对象 self 的类中查找与消息选择器 op 相对应的实现方法。
    • 如果找不到匹配的方法,则尝试通过消息转发机制查找实现。
  2. 压栈参数:

    • 将消息选择器 op 压入栈中。
    • 将消息接收者 self 压入栈中。
    • 将可选参数(如果有)压入栈中。
  3. 调用方法实现:

    • 调用方法实现的地址,该地址通过步骤 1 中的查找获得。
    • 方法实现将从栈中弹出参数并执行消息处理。
  4. 返回值:

    • 方法实现执行完成后,将返回值压入栈中。
    • objc_msgSend 函数返回栈顶的值。

实例分析

为了更深入地了解 objc_msgSend 的工作原理,让我们编写一个示例程序并对其汇编代码进行分析。

#import <Foundation/Foundation.h>

@interface Person : NSObject
- (void)sayHello;
@end

@implementation Person
- (void)sayHello {
    NSLog(@"Hello, world!");
}
@end

int main() {
    Person *person = [[Person alloc] init];
    [person sayHello];
    return 0;
}

使用 xcrun -sdk iphoneos clang -arch arm64 -S -o assembly.s main.m 命令将此程序编译成汇编代码。然后,我们可以使用 grep 命令查找 objc_msgSend 函数的汇编实现:

grep objc_msgSend assembly.s

输出结果将显示 objc_msgSend 函数的汇编代码,我们可以从中看到函数执行的步骤,正如我们在前面所讨论的。

总结

通过分析 objc_msgSend 的汇编实现,我们可以深入了解 iOS 消息发送机制。我们了解到 objc_msgSend 负责查找方法实现、压栈参数、调用方法实现并返回结果。这种对底层机制的理解有助于我们编写出更健壮、更高效的 Objective-C 代码。