x86汇编程序 - 哪个寄存器要推送?

时间:2014-06-13 03:51:49

标签: assembly x86

x86汇编程序通常以以下序言开头:

push        ebp                ; Save ebp
mov         ebp, esp           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

我已经看到函数push在1到4个寄存器中。

除了推送所需的ebp之外,还有什么决定您是否推送ediesi和/或ebx

你应该总是推他们吗?我无法找到解决此问题的参考资料。

3 个答案:

答案 0 :(得分:3)

推送你不会修改的寄存器是没有意义的。除此之外,您可以选择保留哪些寄存器。采用一些约定,以便调用代码和被调用代码都知道它负责的内容。

答案 1 :(得分:1)

您正在查看caller vs callee save registers。基本思想是,如果要将值存储在被调用者保存的寄存器中,则需要将其当前值保存在某处,以便在函数调用结束时将其恢复。

答案 2 :(得分:1)

此Wikipedia部分可能有所帮助: http://en.wikipedia.org/wiki/X86_calling_conventions#Register_preservation

一般来说,除了明确告知您不必保留的寄存器外,您保留每个寄存器。如果使用32位代码并且被调用,则不必保留EAX,ECX或EDX,但是您必须保留其他所有内容。在64位代码中有更多寄存器,因此您也必须保留它们。

在您的示例中,您必须推送EBP,因为您更改了它。在编写程序集以使用EBP索引参数时,这很常见。参数被压入堆栈,然后返回地址。因此,要获得参数,您必须访问堆栈。如果ESP正在改变它,那么记住你的参数相对于ESP的位置会非常痛苦。所以我们保存一个&#34;书签&#34;使用EBP。

但如果你不需要这样做,那就不要了!例如,Microsoft使用的__fastcall调用约定将传递ECX中的第一个参数。我有简单的代码,从不将任何东西推送到堆栈,只使用EAX和ECX。