今天说的承接函数栈帧详解(1),具体谈谈MyAdd()函数内部的事情。
int MyAdd(int a, int b)
{
int c = 0
c = a + b;
return c;
}
int main()
{
int x = 0xA;
int y = 0xB;
int z = 0;
z = MyAdd(x, y);
printf("z = %d\n", z);
return 0;
}
今天的汇编语言
int MyAdd(int a, int b)
{
001E2EC0 push ebp
001E2EC1 mov ebp,esp
001E2EC3 sub esp,0CCh
001E2EC9 push ebx
001E2ECA push esi
001E2ECB push edi
001E2ECC lea edi,[ebp-0Ch]
001E2ECF mov ecx,3
001E2ED4 mov eax,0CCCCCCCCh
001E2ED9 rep stos dword ptr es:[edi]
001E2EDB mov ecx,1EC003h
001E2EE0 call 001E130C
int c = 0;
001E2EE5 mov dword ptr [ebp-8],0
c =a + b;
001E2EEC mov eax,dword ptr [ebp+8]
001E2EEF add eax,dword ptr [ebp+0Ch]
001E2EF2 mov dword ptr [ebp-8],eax
return c;
001E2EF5 mov eax,dword ptr [ebp-8]
}
001E2EF8 pop edi
001E2EF9 pop esi
001E2EFA pop ebx
001E2EFB add esp,0CCh
001E2F01 cmp ebp,esp
001E2F03 call 001E1235
001E2F08 mov esp,ebp
001E2F0A pop ebp
001E2F0B ret
00821740 push ebp
这条命令是将ebp(也就是栈底)的内容压入栈中,同时栈顶也发生变化
mov:数据转移指令
00821741 mov ebp,esp
该命令的意思是将esp的内容覆盖到ebp中
那么我们可能会发出疑惑,那栈底怎么办,是不是找不回来了?实际上不是的,上一步我们不是把栈底的内容给保存了吗!!!
sub:减法命令
00821743 sub esp,0CCh
//0CCh 的大小和你定义的函数的规模有关
该命令的意思是esp减去一定的值,结果放在esp中
到这里我们已近形成了MyAdd()的栈帧了
int c = 0;
001E2EE5 mov dword ptr [ebp-8],0
//在ebp-8处在开辟一个空间,将c的值放进去
c =a + b;
001E2EEC mov eax,dword ptr [ebp+8]
001E2EEF add eax,dword ptr [ebp+0Ch]
001E2EF2 mov dword ptr [ebp-8],eax
一条一条分析
001E2EEC mov eax,dword ptr [ebp+8]
把ebp+8放在eax中
那么ebp+8是多少呢?答案就是我们的x值的拷贝
同理
001E2EEF add eax,dword ptr [ebp+0Ch]
这个命令是将ebp+0Ch的内容和eax加起来放到 eax中
ebp+0Ch就是y值的拷贝
001E2EF2 mov dword ptr [ebp-8],eax
001E2EF5 mov eax,dword ptr [ebp-8]
001E2F08 mov esp,ebp
pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
001E2F0A pop ebp
ret:恢复返回地址,压入eip,类似pop eip命令
001E2F0B ret
释放临时拷贝的变量
001E1E87 add esp,8
意思是esp+8放在esp中
现在我们已经返回到MyAdd执行之前了
001E1E8A mov dword ptr [ebp-20h],eax
接收返回值
将eax的值放到ebp-20(也就是z)
返回的本质
为什么函数的的栈帧是由编译器决定的?
我们C语言中很多数据类型,这就是的编译器有能力知道所有类型变量的大小。
有关栈帧的知识大概都说的差不多了,后面我会看看是否还要补充一些知识。