首页
社区
课程
招聘
[求助]我学过汇编语言,但不懂什么事堆栈平衡,谁告诉我一下?
发表于: 2010-2-3 12:43 20451

[求助]我学过汇编语言,但不懂什么事堆栈平衡,谁告诉我一下?

2010-2-3 12:43
20451
我学过汇编语言,但不懂什么事堆栈平衡(平衡堆栈),谁告诉我一下?O(∩_∩)O谢谢了

[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费
支持
分享
最新回复 (21)
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谁来看看啊。。。求求了
2010-2-3 12:47
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
对于堆栈平衡,我的理解是:

程序经过编译链接,高级语言中的一个语句转换成一段汇编代码。而这段汇编代码执行前后esp、ebp应该保持不变。也就是说每个子程序调用前后esp、ebp不应改变。只有这样,才能让一段代码的执行不影响到以前各次调用的返回地址,从而保证整个程序的正确运行。

直观的来解释一下吧,下面是一个简单的C代码。

#include <stdio.h>
#include <stdlib.h>

int _cdecl myadd1(int a,int b)  //返回值类型和函数名之间的关键字是堆栈调用约定
{
        return a+b;
}

int _stdcall myadd2(int a,int b)
{
        return a+b;
}

int myadd3(int a,int b)
{
        return a+b;
}

int main()
{
        int a=1,b=2;
        myadd1(a,b);
        myadd2(a,b);
        myadd3(a,b);
        system("pause");
        return 0;
}

OD反汇编后得到如下代码:

0041367E    C745 F8 0100000>mov     dword ptr [ebp-8], 1
00413685    C745 EC 0200000>mov     dword ptr [ebp-14], 2
0041368C    8B45 EC         mov     eax, dword ptr [ebp-14]
0041368F    50              push    eax
00413690    8B4D F8         mov     ecx, dword ptr [ebp-8]
00413693    51              push    ecx
00413694    E8 51DBFFFF     call    004111EA                         ; myadd1
00413699    83C4 08         add     esp, 8
0041369C    8B45 EC         mov     eax, dword ptr [ebp-14]
0041369F    50              push    eax
004136A0    8B4D F8         mov     ecx, dword ptr [ebp-8]
004136A3    51              push    ecx
004136A4    E8 37DBFFFF     call    004111E0                         ; myadd2
004136A9    8B45 EC         mov     eax, dword ptr [ebp-14]
004136AC    50              push    eax
004136AD    8B4D F8         mov     ecx, dword ptr [ebp-8]
004136B0    51              push    ecx
004136B1    E8 2FDBFFFF     call    004111E5                         ; myadd3
004136B6    83C4 08         add     esp, 8
004136B9    8BF4            mov     esi, esp
004136BB    68 3C574100     push    0041573C                         ; ASCII "pause"
004136C0    FF15 C0824100   call    dword ptr [<&MSVCR90D.system>]   ; msvcr90d.system

单步运行,源码中的子函数myadd1调用前相关寄存器值如下:
ESP 0012FE84
EBP 0012FF68
EIP 0041368F

myadd1调用完毕后寄存器值如下:
ESP 0012FE84
EBP 0012FF68
EIP 0041369C

myadd2调用前:
ESP 0012FE84
EBP 0012FF68
EIP 0041369F

调用后
ESP 0012FE84
EBP 0012FF68
EIP 004136A9

myadd3调用前
ESP 0012FE84
EBP 0012FF68
EIP 004136AC

调用后
ESP 0012FE84
EBP 0012FF68
EIP 004136B9

从反汇编代码中可以看出,_cdecl是有调用者来维护堆栈平衡的,而_stdcall是有子函数负责维护,此处默认的调用约定是_cdecl。
2010-2-3 16:00
0
雪    币: 173
活跃值: (132)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
简单的说就是在函数调用的时候,将函数返回地址, 参数压栈, 在函数执行结束以后恢复堆栈的过程。
实例如下:
sub proc c _var1, _var2
mov eax, _var1
mov ebx, _var2
ret
sub endp

编译后再进行反汇编:
:00401000 55 push ebp
:00401001 8BEC mov ebp, esp
:00401003 8B4508 mov eax, dword ptr [ebp + 08]
:00401006 8B5D0C mov ebx, dword ptr [ebp + 0C]
:00401009 C9 leave
:0040100A C3 ret

压入参数
:00401003 8B4508 mov eax, dword ptr [ebp + 08]
:00401006 8B5D0C mov ebx, dword ptr [ebp + 0C]

一个函数的执行过程如下:
ebp用来存取局部变量
push _var2
push _var1
push 函数的返回地址
push ebp
mov ebp, esp
push 局部变量2
push 局部变量1

_var1的地址就是[ebp+08]
_var2的地址就是[ebp+0c]
[ebp]存放的就是原来ebp的值
[ebp+04]存放的就是函数返回地址
这里使用leave来实现堆栈平衡,即将esp+0c。。。

了解不?
2010-2-3 16:21
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
把堆栈比喻成一个公用的书箱,一次只能放一本书,再放的话就是往第一本书上螺了。假如你放了三本书(参数或局部变量),你用完了箱子走人,因为箱子是公用的,你得把箱子还原回原来的样子,你自己或由管理员帮你把箱子还原。。。。你不还原的话,别的人(程序)就不能用书箱了,否则就乱套了。把这个还原比喻成堆栈平衡。。。。。这样楼主理解不知咋样。。。
2010-2-17 11:09
0
雪    币: 196
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
LZ说的很搞笑,学过汇编,但是不会堆栈原理,那也就不算是学过汇编拉
2010-2-20 09:19
0
雪    币: 456
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
比喻很生动,通俗易懂。
2010-5-6 19:35
0
雪    币: 37
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习了,感谢大家
2010-5-10 15:00
0
雪    币: 189
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
pushad
pobad
2010-5-10 15:26
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼上的太精简了吧 呵呵
2010-5-12 00:09
0
雪    币: 235
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
看来 汇编还没学明白。建议好好看看 罗云彬的书
2010-5-17 11:03
0
雪    币: 54
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
这个不是一句两语能说清楚的
2010-5-19 09:46
0
雪    币: 780
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
有借有还,再借不难
2010-5-19 09:48
0
雪    币: 457
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
这位人兄这样说有点过份吧,不究竟楼主也是好学者来。。人兄你好高吗?
2010-5-19 12:08
0
雪    币: 427
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
楼上几为说的都比较详细了,学习下,我的理解就是函数或子程序调用的前后使堆栈保持不变的过程就是平衡堆栈,如果调用前后堆栈改变,就乱了,没人敢调这个子程序或函数,例如在call的子程序或函数末尾有个ret 8在反回时add esp,8,不知对不对,还望各位纠正
2010-6-2 07:58
0
雪    币: 249
活跃值: (201)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
后进先出。。进多少就要弹多少。
2010-6-2 22:03
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
学习了,汇编确实听头疼 的。
2010-6-13 16:53
0
雪    币: 253
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
我理解所谓的堆栈平衡就是堆栈的还原,保证程序的正常运行
2010-6-14 09:41
0
雪    币: 234
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
菜鸟之路~~~~~~
2010-7-7 05:57
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
我也不懂,虽然学过好几年了。哈哈
2010-7-10 18:18
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
嗯同意你的观点
2010-7-13 17:06
0
雪    币: 285
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习了,谢谢楼下的朋友
2010-7-14 08:45
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册