如何删除函数参数

时间:2018-02-15 13:38:01

标签: assembly x86 32-bit callstack calling-convention

当我查看一些汇编代码时,我注意到函数具有以下结构:

My_Function:
  ; Function Prologue
  push EBP
  mov EBP, ESP
  sub ESP, 0x28 ;40 Bytes local variable allocation

  ; Some code here

  ; Function epilogue
  leave
  ret

因此,如果我们假设My_Function采用1个字节的参数,那么从堆栈帧中删除的位置。据我所知,函数的堆栈包含以下结构(从较低地址到较高地址):

LOW ADDRESS >  | Local Variables |
               |  Old EBP Value  |
               |  Return Address |
HIGH ADDRESS > |    Arguments    |
               -------------------
               | Previous Stack  |
               |     Frame       |

哪个汇编命令“删除”函数的参数?

据我所知leaveret(所谓的函数结尾),修改值中的$esp$ebp寄存器以指向前一个堆栈帧。但我不确定当函数结尾执行时$esp是否恰好指向前一个堆栈帧的局部变量“start”,如您所见:

在执行功能结尾之前:

LOW ADDRESS >  | Local Variables | < ESP
               |  Old EBP Value  | < EBP
               |  Return Address |
               |    Arguments    |
               -------------------
               | Local Variables |
               |  Old EBP Value  |
               |  Return Address |
HIGH ADDRESS > |    Arguments    |

执行功能结尾后,有两个选项:

1)选项1:

LOW ADDRESS >  | Local Variables | < ESP
               |  Old EBP Value  | < EBP
               |  Return Address |

高地址&gt; |参数|

2)选项2:

               |    Arguments    | < ESP
               -------------------
LOW ADDRESS >  | Local Variables | 
               |  Old EBP Value  | < EBP
               |  Return Address |

高地址&gt; |参数|

哪个选项是正确的,哪个命令的函数负责使esp寄存器指向正确的地址?

1 个答案:

答案 0 :(得分:-3)

函数的参数并不总是在栈上传递。 x86和x86-64的大多数ABI约定规定在寄存器中传递第一个参数,并且只有当它们中有太多传递时才会在堆栈中传递其余的参数。

除了x86-64 ABI:https://www.uclibc.org/docs/psABI-x86_64.pdf关于调用约定:

calling conventions

这样做的好处是内存访问比寄存器访问慢,所以只要有可能就必须避免它们。返回值也是如此 - 如果可能,它会在寄存器中返回。

如果堆栈上确实存在参数,以及本地自动变量,它们可以被解除分配&#34;只需恢复以前保存的RSP值即可。那不是leave那么做的吗?