Win32 环境下的堆栈

原文已经找不到,作者应该是:http://blog.csdn.net/slimak   但是没有找到此文,其中丢了2幅图

简介

Win32环境下利用调试器调试应用程序的时候经常要和堆栈(Stack)打交道,尤其是在需要手工遍历堆栈(Manually Walking Stack)的时候我们需要对堆栈的工作过程有一个比较清晰的了解.接下来的这些文字将通过一个例子程序详细的讲解堆栈的工作过程.

关键字

调试堆栈 Stack Stack-Frame

目录

1.堆栈是什么?

2.堆栈里面放的都是什么信息?

3.堆栈是在什么时候被建立起来的?它的默认大小是多少?

4.默认才1M??那要是我的程序使用超过了1M的堆栈怎么办?

5.什么叫Stack Frame?

6.在一次函数调用中,堆栈是如何工作的?

7.老大,结合一个例子讲讲吧?

1.堆栈是什么?

从内存管理角度看,堆栈是就是一块连续的内存空间,对它的操作采用先入后出的规则,他的生长方向与内存的生长方向正好相反,也就是说它是从高地址向低地址生长.

Win32程序内部的角度看,每一个线程有自己的堆栈,它主要用来给线程提供一个暂时存放数据的区域,程序使用POP/PUSH指令来对堆栈进行操作.

2.堆栈里面放的都是什么信息?

堆栈中存放的信息包括:

当前正在执行的函数的局部变量;

函数返回地址;

该函数的上层函数传给该函数的参数;

EBP的值;

一些通用寄存器(EDI,ESI…)的值。

 

注意这里提到的正在执行的函数,比如有下面的一段C代码:

void B()

{

printf(“B\n”);

}

void A()

{

B();

}

那么当程序执行到B函数的printf函数的时候我们说正在执行的函数包括A和B而不仅仅是B函数,这一点需要注意.

3.堆栈是在什么时候被建立起来了?它的默认大小是多少?

堆栈是在我们的main主函数被系统调用之前被建立起来的,对于非主线程它是在线程被建立之前创建的,

它的默认大小是1M,

如果需要修改堆栈的大小的话可以在VC6++中通过使用/STACK编译项实现:

#pragmacomment(linker,“/STACK:2048,1024″)//预约(Reserve)2M,提交(Commit)1M

关于预约(Reserve)和提交(Commit)的概念请参看Programming Applications for Microsoft Windows“( Jeffrey Richter,Chapter 15Using Virtual Memory in Your Own Applications)

4.默认才1M??那要是我的程序使用超过了1M的堆栈怎么办?

系统通过使用异常捕获(Exception Handling)机制来捕获应用程序企图去访问超过该程序提交(Commit)的堆栈范围这种异常,假如你程序预约了2M并且提交了1M大小的堆栈,那么当你的程序企图访问超过1M的范围的时候会产生一个异常并且被系统捕获,系统会帮你继续从另外1M预约的内存中提交内存来满足你的需求,如果你要求提交的大小甚至超过了2M(你一开始预约的大小)在 NT系统下(98除外)系统也会尝试去分配(allocate)内存来满足你,但是系统并不保证分配会成功

5.什么叫Stack Frame?

Stack Frame这个词你可以在各种各样的汇编书籍中看到,到底它表示什么意思呢?也许你看完文章的后半部分就会明白,在此我们先给它一个定义,你看完整篇文章在回过头来回味一下就会知道它的确切含义了,Stack Frame是堆栈中的一块区域,它保存着一个函数的返回地址,和该函数内部使用的局部数据(Local Data),它是由函数入口处的SUB ESP,48h之类的语句来建立的.

6.在一次函数调用中,堆栈是如何工作的?

假设我们的主角叫A函数…

a.首先上级函数传给A函数的参数被压入堆栈中(至于是谁来做这个压栈操作取决于A函数的调用方式:是__stdcall, __cdecl还是其他);

b.然后是返回地址(A函数执行完后接下来程序继续执行的地址)入栈;

c.接下来是当前的EBP;

d.如果A函数有局部变量,就在堆栈中开辟相应的空间以构造那些变量变量(A函数执行结束,这些局部变量的内容将被忽略/遗弃,但是不被清除,比如A函数中有一个变量int m存在于地址0×0012FFCC处,函数结束时9依然存在于0×0012FFCC处没有被清除,但是此时它已经没有任何意义了,

e.在函数返回的时候,弹出EBP,恢复堆栈到函数调用前的地址,弹出返回地址到EIP以继续执行程序。

7.结合一个例子

下面就是我们要拿来做模特的代码,程序很简单,wWinMain调用AFunc,AFunc再调用BFunc,下面的讲解过程中我们要观摩这个程序的汇编代码形式,可以通过在VC6++该工程的Debug模式中按F5然后Ctrl+Tab做到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值