您的位置:首页 > 其它

对栈的一些理解

2018-03-24 14:55 176 查看
举例分析

小结:

对开辟栈帧的理解

之前总结过一篇有关函数栈帧的博客:

函数栈帧以及调用约定相关的一些总结

但是感觉自己还是有一点知识点没有弄懂,今天中午跟郭哥吃过饭一起探讨有关壳的问题的时候,顺便把这个问题请教了一下郭哥,终于弄明白了,在此要特地感谢他,这里把一些心得体会写出来;

先看一幅图(选自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


栈中数据对应地址
。。。。。。
。。。。。。
data1Addr1
data2Addr2
data3Addr3
。。。。。。

举例分析

结合上面这幅图讲讲:

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这个地址这里:

栈中数据对应地址
。。。。。。
。。。。。。
z1000
y1004
buffer1008
。。。。。。
执行push y之后:esp指向996了,esp变化了,此时此时Z所对应的地址仍然为1000,但是用esp表示的话则为esp+4,而Z则就用[esp+4]表示,所以图中push Z的时候写为 push dword [esp+4]:

栈中数据对应地址
。。。。。。
y996
z1000
y1004
buffer1008
。。。。。。

小结:

esp是一个寄存器,这个寄存器里面存放的是一个地址,同时这个地址可能是不断变化的.

对开辟栈帧的理解

看几条指令(基于ebp的栈帧):

push ebp;//把ebp里面的地址压入栈中保存了起来;这一步作用:保存上一个栈帧的底部
mov ebp,esp;//把esp里面的地址放入ebp寄存器里面;此时esp和ebp指向同一个地址,即栈顶和栈底重合;这一步作用:设置新栈帧的底部
sub esp,0x50;//设置新栈帧的顶部,为新栈帧开辟空间
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: