常見函數調用約定(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
=
a
+
b
+
c
+
d
+
e
+
f
+
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
=
a
+
b
+
c
+
d
+
e
+
f
+
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
=
a
+
b
+
c
+
d
+
e
+
f
+
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:函數調用結束后由被調用函數清除棧內數據。
五、常見問題
-
__fastcall在寄存器中放入不大於4字節的參數,故性能較高,適用於需要高性能的場合。
-
不同編譯器設定的棧結構不盡相同,跨開發平台時由函數調用者清除棧內數據不可行。
-
某些函數的參數是可變的,如printf函數,這樣的函數只能由函數調用者清除棧內數據。
-
由調用者清除棧內數據時,每次調用都包含清除棧內數據的代碼,故可執行文件較大。
六、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