Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does GCC insert seemingly non-essential instructions before a printf call?
    primarykey
    data
    text
    <p>I'm trying to learn x86 on my own and I decided to dissect a simple c program and see what GCC outputs. The program is this:</p> <pre><code>#include &lt;stdio.h&gt; int main() { printf("%s","Hello World"); return 0; } </code></pre> <p>I compiled the code with -S and then stripped out things that I found unnecessary and reduced the assembly code to this.</p> <pre><code>.pfArg: .string "%s" .text .Hello: .string "Hello World" .text .globl main .type main, @function main: pushq %rbp # push what was in base pointer onto stack movq %rsp, %rbp # move stack pointer to base pointer subq $16, %rsp # subtract 16 from sp and store in stack pointer # prepare arguments for printf movl $.Hello, %esi # put &amp; of "Hello World" into %esi movq $.pfArg, %rdi # put &amp; of "%d" into %eax call printf leave ret </code></pre> <p>Now almost everything in the code above makes sense to me except the first two under main. Although this is what I get without stripping things out.</p> <pre><code>.LC0: .string "%s" .LC1: .string "Hello World" .text .globl main .type main, @function main: .LFB0: pushq %rbp # push what was in base pointer onto stack movq %rsp, %rbp # move stack pointer to base pointer # prepare arguments for printf movl $.LC0, %eax # put arg into %eax movl $.LC1, %esi # put second arg into %esi movq %rax, %rdi # move value in %rax to %rdi ???? ( why not just put $.LCO into %rax directly ) movl $0, %eax # clear out %eax ???? ( why do we need to clear it out ) call printf movl $0, %eax # return 0 leave ret .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" .section .note.GNU-stack,"",@progbits </code></pre> <p>There are 2 instructions that I've marked with ???? that I don't understand. </p> <p>The first instruction is moving what is in %rax into %rdi to prepare for the printf call. Thats all fine except we just moved $.LC0 (which is the string "%s") into %eax. This seems unnecessary why didn't we just move $.LC0 into %rdi in the first place instead of moving it into %eax and then into %rdi?</p> <p>The second instruction is clearing out %eax which I understand to be the return value of a function. But if the function is going to just clobber it anyways why do GCC care to clear it out?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload