Does the return value always go into eax register after a method call?

22,534

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.

Share:
22,534

Related videos on Youtube

Bartlomiej Lewandowski
Author by

Bartlomiej Lewandowski

Currently working as a developer on expanding the JIRA Connect ecosystem.

Updated on January 28, 2020

Comments

  • Bartlomiej Lewandowski
    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
      Kerrek SB over 10 years
      Why not compile a couple of examples and see for yourself?
    • Thomas Matthews
      Thomas Matthews over 10 years
      No, the ARM7 processor doesn't have an EAX register. Neither do other processors.
    • harold
      harold over 10 years
      Obviously 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
      Ira Baxter over 10 years
      Bottom 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
      James over 10 years
      not if your methods return void and pass values through references or pointers.
  • Ira Baxter
    Ira Baxter over 10 years
    The 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
    qwm over 10 years
    Just for the sake of completeness: Borland's compilers on Windows use eax as a first argument with __fastcall ;)
  • Marco van de Voort
    Marco van de Voort over 10 years
    addition: 64-bit values afaik are returned in edx:eax on x86
  • qwm
    qwm over 10 years
    @MarcovandeVoort yes, you're right, though it is true for integer values only.
  • Marco van de Voort
    Marco van de Voort over 10 years
    Well, for integer values other than COMP :-)
  • phuclv
    phuclv almost 9 years
    your code is 64 bits, not 32. There's no rax, rbp, rsp... on 32-bit x86
  • Harsh
    Harsh over 3 years
    Can 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 the func() call (line 5 to line 8)?
  • Matt Kleinsmith
    Matt Kleinsmith about 3 years
    I like this answer because it names the context, giving a searchable term in case someone wants to orient themselves further.