我正在尝试反汇编简单c程序的二进制文件(用clang
编译),我对生成的某条指令感到困惑。
下面是两个带标准参数的空-O0
函数,其中一个返回值,另一个不返回值:
// return_void.c
void main(int argc, char** argv)
{
}
// return_0.c
int main(int argc, char** argv)
{
return 0;
}
现在,当我拆卸它们的组件时,它们看起来完全不同,但有一行我不明白:
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
它只在我使用函数is not void时生成,所以我认为它可能是返回0的另一种方式,但是当我更改返回的常量时,这一行根本没有改变:
// 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
为什么会产生这条线,它的目的是什么?
最佳答案
以下代码揭示了该区域的用途
int main(int argc, char** argv)
{
if (rand() == 42)
return 1;
printf("Helo World!\n");
return 0;
}
一开始是的
movl $0, -4(%rbp)
那么早期的回报如下
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
模式下工作。