C语言函数
Tutorial: C与汇编
Category: C语言
Published: 2026-04-07 13:58:26
Views: 20
Likes: 0
Comments: 0
1. 函数调用
int plus(int x, int y)
{
return x + y;
}
void main()
{
plus(1, 2);
return;
}
1: int plus(int x, int y)
2: {
00401020 push ebp ; 保存调用者的基指针
00401021 mov ebp, esp ; 新的基指针现在是栈顶
00401023 sub esp, 0x40 ; 在栈上分配64字节空间给局部变量
00401026 push ebx ; 保存ebx寄存器的值
00401027 push esi ; 保存esi寄存器的值
00401028 push edi ; 保存edi寄存器的值
00401029 lea edi, [ebp - 0x40] ; 将局部变量的起始指针传给edi
0040102C mov ecx, 0x10 ; 将16(用于循环计数)传递给ecx
00401031 mov eax, 0xCCCCCCCC ; 调试目的的模式填充值放入eax
00401036 rep stos dword ptr [edi] ; 用0xCCCCCCCC填充局部变量区域
3: return x + y;
00401038 mov eax, dword ptr [ebp+8] ; 将x的值加载到eax
0040103B add eax, dword ptr [ebp+0xC] ; 将y的值加到eax,得和
4: }
0040103E pop edi ; 恢复edi寄存器原来的值
0040103F pop esi ; 恢复esi寄存器原来的值
00401040 pop ebx ; 恢复ebx寄存器原来的值
00401041 mov esp, ebp ; 重置栈指针,丢弃局部变量
00401043 pop ebp ; 恢复调用者的基指针
00401044 ret ; 返回到调用者,返回值在eax中
6: void main()
7: {
00401050 push ebp ; 保存调用者的基指针
00401051 mov ebp, esp ; 新的基指针现在是栈顶
00401053 sub esp, 0x40 ; 在栈上分配64字节空间给局部变量
00401056 push ebx ; 保存ebx寄存器的值
00401057 push esi ; 保存esi寄存器的值
00401058 push edi ; 保存edi寄存器的值
00401059 lea edi, [ebp - 0x40] ; 将局部变量的起始指针传给edi
0040105C mov ecx, 0x10 ; 将16(用于循环计数)传递给ecx
00401061 mov eax, 0xCCCCCCCC ; 调试目的的模式填充值放入eax
00401066 rep stos dword ptr [edi] ; 用0xCCCCCCCC填充局部变量区域
8: plus(1, 2);
00401068 push 2 ; 将2作为函数参数压栈
0040106A push 1 ; 将1作为函数参数压栈
0040106C call @ILT+0(plus) (00401005) ; 调用plus函数
00401071 add esp, 8 ; 清理栈上的参数空间(两个int,每个占用4字节)
9: return;
10: }
00401074 pop edi ; 恢复edi寄存器原来的值
00401075 pop esi ; 恢复esi寄存器原来的值
00401076 pop ebx ; 恢复ebx寄存器原来的值
00401077 add esp, 0x40 ; 清理栈空间(加回先前分配的局部变量大小)
0040107A cmp ebp, esp ; 检查栈指针和基指针是否一致(安全检查)
0040107C call __chkesp (004010a0) ; 如果不一致,调用__chkesp处理潜在的栈问题
00401081 mov esp, ebp ; 恢复栈指针
00401083 pop ebp ; 恢复调用者的基指针
00401084 ret ; 返回到调用者,结束main函数
2. 分析
1. 原始
esp = 0019FEE4
ebp = 0019FF30
2. push 2
esp = 0019FEE0
ebp = 0019FF30
3. push 1
esp = 0019FEDC
ebp = 0019FF30
4. call 00401005
esp = 0019FED8
ebp = 0019FF30
5. 00401005 jmp plus (00401020)
6. 00401020 push ebp
esp = 0019FED4
ebp = 0019FF30
7. mov ebp, esp
esp = 0019FED4
ebp = 0019FED4
8. sub esp, 0x40 ; 在栈上分配64字节空间给局部变量
esp = 0019FE94
ebp = 0019FED4
9. 00401026 push ebx ; 保存ebx寄存器的值
00401027 push esi ; 保存esi寄存器的值
00401028 push edi ; 保存edi寄存器的值
esp = 0019FE88
ebp = 0019FED4
10. 00401059 lea edi, [ebp - 0x40] ; 将局部变量的起始指针传给edi
esp = 0019FE88
ebp = 0019FED4
edi = 0019FE94
11. 0040105C mov ecx, 0x10 ; 将16(用于循环计数)传递给ecx
12. 00401061 mov eax, 0xCCCCCCCC ; 调试目的的模式填充值放入eax
13. 00401066 rep stos dword ptr [edi] ; 用0xCCCCCCCC填充局部变量区域 16次,一次4字节(eax) = 64 字节
esp = 0019FE88
ebp = 0019FED4
edi = 0019FED4
14. 00401038 mov eax, dword ptr [ebp+8] ; 将x的值加载到eax 19FED4 + 8 = 19FEDC = 1
15. 0040103B add eax, dword ptr [ebp+0xC] ; 将y的值加到eax,得和 19FED4 + C = 19FEDC = 19FEE0
16. 0040103E pop edi ; 恢复edi寄存器原来的值
17. 0040103F pop esi ; 恢复esi寄存器原来的值
18. 00401040 pop ebx ; 恢复ebx寄存器原来的值
esp = 0019FE94
ebp = 0019FED4
edi = 0019FF30
19. 00401041 mov esp, ebp ; 重置栈指针,丢弃局部变量
esp = 0019FED4
ebp = 0019FED4
edi = 0019FF30
20. 00401043 pop ebp ; 恢复调用者的基指针
esp = 0019FED8
ebp = 0019FF30
edi = 0019FF30
21. 00401044 ret ; 返回到调用者,返回值在eax中
esp = 0019FEDC
ebp = 0019FF30
edi = 0019FF30
22. 00401077 add esp,8
esp = 0019FEE4
ebp = 0019FF30
edi = 0019FF30
00401074 pop edi ; 恢复edi寄存器原来的值
00401075 pop esi ; 恢复esi寄存器原来的值
00401076 pop ebx ; 恢复ebx寄存器原来的值
00401077 add esp, 0x40 ; 清理栈空间(加回先前分配的局部变量大小)
0040107A cmp ebp, esp ; 检查栈指针和基指针是否一致(安全检查)
0040107C call __chkesp (004010a0) ; 如果不一致,调用__chkesp处理潜在的栈问题
00401081 mov esp, ebp ; 恢复栈指针
00401083 pop ebp ; 恢复调用者的基指针
00401084 ret ; 返回到调用者,结束main函数