x86上为啥C语言调用一个函数要先把参数压栈,之后才是返回地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了x86上为啥C语言调用一个函数要先把参数压栈,之后才是返回地址相关的知识,希望对你有一定的参考价值。

返回地址先于参数入栈是不可能的== 因为参数入栈是调用函数通过push指令完成的 而返回地址入栈则是在call指令中自动完成的 因此如果一定要先把返回地址压栈 就需要先调用call指令 call指令返回之后 程序就已经在被调函数里面了 调用函数已经失去了控制权 不可能再通过push指令把参数压栈了……

此外额我觉得这涉及到x86的一个规范吧…… 函数调用时参数压栈和被调函数返回后参数出栈都是由调用函数来完成 被调函数不参与(否则如果两者同时参与很容易把栈搞混乱) 如果参数在返回地址上方 被调函数返回的时候 为了取得返回地址 被调函数必须先把参数出栈 这就与之前说的规范冲突了
参考技术A 这个没有为什么。除了硬性的逻辑需求,就是约定。
逻辑需求就是你必须在call指令之前完成参数传递,也就是你所说的压栈,这是__cdecl调用约定。其实还有fastcall调用约定,这个在86_32环境下两个及以下参数是不需要入栈的,因为它使用ecx和edx寄存器传递。入栈顺序方面,就是约定了,这个并不是刚需,但为了保证可移植性,由人来定义的一种方法形式。
关于你说的返回地址,这个并不是主动的push rip+n什么的(而且不支持这个指令)。而是call指令的效果。

c语言中函数定义和声明有啥区别

从C语言编译器的角度来看,函数声明只是一种协议,它告诉了调用者在调用这个函数之前需要给他什么参数,一般参数是通过寄存器或者压栈的方式传给被调用函数的,具体这些参数如何使用以及返回什么值到相应的寄存器里返回给调用者则是定义所描述的。 参考技术A C语言中,无论是常量,变量,只有先定义才能使用。函数声明,为了减少函数的混淆,所以要有个函数名,即声明。函数定义是系统要求的,不定义就错误,而函数声明实际上不定义也行,但为了方便和减少错误,人为规定要声明。 参考技术B 不是一个意思追问

怎么满意

我也知道不是一个意思

参考技术C 声明 是告知下面的代码:有这个函数可以用
定义 是对这个函数的具体实现

以上是关于x86上为啥C语言调用一个函数要先把参数压栈,之后才是返回地址的主要内容,如果未能解决你的问题,请参考以下文章

x64 stack walking调用约定函数参数识别

c语言函数调用规则

为啥函数参数在 x86 上占用至少 4 个字节的堆栈?

ARM中C和汇编的相互调用(5个数求和字符串拷贝)

汇编对比函数参数进堆栈顺序

深度解刨C语言可变参数列表