飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4085|回复: 2

[macOS] 初探OSX x86_64传参

[复制链接]
  • TA的每日心情
    无聊
    2016-10-10 10:27
  • 签到天数: 26 天

    [LV.4]偶尔看看III

    发表于 2016-5-31 14:30:45 | 显示全部楼层 |阅读模式
    近来在搞OSX/iOS方面的东西,本篇文章仅为我想探索下xcode编译出的x64在传参规则上与vs编译是否有什么不同,毫无技术含量。
    Win x64传参请移步 -> [初探x64参数变量及栈空间布局]

    编译器会为函数开辟函数自己的栈桢,空函数(无参数、无变量)源码如下:

            #import <Foundation/Foundation.h>
            float testfun1(){
                            return 1.0f;
            }
            int testfun2(){
                            return 2;
            }
            int main(int argc, const char * argv[]) {
                            NSLog(@"testfun : %f %d", testfun1(), testfun2());
                            return 0;
            }

    从汇编上可以看到函数框架的返回值是在rax或者xmm0:

            __text:0000000100000F10                 public _testfun1
            __text:0000000100000F10 _testfun1       proc near               ; CODE XREF: _main+16p
            __text:0000000100000F10                 push    rbp
            __text:0000000100000F11                 mov     rbp, rsp
            __text:0000000100000F14                 movss   xmm0, cs:dword_100000F9C
            __text:0000000100000F1C                 pop     rbp
            __text:0000000100000F1D                 retn
            __text:0000000100000F1D _testfun1       endp

            __text:0000000100000F20                 public _testfun2
            __text:0000000100000F20 _testfun2       proc near               ; CODE XREF: _main+24p
            __text:0000000100000F20                 push    rbp
            __text:0000000100000F21                 mov     rbp, rsp
            __text:0000000100000F24                 mov     eax, 2
            __text:0000000100000F29                 pop     rbp
            __text:0000000100000F2A                 retn
            __text:0000000100000F2A _testfun2       endp

    众所周知x64下有以下寄存器:
    `rax、rbx、rcx、rdx、rdi、rsi、rbp、rsp、r8、r9、r10、r11、r12、r13、r14、r15、rip、rflags`

    测试程序的源代码如下:

        int testfun(char a, int b, int c, int d, int e, int f,int g, int h, int i, int j, int k){
            return (int)(a + b + c + d + e + f + g + h + i + j + k);
        }
        int main(int argc, const char * argv[]) {
            NSLog(@"testfun : %d", testfun(1,2,3,4,5,6,7,8,9,10,11));
            return 0;
        }

    汇编层如下:

        __text:0000000100000EB0                 public _main
        __text:0000000100000EB0 _main           proc near
        __text:0000000100000EB0
        __text:0000000100000EB0 arg7_rsp_80     = dword ptr -80h
        __text:0000000100000EB0 var_7C          = dword ptr -7Ch
        __text:0000000100000EB0 arg8_rsp_78     = dword ptr -78h
        __text:0000000100000EB0 var_74          = dword ptr -74h
        __text:0000000100000EB0 arg9_rsp_70     = dword ptr -70h
        __text:0000000100000EB0 var_6C          = dword ptr -6Ch
        __text:0000000100000EB0 arg10_rsp_68    = dword ptr -68h
        __text:0000000100000EB0 var_64          = dword ptr -64h
        __text:0000000100000EB0 arg11_rsp_60    = dword ptr -60h
        __text:0000000100000EB0 var_5C          = dword ptr -5Ch
        __text:0000000100000EB0 arg7_rbp_4c     = dword ptr -4Ch
        __text:0000000100000EB0 arg8_rbp_48     = dword ptr -48h
        __text:0000000100000EB0 arg9_rbp_44     = dword ptr -44h
        __text:0000000100000EB0 arg10_rbp_40    = dword ptr -40h
        __text:0000000100000EB0 arg11_rbp_3c    = dword ptr -3Ch
        __text:0000000100000EB0 var_38          = qword ptr -38h
        __text:0000000100000EB0 var_30          = dword ptr -30h
        __text:0000000100000EB0 var_2C          = dword ptr -2Ch
        __text:0000000100000EB0
        __text:0000000100000EB0                 push    rbp
        __text:0000000100000EB1                 mov     rbp, rsp
        __text:0000000100000EB4                 push    r15
        __text:0000000100000EB6                 push    r14
        __text:0000000100000EB8                 push    r13
        __text:0000000100000EBA                 push    r12
        __text:0000000100000EBC                 push    rbx
        __text:0000000100000EBD                 sub     rsp, 58h
        __text:0000000100000EC1                 mov     eax, 1
        __text:0000000100000EC6                 mov     ecx, 2
        __text:0000000100000ECB                 mov     edx, 3          ; rdx == arg3
        __text:0000000100000ED0                 mov     r8d, 4
        __text:0000000100000ED6                 mov     r9d, 5
        __text:0000000100000EDC                 mov     r10d, 6
        __text:0000000100000EE2                 mov     r11d, 7
        __text:0000000100000EE8                 mov     ebx, 8
        __text:0000000100000EED                 mov     r14d, 9
        __text:0000000100000EF3                 mov     r15d, 0Ah
        __text:0000000100000EF9                 mov     r12d, 0Bh
        __text:0000000100000EFF                 mov     [rbp+var_2C], 0
        __text:0000000100000F06                 mov     [rbp+var_30], edi
        __text:0000000100000F09                 mov     [rbp+var_38], rsi
        __text:0000000100000F0D                 mov     edi, eax        ; rdi == arg1
        __text:0000000100000F0F                 mov     esi, ecx        ; rsi == arg2
        __text:0000000100000F11                 mov     ecx, r8d        ; rcx == arg4
        __text:0000000100000F14                 mov     r8d, r9d        ; r8 == arg5
        __text:0000000100000F17                 mov     r9d, r10d       ; r9 == arg6
        __text:0000000100000F1A                 mov     [rsp+80h+arg7_rsp_80], 7
        __text:0000000100000F21                 mov     [rsp+80h+arg8_rsp_78], 8
        __text:0000000100000F29                 mov     [rsp+80h+arg9_rsp_70], 9
        __text:0000000100000F31                 mov     [rsp+80h+arg10_rsp_68], 0Ah
        __text:0000000100000F39                 mov     [rsp+80h+arg11_rsp_60], 0Bh
        __text:0000000100000F41                 mov     [rbp+arg11_rbp_3c], r12d
        __text:0000000100000F45                 mov     [rbp+arg10_rbp_40], r15d
        __text:0000000100000F49                 mov     [rbp+arg9_rbp_44], r14d
        __text:0000000100000F4D                 mov     [rbp+arg8_rbp_48], ebx
        __text:0000000100000F50                 mov     [rbp+arg7_rbp_4c], r11d
        __text:0000000100000F54                 call    _testfun
        __text:0000000100000F59                 lea     r13, cfstr_TestfunD ; "testfun : %d"
        __text:0000000100000F60                 mov     rdi, r13
        __text:0000000100000F63                 mov     esi, eax
        __text:0000000100000F65                 mov     al, 0
        __text:0000000100000F67                 call    _NSLog
        __text:0000000100000F6C                 xor     eax, eax
        __text:0000000100000F6E                 add     rsp, 58h
        __text:0000000100000F72                 pop     rbx
        __text:0000000100000F73                 pop     r12
        __text:0000000100000F75                 pop     r13
        __text:0000000100000F77                 pop     r14
        __text:0000000100000F79                 pop     r15
        __text:0000000100000F7B                 pop     rbp
        __text:0000000100000F7C                 retn
        __text:0000000100000F7C _main           endp

    栈空间布局:

              ... testfun stack ...
        00007FFF5FBFFBA8  0000000100000F59 <- testfun retn eip -> main
        00007FFF5FBFFBB0  ???????????????? <- 第六个参数
        00007FFF5FBFFBB8  ????????????????    ....
        00007FFF5FBFFBC0  ????????????????    ....
        00007FFF5FBFFBC8  ????????????????    ....
        00007FFF5FBFFBD0  ???????????????? <- 最后的参数
               ... rsp offset 58h ...
        00007FFF5FBFFBD8  ????????????????        
        00007FFF5FBFFBE0  ???????????????? <- 高位 Endarg-m
                                              地位 Endarg-n
        00007FFF5FBFFBE8  ???????????????? <- 高位 Endarg-2
                                              地位 Endarg-3
        00007FFF5FBFFBF0  ???????????????? <- 高位 最后的参数
                                              地位 Endarg-1
        00007FFF5FBFFBF8  ???????????????? <- 保存的rsi
        00007FFF5FBFFC00  0000000000000001 <- 高位 mov  [rbp+var_2C], 0
                                              低位 edi
               ... rsp offset 58h ...
        00007FFF5FBFFC08  0000000000000000 <- 保存的rbx
        00007FFF5FBFFC10  0000000000000000 <- 保存的r12
        00007FFF5FBFFC18  0000000000000000 <- 保存的r13
        00007FFF5FBFFC20  0000000000000000 <- 保存的r14
        00007FFF5FBFFC28  0000000000000000 <- 保存的r15
        00007FFF5FBFFC30  00007FFF5FBFFC40 <- 保存的rbp
        00007FFF5FBFFC38  00007FFF8C0F85AD <- main 函数retn eip



    通过调试发现如果参数是非float/double,前6个参数将是通过寄存器传递,其顺序是:`RDI RSI RDX RCX R8 R9`超过6个参数后将通过栈进行传递;而如果参数是float/double,前16个为寄存器传参,其顺序是`xmm0~xmm15`,超过16个参数后将通过栈进行传递;混合类型为上述两种传参规则的结合。

    评分

    参与人数 1威望 +20 飘云币 +20 收起 理由
    gagmeng + 20 + 20 很给力!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2018-7-9 08:20
  • 签到天数: 869 天

    [LV.10]以坛为家III

    发表于 2016-5-31 14:38:21 | 显示全部楼层
    沙发,前排学习,顺带膜拜下大神!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2016-5-31 15:05
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-5-31 15:15:31 | 显示全部楼层
    前排学习,大神
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表