Does the return value always go into eax register after a method call?
Solution 1
It's all specific to calling convention.
For most calling conventions floating point numbers are returned either on FPU-stack or in XMM registers.
Call to the function returning a structure
some_struct foo(int arg1, int arg2);
some_struct s = foo(1, 2);
will be compiled into some equivalent of:
some_struct* foo(some_struct* ret_val, int arg1, int arg2);
some_struct s; // constructor isn't called
foo(&s, 1, 2); // constructor will be called in foo
Edit: (add info)
just to clarify: this works for all structs and classes even when sizeof(some_struct) <= 4
. So if you define small useful class like ip4_type
with the only unsigned
field and some constructors/convertors to/trom unsigned
, in_addr
, char*
it will lack efficiency compared to use of raw unigned
value.
Solution 2
If the function get inlined, the result is not saved in eax, also if results are passed by reference/pointer, that register won't be used.
look at what happens to a function that return doubles (on a 32 bit machine)
double func(){
volatile double val=5.0;
return val;
}
int main(){
double val = func();
return 0;
}
doubles are not in eax.
func():
pushq %rbp
movq %rsp, %rbp
movabsq $4617315517961601024, %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
subq $24, %rsp
call func()
movsd %xmm0, -24(%rbp)
movq -24(%rbp), %rax
movq %rax, -8(%rbp)
movl $0, %eax
leave
ret
Solution 3
It really depends on the calling convention used, but typically EAX
is used for 32-bit and smaller integral data types, floating point values tend to use FPU or MMX registers, and 64-bit integral types tend to use a combination of EAX
and EDX
instead. Then there is the issue of complex class/struct types, in which case the compiler may decide to optimize away the return value and use an extra output parameter on the call stack to pass the returned object by reference to the caller.
Solution 4
You are asking questions about the ABI (Application Binary Interface). This varies depending on the operating system. You should look it up. You can find some good info and links to other documents at http://en.wikipedia.org/wiki/X86_calling_conventions
To answer your question, yes, as far as I know, all of the popular operating systems use the A register to return the result.
Related videos on Youtube
Bartlomiej Lewandowski
Currently working as a developer on expanding the JIRA Connect ecosystem.
Updated on January 28, 2020Comments
-
Bartlomiej Lewandowski over 4 years
I have written a hooking library, that examines a PE executables dll import table, to create a library that enables changing of parameters and return values. I have a few questions on how the return value is passed from a function.
I have learned that the return value of a function is saved in the accumulator register. Is this always the case? If not, how does the compiler know where to look for the function result?
What about the return type size? An integer will easily fit, but what about a bigger structure? Does the caller reserve stack space so the method it calls could write the result onto stack?
-
Kerrek SB over 10 yearsWhy not compile a couple of examples and see for yourself?
-
Thomas Matthews over 10 yearsNo, the ARM7 processor doesn't have an EAX register. Neither do other processors.
-
harold over 10 yearsObviously if the return type does not fit in
eax
, it can't be in it. Refer to the documentation of whatever calling convention you're using. -
Ira Baxter over 10 yearsBottom line: it depends completely on the compiler and the conventions it uses. (I build a compiler that passes double float args in EAX/EDX [sometimes]).
-
James over 10 yearsnot if your methods return void and pass values through references or pointers.
-
-
Ira Baxter over 10 yearsThe MS Windows32 coventions do not pass arguments in EAX: Standard CDECL calls push arguments in the stack; fastcall's first argument is in ECX. Oh, you mean popular operating systems, unlike Windows :-}
-
qwm over 10 yearsJust for the sake of completeness: Borland's compilers on Windows use eax as a first argument with __fastcall ;)
-
Marco van de Voort over 10 yearsaddition: 64-bit values afaik are returned in edx:eax on x86
-
qwm over 10 years@MarcovandeVoort yes, you're right, though it is true for integer values only.
-
Marco van de Voort over 10 yearsWell, for integer values other than COMP :-)
-
phuclv almost 9 yearsyour code is 64 bits, not 32. There's no rax, rbp, rsp... on 32-bit x86
-
Harsh over 3 yearsCan someone help me figure out why is this happening:
movq %rax, -8(%rbp) movq -8(%rbp), %rax movq %rax, -24(%rbp) movsd -24(%rbp), %xmm0
in thefunc()
call (line 5 to line 8)? -
Matt Kleinsmith about 3 yearsI like this answer because it names the context, giving a searchable term in case someone wants to orient themselves further.