常见函数调用约定(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( 1 2 3 4 5 6 7 );
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( 1 2 3 4 5 6 7 );
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( 1 2 3 4 5 6 7 );
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( 1 2 3 4 5 6 7 );
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( 1 2 3 4 5 6 7 );
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( 1 2 3 4 5 6 7 );
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("\n");
               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

猜你喜欢

转载自www.cnblogs.com/sinferwu/p/12810595.html