Why does 0 move onto the stack when using the return value?

I am experimenting with disassembling binary files of clangsimple C programs (compiled with -O0), and I am confused by some of the command that is being generated.

Here are two empty mainfunctions with standard arguments, one of which does not return a value, and the other:

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

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

Now, when I parse their assemblies, they look different, but there is one line that I do not 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

It is only generated when I use this function, it is not void, so I thought it might be a different way to return 0, but when I changed the returned constant, this line did not 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 created and what is its purpose?

+4
4

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 , .

+3

clang ( edi rsi) - 0 . , clang SSA- :

int main(int argc, char** argv)
{
    int a;

    a = 0;
    return a;
}

, . clang , , eax , -4(%rbp). , . , .

+2
movl   $0x0,-0x4(%rbp)

0 %rbp - 4. , clang main.

clang:

. ; return, , . phi , , - (, ++).

, main, .

Source: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-February/019767.html

0
source

According to the standard (for hosted environments) 5.1.2.2.1 , mainreturrn a is required int. Therefore, one should not expect certain behavior if it violates.

Furthermore, mainit is not really necessary to explicitly return 0; it returns implicitly if it reaches the end of the function. (Please note that this is only for main, which also does not have a prototype.

0
source

All Articles