首页
社区
课程
招聘
堆栈空间分配问题
发表于: 2010-3-25 18:33 4215

堆栈空间分配问题

2010-3-25 18:33
4215
一段汇编程序,开始处如下:

push ebp
mov  ebp ,esp
sub esp 40h //请教这里的40h是怎么算出来的
push esi
push edi
push ebx
lea edi [ebp- 40h]
mov ecx 10h
...

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 594
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
void test(void)
{
char buffer[40h];
...
...
}
2010-3-25 19:03
0
雪    币: 63
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
在程序开始执行的时候,一般先要“扫描”下要执行的函数中定义的局部变量,计算出他们所要占用的空间大小之和,一次在堆栈中分配好,以便在接下来在这个堆栈中为各个变量分配具体的空间。
一般在一个被调用的函数开始要执行时就是这样为局部变量分配空间的,但lz说程序开始的时候因此就不是楼上所说的这种情况了,这属于调用的约定。在编译成汇编代码时,函数使用的栈默认就为40H,即64个字节。而且增加一个变量就会加4字节,因为win32下栈的粒度为4字节。这些都是函数调用预先都定义好的。主要是对debug版本程序的一种保护机制,为了防止堆栈操作的溢出,一般里面放的都是中断指令int 3.
2010-3-25 19:36
0
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
LS说了。
不过并不是所有的编译器都是这样。
看LZ的代码应该是VC的
2010-3-25 20:13
0
雪    币: 72
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
是vc6的,的确如果没有定义变量则为sub esp ,40h ,否则则以4的倍数字节增加

但vs2005却是sub esp,0C0H,每次增加12个字节,不知道是为什么?
2010-3-25 20:45
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
编译器根据变量所暂内存的大小,一般是4个字节对齐 来分配多少字节给这个变量存储数据,sub esp,40 栈顶向下减少40个字节用来存放局部变量
2010-3-25 20:59
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
那么ebp 就是堆栈的首地址,那么ebp-4 堆栈减少4个字节 来存放数据。
2010-3-25 21:01
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
外部参数吧
2010-3-25 21:04
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
汇编就像千军万马过独木桥   我正在学习中  看不懂发的帖
2010-3-25 21:15
0
雪    币: 401
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好像从VS2003开始就变成0xC0个字节了,不过无所谓,只要编译器觉得够用,分配0xC0个字节还是0x40个字节都行,不同的编译器分配的也不一样。
2010-3-25 21:36
0
雪    币: 72
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
多谢各位,本来是想知道sub esp, 40h这个值是怎么算出来的,看来是编译器决定的。。。
还有
push ebx
lea edi [ebp- 40h]
mov ecx 10h
push ecx, 10h
mov eax, 0CCCCCCCCh
rep stosd          //这个填充过程为什么是从edi开始向高地址填充而不是向低地址呢?
2010-3-25 22:24
0
雪    币: 63
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
这个问题你具体看下rep stosd的具体执行过程吧,它影响的是ecx,循环一次ecx的值就改变一次。。同时要执行add edi,4,所以嘛,就可以理解通了。但是这个地方有时也会是sub edi,4.
与具体的寻址方向有关,具体是高端寻址还是低端寻址来决定
2010-3-26 08:05
0
雪    币: 594
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这一段汇编程序只有在 Debug Build 才会有的:

push ebp
mov  ebp ,esp
sub esp 40h
push esi
push edi
push ebx
lea edi [ebp- 40h]
mov ecx 10h
...

上一次我给的解答:
void test(void)
{
char buffer[40h];
...
...
}

Release Build 的汇编程序如下:

sub esp, 40h
...
...
add esp, 40h
ret

===========================================
这个填充过程为什么是从edi开始向高地址填充而不是向低地址呢?

解答如下:

push ebp
mov ebp,esp
sub  esp,40h
push ebx
push esi
push edi
lea edi,[ebp-40h]
mov ecx,10h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]

开始:
// ESP = 0013FF30 EBP = 0013FF80

push        ebp               

// ESP = 0013FF2C EBP = 0013FF80

mov         ebp,esp           

// ESP = 0013FF2C EBP = 0013FF2C     <==== 注意 ESP

sub         esp,40h           

// ESP = 0013FEEC EBP = 0013FF2C

push        ebx               

// ESP = 0013FEE8 EBP = 0013FF2C

push        esi               

// ESP = 0013FEE4 EBP = 0013FF2C

push        edi               

// ESP = 0013FEE0 EBP = 0013FF2C

lea         edi,[ebp-40h]     

// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEEC

mov         ecx,10h           

// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEEC ECX = 00000010

mov         eax,0CCCCCCCCh   

// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEEC EAX = CCCCCCCC

rep stos    dword ptr [edi]   

// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEF0 ECX = 0000000F
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEF4 ECX = 0000000E
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FEF8 ECX = 0000000D
..
..
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FF20 ECX = 00000003
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FF24 ECX = 00000002
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FF28 ECX = 00000001

结束:
// ESP = 0013FEE0 EBP = 0013FF2C EDI = 0013FF2C ECX = 00000000

EDI 是从低地址向高地址填充的!
2010-3-26 09:27
0
雪    币: 72
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
明白了,多谢!
2010-3-26 09:27
0
游客
登录 | 注册 方可回帖
返回
//