【发布时间】:2020-03-03 14:15:46
【问题描述】:
假设这段代码:
int add(int a, int b){
int c = a+b;
return c;
}
int main(){
printf("%d\n", add(3,4));
}
以下通常是在汇编中的实现方式:
- push 4 to stack
- push 3 to stack
- push return address which is the address of the next instruction, `print()` to stack
- call add
- do addition and push c on the stack
- pop c from stack ??
- return to main
那么返回值会发生什么,它不能在add 帧上,因为它会在最后被清除。它会被放入main 的堆栈中吗?
让我们假设这些值被推送到大头钉而不是寄存器。
【问题讨论】:
-
返回值通常存放在寄存器中。但当然取决于 ABI..
-
对于此类类型,传入一个隐藏指针。有关详细信息,请参阅 ABI 文档和/或检查编译器生成的汇编代码。
-
如果你正在设计一个函数如何被调用以及如何返回值的协议,并且你不使用寄存器来返回值,那么逻辑选择包括在调用者的堆栈帧中指定一个位置,其中返回值将被写入或让调用者传递将写入返回值的地址。例如,如果期望返回一个四字节的
int,调用者可能会在堆栈上为其腾出空间,然后执行调用指令。被调用的例程会将其返回值写入该保留空间,高于堆栈指针。 -
在常见的 ABI 中,当函数返回类型是大对象时,可能是几百字节的结构,调用函数会传递一个指向空间的指针。这个指针没有出现在源代码的显式参数中;它以对常规源代码“隐藏”的方式传递。被调用函数使用该指针写入结果。
-
哪个汇编程序?请添加相关的系统标签,例如 x86。请参阅stackoverflow.com/tags/assembly/info 了解标签用法。在混合 C 和汇编程序时,ABI 调用约定也很重要,因此您还必须指定编译器和操作系统(如果有)。
标签: c assembly calling-convention