对栈的一些理解
2018-03-24 14:55
176 查看
举例分析
小结:
对开辟栈帧的理解
之前总结过一篇有关函数栈帧的博客:
函数栈帧以及调用约定相关的一些总结
但是感觉自己还是有一点知识点没有弄懂,今天中午跟郭哥吃过饭一起探讨有关壳的问题的时候,顺便把这个问题请教了一下郭哥,终于弄明白了,在此要特地感谢他,这里把一些心得体会写出来;
先看一幅图(选自IDA权威指南):
注意图中是基于esp的栈帧!!!
下面是对demo_stack frame函数中bar的调用代码为例:
esp和ebp都是寄存器,esp始终指向栈顶的意思是:esp这个寄存器里面始终存放的是栈顶的地址,只不过这个栈顶地址很有可能是经常变化的,栈顶所对应的一个”容器”里面存放了一个数据,这个数据就是被压入栈的数据(其实栈中其他数据也类似,就是说一个数据对应一个地址),同理EBP也是这样去理解!
对上面那段代码(这段代码是与基于esp的栈帧对应的)的解释:
根据上面那副图的偏移量,1处的push准确的将局部变量y压入栈中;初看起来,似乎2处的push错误地再次引用了局部变量y,然而,这里是基于esp的栈帧!结合上表来理解,假设执行完push y之后,此时栈顶为addr2,即esp这个寄存器里面存放的是Addr2的地址,而在这一步之前栈顶为addr3(esp这个寄存器里面存放的是Addr3的地址),即进行了一次push y操作之后,栈顶被抬高了,栈顶是变化的!此时esp中存的是Addr2,再压一次栈push z,其所对应的指令为push [esp + 4] (这里指令中的esp指的是addr2),这一步之后,栈顶又会变成addr1.
分步解析一下:假设原来栈是这样的:
esp指向1000这个地址这里:
执行push y之后:esp指向996了,esp变化了,此时此时Z所对应的地址仍然为1000,但是用esp表示的话则为esp+4,而Z则就用[esp+4]表示,所以图中push Z的时候写为 push dword [esp+4]:
小结:
对开辟栈帧的理解
之前总结过一篇有关函数栈帧的博客:
函数栈帧以及调用约定相关的一些总结
但是感觉自己还是有一点知识点没有弄懂,今天中午跟郭哥吃过饭一起探讨有关壳的问题的时候,顺便把这个问题请教了一下郭哥,终于弄明白了,在此要特地感谢他,这里把一些心得体会写出来;
先看一幅图(选自IDA权威指南):
注意图中是基于esp的栈帧!!!
下面是对demo_stack frame函数中bar的调用代码为例:
push dword [esp+4];//push y,1th push dword [esp+4];//push z,2th call bar add esp,8
栈中数据 | 对应地址 |
---|---|
。。。 | 。。。 |
。。。 | 。。。 |
data1 | Addr1 |
data2 | Addr2 |
data3 | Addr3 |
。。。 | 。。。 |
举例分析
结合上面这幅图讲讲:esp和ebp都是寄存器,esp始终指向栈顶的意思是:esp这个寄存器里面始终存放的是栈顶的地址,只不过这个栈顶地址很有可能是经常变化的,栈顶所对应的一个”容器”里面存放了一个数据,这个数据就是被压入栈的数据(其实栈中其他数据也类似,就是说一个数据对应一个地址),同理EBP也是这样去理解!
对上面那段代码(这段代码是与基于esp的栈帧对应的)的解释:
根据上面那副图的偏移量,1处的push准确的将局部变量y压入栈中;初看起来,似乎2处的push错误地再次引用了局部变量y,然而,这里是基于esp的栈帧!结合上表来理解,假设执行完push y之后,此时栈顶为addr2,即esp这个寄存器里面存放的是Addr2的地址,而在这一步之前栈顶为addr3(esp这个寄存器里面存放的是Addr3的地址),即进行了一次push y操作之后,栈顶被抬高了,栈顶是变化的!此时esp中存的是Addr2,再压一次栈push z,其所对应的指令为push [esp + 4] (这里指令中的esp指的是addr2),这一步之后,栈顶又会变成addr1.
分步解析一下:假设原来栈是这样的:
esp指向1000这个地址这里:
栈中数据 | 对应地址 |
---|---|
。。。 | 。。。 |
。。。 | 。。。 |
z | 1000 |
y | 1004 |
buffer | 1008 |
。。。 | 。。。 |
栈中数据 | 对应地址 |
---|---|
。。。 | 。。。 |
y | 996 |
z | 1000 |
y | 1004 |
buffer | 1008 |
。。。 | 。。。 |
小结:
esp是一个寄存器,这个寄存器里面存放的是一个地址,同时这个地址可能是不断变化的.对开辟栈帧的理解
看几条指令(基于ebp的栈帧):push ebp;//把ebp里面的地址压入栈中保存了起来;这一步作用:保存上一个栈帧的底部 mov ebp,esp;//把esp里面的地址放入ebp寄存器里面;此时esp和ebp指向同一个地址,即栈顶和栈底重合;这一步作用:设置新栈帧的底部 sub esp,0x50;//设置新栈帧的顶部,为新栈帧开辟空间
相关文章推荐
- 9054 DMA、中断、基地址寄存器的一些理解
- 关于sql和mysql对于别名不能调用的一些理解
- 一些常用css技巧的为什么(二)我所理解的line-height
- 初学树剖的一些理解
- 关于socket的一些个人理解
- wap游戏的一些理解
- handler 与message的一些理解
- 关于对驱动的一些理解
- KVC,KVO的一些原理理解与使用介绍[续]
- 对泛型的一些理解
- POJ 3322 Bloxorz I (bfs+辅助数组+状态压缩+自己的一些搜索理解)
- JHTP练习题及课题_第六章_深入理解方法 (附加一些感慨)
- 对I2C总线协议的一些理解
- iOSBlock的一些理解
- 关于动态网页的一些理解
- spring容器的一些理解
- 关于Mvvm的一些深入理解
- SSH网上商城初步——一些概念的理解
- CCMenu位置的一些理解和制作一个中心放大的按钮(无需修改底层代码)
- jQuery中移动元素的一些理解