本文介绍了在C和C ++中调用函数时EAX寄存器的初始化差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当编译为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寄存器的初始化差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 15:37