查看: 528|回复: 1

[原创图文] 聊一聊堆栈

[复制链接]

1

主题

3

帖子

0

精华

初级会员

Rank: 4

学币
4
荣耀
0
rank
0
违规
0

    发表于 2019-3-11 09:58:01 | 显示全部楼层 |阅读模式
    vc 写的程序,反汇编之后,每个call都有一部分相似代码,大体如下。
    push ebp
    mov ebp,esp

    ……

    mov esp,ebp
    pop ebp
    retn

    我们都知道,esp 在程序运行时始终是栈顶指针。程序运行的时候,esp寄存器随时在发生变化,所以在访问保存在堆栈中的“函数的局部变量和参数”时,用esp来寻找就会非常的困难。所以,调用新函数时,将esp的值保存在ebp中,再以ebp为基准,就能够快速方便的访问到函数的局部变量、参数、以及返回地址。

    我们还知道,堆栈是负增长,就是最后入栈的值保存在较小的内存地址。所以我们可以总结一下规律。
    1、通常情况下(32位系统,vc编译),ebp保存着调用函数最初的esp值,方便程序结束后恢复esp。
    2、ebp+4 保存的是函数的返回地址。
    3、ebp+8、esp+C 保存的是函数的参数。
    4、ebp-4、ebp-8 。。。 保存的是函数的局部变量

    再说几个跟栈有关的指令:
    1、call指令:相当于push call 的下一跳政令,再jmp到call的地址,比如说 有代码 call  40000,他下面的代码地址是100004,则这个call指令相当于push 100004, jmp 40000。压入栈的这个100004 ,在函数中就会变为 ebp+4 里面的值,为啥会变成ebp+4,上面说了,这里再说一下, 函数一进去就是 push ebp 所以,esp里面存了ebp的值,刚刚压入得100004,存放在了ebp+4中,下一条mov ebp,esp 使得 ebp==esp ,这样再找压人内容时,自然就可以通过ebp+4来找到。
    2、retn指令 :相当于 jmp [esp],实际上是mov eip,100004。

    评分

    参与人数 1荣耀 +2 收起 理由
    xuenixiang + 2 赞一个!

    查看全部评分

    温馨提示:
    1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
    2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
    3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
    发表于 2019-3-11 16:27:05 | 显示全部楼层
    EBP主要是用来体现函数局部变量的,栈帧技术就是利用EBP来实现局部变量有条不紊的调用
    善莫大焉-2019
    关闭

    论坛公告上一条 /1 下一条

    快速回复 返回顶部 返回列表