建项目运行中断调试,lldb中显示寄存器看到有rax-r15, stm0-stm7, xmm0-xmm15, ymm0-ymm15,即为x64体系支持sse4。

再在lldb中查看寄存器别名得到以下对应:

rax 
rbx 
rcxarg4
rdxarg3
rdiarg1
rsiarg2
rbpfp
rspsp
r8arg5
r9arg6
r10 
r11 
r12 
r13 
r14 
r15 
rippc
rflagsflags
cs 
fs 
gs 

函数传参数的方式一清二楚,不是以前ia32时代传到街知巷闻的参数从右往左依次压栈的方式(系统调用和__fastcall以及汇编函数除外),函数传参数依次使用rdi,rsi,rdx,rcx,r8,r9。除此之外还用上xmm0-xmm7寄存器。

请看下面代码:

/////////////////////////////////////////////////////////////////////
//
// SaveRegisters
//
// Pushes a stack frame and saves all registers that might contain
// parameter values.
//
// On entry:
// stack = ret
//
// On exit:
// %rsp is -byte aligned
//
///////////////////////////////////////////////////////////////////// .macro SaveRegisters push %rbp
.cfi_def_cfa_offset
.cfi_offset rbp, - mov %rsp, %rbp
.cfi_def_cfa_register rbp sub $$0x80+, %rsp // + for alignment movdqa %xmm0, -0x80(%rbp)
push %rax // might be xmm parameter count
movdqa %xmm1, -0x70(%rbp)
push %a1
movdqa %xmm2, -0x60(%rbp)
push %a2
movdqa %xmm3, -0x50(%rbp)
push %a3
movdqa %xmm4, -0x40(%rbp)
push %a4
movdqa %xmm5, -0x30(%rbp)
push %a5
movdqa %xmm6, -0x20(%rbp)
push %a6
movdqa %xmm7, -0x10(%rbp) .endmacro

除了上面提到的寄存器外,r12-r15和rbx的用途能用下面几处反汇编就明白了。

然后翻看调用栈下几个栈的反汇编:

14 - CFRunLoopRunSpecific

15 - -[UIApplication _run]

16 - UIApplicationMain

UIKit`UIApplicationMain:
0x10f0c1bf6 <+>: pushq %rbp
0x10f0c1bf7 <+>: movq %rsp, %rbp
0x10f0c1bfa <+>: pushq %r15
0x10f0c1bfc <+>: pushq %r14
0x10f0c1bfe <+>: pushq %r13
0x10f0c1c00 <+>: pushq %r12
0x10f0c1c02 <+>: pushq %rbx
0x10f0c1c03 <+>: pushq %rax
0x10f0c1c04 <+>: movq %rcx, %rbx
0x10f0c1c07 <+>: movq %rsi, %r15
0x10f0c1c0a <+>: movl %edi, %r12d
UIKit`-[UIApplication _run]:
0x10f0bce26 <+>: pushq %rbp
0x10f0bce27 <+>: movq %rsp, %rbp
0x10f0bce2a <+>: pushq %r15
0x10f0bce2c <+>: pushq %r14
0x10f0bce2e <+>: pushq %r12
0x10f0bce30 <+>: pushq %rbx
0x10f0bce31 <+>: movq %rdi, %rbx
0x10f0bce34 <+>: callq 0x10fb23e34 ; symbol stub for: objc_autoreleasePoolPush
0x10f0bce39 <+>: movq %rax, %r14
0x10f0bce3c <+>: xorl %eax, %eax
0x10f0bce3e <+>: callq 0x10f4c6d50 ; _UIAccessibilityInitialize
0x10f0bce43 <+>: movq 0xc68766(%rip), %rsi ; "_registerForUserDefaultsChanges"
0x10f0bce4a <+>: movq 0xce632f(%rip), %r15 ; (void *)0x000000010e344800: objc_msgSend
0x10f0bce51 <+>: movq %rbx, %rdi
CoreFoundation`CFRunLoopRunSpecific:
0x10e7d7c40 <+>: pushq %rbp
0x10e7d7c41 <+>: movq %rsp, %rbp
0x10e7d7c44 <+>: pushq %r15
0x10e7d7c46 <+>: pushq %r14
0x10e7d7c48 <+>: pushq %r13
0x10e7d7c4a <+>: pushq %r12
0x10e7d7c4c <+>: pushq %rbx
0x10e7d7c4d <+>: subq $0xe8, %rsp
0x10e7d7c54 <+>: movl %edx, -0xec(%rbp)
0x10e7d7c5a <+>: movsd %xmm0, -0xe8(%rbp)
0x10e7d7c62 <+>: movq %rsi, %r14
0x10e7d7c65 <+>: movq %rdi, %r12
0x10e7d7c68 <+>: movq 0x311459(%rip), %rax ; (void *)0x00000001114c0070: __stack_chk_guard
0x10e7d7c6f <+>: movq (%rax), %rax
0x10e7d7c72 <+>: movq %rax, -0x30(%rbp)

代码的共通点都是在函数开始运算之前将r12-r15以及rbx压入栈,r12-r15以及rbx主要用于函数局部变量或临变量。在UIApplicationMain函数中一开始入栈保存后,马上将输入参数传送到rbx,r15,r12进行运算。

已经约模弄清楚了一条路了,下面就开始反汇编逆向分析,但我的平台是simulator x64。

ps:后面还会介绍objc其它传参方式, 以及windows和linux(也就是vc与gcc)在x64平台的传参方式。

05-27 14:49