汇编中的堆栈平衡

什么是堆栈平衡

这里有两种情况:

  • 如果要返回父程序,则当我们在堆栈中进行堆栈操作的时候,一定要保证在RET这条指令之前,ESP指向的是压入的我们压入的地址

这句话我是这么理解的,就是当你调用函数的时候,比如使用CALL指令,当使用堆栈的时候,使用前ESP指向那个地址,使用后RET返回前就必须是那个地址,如果不是那个地址,那么堆栈就是不平衡的,程序就崩溃了。

直接上图分析一下:

在这里插入图片描述这个程序运行起来以后一定是会崩溃的,在函数执行结束前,它使用了堆栈,向栈顶push了eax的值,使栈顶指针ESP的值-4,这样ret程序就飞了,因为push把它带到了另一个世界。
在这里插入图片描述运行结果:

可以看到,反汇编窗口直接没了,原因就是他没有00000003这个地址,程序就这样飞走了,这是第一种情况。
在这里插入图片描述

  • 如果通过堆栈传递参数了。那么在程序执行完毕后,要平衡因参数导致的堆栈变化

这句话的意思就是,当我们使用堆栈传参的时候,在程序执行完毕后这些参数应该一起被清理掉,也就是加了几条参数,就要在堆栈中加几个地址,这么做可以理解为清理垃圾。

上图分析一波:

这是第一次堆栈传参,在程序执行完毕前,堆栈一直都是平衡的,也没有垃圾可以清理,但如果我们需要接着向堆栈中压入数据,那么程序执行完毕后的垃圾就出现了。
在这里插入图片描述
这是第二次传参:之前程序执行结束后的参数没有被清理,导致后面的参数直接依次压入栈顶,多使用了两个地址,后边的000000001与000000002我们都不会再用了,但是没有被覆盖掉,这样多几个堆栈传参操作,程序的性能就会越来越差,直至崩溃。
在这里插入图片描述

如何进行堆栈平衡

这里有两个办法:

  • 外平栈

就是从程序外部加一行代码去平衡堆栈,方法很简单,程序执行结束多用几个地址就多加几个地址。注意观察堆栈的变化。
在这里插入图片描述

  • 内平栈

就是改变ret返回时esp栈顶指针的变化,用几个参数就加几个地址。注意观察堆栈的变化。

这里向堆栈传递了2个参数,我们在程序执行完毕前加了条ret 8,程序执行完毕后栈顶指针ESP的值就会多+8,这样就完美清理我们传递的那两个参数所占用的地址了。

运行结果:
在这里插入图片描述

总结:汇编语言是门抽象艺术,需要多加思考,勤加练习!

发布了60 篇原创文章 · 获赞 68 · 访问量 8426

猜你喜欢

转载自blog.csdn.net/qq_43573676/article/details/104376354
今日推荐