首页
社区
课程
招聘
4
[原创]常见函数调用约定(x86、x64、arm、arm64)
发表于: 2018-2-8 22:42 24595

[原创]常见函数调用约定(x86、x64、arm、arm64)

2018-2-8 22:42
24595

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

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

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

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

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

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

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

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

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

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

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

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

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

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

参数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
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
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)
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)
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                                   # 没做栈平衡
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

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-10-26 12:19 被有影编辑 ,原因:
收藏
免费 4
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-2-7 04:58
Leong Vinson
为你点赞~
2022-10-18 10:20
hackbs
为你点赞~
2021-10-21 10:41
Jaychouzzk
为你点赞~
2021-4-19 20:17
最新回复 (24)
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主辛苦了
2018-2-8 23:46
0
雪    币: 407
活跃值: (566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享  辛苦
2018-2-9 00:38
0
雪    币: 5997
活跃值: (4324)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
4
感谢分享,还差linux和mac,楼主继续
2018-2-18 07:16
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
5
可以
2018-2-18 08:05
0
雪    币: 55943
活跃值: (21560)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
6
小结的不错,有些地方可以在深入些
2018-2-18 08:51
0
雪    币: 3411
活跃值: (2132)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
能收录优秀的一看就知道是出自大神之作。
2018-2-18 12:32
0
雪    币: 1262
活跃值: (275)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
kanxue 小结的不错,有些地方可以在深入些
感谢评优。新手自学中,目前还不是很懂哪些地方可以深入些?能不能指教一下?
2018-2-18 13:03
0
雪    币: 136
活跃值: (16)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
感谢分享    辛苦
2018-2-18 17:03
0
雪    币: 697
活跃值: (60)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
Mark
2018-2-20 10:42
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
2018-2-20 21:20
0
雪    币: 0
活跃值: (87)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
有影 感谢评优。新手自学中,目前还不是很懂哪些地方可以深入些?能不能指教一下?
对  arm  稍微熟悉一点。  arm里面参数超过了四个,四个之外的参数就不是存储到寄存器中,而是压栈了。
类似这些吧。
2018-2-23 09:40
0
雪    币: 1449
活跃值: (128)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
x86/x64调用约定最后ret  n返回的地方有点问题,ret  n的执行流程应该是pop  eip  也就是ret  然后再add  esp,  n  楼主  你看看是不是这样
2018-4-17 16:46
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
kanxue 小结的不错,有些地方可以在深入些
一楼的文章代码着色如何在复制到word文档中的时候能操持呢?
复制进去没有着色了。
2018-4-17 19:06
0
雪    币: 5
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
感谢分享,学习中
2018-4-20 11:17
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
谢谢分享,辛苦了
2018-6-11 06:34
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
lz  很用心,支持。函数调用约定调试常用到。
2018-6-19 13:27
0
雪    币: 15
活跃值: (445)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
总结的不错
2018-6-19 17:57
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
优秀, 指出一点笔误:c++ arm64  "this指针存放R0中", 应该是X0中吧
2018-10-12 10:35
0
雪    币: 1262
活跃值: (275)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
andrOday 优秀, 指出一点笔误:c++ arm64 "this指针存放R0中", 应该是X0中吧
感谢指出,已修改。
2018-10-26 12:19
0
雪    币: 9
活跃值: (230)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
 X64调用约定应该是_fastCall的扩展,调用方释放栈
2018-10-29 08:59
0
雪    币: 4267
活跃值: (3104)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
22
X64平台不同编译器传参方式:
vc调用的传参方式。前4个参数使用rcx,rdx,r8,r9,之后的参数使用堆栈。
GCC前6个参数使用rdi、rsi、rdx、rcx、r8、r9,剩下的参数用栈。注意rdx、rcx的顺序和MSVC上不一样。
最后于 2019-1-25 18:02 被chpeagle编辑 ,原因:
2019-1-25 17:24
1
雪    币: 14
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23

2019-11-8 00:23
0
雪    币: 83
活跃值: (1092)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
24
chpeagle X64平台不同编译器传参方式:vc调用的传参方式。前4个参数使用rcx,rdx,r8,r9,之后的参数使用堆栈。GCC前6个参数使用rdi、rsi、rdx、rcx、r8、r9,剩下的参数用栈。注意rd ...
感谢
2019-11-8 03:56
0
雪    币: 7132
活跃值: (2031)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
25

111

最后于 2021-3-25 15:57 被TopC编辑 ,原因: 看错了,楼主总结的很对
2021-3-25 15:52
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册