Where in memory are return values stored in memory?
Consider the follwing code:
int add(int a, int b) {
int result = a+b;
return result;
}
void main() {
int sum = add(2, 3);
}
When add(2, 3)
is called, the 2 function parameters are pushed on the stack, the stack frame pointer is pushed on the stack, and a return address is pushed on the stack. The flow of execution then jumps to add(...)
, and local variables within that function are also stored on the stack.
When add(...)
is complete, and executes the return
instruction... where does the return value get stored? How does [result]
end up in [sum]
?
The short answer: It will be stored in the text or code section of the binary only once irrespective of the number of instances of the class created.
Variables are usually stored in RAM. This is either on the heap (e.g. all global variables will usually go there) or on the stack (all variables declared within a method/function usually go there). Stack and Heap are both RAM, just different locations.
The actual method is stored in the Method Area. Parameters, return values, local variables,... are stored within a Method Frame, which in return resides on the Stack.
Global variables are stored in the data section.
This clearly depends on your hardware architecture and your compiler. On 64-bit x86 using gcc
, your code compiles to:
.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
Here, the compiler is using the EAX register to communicate the result of add
to the caller.
You can read up on x86 calling conventions in Wikipedia.
There is no general answer to this question, because it depends on the target architecture. There is usually a Binary API Spec for any target architecture that defines that and the compiler creates codes that works according to this spec. Most architectures use a register for passing the return value back, simply because it is the fastest way to do it. That is only possible if the value will fit into a register, of course. If not, they might use a register pair (e.g. lower 32 bit in one register, upper 32 bit in another one), or they will pass it back via the stack. Some architectures never use registers and always pass back via the stack. Since the caller must create a stack frame before calling the function (there are exceptions to this rule, but lets stay with the default case here), the stack frame is still there when the function returns to the caller and the caller knows how to access it, it has to know that, since it must also clean the stack frame on return. On most architectures the caller cleans the stack frame, not the callee, since the caller knows how many arguments it has passed via stack (e.g. for a C function that takes a variable number of arguments), while the callee does not (not at compile time, the callee may only know that at runtime), thus it makes more sense to let the caller clean it. And before doing that, the caller can read back any value of the stack frame it wishes to retrieve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With