问题描述
当编译为C程序或C ++程序(对于Linux x86-64)时,小程序的程序集之间存在一个奇怪的差异.
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).
相关代码:
int fun();
int main(){
return fun();
}
将其编译为带有gcc -O2
的C程序会产生:
Compiling it as a C-program (with gcc -O2
) yields:
main:
xorl %eax, %eax
jmp fun
但是将其编译为C ++程序(具有g++ -02
)会产生:
But compiling it as a C++-program (with g++ -02
) yields:
main:
jmp _Z3funv
我感到困惑的是,C版本使用0
(xorl %eax, %eax
)初始化了主函数的返回值.
I find it puzzling, that the C-version initializes the return value of the main-function with 0
(xorl %eax, %eax
).
C语言的哪些功能是这种必要性的原因?
Which feature of the C-language is responsible for this necessity?
的确,对于int fun(void);
来说,它不是eax寄存器的初始化.
It is true that, for int fun(void);
the is no initialization of the eax-register.
如果根本没有fun
的原型,即:
If there is no prototype of fun
at all, i.e.:
int main(){
return fun();
}
然后,C编译器再次将eax寄存器清零.
then the C-compiler zeros the eax-register once again.
推荐答案
在C中,int fun();
可以接受任意数量的参数,因此它甚至可以是varargs函数.但是在C ++中,这意味着它不接受任何参数.
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.
x86-64 sysv abi约定要求寄存器AL
必须包含调用varargs函数时使用的SSE寄存器数.您当然不传递任何参数,因此将其置零.为了方便起见,编译器决定将整个eax
都清零.将您的原型声明为int fun(void);
,xor
将消失.
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.
这篇关于在C和C ++中调用函数时EAX寄存器的初始化差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!