小妹刚学汇编,问个很菜的问题。

时间:2022-01-28 01:01:17
以下摘自一篇文章:  

push    ebp             ;ebp入栈  
mov     ebp, esp        ;因为esp是堆栈指针,无法暂借使用,所以得用ebp来存取堆栈  
sub     esp, 4*5        ;下面的wsprintf一共使用了5个参数,每个参数占用4个字节,所以要入栈4*5个字节  
push    1111  
push    2222  
push    3333  
push    offset szFormat  
push    offset szOut  
call    wsprintf        ;调用wsprintf  
add     esp, 4*5        ;堆栈使用完毕,“还”回4*5个字节给系统  
...  
mov     esp, ebp        ;恢复esp的值  
pop     ebp             ;ebp出栈 

我不明白:
对esp先是
sub esp,4*5,
最后再
add  asp,4*5
这样esp的值不是已恢复了吗,为什么前面还要  
 mov     ebp,
然后后面又要
esp mov     esp, ebp
 ?

6 个解决方案

#1


主要是为了防止子程中的误操作导致堆栈失衡吧. sub esp, 4*5 和 add esp, 4*5 仅仅是就调用 wsprintf 函数来的. 其他可能还有涉及到堆栈的操作的. 

另外, 趁着还没有人回复, 自己把另外的两个帖子给删了吧, 不会有不良影响的, 是网页响应慢多点了几下回复的?

#2


这个是一个历史问题。

注意,由于这段代码是由编译器生成的。所以,不存在什么“误操作导致堆栈失衡”的问题。我刚才临时查了一下,在一篇讲Eudora 4.3.0.46的修改的文章里提到,Eudora里有这样的代码:MOV AL,[ESP+08]。这样,文章里的“无法暂借使用”也说不通的。

原因和Borland的Turbo Pascal有关

熟悉Turbo Pascal的人都知道,在编译以后的Pascal程序里,子程序的开头都有下面的语句

push bp
mov bp,sp

实际上,这个就是pascal的标准调用框架。因为在pascal的过程和函数里,对堆栈参数的访问是通过bp进行的。这个是borland的约定。pascal约定的影响相当广泛,从这段程序就可以看出来。

#3


这样用ebp来寻址堆栈中的参数比较方便,因为进栈出栈操作会改变esp的值,如果用esp来寻值,原来esp+n的参数现在就会改变,可能是esp+n+2,或者esp+n-2

#4


基本是这样的

特别是在里面有分支的时候,用esp有时就很讨厌。

#5



先保存调用者的栈底地址,然后用调用者的栈顶作为自己的栈底,从此开始自己栈的生长(有些书称此行为为打开堆栈)。

sub     esp, 4*5
是为了开辟一个可以存放5个双字的空间以便存储其自己的push和pop

那么后面的3个操作跟上面的3个是成对的,意思就比较明白了

以上是我的理解。

#6


该说的上面的帅哥们都说了~~我也不用多说了~~

#1


主要是为了防止子程中的误操作导致堆栈失衡吧. sub esp, 4*5 和 add esp, 4*5 仅仅是就调用 wsprintf 函数来的. 其他可能还有涉及到堆栈的操作的. 

另外, 趁着还没有人回复, 自己把另外的两个帖子给删了吧, 不会有不良影响的, 是网页响应慢多点了几下回复的?

#2


这个是一个历史问题。

注意,由于这段代码是由编译器生成的。所以,不存在什么“误操作导致堆栈失衡”的问题。我刚才临时查了一下,在一篇讲Eudora 4.3.0.46的修改的文章里提到,Eudora里有这样的代码:MOV AL,[ESP+08]。这样,文章里的“无法暂借使用”也说不通的。

原因和Borland的Turbo Pascal有关

熟悉Turbo Pascal的人都知道,在编译以后的Pascal程序里,子程序的开头都有下面的语句

push bp
mov bp,sp

实际上,这个就是pascal的标准调用框架。因为在pascal的过程和函数里,对堆栈参数的访问是通过bp进行的。这个是borland的约定。pascal约定的影响相当广泛,从这段程序就可以看出来。

#3


这样用ebp来寻址堆栈中的参数比较方便,因为进栈出栈操作会改变esp的值,如果用esp来寻值,原来esp+n的参数现在就会改变,可能是esp+n+2,或者esp+n-2

#4


基本是这样的

特别是在里面有分支的时候,用esp有时就很讨厌。

#5



先保存调用者的栈底地址,然后用调用者的栈顶作为自己的栈底,从此开始自己栈的生长(有些书称此行为为打开堆栈)。

sub     esp, 4*5
是为了开辟一个可以存放5个双字的空间以便存储其自己的push和pop

那么后面的3个操作跟上面的3个是成对的,意思就比较明白了

以上是我的理解。

#6


该说的上面的帅哥们都说了~~我也不用多说了~~