这里有一个(x64)例子,刚好说明寄存器在函数中的位置编排。rdi是第一个不为浮点或数据结构对象的参数,这里的第一个参数实质上与我们定义的函数类型的第一个参数不是对应的。当函数类型是类成员函数,rdi首先安放this指针。当函数类型返回数据结构对象时,rdi优先安排返回结果的指针(这个临时对象就在上一级的栈中,指针指向临时对象)。如果满足上面两种情况,临时对象地址优先,这时rdi是临时对象,rsi才是this指针。
下面是我自制反汇编工具生成的代码:
// -[CALayer setAffineTransform:(CGAffineTransform)] void CALayer20_setAffineTransform3A_(id self, SEL sel, CGAffineTransform affineTransform) { // 0 pushq %rbp // 1 rbp = rsp; // 4 pushq %r14 // 6 pushq %rbx // 7 rsp = rsp - 0x100; // 14 rbx = rdi; // 17 r14 = &_90; // 24 rsi = &arg_10; // 28 rdi = r14; // 31 call CATransform3DMakeAffineTransform_(); // 36 rax = "setTransform:"; // 43 ecx = 0x10; // 48 rdi = rsp; // 51 rsi = r14; // 54 rep // 55 = (int64_t)(int64_t&)rsi->_0; // 57 rdi = rbx; // 60 rsi = rax; // 63 call objc_msgSend(rbx, "setTransform:", ...); // 69 rsp = rsp + 0x100; // 76 popq %rbx // 77 popq %r14 // 79 popq %rbp /***** * global variables * */ // 36 extern ent_off__0x6c861; movq 0x6c836(%rip), %rax; "setTransform:" }
很容易看出两处函数使用
CATransform3DMakeAffineTransform_
[self setTransform]
这里的CATransform3DMakeAffineTransform_返回的就是临时对象CATransform3D,虽然它使用了寄存器rdi和rsi,但它的函数原型只有一个参数,"CATransform3D CATransform3DMakeAffineTransform(CGAffineTransform m);"。
注:_90表示rbp-0x90,即为局部变量。
arg_10表示rbp+0x10,即为上级的栈中调用参数,并且是第一个用栈传递的参数(请注意这里第一个的表述)。
在-[CALayer setAffineTransform:]函数中,我们通常会认为CGAffineTransform参数在rdx,但这里不是,因为是一个对象传参,所以在传参时产生的临时对象,用栈来传递这个对象。
行55的汇编是 movsq (%rsi), es:(%rdi),就是等同于memcpy,其实就是两个对象简单copy。结合上面的rcx寄存和rep指令,就是复制了10个8字节长到rsp,作为-[CALayer setTransform:]的参数,使用栈传参数。
现在就可以得到最后的翻译:
// -[CALayer setAffineTransform:(CGAffineTransform)] void CALayer20_setAffineTransform3A_(id self, SEL sel, CGAffineTransform affineTransform) { // 31 call CATransform3D m = CATransform3DMakeAffineTransform_(affineTransform); // 63 call objc_msgSend(self, "setTransform:", m); }