初学者学习程序集在函数调用后保留esp

时间:2010-03-12 00:28:03

标签: assembly stack

我是初学者学习一些程序集,在函数调用之前保留ESP寄存器是否重要,如果你通过加或减来做?很难解释,请考虑以下

mov esi, esp
sub esp, 12 // on 32bit OS this would mean that there are 3 arguments to the function
// push, function call etc
cmp esi, esp // should be the same

mov esi, esp
// push, function call etc
add esp, 12
cmp esi, esp // should be the same

另外如果由于某种原因cmp失败,可以安全地使用mov esp,esi来重新对齐堆栈吗?

由于

编辑:为了像sprintf这样的调用,我怎么还需要这样做,但MessageBox似乎为我修复了ESP?我怎么知道什么功能需要这个和什么不需要?

2 个答案:

答案 0 :(得分:4)

是的,重要的是在使用esp时使符号正确(在这种情况下,减去,但有时你需要在引用已经在堆栈上的东西时添加,比如函数内的参数)。原因是堆栈在内存中向下向下。这与我们通常认为的堆栈(你把东西置于顶部并从顶部移除它们)相反,在内存中随着stac k的增长,这将是越来越高的地址。但是X86(以及大多数其他)处理器上的调用堆栈实际上是向下增长的。这就像在堆栈底部添加板块,并从底部移除它们......在内存中,随着更多内容添加到堆栈中,地址越来越低。

是的,只要您确定要将其设置为堆栈内的有效位置,并且只要您确定不需要任何通过这样做你丢失的信息。在这种情况下,你正在将esp保存在esi中,正是出于这个原因...你可以从esi中恢复esp所以无论之前的函数调用是什么,你都知道esp就在你想要的地方。

sprint和MessageBox之间的区别在于“调用约定”。这告诉更高级语言(C)如何在调用它们时处理堆栈帧和寄存器。 sprintf是cdecl,而MessageBox是stdcall

答案 1 :(得分:1)

  

另外我怎么需要为sprintf这样的调用做这个,但是MessageBox似乎为我修复了ESP?

这是因为MessageBox()函数在返回时清除堆栈中的参数。它可以这样做,因为参数的数量是固定的。

但是,使用可变数量的参数调用sprintf()函数。该函数不知道调用者可能已经向堆栈推送了多少,因此调用者有责任在调用返回时清除它们。