能力值:
( LV2,RANK:10 )
在线值:
|
-
-
2 楼
谁来看看啊。。。求求了
|
能力值:
( 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。
|
能力值:
( 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。。。
了解不?
|
能力值:
( LV5,RANK:60 )
|
-
-
5 楼
把堆栈比喻成一个公用的书箱,一次只能放一本书,再放的话就是往第一本书上螺了。假如你放了三本书(参数或局部变量),你用完了箱子走人,因为箱子是公用的,你得把箱子还原回原来的样子,你自己或由管理员帮你把箱子还原。。。。你不还原的话,别的人(程序)就不能用书箱了,否则就乱套了。把这个还原比喻成堆栈平衡。。。。。这样楼主理解不知咋样。。。
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
6 楼
LZ说的很搞笑,学过汇编,但是不会堆栈原理,那也就不算是学过汇编拉
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
7 楼
比喻很生动,通俗易懂。
|
能力值:
( LV2,RANK:10 )
在线值:

|
-
-
8 楼
学习了,感谢大家
|
能力值:
( LV2,RANK:10 )
在线值:

|
-
-
9 楼
pushad
pobad
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
楼上的太精简了吧 呵呵
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
11 楼
看来 汇编还没学明白。建议好好看看 罗云彬的书
|
能力值:
( LV2,RANK:10 )
在线值:

|
-
-
12 楼
这个不是一句两语能说清楚的
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
有借有还,再借不难
|
能力值:
( LV2,RANK:10 )
在线值:

|
-
-
14 楼
这位人兄这样说有点过份吧,不究竟楼主也是好学者来。。人兄你好高吗?
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
楼上几为说的都比较详细了,学习下,我的理解就是函数或子程序调用的前后使堆栈保持不变的过程就是平衡堆栈,如果调用前后堆栈改变,就乱了,没人敢调这个子程序或函数,例如在call的子程序或函数末尾有个ret 8在反回时add esp,8,不知对不对,还望各位纠正
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
后进先出。。进多少就要弹多少。
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
17 楼
学习了,汇编确实听头疼 的。
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
我理解所谓的堆栈平衡就是堆栈的还原,保证程序的正常运行
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
19 楼
菜鸟之路~~~~~~
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
20 楼
我也不懂,虽然学过好几年了。哈哈
|
能力值:
( LV2,RANK:10 )
在线值:
|
-
-
21 楼
嗯同意你的观点
|
能力值:
( LV2,RANK:10 )
|
-
-
22 楼
学习了,谢谢楼下的朋友
|
|
|