返回

深入剖析 iOS 底层:揭秘 `objc_msgSend` 汇编源码,助你领略消息发送机制的精髓

IOS

揭秘 objc_msgSend:消息发送机制的奥秘

在 Objective-C 中,消息发送是对象之间通信的核心机制。当我们向一个对象发送消息时,实际执行的是 objc_msgSend 函数,该函数负责将消息传递给对象并执行相应的方法。

objc_msgSend 函数的汇编代码位于 objc4.tbd 文件中,我们可以通过一些工具来查看该文件的内容。我们可以看到,objc_msgSend 函数非常复杂,涉及到大量汇编指令和寄存器的操作。

为了便于理解,我们将 objc_msgSend 函数的工作原理拆分成几个步骤:

  1. 确定接收者和选择器: objc_msgSend 函数首先会确定消息的接收者和选择器。接收者是消息发送的目标对象,而选择器是消息的名称,它标识了要调用的方法。
  2. 查找方法实现: 在确定了接收者和选择器之后,objc_msgSend 函数会查找要调用的方法实现。方法实现是方法的具体代码,它告诉我们如何执行该方法。
  3. 压入参数: 在找到方法实现之后,objc_msgSend 函数会将消息的参数压入栈中。参数的顺序与方法的参数列表顺序一致。
  4. 调用方法实现: 最后,objc_msgSend 函数会调用方法实现。方法实现会从栈中弹出参数,并执行方法的代码。

手把手理解 objc_msgSend 汇编源码

为了更深入地理解 objc_msgSend 函数的汇编源码,我们不妨通过一个简单的例子来进行演示。假设我们有一个名为 Person 的类,该类具有一个名为 sayHello 的方法,该方法接受一个字符串参数并打印该字符串。

@interface Person : NSObject

- (void)sayHello:(NSString *)name;

@end

@implementation Person

- (void)sayHello:(NSString *)name {
    NSLog(@"Hello, %@!", name);
}

@end

为了调用 sayHello 方法,我们可以使用 objc_msgSend 函数。以下是在汇编代码中调用 sayHello 方法的示例:

mov r0, #selector(sayHello:)
ldr r1, [r0]
ldr r2, [r1]
mov r3, #0
mov r0, r2
blx r0

在这段汇编代码中:

  • mov r0, #selector(sayHello:):将 sayHello: 方法的选择器加载到寄存器 r0 中。
  • ldr r1, [r0]:将 sayHello: 方法实现的地址加载到寄存器 r1 中。
  • ldr r2, [r1]:将 sayHello: 方法实现的入口点加载到寄存器 r2 中。
  • mov r3, #0:将整数 0 加载到寄存器 r3 中,因为 sayHello: 方法没有参数。
  • mov r0, r2:将 sayHello: 方法实现的入口点加载到寄存器 r0 中。
  • blx r0:调用 sayHello: 方法实现。

总结

通过对 objc_msgSend 汇编源码的剖析,我们深入了解了消息发送机制的运作原理。我们看到了 objc_msgSend 函数是如何确定接收者和选择器、查找方法实现、压入参数和调用方法实现的。通过这些步骤,我们得以理解消息发送机制是如何将消息传递给对象并执行相应的方法的。