gpt4 book ai didi

assembly - 无法理解调用者不需要清理堆栈的 cdecl 调用约定示例

转载 作者:行者123 更新时间:2023-12-02 01:02:40 25 4
gpt4 key购买 nike

我正在阅读 IDA Pro Book .在讨论调用约定的第 86 页上,作者展示了一个 cdecl 调用约定示例,它消除了调用者从堆栈中清除参数的需要。我正在重现下面的代码片段:

; demo_cdecl(1, 2, 3, 4); //programmer calls demo_cdecl
mov [esp+12], 4 ; move parameter z to fourth position on stack
mov [esp+8], 3 ; move parameter y to third position on stack
mov [esp+4], 2 ; move parameter x to second position on stack
mov [esp], 1 ; move parameter w to top of stack
call demo_cdecl ; call the function

作者接着说

in the above example, the compiler has preallocated storage space for the arguments to demo_cdecl at the top of the stack during the function prologue.

我假设在代码片段的顶部有一个 sub esp, 0x10。否则,您只会破坏堆栈。

他后来说,当对 demo_cdecl 的调用完成时,调用者不需要调整堆栈。但可以肯定的是,调用后必须有一个add esp, 0x10

我到底错过了什么?

最佳答案

I am going to assume that there is a sub esp, 0x10 at the top of the code snippet. Otherwise, you would just be corrupting the stack.

参数存储在距堆栈指针正偏移的地址处。请记住,堆栈向下增长。这意味着保存这些参数所需的空间已经分配(可能由调用者的序言代码分配)。这就是为什么每个调用序列都不需要 sub esp, N 的原因。

He later says that the caller doesn't need to adjust the stack when call to demo_cdecl completes. But surely, there has to be a add esp, 0x10 after the call.

在 cdecl 调用约定中,调用者总是必须以某种方式清理堆栈。如果分配是由调用者的序言完成的,它将由尾声(与调用者的局部变量一起)释放。否则,如果被调用者的参数分配在调用者代码中间的某处,那么最简单的清理方法是在调用指令之后使用 add esp, N

cdecl 调用约定的这两种不同实现之间存在折衷。在序言中分配参数意味着必须分配任何被调用者所需的最大空间。它将为每个被调用者重用。然后在调用者的最后,会被清理一次。所以这可能会不必要地浪费堆栈空间,但它可能会提高性能。在另一种技术中,调用者仅在实际将要到达关联的调用点时才为参数分配空间。然后在被调用者返回后立即执行清理。所以没有堆栈空间被浪费。但是必须在调用者的每个调用点执行分配和清理。您还可以想象一个介于这两个极端之间的实现。

关于assembly - 无法理解调用者不需要清理堆栈的 cdecl 调用约定示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49513707/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com