博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
汇编-程序运行时栈模型介绍
阅读量:6194 次
发布时间:2019-06-21

本文共 1932 字,大约阅读时间需要 6 分钟。

  本文我们单考虑内存中的栈区域,考虑函数的调用、参数的传递和局部变量的使用——这一切在汇编的抽象级别是如果进行的。

  (Contents from Assembly Language For x86 Processors Sixth Edition By Kip R.Irvine)

  

  首先一上来作者用了这么一段话非常精炼的总结了stack的几乎所有功能,其实要想完全掌握这个概念,脑中只要把调用子程序时生成stack的动态模型给记住即可。为了便于大家对stack模型的理解,我根据ebp相对固定的特点,将stack模型分为两部分,分别是ebp之下的空间和ebp之上的空间。


1. EBP之下的空间

1.1 Prologue

在一进入子程序的时候,我们首先要做的是设置栈顶的位置,数据入栈出栈有esp掌控位置的变化,但我们也需要一个固定不变的位置来在内存中标记当前stack的具体位置,这项工作就由ebp寄存器来完成。

首先保存ebp的值,然后将ebp指向esp

 

1.2 Saving and Restoring Registers

Ideally,the registers in question should be pushed on the stack just after setting EBP to ESP,and just before reserving space for local variables.

通过书中的这句话我们可以很清晰的看到将寄存器的值push进栈(保存其值以便返回前恢复)这个步骤具体是在什么时候进行的,而我们之所以要保存一些寄存器的值,是因为在子程序的调用过程中,我们可能会需要借用一些寄存器来处理相应的数据,为了保护寄存器原来的值不被这次调用破坏,我们会选择先将其保存起来。这一行为的专业术语我们称之为保护现场

 

1.3 Local Variables

Mysub proc    push ebp    mov ebp,esp    sub esp,8    mov DWORD PTR [ebp-4],10    mov DWORD PTR [ebp-8],20    mov esp,ebp    pop ebp    retMysub endp

在我们想创建局部变量之前,首先要为他们在stack中开辟一段空间,而这个任务就由sub esp,8这条指令来完成,其内存模型如下图:

显而易见,ebp保持位置不变,esp进行相应的移动为局部变量的存储创造空间。那么这些创造出来的空间在子程序调用结束后该怎么处理呢?请见1.4

 

1.4 Epilogue

在runtime stack中为local variable和一些要保存原来值的registers预留了空间,在子程序调用结束后,这些空间必须要被释放出来,如果不释放,那么当pop ebp时,ebp就不能得到stack为他保留的值了。因此epilogue这一环节的意义可以总结为释放stack中ebp和esp之间的空间,从而使得ret 指令在调用结束后能将程序返回到正确的地址。

 

2. EBP之上的空间

2.1 Stack Parameters

push 6push 5call AddTwoNum

 上述语句的执行会产生下面的stack:

在调用子程序(subroutine)的时候,调用者会将实参push进栈,以便稍后的调用过程中使用。注意我们传递参数这一步是在调用(call)之前进行的,比如如下代码,要在调用计算两数和的子程序之前就将我们需要的参数push进栈。调用子程序的call指令就相当于将子程序的返回地址压栈。

 

2.2 参数空间的释放

我们看这样一个例子,在main函数中调用Example1函数,再在Example1中调用AddTwo函数,然后ret,通过这个例子来说明子程序返回时释放参数空间的重要性

我们先看一下程序的栈模型:

在AddTwo子程序调用结束后,ret指令会返回到当前ESP所指向的地址,也就是之前传递的参数5和6的位置,这就导致了错误的产生——我们没有跳转到return address上去啊!解决这种错误有两种方法,一是在caller中释放该调用的空间,另一个是在子程序中自行完成,二者的实现分别如下:

在caller中释放参数空间:

在子程序中释放空间:

这种方法也被称为STDCALL Calling Convention)

通常情况下也就是子程序的连续或循环调用可能会出现此种错误,需要注意

转载于:https://www.cnblogs.com/immortal-worm/p/5487417.html

你可能感兴趣的文章
我的友情链接
查看>>
LVM的综合性介绍及实现
查看>>
DNS服务器中很重要的几个搭建配置---不看后悔哦
查看>>
CAP理论
查看>>
Skype for Business Server 2015-02-Office Web Apps-部署
查看>>
Skype for Business Server 2015-03-后端服务器-3-验证
查看>>
Docker容器部署时区问题的坑
查看>>
ASP.NET MVC ModelState与数据验证【转】
查看>>
win10 中xshell输入中文显示问号问题
查看>>
华为产品升级及打补丁具体步骤
查看>>
There is already an open DataReader associated with this Command which must be closed first
查看>>
【记录】mysql使用like匹配数据时关于通配符的使用误区
查看>>
activemq安全设置 设置admin的用户名和密码
查看>>
负载均衡方案对比表
查看>>
zabbix3配置阿里云邮箱告警
查看>>
Java的类的创建
查看>>
centos学习(之一)-centos6.6环境搭建
查看>>
基于echarts实时温度折线图表
查看>>
百度云盘API使用
查看>>
对于动态生成的html元素绑定$(document).click()在 iphone上失效
查看>>