X86 STDCALL vs CDECL:`ret`vs`sub esp`与调用约定有关吗?

X86 STDCALL vs CDECL:`ret`vs`sub esp`与调用约定有关吗?,x86,x86-64,calling-convention,stdcall,cdecl,X86,X86 64,Calling Convention,Stdcall,Cdecl,在中,第325页,在8.2.4 32位调用约定下 C调用约定。。。C调用约定以一种简单的方式解决了清理运行时堆栈的问题:当程序调用一个子例程时,它会在调用指令之后使用一条语句向堆栈指针(ESP)添加一个等于子例程参数组合大小的值。下面是一个示例,其中在执行调用指令之前,将两个参数(5和6)推送到堆栈上 Example1 PROC push 6 push 5 call AddTwo add esp, 8 ret Example1 ENDP 因此,在子程序返回后,用C/C++编

在中,第325页,在8.2.4 32位调用约定下

C调用约定。。。C调用约定以一种简单的方式解决了清理运行时堆栈的问题:当程序调用一个子例程时,它会在
调用
指令之后使用一条语句向堆栈指针(
ESP
)添加一个等于子例程参数组合大小的值。下面是一个示例,其中在执行
调用
指令之前,将两个参数(5和6)推送到堆栈上

Example1 PROC
  push 6
  push 5
  call AddTwo
  add esp, 8
  ret
Example1 ENDP
因此,在子程序返回后,用C/C++编写的程序总是从调用程序的堆栈中删除参数

它接着说

STDCALL调用约定从堆栈中删除参数的另一种常见方法是使用名为
STDCALL
的约定。在下面的
AddTwo
过程中,我们向
RET
指令提供了一个整数参数,返回调用过程后,该参数又向ESP添加8。整数必须等于过程参数消耗的堆栈空间字节数:

AddTwo PROC
  push ebp
  mov ebp,esp
  mov eax,[ebp+12]
  add eax,[ebp+8]
  pop ebp
  ret 8
AddTwo ENDP
应该指出的是,与C一样,
STDCALL
,将参数按相反顺序推送到堆栈上。通过在
RET
指令中使用prameter,
STDCALL
减少了为子程序调用生成的代码量(一条指令),并确保调用程序永远不会忘记清理堆栈。另一方面,C调用约定允许子例程声明数量可变的参数。调用方可以决定要传递多少个参数


这段代码有点混乱,因为一个显示调用,另一个显示函数。为了简单起见,它们应该同时显示两者。为了调用约定,对堆栈的修改分为两个阶段

  • 在为调用做准备时,将参数和推送到堆栈上
  • 在被调用函数中,在堆栈上分配局部变量
这两种约定之间的区别不是“一条指令”,也不是每一个指令都与
RET
有关,而是在哪里进行清理。参数放置在调用之前的堆栈上,因此它们应该

  • 当函数清除自身(局部变量)时,将被清除
  • 在函数返回后将被清除
  • 作为导入说明,第一个选项有一些优点,即声明一个参数数量可变的函数

    整个
    RET
    部分似乎让人分心,因为x86没有特定的调用约定。事实上,Windows 10在ARM上运行,而且在第一个示例中,编译器可以编写

    ret 8
    
    而不是


    这也会产生同样的效果。事实上,它会保存一条指令

    ret8
    addesp,8
    ret
    是不同的
    ret 8
    首先从堆栈中弹出返回地址,然后通过向其添加立即值来调整ESP。此外,stdcall约定强制您在每次调用后“释放”本地堆栈空间,而使用C约定,您可以保持
    ESP
    修改,并在原始函数返回后将该局部区域用于其他目的,例如为下一次调用准备参数或只是在那里存储一些局部区域,或者在使用单个
    子esp进行多次调用后释放所有参数,
    ,等等。。。和往常一样,在汇编中,你给指令组的上下文/解释/逻辑越多,你就越有可能错过一些微妙的细节或优化的可能性,你不会想得太多吧。A:显然是的?调用约定确实定义了子例程应该如何返回(即,使用什么机制给出子例程的返回点)以及CPU应该处于什么状态,因此子例程末尾的清理代码与调用约定有关(虽然您也可以用另一种方式实现它,但前提是您找到了更适合您的情况的方法,比如跳转到其他子例程的尾部而不是调用它,等等)=因此,我不确定问题是什么,答案中到底需要什么?问题是什么?STDCALL和CDECL在概念上的主要区别是CDECL允许var args,STDCALL按照调用方的预期处理参数,而CDECL按照调用方的使用来处理参数(是的,早期的C允许这样做)。
     add esp,8
     ret