为什么在使用返回值时将0移到堆栈? [英] Why is 0 moved to stack when using return value?

查看:73
本文介绍了为什么在使用返回值时将0移到堆栈?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试反汇编简单的C程序(与-O0编译)的clang二进制文件,并且对要生成的某些指令感到困惑.

I'm experimenting disassembling clang binaries of simple C programs (compiled with -O0), and I'm confused about a certain instruction that gets generated.

这里有两个带有标准参数的空main函数,其中一个返回值,而另一个不返回值:

Here are two empty main functions with standard arguments, one of which returns value and other does not:

// return_void.c
void main(int argc, char** argv)
{
}

// return_0.c
int main(int argc, char** argv)
{
    return 0;
}

现在,当我分解它们的程序集时,它们看上去有很大的不同,但是我不明白其中一行:

Now, when I disassemble their assemblies, they look reasonably different, but there's one line that I don't understand:

return_void.bin:
(__TEXT,__text) section
_main:
0000000000000000    pushq   %rbp
0000000000000001    movq    %rsp, %rbp
0000000000000004    movl    %edi, -0x4(%rbp)
0000000000000007    movq    %rsi, -0x10(%rbp)
000000000000000b    popq    %rbp
000000000000000c    retq

return_0.bin:
(__TEXT,__text) section
_main:
0000000100000f80    pushq   %rbp                
0000000100000f81    movq    %rsp, %rbp          
0000000100000f84    xorl    %eax, %eax          # We return with EAX, so we clean it to return 0
0000000100000f86    movl    $0x0, -0x4(%rbp)    # What does this mean?
0000000100000f8d    movl    %edi, -0x8(%rbp)
0000000100000f90    movq    %rsi, -0x10(%rbp)
0000000100000f94    popq    %rbp
0000000100000f95    retq

仅当我使用该函数不无效时才会生成它,因此我认为这可能是返回0的另一种方式,但是当我更改返回的常量时,此行完全没有改变:

It only gets generated when I use the function is not void, so I thought that it might be another way to return 0, but when I changed the returned constant, this line didn't change at all:

// return_1.c
int main(int argc, char** argv)
{
    return 1;
}

empty_return_1.bin:
(__TEXT,__text) section
_main:
0000000100000f80    pushq   %rbp
0000000100000f81    movq    %rsp, %rbp
0000000100000f84    movl    $0x1, %eax           # Return value modified
0000000100000f89    movl    $0x0, -0x4(%rbp)    # This value is not modified
0000000100000f90    movl    %edi, -0x8(%rbp)
0000000100000f93    movq    %rsi, -0x10(%rbp)
0000000100000f97    popq    %rbp
0000000100000f98    retq

为什么会生成此行,它的目的是什么?

Why is this line getting generated and what is it's purpose?

推荐答案

以下代码揭示了该区域的目的

The purpose of that area is revealed by the following code

int main(int argc, char** argv)
{
    if (rand() == 42)
      return 1;

    printf("Helo World!\n");
    return 0;
}

一开始就是

movl    $0, -4(%rbp)

然后,早期收益如下所示

then the early return looks as follows

callq   rand
cmpl    $42, %eax
jne .LBB0_2
movl    $1, -4(%rbp)
jmp .LBB0_3

然后在最后

.LBB0_3:
movl    -4(%rbp), %eax
addq    $32, %rsp
popq    %rbp
retq

因此,确实保留了该区域来存储函数返回值.似乎并不是非常必要,它也没有在优化的代码中使用,但是在-O0模式下它才是它的工作方式.

So, this area is indeed reserved to store the function return value. It doesn't appear to be terribly necessary and it is not used in optimized code, but in -O0 mode that's the way it works.

这篇关于为什么在使用返回值时将0移到堆栈?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆