栈
- 栈:往低地址方向生长
栈中填充 cc --> int3(汇编指令):起到中断的作用。即使栈被当做代码段来执行,也不会出现大问题。 - esp:栈顶指针。通过push、pop操作
push 4:压栈,减
pop eax:出栈,加
call 地址:将下一条指令地址压栈 - ebp:栈底指针。局部变量的地址都是相对与他的。(参数+;局部变量-)
函数调用
test(1, 3);
//将函数参数压入栈空间
00D21868 push 3
00D2186A push 1
//调用 __empty_global_delete,后jmp到test函数代码,同时将下条指令的地址压栈
00D2186C call __empty_global_delete (0D213B1h)
//因为压入了两个参数,所以要出栈。堆栈平衡
00D21871 add esp,8
void test(int val1, int val2)
{
//将ebp压栈,同时ebp=esp都在栈顶
00D21800 push ebp
00D21801 mov ebp,esp
//指定栈空间大小
00D21803 sub esp,0C0h
//保护现场
00D21809 push ebx
00D2180A push esi
00D2180B push edi
00D2180C lea edi,[ebp-0C0h]
00D21812 mov ecx,30h
00D21817 mov eax,0CCCCCCCCh
00D2181C rep stos dword ptr es:[edi]
00D2181E mov ecx,offset _280923C9_main@cpp (0D2C029h)
00D21823 call @__CheckForDebuggerJustMyCode@4 (0D21311h)
return;
}
//恢复现场
00D21828 pop edi
00D21829 pop esi
00D2182A pop ebx
//栈顶回到压入test函数参数、压入ebp后的栈顶位置
00D2182B add esp,0C0h
00D21831 cmp ebp,esp
00D21833 call __RTC_CheckEsp (0D2123Ah)
//ebp回到栈顶
00D21838 mov esp,ebp
00D2183A pop ebp
//执行主函数call后,保存地址的指令
00D2183B ret
绝大部分编译器在Debug下,会在所分配的空间前/后添加一些额外的空间,并根据不同的情况为这些额外的空间设定特定的初值。当这些初值被用户程序修改时,就说明程序发生了越界等错误行为。 在Release下,将取消这些额外的空间,并进行优化(如果你定义的变量(部分类对象除外,因为类有构造和析构)未被使用过,将被忽略,也就是说,不会为它分配空间)。