函数的栈和栈帧?
1.调用该函数之前,参数入栈,进入函数第一行代码,返回值入栈一次
2.以codec的函数约定,参数入栈是反顺序的
main:
ebp 00000000
esp 0018FFF0
1.push xxx
esp=0018ffec
2.在主栈中建立栈帧
push ebp
mov ebp,esp
建立栈帧就是在主函数中重新确定一块空间作为栈的内部栈(它用作函数中的函数存储临时变量)
栈的演化
以xxxx第5章节,stack.exe为例
红色标记表示当前esp值
- 初始栈的情况
Main:
ebp 00000000
esp 0018FFF0
- push 100
main:
ebp 00000000
esp 0018ffec <-100
esp 0018FFF0
小结:在主程序中ebp<esp 入栈esp减小
3.添加参数push ecx
Main:
00000000
Esp 0018ffd8 倒数第二个参数push 参数1
Esp 0018ffdc 倒数第一个参数 push 参数2
Esp 0018ffe0
0018fff0
4.进入内部函数第一行
Main:
00000000
Esp 0018ffd4 <-存储函数返回地址(call函数的下一行)
Esp 0018ffd8 倒数第二个参数push 参数1
Esp 0018ffdc 倒数第一个参数 push 参数2
Esp 0018ffe0
0018fff0
5.建立栈帧(ebp为帧 esp为栈寄存器) (栈帧一般是在进入函数内部后创建,这里演示栈帧造成的ebp esp变化情况)
Push ebp
Mov ebp,esp
Main:
00000000
ebp esp 0018ffd0 ç00000000 所以栈帧中第一个4字节存储上一级栈ebp的地址
Esp 0018ffd4 <-存储函数返回地址(call函数的下一行) <-内部函数第一行
<-进入函数
Esp 0018ffd8 倒数第二个参数push 参数1
Esp 0018ffdc 倒数第一个参数 push 参数2
Esp 0018ffe0
0018fff0
6.sub esp,8 在栈帧中为函数分配局部变量存储空间(局部变量以mov 地址,局部变量值 方式存储,而不是push)
Main:
00000000
esp 0018ffc8
<-这里是新创建的栈帧,即主函数内的新函数栈。它用于存储新函数的局部变量(mov 地址,局部变量值)
ebp esp 0018ffd0 00000000 所以栈帧中第一个4字节存储上一级栈ebp的地址
Esp 0018ffd4 <-存储函数返回地址(call函数的下一行) <-内部函数第一行
<-进入函数
Esp 0018ffd8 倒数第二个参数push 参数1
Esp 0018ffdc 倒数第一个参数 push 参数2
Esp 0018ffe0
0018fff0
7.push eax 在函数内部push和在主函数中push好像是一样的,与新建的栈帧没啥关系
Main:
00000000
esp 0018ffc4
esp 0018ffc8
<-这里是新创建的栈帧,即主函数内的新函数栈。它用于存储新函数的局部变量(mov 地址,局部变量值)
ebp esp 0018ffd0 00000000 所以栈帧中第一个4字节存储上一级栈ebp的地址
Esp 0018ffd4 <-存储函数返回地址(call函数的下一行) <-内部函数第一行
<-进入函数
Esp 0018ffd8 倒数第二个参数push 参数1
Esp 0018ffdc 倒数第一个参数 push 参数2
Esp 0018ffe0
0018fff0
总结:
根据以上,当断点在函数第一行时 定位参数 返回地址
Esp 返回地址
Esp+4 第一个参数
Esp+8 第二个参数
如果断点在建立栈帧后(即进入函数后执行完push ebp mov ebp,esp)
Ebp+4 返回地址
Esp+8 第一个参数
Esp+c 第二个参数