0

I started to learn Assembly so I use the command gcc -S file.c to get an Assembly version of my C code.

Everything is working fine but I noticed that when I put a simple code, for example:

void    ft_return_strlen(char *str)
{
    int     a;

    a = strlen(str);
    return (a);
}

The gcc -S file.c command gives me this:

_ft_return_strlen:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rdi
    callq   _ft_strlen
    movl    %eax, -12(%rbp)
    movl    -12(%rbp), %eax
    addq    $16, %rsp
    popq    %rbp
    retq

Even if this function is useless, why is gcc giving me these lines?

    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rdi

Aren't they useless? If these lines were really useless, do they come from my code or from the gcc? Is there a way to improve this?

1 Answers1

1

Unoptimised, the compiler allocates space for a variable str, which is -8(%rbp). All the code at the top is to make a space on the stack between registers rbp and rsp for the local variables.

The function call puts that in register rdi, but the debugger needs to see it in variable named str. And if in the debugger you were to change the variable str, that new value needs to be copied back out as an argument to strlen.

The same then happens to the variable a, -12(%rbp), which has to be copied from the return register rax, and then copied back to be returned, just incase you edit it in the debugger.

With optimisation, the variables are discarded completely, but the debugger is aware that the equivalent are in registers. At maximum optimisation, the whole function could be deleted, or replaced with a jmp to strlen, but then you wouldn't be able to debug it at all!

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27
  • *but the debugger is aware that the equivalent are in registers* Unfortunately you usually get "optimized out", instead of the compiler printing a variable that lives in a register. At least on GNU/Linux with GDB. – Peter Cordes Feb 07 '20 at 20:41
  • @PeterCordes yes, it is of limited value in the debugger as the registers regularly get reused, but occasionally it will give the answer, I find. – Gem Taylor Feb 07 '20 at 20:47
  • If you're looking at the asm yes of course you can `print $rdi` yourself, but I've usually found that when a var is optimized into registers, GDB simply doesn't know where to look. Probably in most of those cases the C var got optimized away and replaced with a GCC-invented temporary. (If you look at GCC asm output with `-fverbose-asm`, you see names like `D.1234`). I had assumed that the debug info format might not even have a way to indicate that a C var was in a register, but maybe that's not the case. – Peter Cordes Feb 07 '20 at 20:50