windows stack分析
来源:互联网 发布:单片机采集脉冲信号 编辑:程序博客网 时间:2024/05/14 08:53
从Stack说开去
从我个人的经验看,谈到内存时说堆的文章最多,说stack的最少。我这里反其道而行的原因是stack其实要比堆更重要,可以有不使用堆的程序,但你不可能不使用stack,虽然由于对stack的管理是由编译器确定了的,进而他较少出错。
通过链接开关/STACK:reserve[,commit]可以指定进程主线程的stack大小,当你建立其他线程时如果不指定dwStackSize参数,则也将使用/STACK所指定的值。微软说,如果指定较大的commit值将有利于提升程序的速度,我没验证过,但理应如此。通常并不需要对STACK进行什么设定,缺省的情况下将保留1M空间,并提交两个页(8K for x86)。而1M空间对于大多数程序而言是足够的,但为防止stack overflow有三点需要指出一是当需要非常大的空间时最好用全局数组或用VirtualAlloc进行分配,二是引用传递或用指针传递尺寸较大的函数参数(这点恐怕地球人都知道),三是进行深度递归时一定要考虑会不会产生stack溢出,如果有可能,可以采用我在《递归与goto》一文中提到的办法来仿真递归,这时候可以使用堆或自由存储来代替stack。同时结构化异常被用来控制是否为stack提交新的页面。(这部分写的比较简略因为很多人都写过,推荐阅读Jeffery Ritcher《Windows核心编程》第16章)
下面我们来看一下stack的使用。
假设我们有这样一个简单之极的函数:
int __stdcall add_s(int x,int y)
{
int sum;
sum=x+y;
return sum;
}
这样在调用函数前,通常我们会看到这样的指令。
mov eax,dword ptr [ebp-8]
push eax
mov ecx,dword ptr [ebp-4]
push ecx
此时把函数参数压入堆栈,而stack指针ESP递减,stack空间减小。
在进入函数后,你将会看到如下指令:
push ebp
mov ebp,esp
sub esp,44h
这三句建立stack框架,并减小esp为局部变量预留空间。建立stack框架后,[ebp+*]指向函数参数,[ebp-*]指向局部变量。
另外在很多情况下你会看到如下三条指令
push ebx
push esi
push edi
这三句把三个通用寄存器压入堆栈,这样这三个寄存器就可以用来存放一些变量,进而提升运行速度。
很奇怪,我这个函数根本用不到这三个寄存器,可编译器也生成了上述三条指令。
对stack中内容的读取,是靠基址指针ebp进行的。所以对应于sum=x+y;一句你会看到
mov eax,dword ptr [ebp+8]
add eax,dword ptr [ebp+0Ch]
mov dword ptr [ebp-4],eax
其中[ebp+8]是x,[ebp+0Ch]是y,记住压栈方向为从右向左,所以y要在x上边。
我们再看一下函数退出时的情况:
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 8
此时恢复stack框架,使esp与刚进入这个函数时相同,ret 8使esp再加8,使esp与没调用这个函数的时候一致。如果使用__cdecl调用规则,则由调用方以类似add esp,8进行清场工作,使stack的大小与未进行函数调用时一致。Stack的使用就这样完全被编译器实现了,只要不溢出就和我们无关,也许也算一种内存的智能管理。最后要补充的两点是:首先stack不像heap会自动扩充,如果你用光了储备,他会准时溢出。其次是不要以为你使用了缺省参数进行链接,你就有1M的stack,看看启动代码你就知道在你拥有stack之前,C Run –Time
Library以用去了一小部分stack的空间。
从我个人的经验看,谈到内存时说堆的文章最多,说stack的最少。我这里反其道而行的原因是stack其实要比堆更重要,可以有不使用堆的程序,但你不可能不使用stack,虽然由于对stack的管理是由编译器确定了的,进而他较少出错。
通过链接开关/STACK:reserve[,commit]可以指定进程主线程的stack大小,当你建立其他线程时如果不指定dwStackSize参数,则也将使用/STACK所指定的值。微软说,如果指定较大的commit值将有利于提升程序的速度,我没验证过,但理应如此。通常并不需要对STACK进行什么设定,缺省的情况下将保留1M空间,并提交两个页(8K for x86)。而1M空间对于大多数程序而言是足够的,但为防止stack overflow有三点需要指出一是当需要非常大的空间时最好用全局数组或用VirtualAlloc进行分配,二是引用传递或用指针传递尺寸较大的函数参数(这点恐怕地球人都知道),三是进行深度递归时一定要考虑会不会产生stack溢出,如果有可能,可以采用我在《递归与goto》一文中提到的办法来仿真递归,这时候可以使用堆或自由存储来代替stack。同时结构化异常被用来控制是否为stack提交新的页面。(这部分写的比较简略因为很多人都写过,推荐阅读Jeffery Ritcher《Windows核心编程》第16章)
下面我们来看一下stack的使用。
假设我们有这样一个简单之极的函数:
int __stdcall add_s(int x,int y)
{
int sum;
sum=x+y;
return sum;
}
这样在调用函数前,通常我们会看到这样的指令。
mov eax,dword ptr [ebp-8]
push eax
mov ecx,dword ptr [ebp-4]
push ecx
此时把函数参数压入堆栈,而stack指针ESP递减,stack空间减小。
在进入函数后,你将会看到如下指令:
push ebp
mov ebp,esp
sub esp,44h
这三句建立stack框架,并减小esp为局部变量预留空间。建立stack框架后,[ebp+*]指向函数参数,[ebp-*]指向局部变量。
另外在很多情况下你会看到如下三条指令
push ebx
push esi
push edi
这三句把三个通用寄存器压入堆栈,这样这三个寄存器就可以用来存放一些变量,进而提升运行速度。
很奇怪,我这个函数根本用不到这三个寄存器,可编译器也生成了上述三条指令。
对stack中内容的读取,是靠基址指针ebp进行的。所以对应于sum=x+y;一句你会看到
mov eax,dword ptr [ebp+8]
add eax,dword ptr [ebp+0Ch]
mov dword ptr [ebp-4],eax
其中[ebp+8]是x,[ebp+0Ch]是y,记住压栈方向为从右向左,所以y要在x上边。
我们再看一下函数退出时的情况:
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 8
此时恢复stack框架,使esp与刚进入这个函数时相同,ret 8使esp再加8,使esp与没调用这个函数的时候一致。如果使用__cdecl调用规则,则由调用方以类似add esp,8进行清场工作,使stack的大小与未进行函数调用时一致。Stack的使用就这样完全被编译器实现了,只要不溢出就和我们无关,也许也算一种内存的智能管理。最后要补充的两点是:首先stack不像heap会自动扩充,如果你用光了储备,他会准时溢出。其次是不要以为你使用了缺省参数进行链接,你就有1M的stack,看看启动代码你就知道在你拥有stack之前,C Run –Time
Library以用去了一小部分stack的空间。
0
上一篇:windbg调试kvm windows虚机
下一篇:VS2010
相关热门文章
- 10种启动故障解决方法(转)...
- 关于自动弹出网页的解决方法...
- Auto CAD 2007中文版 迅雷免费...
- 出现“high definition audio...
- 全国计算机一级考试试题...
- 关于enqueue 的dump 文件帮看...
- tar --newer 05/12/2013 这个...
- 请教nginx代理tomcat作为子目...
- LDAP安装 bus error是什么问...
- select语句不修改sql,如何优...
给主人留下些什么吧!~~
评论热议
- windows stack分析
- Windows Phone App的dump文件实例分析-Stack Overflow
- Windows NT Stack Trace
- windows stack trace
- heap stack 区别分析
- Stack源码分析
- Vector和Stack分析
- Stack源码分析
- Z-Stack分析--HAL_BOARD_INIT()
- Z-Stack分析--zmain_vdd_check()
- Vector和Stack分析
- 《Java源码分析》:Stack
- Stack源码分析
- Stack源码分析
- 【集合类分析】Stack
- 《Java源码分析》:Stack
- ndk-stack 分析 android crash stack
- Windows DNS DnssrvQuery() Stack Overflow
- 链接静态库循环依赖解决方法
- ubuntu 10.04显示grub菜单
- rdp 6.x auto-logon windows xp(file or activx)
- C++中虚函数的内部实现
- windbg调试kvm windows虚机
- windows stack分析
- jQuery:如何给动态生成的元素绑定事件?
- 内存屏障(memory barrier)
- VS2010
- mkfs.jffs2指定dev table文件创建rootfs
- 十道海量数据处理面试题与十个方法大总结
- linux 中的调试符号文件
- 无法安装ubuntu(alternative)系统解决方法
- ubuntu自动登录tty1(shell,text)配置
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
龙膜好还是威固好
威固和量子膜哪个好
量子膜和威固
3m太阳膜
3m防爆膜
子曰君子不重则不威学则不固
威途
威兔手机
威途手机
vertu威图
诺基亚威图
漫威毒液六种形态图
威能壁挂炉使用步骤图
威图诺基亚
威图手机有什么特殊功能
威图手机价格表
漫威顺序一览图
漫威正确观影顺序一张图2019
威图手机为什么那么贵
江铃宝威电路图
洛基亚威图
图威手机价格
威图是诺基亚的吗
威图手机图片和价格
威图vertu手机
伟图手机
威图价格表
诺基亚 威图
纬图手机
威图图片真实
威图手机是诺基亚的吗
威图手机报价及图片
唯图手机
微图手机
威图机柜
威图手机为什么贵
图威手机
威图手机多少钱
威图是什么牌子
威图总裁手机报价
威图是什么系统