当他们说“参数以相反的顺序推动”时,这是什么意思?

Joh*_*ohn 3 x86 assembly calling-convention

cdecl调用约定中,它指出:

Arguments are pushed in the reverse order (right to left)
Run Code Online (Sandbox Code Playgroud)

我的问题是:逆序相对于什么非逆序?与功能文档相关吗?例如,如果我有以下函数文档:

void __cdecl foo (int arg1, int arg2, int arg3)
Run Code Online (Sandbox Code Playgroud)

那么我是否应该只查看函数文档中参数的顺序并反转推入堆栈的增强?

Ale*_*own 5

根据 asm 指令顺序和执行顺序,第一个函数参数被推到最后。然而,由于堆栈向下增长,第一个参数具有最低的地址。

此方案意味着第一个参数(和第二个等)始终可以作为当前堆栈指针的常量偏移量进行访问 - 它位于返回地址之后。

是的,您应该完全按照问题末尾的建议进行操作,尽管常见的技术是在函数头部的堆栈上保留空间,该空间足够大以支持所有堆栈变量以及任何所需的函数调用参数(但不是返回地址)并简单地进行堆栈相对存储来设置参数。

请注意,在许多 ISA ABI 中,前几个参数在寄存器中传递,而不是在堆栈上传递,但无论如何都会保留堆栈空间,以便跨嵌套函数调用进行可能的存储。


Ira*_*ter 5

如果您的函数调用是:

  foo( arg1, arg2, ... argN )
Run Code Online (Sandbox Code Playgroud)

那么“参数顺序”将从左到右(arg1 到 argN)。函数调用代码将是:

  push  arg1
  push  arg2
  ...
  push  argN
  call  foo
Run Code Online (Sandbox Code Playgroud)

“逆序(从右到左)”将是 argN 到 arg1:

  push  argN
  ...
  push  arg1
  call  foo
Run Code Online (Sandbox Code Playgroud)

当然,args 可能不是单个 DWORDS,因此推送操作可能不是单个指令。编译器也可能非常聪明,为参数预先分配堆栈空间,然后通过各种 MOV 指令将参数填充到分配的堆栈空间中的偏移量,可能不按任何特定顺序。因此,根据“好像”推动已经完成的想法来解释“推动论点”。