这是 ARM RISC 代码,ARM 的首选编程模式是相对的——不要使用绝对地址,始终使用“IP+/-offset”。在这里,被调用的地址超出了直接调用或跳转的范围,编译器使用了他能找到的最近的地址。它增加了一个额外的跳跃(或超过 1 个!),但它与位置无关。(*)
编译器无法使用简单的指令构造到目标地址的跳转,因为您无法立即使用 RISC 汇编加载每个可能的 2^32 数字。
如果例程objc_msgSend
自己返回,那么这相当于call objc_msgSend; return
-- 只是更短。从当前函数的角度来看,这两种形式都只做一次“返回”。
(*) 您可以在反汇编屏幕截图中看到(??为什么不是文本?) R12 加载了目标地址和当前地址之间的差异。这个差异是由编译器计算出来的;它不会在原始二进制文件中显示为减法,这是 IDA 的工作。然后将差值添加到当前地址——不管它是什么!立即objc_msgSend - 0x1AE030
数使用足够少的位在一条指令中加载到 R12 中(您应该熟悉的 ARM RISC '功能')。
如果您想知道语法:这只是 IDA,告诉您这是直接跳转到已知标签。据推测,如果你的代码足够长,你可能会发现到这个标签的距离又太大了,所以你可能会发现.j__label
j__j__objc_msgSend