为什么在使用返回值时将0移到堆栈? [英] Why is 0 moved to stack when using return value?
问题描述
我正在尝试反汇编简单的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屋!