[英]x86 Assembler - Which registers to push?
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个寄存器push
任何地方。
除了推送ebp
(这是必需的)之外,什么决定您是否还要推送edi
, esi
和/或ebx
?
你应该一直推动他们吗? 我找不到为我解决此问题的参考。
推送没有修改的寄存器没有任何意义。 除此之外,您还可以选择保留哪些寄存器。 采用某种约定,以便调用代码和被调用代码都知道它负责什么。
您会看到调用方与被调用方保存寄存器 。 基本思想是,如果要将值存储在保存有被调用方的寄存器中,则需要将其当前值保存在某个位置,以便可以在函数调用结束时将其恢复。
此Wikipedia部分可能会有所帮助: http : //en.wikipedia.org/wiki/X86_calling_conventions#Register_preservation
一般而言,您会保留每个寄存器,但明确告知您不必保留的寄存器除外。 如果使用32位代码进行调用,则不必保留EAX,ECX或EDX,但是必须保留其他所有内容。 在64位代码中,有更多寄存器,因此您也必须保留它们。
在您的示例中,您必须推送EBP,因为您对其进行了更改。 在编写程序集以使用EBP索引参数时,这很常见。 将参数压入堆栈,然后压入返回地址。 因此,要获取参数,您必须访问堆栈。 如果ESP发生了变化,那么记住参数相对于ESP的位置将是一个巨大的痛苦。 因此,我们使用EBP保存了一个“书签”。
但是,如果您不需要这样做,那就不要! 例如,Microsoft使用的__fastcall调用约定将传递ECX中的第一个参数。 我有简单的代码,永远不会将任何内容推入堆栈,而仅使用EAX和ECX。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.