zoukankan      html  css  js  c++  java
  • 常见函数调用约定(x86、x64、arm、arm64)

    常见函数调用约定(x86、x64、arm、arm64)

    我学习逆向,整理的一些常见的函数调用约定反汇编笔记。由于我是新手,肯定有一些疏漏不完善的,我遇到了会实时更新的。

    更新时间:2018年3月7日

    X86 函数调用约定

    X86 有三种常用调用约定,cdecl(C规范)/stdcall(WinAPI默认)/fastcall 函数调用约定。

    cdecl 函数调用约定

    参数从右往左依次入栈,调用者实现栈平衡,返回值存放在 EAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    20:       int cdecl_sum = cdecl_add(1234567);
    00401138   push        7
    0040113A   push        6
    0040113C   push        5
    0040113E   push        4
    00401140   push        3
    00401142   push        2
    00401144   push        1
    00401146   call        @ILT+5(_cdecl_add) (0040100a)
    0040114B   add         esp,1Ch  # 栈平衡
    0040114E   mov         dword ptr [ebp-4],eax    # 返回值
     
    3:    int __cdecl cdecl_add(int a, int b, int c, int d, int e, int f, int g)
    4:    {
    00401030   push        ebp
    00401031   mov         ebp,esp
    00401033   sub         esp,44h
    00401036   push        ebx
    00401037   push        esi
    00401038   push        edi
    00401039   lea         edi,[ebp-44h]
    0040103C   mov         ecx,11h
    00401041   mov         eax,0CCCCCCCCh
    00401046   rep stos    dword ptr [edi]
    5:        int sum = a+b+c+d+e+f+g;
    00401048   mov         eax,dword ptr [ebp+8]
    0040104B   add         eax,dword ptr [ebp+0Ch]
    0040104E   add         eax,dword ptr [ebp+10h]
    00401051   add         eax,dword ptr [ebp+14h]
    00401054   add         eax,dword ptr [ebp+18h]
    00401057   add         eax,dword ptr [ebp+1Ch]
    0040105A   add         eax,dword ptr [ebp+20h]
    0040105D   mov         dword ptr [ebp-4],eax
    6:        return sum;
    00401060   mov         eax,dword ptr [ebp-4]    # 存放返回值
    7:    }
    00401063   pop         edi
    00401064   pop         esi
    00401065   pop         ebx
    00401066   mov         esp,ebp
    00401068   pop         ebp
    00401069   ret

    stdcall 函数调用约定

    参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 EAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    21:       int stdcall_sum = stdcall_add(1234567);
    00401151   push        7
    00401153   push        6
    00401155   push        5
    00401157   push        4
    00401159   push        3
    0040115B   push        2
    0040115D   push        1
    0040115F   call        @ILT+15(_stdcall_add@28) (00401014)
    00401164   mov         dword ptr [ebp-8],eax    # 返回值
     
    9:    int __stdcall stdcall_add(int a, int b, int c, int d, int e, int f, int g)
    10:   {
    00401080   push        ebp
    00401081   mov         ebp,esp
    00401083   sub         esp,44h
    00401086   push        ebx
    00401087   push        esi
    00401088   push        edi
    00401089   lea         edi,[ebp-44h]
    0040108C   mov         ecx,11h
    00401091   mov         eax,0CCCCCCCCh
    00401096   rep stos    dword ptr [edi]
    11:       int sum = a+b+c+d+e+f+g;
    00401098   mov         eax,dword ptr [ebp+8]
    0040109B   add         eax,dword ptr [ebp+0Ch]
    0040109E   add         eax,dword ptr [ebp+10h]
    004010A1   add         eax,dword ptr [ebp+14h]
    004010A4   add         eax,dword ptr [ebp+18h]
    004010A7   add         eax,dword ptr [ebp+1Ch]
    004010AA   add         eax,dword ptr [ebp+20h]
    004010AD   mov         dword ptr [ebp-4],eax
    12:       return sum;
    004010B0   mov         eax,dword ptr [ebp-4]    # 存放返回值
    13:   }
    004010B3   pop         edi
    004010B4   pop         esi
    004010B5   pop         ebx
    004010B6   mov         esp,ebp
    004010B8   pop         ebp
    004010B9   ret         1Ch  # 栈平衡(等价于先 add esp, 1Ch 再 ret)

    fastcall 函数调用约定

    参数1、参数2分别保存在 ECX、EDX ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 EAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    25:       int fastcall_sum = fastcall_add(1234567);
    00401167   push        7
    00401169   push        6
    0040116B   push        5
    0040116D   push        4
    0040116F   push        3
    00401171   mov         edx,2
    00401176   mov         ecx,1
    0040117B   call        @ILT+0(@fastcall_add@28) (00401005)
    00401180   mov         dword ptr [ebp-0Ch],eax  # 返回值
     
    15:   int __fastcall fastcall_add(int a, int b, int c, int d, int e, int f, int g)
    16:   {
    004010D0   push        ebp
    004010D1   mov         ebp,esp
    004010D3   sub         esp,4Ch
    004010D6   push        ebx
    004010D7   push        esi
    004010D8   push        edi
    004010D9   push        ecx
    004010DA   lea         edi,[ebp-4Ch]
    004010DD   mov         ecx,13h
    004010E2   mov         eax,0CCCCCCCCh
    004010E7   rep stos    dword ptr [edi]
    004010E9   pop         ecx
    004010EA   mov         dword ptr [ebp-8],edx
    004010ED   mov         dword ptr [ebp-4],ecx
    17:       int sum = a+b+c+d+e+f+g;
    004010F0   mov         eax,dword ptr [ebp-4]
    004010F3   add         eax,dword ptr [ebp-8]
    004010F6   add         eax,dword ptr [ebp+8]
    004010F9   add         eax,dword ptr [ebp+0Ch]
    004010FC   add         eax,dword ptr [ebp+10h]
    004010FF   add         eax,dword ptr [ebp+14h]
    00401102   add         eax,dword ptr [ebp+18h]
    00401105   mov         dword ptr [ebp-0Ch],eax
    18:       return sum;
    00401108   mov         eax,dword ptr [ebp-0Ch]  # 存放返回值
    19:   }
    0040110B   pop         edi
    0040110C   pop         esi
    0040110D   pop         ebx
    0040110E   mov         esp,ebp
    00401110   pop         ebp
    00401111   ret         14h  # 栈平衡(等价于先 add esp, 14h 再 ret)

    X64 函数调用约定

    X64只有一种 fastcall 函数调用约定

    fastcall 函数调用约定

    参数1、参数2、参数3、参数4分别保存在 RCX、RDX、R8D、R9D ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 RAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    # 该代码是 msvc 2017 x64 生成的汇编代码
        int fastcall_sum = fastcall_add(1234567);
    00007FF6577A366E  mov         dword ptr [rsp+30h],7
    00007FF6577A3676  mov         dword ptr [rsp+28h],6 
    00007FF6577A367E  mov         dword ptr [rsp+20h],5 
    00007FF6577A3686  mov         r9d,4 
    00007FF6577A368C  mov         r8d,3 
    00007FF6577A3692  mov         edx,2 
    00007FF6577A3697  mov         ecx,1 
    00007FF6577A369C  call        fastcall_add (07FF6577A11C2h
    00007FF6577A36A1  mov         dword ptr [fastcall_sum],eax  # 返回值
     
    int __fastcall fastcall_add(int a, int b, int c, int d, int e, int f, int g)
    {
    00007FF6D22D1790  mov         dword ptr [rsp+20h],r9d 
    00007FF6D22D1795  mov         dword ptr [rsp+18h],r8d 
    00007FF6D22D179A  mov         dword ptr [rsp+10h],edx 
    00007FF6D22D179E  mov         dword ptr [rsp+8],ecx 
    00007FF6D22D17A2  push        rbp 
    00007FF6D22D17A3  push        rdi 
    00007FF6D22D17A4  sub         rsp,0E8h 
    00007FF6D22D17AB  mov         rbp,rsp 
    00007FF6D22D17AE  mov         rdi,rsp 
    00007FF6D22D17B1  mov         ecx,3Ah 
    00007FF6D22D17B6  mov         eax,0CCCCCCCCh 
    00007FF6D22D17BB  rep stos    dword ptr [rdi] 
    00007FF6D22D17BD  mov         ecx,dword ptr [rsp+108h
        int sum = + + + + + + g;
    00007FF6D22D17C4  mov         eax,dword ptr [b] 
    00007FF6D22D17CA  mov         ecx,dword ptr [a] 
    00007FF6D22D17D0  add         ecx,eax 
    00007FF6D22D17D2  mov         eax,ecx 
    00007FF6D22D17D4  add         eax,dword ptr [c] 
    00007FF6D22D17DA  add         eax,dword ptr [d] 
    00007FF6D22D17E0  add         eax,dword ptr [e] 
    00007FF6D22D17E6  add         eax,dword ptr [f] 
    00007FF6D22D17EC  add         eax,dword ptr [g] 
    00007FF6D22D17F2  mov         dword ptr [sum],eax 
        return sum;
    00007FF6D22D17F5  mov         eax,dword ptr [sum]       # 存放返回值
    }
    00007FF6D22D17F8  lea         rsp,[rbp+0E8h
    00007FF6D22D17FF  pop         rdi 
    00007FF6D22D1800  pop         rbp 
    00007FF6D22D1801  ret                                   # 没做栈平衡

    ARM/ARM64 函数调用约定

    ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb过程调用标准)的函数调用约定。

    ATPCS 函数调用约定

    ARM

    参数1~参数4 分别保存到 R0~R3 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 R0 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    ; 该代码是 arm-linux-androideabi-gcc + IDA PRO 生成的反汇编代码
    .text:00008438                 MOV             R3, #5
    .text:0000843C                 STR             R3, [SP]
    .text:00008440                 MOV             R3, #6
    .text:00008444                 STR             R3, [SP,#4]
    .text:00008448                 MOV             R3, #7
    .text:0000844C                 STR             R3, [SP,#8]
    .text:00008450                 MOV             R3, #8
    .text:00008454                 STR             R3, [SP,#12]
    .text:00008458                 MOV             R3, #9
    .text:0000845C                 STR             R3, [SP,#16]
    .text:00008460                 MOV             R3, #10
    .text:00008464                 STR             R3, [SP,#20]
    .text:00008468                 MOV             R0, #1
    .text:0000846C                 MOV             R1, #2
    .text:00008470                 MOV             R2, #3
    .text:00008474                 MOV             R3, #4
    .text:00008478                 BL              add
    .text:0000847C                 STR             R0, [R11,#-8]
     
    .text:000083C4                 EXPORT add
    .text:000083C4
    .text:000083C4                 STR             R11, [SP,#-4]!
    .text:000083C8                 ADD             R11, SP, #0
    .text:000083CC                 SUB             SP, SP, #0x1C
    .text:000083D0                 STR             R0, [R11,#-16]
    .text:000083D4                 STR             R1, [R11,#-20]
    .text:000083D8                 STR             R2, [R11,#-24]
    .text:000083DC                 STR             R3, [R11,#-28]
    .text:000083E0                 LDR             R2, [R11,#-16]
    .text:000083E4                 LDR             R3, [R11,#-20]
    .text:000083E8                 ADD             R2, R2, R3
    .text:000083EC                 LDR             R3, [R11,#-24]
    .text:000083F0                 ADD             R2, R2, R3
    .text:000083F4                 LDR             R3, [R11,#-28]
    .text:000083F8                 ADD             R2, R2, R3
    .text:000083FC                 LDR             R3, [R11,#4]
    .text:00008400                 ADD             R2, R2, R3
    .text:00008404                 LDR             R3, [R11,#8]
    .text:00008408                 ADD             R2, R2, R3
    .text:0000840C                 LDR             R3, [R11,#12]
    .text:00008410                 ADD             R3, R2, R3
    .text:00008414                 STR             R3, [R11,#-8]
    .text:00008418                 LDR             R3, [R11,#-8]
    .text:0000841C                 MOV             R0, R3            # 返回值
    .text:00008420                 SUB             SP, R11, #0
    .text:00008424                 LDR             R11, [SP],#4
    .text:00008428                 BX              LR
    ARM64

    参数1~参数8 分别保存到 X0~X7 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    ; 该代码是 aarch64-linux-android-gcc + IDA PRO 生成的反汇编代码
    .text:000000000040065C                 MOV             W0, #9
    .text:0000000000400660                 STR             W0, [SP]
    .text:0000000000400664                 MOV             W0, #10
    .text:0000000000400668                 STR             W0, [SP,#8]
    .text:000000000040066C                 MOV             W0, #1
    .text:0000000000400670                 MOV             W1, #2
    .text:0000000000400674                 MOV             W2, #3
    .text:0000000000400678                 MOV             W3, #4
    .text:000000000040067C                 MOV             W4, #5
    .text:0000000000400680                 MOV             W5, #6
    .text:0000000000400684                 MOV             W6, #7
    .text:0000000000400688                 MOV             W7, #8
    .text:000000000040068C                 BL              add
    .text:0000000000400690                 STR             W0, [X29,#28]
     
    .text:00000000004005E8                 EXPORT add
    .text:00000000004005E8
    .text:00000000004005E8                 SUB             SP, SP, #0x30
    .text:00000000004005EC                 STR             W0, [SP,#28]
    .text:00000000004005F0                 STR             W1, [SP,#24]
    .text:00000000004005F4                 STR             W2, [SP,#20]
    .text:00000000004005F8                 STR             W3, [SP,#16]
    .text:00000000004005FC                 STR             W4, [SP,#12]
    .text:0000000000400600                 STR             W5, [SP,#8]
    .text:0000000000400604                 STR             W6, [SP,#4]
    .text:0000000000400608                 STR             W7, [SP]
    .text:000000000040060C                 LDR             W1, [SP,#28]
    .text:0000000000400610                 LDR             W0, [SP,#24]
    .text:0000000000400614                 ADD             W1, W1, W0
    .text:0000000000400618                 LDR             W0, [SP,#20]
    .text:000000000040061C                 ADD             W1, W1, W0
    .text:0000000000400620                 LDR             W0, [SP,#16]
    .text:0000000000400624                 ADD             W1, W1, W0
    .text:0000000000400628                 LDR             W0, [SP,#12]
    .text:000000000040062C                 ADD             W1, W1, W0
    .text:0000000000400630                 LDR             W0, [SP,#8]
    .text:0000000000400634                 ADD             W1, W1, W0
    .text:0000000000400638                 LDR             W0, [SP,#4]
    .text:000000000040063C                 ADD             W0, W1, W0
    .text:0000000000400640                 STR             W0, [SP,#44]
    .text:0000000000400644                 LDR             W0, [SP,#44]        # 返回值
    .text:0000000000400648                 ADD             SP, SP, #0x30
    .text:000000000040064C                 RET

    C++ 函数调用约定

    thiscall用于C++中类成员函数(方法)的调用

    thiscall 函数调用约定

    x86

    参数从右往左依次入栈,this指针存放ECX中,被调用者实现栈平衡,返回值存放在 EAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    16:       int sum = calc.thiscall_add(1234567);
    00401098   push        7
    0040109A   push        6
    0040109C   push        5
    0040109E   push        4
    004010A0   push        3
    004010A2   push        2
    004010A4   push        1
    004010A6   lea         ecx,[ebp-4]                # this指针
    004010A9   call        @ILT+0(Calc::thiscall_add) (00401005)
    004010AE   mov         dword ptr [ebp-8],eax    # 返回值
     
    7:    int Calc::thiscall_add(int a, int b, int c, int d, int e, int f, int g)
    8:    {
    00401020   push        ebp
    00401021   mov         ebp,esp
    00401023   sub         esp,48h
    00401026   push        ebx
    00401027   push        esi
    00401028   push        edi
    00401029   push        ecx
    0040102A   lea         edi,[ebp-48h]
    0040102D   mov         ecx,12h
    00401032   mov         eax,0CCCCCCCCh
    00401037   rep stos    dword ptr [edi]
    00401039   pop         ecx
    0040103A   mov         dword ptr [ebp-4],ecx
    9:        int sum = + + + + + + g;
    0040103D   mov         eax,dword ptr [ebp+8]
    00401040   add         eax,dword ptr [ebp+0Ch]
    00401043   add         eax,dword ptr [ebp+10h]
    00401046   add         eax,dword ptr [ebp+14h]
    00401049   add         eax,dword ptr [ebp+18h]
    0040104C   add         eax,dword ptr [ebp+1Ch]
    0040104F   add         eax,dword ptr [ebp+20h]
    00401052   mov         dword ptr [ebp-8],eax
    10:       return sum;
    00401055   mov         eax,dword ptr [ebp-8]    # 存放返回值
    11:   }
    00401058   pop         edi
    00401059   pop         esi
    0040105A   pop         ebx
    0040105B   mov         esp,ebp
    0040105D   pop         ebp
    0040105E   ret         1Ch        # 栈平衡(等价于先 add esp, 1Ch 再 ret)
    X64

    参数1、参数2、参数3分别保存在RDX、R8D、R9D中,this指针存放RCX中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 RAX 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    # 该代码是 msvc 2017 x64 生成的汇编代码
        int sum = calc.thiscall_add(1234567);
    00007FF602E6190F  mov         dword ptr [rsp+38h],7 
    00007FF602E61917  mov         dword ptr [rsp+30h],6 
    00007FF602E6191F  mov         dword ptr [rsp+28h],5 
    00007FF602E61927  mov         dword ptr [rsp+20h],4 
    00007FF602E6192F  mov         r9d,3 
    00007FF602E61935  mov         r8d,2 
    00007FF602E6193B  mov         edx,1 
    00007FF602E61940  lea         rcx,[calc]              # this指针
    00007FF602E61944  call        Calc::thiscall_add (07FF602E610A0h
    00007FF602E61949  mov         dword ptr [sum],eax    # 返回值
     
    int Calc::thiscall_add(int a, int b, int c, int d, int e, int f, int g)
    {
    00007FF602E61770  mov         dword ptr [rsp+20h],r9d 
    00007FF602E61775  mov         dword ptr [rsp+18h],r8d 
    00007FF602E6177A  mov         dword ptr [rsp+10h],edx 
    00007FF602E6177E  mov         qword ptr [rsp+8],rcx 
    00007FF602E61783  push        rbp 
    00007FF602E61784  push        rdi 
    00007FF602E61785  sub         rsp,0E8h 
    00007FF602E6178C  mov         rbp,rsp 
    00007FF602E6178F  mov         rdi,rsp 
    00007FF602E61792  mov         ecx,3Ah 
    00007FF602E61797  mov         eax,0CCCCCCCCh 
    00007FF602E6179C  rep stos    dword ptr [rdi] 
    00007FF602E6179E  mov         rcx,qword ptr [rsp+108h
        int sum = + + + + + + g;
    00007FF602E617A6  mov         eax,dword ptr [b] 
    00007FF602E617AC  mov         ecx,dword ptr [a] 
    00007FF602E617B2  add         ecx,eax 
    00007FF602E617B4  mov         eax,ecx 
    00007FF602E617B6  add         eax,dword ptr [c] 
    00007FF602E617BC  add         eax,dword ptr [d] 
    00007FF602E617C2  add         eax,dword ptr [e] 
    00007FF602E617C8  add         eax,dword ptr [f] 
    00007FF602E617CE  add         eax,dword ptr [g] 
    00007FF602E617D4  mov         dword ptr [sum],eax 
        return sum;
    00007FF602E617D7  mov         eax,dword ptr [sum]  # 存放返回值
    }
    00007FF602E617DA  lea         rsp,[rbp+0E8h
    00007FF602E617E1  pop         rdi 
    00007FF602E617E2  pop         rbp 
    00007FF602E617E3  ret                                 # 没做栈平衡
    ARM

    参数1、参数2、参数3分别保存在R1、R2、R3中,this指针存放R0中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 R0 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    ; 该代码是 arm-linux-androideabi-gcc + IDA PRO 生成的反汇编代码
    .text:000085BC                 MOV             R3, #4
    .text:000085C0                 STR             R3, [SP] ; int
    .text:000085C4                 MOV             R3, #5
    .text:000085C8                 STR             R3, [SP,#4] ; int
    .text:000085CC                 MOV             R3, #6
    .text:000085D0                 STR             R3, [SP,#8] ; int
    .text:000085D4                 MOV             R3, #7
    .text:000085D8                 STR             R3, [SP,#12] ; int
    .text:000085DC                 MOV             R3, #8
    .text:000085E0                 STR             R3, [SP,#16] ; int
    .text:000085E4                 MOV             R3, #9
    .text:000085E8                 STR             R3, [SP,#20] ; int
    .text:000085EC                 MOV             R3, #10
    .text:000085F0                 STR             R3, [SP,#24] ; int
    .text:000085F4                 MOV             R0, R2  ; this
    .text:000085F8                 MOV             R1, #1  ; int
    .text:000085FC                 MOV             R2, #2  ; int
    .text:00008600                 MOV             R3, #3  ; int
    .text:00008604                 BL              _ZN4Calc12thiscall_addEiiiiiiiiii ; Calc::thiscall_add(int,int,int,int,int,int,int,int,int,int)
    .text:00008608                 MOV             R3, R0
     
    .text:00008544                 EXPORT _ZN4Calc12thiscall_addEiiiiiiiiii
    .text:00008544
    .text:00008544                 STR             R11, [SP,#-4]!
    .text:00008548                 ADD             R11, SP, #0
    .text:0000854C                 SUB             SP, SP, #0x1C
    .text:00008550                 STR             R0, [R11,#-16]
    .text:00008554                 STR             R1, [R11,#-20]
    .text:00008558                 STR             R2, [R11,#-24]
    .text:0000855C                 STR             R3, [R11,#-28]
    .text:00008560                 LDR             R2, [R11,#-20]
    .text:00008564                 LDR             R3, [R11,#-24]
    .text:00008568                 ADD             R2, R2, R3
    .text:0000856C                 LDR             R3, [R11,#-28]
    .text:00008570                 ADD             R2, R2, R3
    .text:00008574                 LDR             R3, [R11,#4]
    .text:00008578                 ADD             R2, R2, R3
    .text:0000857C                 LDR             R3, [R11,#8]
    .text:00008580                 ADD             R2, R2, R3
    .text:00008584                 LDR             R3, [R11,#12]
    .text:00008588                 ADD             R2, R2, R3
    .text:0000858C                 LDR             R3, [R11,#16]
    .text:00008590                 ADD             R3, R2, R3
    .text:00008594                 STR             R3, [R11,#-8]
    .text:00008598                 LDR             R3, [R11,#-8]
    .text:0000859C                 MOV             R0, R3            # 返回值
    .text:000085A0                 SUB             SP, R11, #0
    .text:000085A4                 LDR             R11, [SP],#4
    .text:000085A8                 BX              LR
    ARM64

    参数1~参数7 分别保存到 X1~X7 寄存器中,this指针存放X0中,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    ; 该代码是 aarch64-linux-android-gcc + IDA PRO 生成的反汇编代码
    .text:00000000004006A0                 MOV             W0, #8
    .text:00000000004006A4                 STR             W0, [SP] ; int
    .text:00000000004006A8                 MOV             W0, #9
    .text:00000000004006AC                 STR             W0, [SP,#8] ; int
    .text:00000000004006B0                 MOV             W0, #10
    .text:00000000004006B4                 STR             W0, [SP,#16] ; int
    .text:00000000004006B8                 MOV             X0, X1  ; this
    .text:00000000004006BC                 MOV             W1, #1  ; int
    .text:00000000004006C0                 MOV             W2, #2  ; int
    .text:00000000004006C4                 MOV             W3, #3  ; int
    .text:00000000004006C8                 MOV             W4, #4  ; int
    .text:00000000004006CC                 MOV             W5, #5  ; int
    .text:00000000004006D0                 MOV             W6, #6  ; int
    .text:00000000004006D4                 MOV             W7, #7  ; int
    .text:00000000004006D8                 BL              _ZN4Calc12thiscall_addEiiiiiiiiii ; Calc::thiscall_add(int,int,int,int,int,int,int,int,int,int)
    .text:00000000004006DC                 STR             W0, [X29,#0x1C]
     
    .text:0000000000400628                 EXPORT _ZN4Calc12thiscall_addEiiiiiiiiii
    .text:0000000000400628
    .text:0000000000400628                 SUB             SP, SP, #0x40
    .text:000000000040062C                 STR             X0, [SP,#40]
    .text:0000000000400630                 STR             W1, [SP,#36]
    .text:0000000000400634                 STR             W2, [SP,#32]
    .text:0000000000400638                 STR             W3, [SP,#28]
    .text:000000000040063C                 STR             W4, [SP,#24]
    .text:0000000000400640                 STR             W5, [SP,#20]
    .text:0000000000400644                 STR             W6, [SP,#16]
    .text:0000000000400648                 STR             W7, [SP,#12]
    .text:000000000040064C                 LDR             W1, [SP,#36]
    .text:0000000000400650                 LDR             W0, [SP,#32]
    .text:0000000000400654                 ADD             W1, W1, W0
    .text:0000000000400658                 LDR             W0, [SP,#28]
    .text:000000000040065C                 ADD             W1, W1, W0
    .text:0000000000400660                 LDR             W0, [SP,#24]
    .text:0000000000400664                 ADD             W1, W1, W0
    .text:0000000000400668                 LDR             W0, [SP,#20]
    .text:000000000040066C                 ADD             W1, W1, W0
    .text:0000000000400670                 LDR             W0, [SP,#16]
    .text:0000000000400674                 ADD             W1, W1, W0
    .text:0000000000400678                 LDR             W0, [SP,#12]
    .text:000000000040067C                 ADD             W0, W1, W0
    .text:0000000000400680                 STR             W0, [SP,#60]
    .text:0000000000400684                 LDR             W0, [SP,#60]        # 返回值
    .text:0000000000400688                 ADD             SP, SP, #0x40
    .text:000000000040068C                 RET

    https://bbs.pediy.com/thread-224583.htm

    一、概述

    __stdcall、__cdecl和__fastcall是三种函数调用协议,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。

    二、调用协议常用场合 

    __stdcall:Windows API默认的函数调用协议。

     __cdecl:C/C++默认的函数调用协议。 

    __fastcall:适用于对性能要求较高的场合。

    三、 函数参数入栈方式 

    __stdcall:函数参数由右向左入栈。

     __cdecl:函数参数由右向左入栈。

     __fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。

    四、栈内数据清除方式 

    __stdcall:函数调用结束后由被调用函数清除栈内数据。 

    __cdecl:函数调用结束后由函数调用者清除栈内数据。 

    __fastcall:函数调用结束后由被调用函数清除栈内数据。 

    五、常见问题 

    1. __fastcall在寄存器中放入不大于4字节的参数,故性能较高,适用于需要高性能的场合。 
    2. 不同编译器设定的栈结构不尽相同,跨开发平台时由函数调用者清除栈内数据不可行。 
    3. 某些函数的参数是可变的,如printf函数,这样的函数只能由函数调用者清除栈内数据。
    4. 由调用者清除栈内数据时,每次调用都包含清除栈内数据的代码,故可执行文件较大。 

    六、C语言编译器函数名称修饰规则 

    __stdcall:编译后,函数名被修饰为"_functionname@number"。 

    __cdecl:编译后,函数名被修饰为"_functionname"。 

    __fastcall:编译后, 函数名给修饰为"@functionname@nmuber"。 

    注:"functionname"为函数名,"number"为参数字节数。 

    注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。 

    七、C++语言编译器函数名称修饰规则 

    __stdcall:编译后,函数名被修饰为"?functionname@@YG******@Z"。 

    __cdecl:编译后,函数名被修饰为"?functionname@@YA******@Z"。 

    __fastcall:编译后,函数名被修饰为"?functionname@@YI******@Z"。 

    注:"******"为函数返回值类型和参数类型表。

     注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。 C语言和C++语言间如果不进行特殊处理,也无法实现函数的互相调用。

    https://www.cnblogs.com/aspiration2016/p/6031734.html

    可变参数

    #define  printf(FMT, arg...)   user_printf(FMT,  ##arg)

    #include <stdio.h>
    #include <stdarg.h>
    
    void var_test(char *format, ...)
    {
        va_list list;
        va_start(list,format);
        
        char *ch;
        while(1)
        {
             ch = va_arg(list, char *);
    
             if(strcmp(ch,"") == 0)
             {    
                   printf("
    ");
                   break;
             }
             printf("%s ",ch);
         }
         va_end(list);
    }
    
    int main()
    {
        var_test("test","this","is","a","test","");
        return 0;
    }

    https://www.cnblogs.com/bettercoder/p/3488299.html

  • 相关阅读:
    asp.net将word转成HTML
    asp.net 控件位置form验证
    javascript 正则表达式
    .net framework处理xml
    XMLHTTP与XMLDOC使用介绍(上)
    一个女程序员的征婚信息的select语句
    解决连接MySql4.0数据库出现的"character_set_results"问题
    javascript与cs代码互访
    杜绝<script src="js/tool.js" type="text/javascript"/>这样写的习惯
    总结:常用的正则表达式集合
  • 原文地址:https://www.cnblogs.com/sinferwu/p/12810595.html
Copyright © 2011-2022 走看看