内存中的返回值存储在内存中?
考虑以下代码:
int add(int a, int b) {
int result = a+b;
return result;
}
void main() {
int sum = add(2, 3);
}
Run Code Online (Sandbox Code Playgroud)
当add(2, 3)被调用时,2个函数参数压入堆栈中,堆栈帧指针被压入堆栈,和一个返回地址被压入堆栈.然后执行流程跳转到add(...),并且该函数中的局部变量也存储在堆栈中.
何时add(...)完成,并执行return指令...返回值存储在哪里?[result]最终怎么样[sum]?
这显然取决于您的硬件架构和编译器.在使用64位x86时gcc,您的代码将编译为:
.file "call.c"
.text
.globl add
.type add, @function
add:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
movl -24(%rbp), %eax
movl -20(%rbp), %edx
leal (%rdx,%rax), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax ; return value placed in EAX
leave
ret
.cfi_endproc
.LFE0:
.size add, .-add
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
movl $3, %esi
movl $2, %edi
call add
movl %eax, -4(%rbp) ; the result of add is stored in sum
leave
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
这里,编译器使用EAX寄存器将结果add传递给调用者.
您可以阅读维基百科中的 x86调用约定.
这个问题没有一般的答案,因为它取决于目标架构.对于任何定义该目标体系结构的目标体系结构,通常都有一个二进制API规范,并且编译器会创建根据此规范工作的代码.大多数架构使用寄存器来传回返回值,因为它是最快的方法.当然,只有当值适合寄存器时才有可能.如果不是,它们可能使用寄存器对(例如,一个寄存器中的低32位,另一个寄存器中的高32位),或者它们将通过堆栈传回.有些架构从不使用寄存器,总是通过堆栈传回.由于调用者必须在调用函数之前创建一个堆栈帧(此规则有例外,但让我们保留默认情况),当函数返回调用者并且调用者知道如何访问时,堆栈帧仍然存在它,它必须知道,因为它还必须在返回时清理堆栈帧.在大多数体系结构中,调用者清除堆栈帧而不是被调用者,因为调用者知道它通过栈传递了多少个参数(例如,对于一个接受可变数量参数的C函数),而被调用者则不知道(不是在编译时)时间,被调用者可能只知道在运行时),因此让调用者清理它更有意义.在此之前,调用者可以回读它希望检索的堆栈帧的任何值.
| 归档时间: |
|
| 查看次数: |
6420 次 |
| 最近记录: |