从main函数开始压入f函数的参数开始,堆栈的调用情况如下

图1 压入参数

图二 通过call 命令压入下一跳地址 IP

图三 函数f 通过pushl %ebp 把 ebp保存起来

图四 函数 f 通过movl %esp, %ebp让ebp指向esp,这样esp就可以进行修改,在函数返回的时候用ebp的值对esp进行恢复

图五 函数 f 通过subl $40, %esp 给函数的局部变量预留空间

图六 int数组 aa[5]占用了20个字节的空间,然后 int i占用了4个字节的空间(紧邻着之前压入栈的%ebp)
故,如果aa[5]进行赋值,则会把 i 的值覆盖掉,
如果对aa[6]进行赋值,则会把 栈中的 %ebp 覆盖掉,那么在函数 f 返回的时候则不能对ebp进行恢复,即main函数的ebp变成了我们覆盖掉的值,程序不知道会发生什么事情,但因为我们的程序接下来没有调用栈中的内容,故还是可以运行的。
如果对aa[7]进行赋值,则会把栈中的 %IP 覆盖掉,在函数 f 返回的时候就不能正确地找到下一跳的地址,会crash;
注:相关教程知识阅读请移步到C++教程频道。










