There is a curious difference between assemblies of a small program, when compiled as a C-program or as a C++-program (for Linux x86-64).
The code in question:
int fun(); int main(){ return fun(); }
Compiling it as a C-program (with gcc -O2
) yields:
main: xorl %eax, %eax jmp fun
But compiling it as a C++-program (with g++ -02
) yields:
main: jmp _Z3funv
I find it puzzling, that the C-version initializes the return value of the main-function with 0
(xorl %eax, %eax
).
Which feature of the C-language is responsible for this necessity?
Edit: It is true that, for int fun(void);
the is no initialization of the eax-register.
If there is no prototype of fun
at all, i.e.:
int main(){ return fun(); }
then the C-compiler zeros the eax-register once again.
I know when add integers in assembly, it stores result in the destination. and when we multiply it stores in eax. so if I call the function multiply( 3 , 8 ), the value of eax register after that line should be 120.
eax (or rax) is the return value register. edi (or rdi) is the first function argument. esi (or rsi) is the second function argument.
EAX: The accumulator. This register typically stores return values from functions.
In C int fun();
can take any number of arguments, so it may even be a varargs function. In C++ however it means it takes no arguments.
The x86-64 sysv abi convention demands that the register AL
must contain the number of SSE registers used when invoking a varargs function. You of course pass no argument, so it is zeroed. For convenience the compiler decided to zero the whole eax
. Declare your prototype as int fun(void);
and the xor
shall disappear.
Apparently it is a defensive measure, designed for situations when prototype-less fun
function happens to actually be a variadic function, as explained by @Jester's answer.
Note though that this explanation does not hold any water from the point of view of standard C language.
Since the beginning of standardized times (C89/90) C language explicitly required all variadic functions to be declared with prototype before the point of the call. Calling a non-prototyped variadic function triggers undefined behavior in standard C. So, formally, compilers do not have to accommodate the possibility of fun
being variadic - if it is, the behavior would be undefined anyway.
Moreover, as @John Bollinger noted in the comments, according to the C standard, a non-prototype int fun()
declaration actually precludes further variadic prototype declarations of fun
. I.e. a variadic function cannot be legally pre-declared as a ()
function. That would be another reason why the above non-prototype declaration is sufficient for the compiler to assume that fun
cannot possibly be variadic.
This could actually be a legacy feature, designed to support pre-standard C code, where pre-declaring variadic functions with prototype was not required.
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