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:
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.