#include<stdio.h>
int add(int a, int b)
{
int c = 0;
c = a+b;
return c;
}
int main()
{
int a = 5;
int b = 6;
int c = 0;
c = add(a,b);
printf("c = %d\n",c);
}
---------- E:\c_project\test.c --------------
9:
10: int main()
11: {
00401060 push ebp
00401061 mov ebp,esp
00401063 sub esp,4Ch
00401066 push ebx
00401067 push esi
00401068 push edi
00401069 lea edi,[ebp-4Ch]
0040106C mov ecx,13h
00401071 mov eax,0CCCCCCCCh
00401076 rep stos dword ptr [edi]
12: int a = 5;
00401078 mov dword ptr [ebp-4],5
13: int b = 6;
0040107F mov dword ptr [ebp-8],6 --- (1)
14: int c = 0;
00401086 mov dword ptr [ebp-0Ch],0 --- (2)
15:
16: c = add(a,b);
0040108D mov eax,dword ptr [ebp-8] //此条命令执行前 ESP = 0018FEF0, EBP = 0018FF48 ;
//在vc6.0 的memory 调试框输入 ebp-8 后,对应的值和 上面21行的 --- (1) 结果是一致的,都是 6.
00401090 push eax //执行到此行时,即此条命令执行前,寄存器的状态 ESP = 0018FEF0 EBP = 0018FF48 //第二个参数压栈 ?
00401091 mov ecx,dword ptr [ebp-4] //此条命令执行前,寄存器的状态 ESP = 0018FEEC EBP = 0018FF48 0018FEF0 - 0018FEEC = 4;
00401094 push ecx //此条命令执行前,寄存器的状态 ESP = 0018FEEC EBP = 0018FF48 /第一个参数压栈 ?
00401095 call @ILT+0(_add) (00401005) 跳转到下面的 A: //运行到此行时, 此条命令执行前,寄存器的状态 ESP = 0018FEE8 EBP = 0018FF48
0040109A add esp,8 --------- (3)
0040109D mov dword ptr [ebp-0Ch],eax
17: printf("c = %d\n",c);
004010A0 mov edx,dword ptr [ebp-0Ch]
004010A3 push edx
004010A4 push offset string "c = %d\n" (0042201c)
004010A9 call printf (004010e0)
004010AE add esp,8
18: }
//同时注意call 和 ret 指令对 esp的影响 : CALL和RET指令 ;
CALL和RET指令 --- 汇编学习笔记 : https://blog.csdn.net/qq_37340753/article/details/81585083
00401095 call @ILT+0(_add) (00401005) 执行后对应下面的一行执行情况:
A :
@ILT+0(_add): 00401005 jmp add (00401020) //执行到此行时, 寄存器的状态 : EIP = 00401005, ESP = 0018FEE4, EBP = 0018FF48 ;
执行A 后的跳转和寄存器状态 : EIP = 00401020, ESP = 0018FEE4, EBP = 0018FF48, EFL = 00000216
在实际调试中 : ESP = 0018FEE4, ESP存放0018FEE4这个地址, 地址 0018FEE4 的内容是个地址 40109A ; 存放的是下一条指令: add esp,8 的地址; 下一条指令的地址 也即 返回地址;
1: #include<stdio.h>
2:
3: int add(int a, int b)
4: {
00401020 push ebp //命令执行跳转到此行时, 寄存器的状态 : EIP = 00401020, ESP = 0018FEE4, EBP = 0018FF48, EFL = 00000216;
00401021 mov ebp,esp //EIP = 00401021 ESP = 0018FEE0 EBP = 0018FF48 EFL = 00000216
00401023 sub esp,44h //EIP = 00401023 ESP = 0018FEE0 EBP = 0018FEE0 EFL = 00000216
00401026 push ebx //EIP = 00401026 ESP = 0018FE9C EBP = 0018FEE0 EFL = 00000216
00401027 push esi //EIP = 00401027 ESP = 0018FE98 EBP = 0018FEE0 EFL = 00000216
00401028 push edi //EIP = 00401028 ESP = 0018FE94 EBP = 0018FEE0 EFL = 00000216
00401029 lea edi,[ebp-44h] //EIP = 00401029 ESP = 0018FE90 EBP = 0018FEE0 EFL = 00000216
0040102C mov ecx,11h //EIP = 0040102C ESP = 0018FE90 EBP = 0018FEE0 EFL = 00000216
00401031 mov eax,0CCCCCCCCh //EIP = 00401031 ESP = 0018FE90 EBP = 0018FEE0 EFL = 00000216
00401036 rep stos dword ptr [edi] //在此处下一步,其它寄存器会一直在变化. ECX 和 EDI等寄存器, 直到ECX寄存器为0 //EIP = 00401036 ESP = 0018FE90 EBP = 0018FEE0 EFL = 00000216
//EAX = CCCCCCCC EBX = 7EFDE000 ECX = 00000010 EDX = 00560F40 ESI = 00000000 EDI = 0018FEA0
//EIP = 00401036 ESP = 0018FE90 EBP = 0018FEE0 EFL = 00010216
5: int c = 0;
00401038 mov dword ptr [ebp-4],0 //
6: c = a+b;
0040103F mov eax,dword ptr [ebp+8]
00401042 add eax,dword ptr [ebp+0Ch]
00401045 mov dword ptr [ebp-4],eax
7: return c;
00401048 mov eax,dword ptr [ebp-4]
8: }
0040104B pop edi //EIP = 0040104B ESP = 0018FE90 EBP = 0018FEE0 EFL = 00000202
0040104C pop esi //ESI = 00000000 EDI = 0018FF48 EIP = 0040104C ESP = 0018FE94 EBP = 0018FEE0 EFL = 00000202
0040104D pop ebx //ESI = 00000000 EDI = 0018FF48 EIP = 0040104D ESP = 0018FE98 EBP = 0018FEE0 EFL = 00000202
0040104E mov esp,ebp //ESI = 00000000 EDI = 0018FF48 EIP = 0040104E ESP = 0018FE9C EBP = 0018FEE0 EFL = 00000202
00401050 pop ebp //ESI = 00000000 EDI = 0018FF48 EIP = 00401050 ESP = 0018FEE0 EBP = 0018FEE0 EFL = 00000202
00401051 ret //ESI = 00000000 EDI = 0018FF48 EIP = 00401051 ESP = 0018FEE4 EBP = 0018FF48 EFL = 00000202
--- No source file ----------------
执行完ret指令后,跳转到上面的主程序中的 --------- (3)
0040109A add esp,8 //执行到此行时, EIP = 0040109A ESP = 0018FEE8 EBP = 0018FF48 EFL = 00000202
0040109D mov dword ptr [ebp-0Ch],eax
17: printf("c = %d\n",c);
004010A0 mov edx,dword ptr [ebp-0Ch]
004010A3 push edx
004010A4 push offset string "c = %d\n" (0042201c)
004010A9 call printf (004010e0)
004010AE add esp,8
18: }
004010B1 pop edi
004010B2 pop esi
004010B3 pop ebx
004010B4 add esp,4Ch
004010B7 cmp ebp,esp
004010B9 call __chkesp (00401160)
004010BE mov esp,ebp
004010C0 pop ebp
004010C1 ret
//运行在函数add之前的esp, ebp;
EIP = 00401086 ESP = 0018FEF0
EBP = 0018FF48 EFL = 00000216