Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In the x86_64 ABI, if a function has variable arguments then <code>AL</code> (which is part of <code>EAX</code>) is expected to hold the number of vector registers used to hold arguments to that function.</p> <p>In your example:</p> <pre><code>printf("%d", 1); </code></pre> <p>has an integer argument so there’s no need for a vector register, hence <code>AL</code> is set to 0.</p> <p>On the other hand, if you change your example to:</p> <pre><code>printf("%f", 1.0f); </code></pre> <p>then the floating-point literal is stored in a vector register and, correspondingly, <code>AL</code> is set to <code>1</code>:</p> <pre><code>movsd LC1(%rip), %xmm0 leaq LC0(%rip), %rdi movl $1, %eax call _printf </code></pre> <p>As expected:</p> <pre><code>printf("%f %f", 1.0f, 2.0f); </code></pre> <p>will cause the compiler to set <code>AL</code> to <code>2</code> since there are two floating-point arguments:</p> <pre><code>movsd LC0(%rip), %xmm0 movapd %xmm0, %xmm1 movsd LC2(%rip), %xmm0 leaq LC1(%rip), %rdi movl $2, %eax call _printf </code></pre> <hr/> <p>As for your other questions:</p> <blockquote> <p><code>puts</code> is also zeroing out <code>%eax</code> right before the call though it only takes a single pointer. Why is this?</p> </blockquote> <p>It shouldn’t. For instance:</p> <pre><code>#include &lt;stdio.h&gt; void test(void) { puts("foo"); } </code></pre> <p>when compiled with <code>gcc -c -O0 -S</code>, outputs:</p> <pre><code>pushq %rbp movq %rsp, %rbp leaq LC0(%rip), %rdi call _puts leave ret </code></pre> <p>and <code>%eax</code> is not zeroed out. However, if you remove <code>#include &lt;stdio.h&gt;</code> then the resulting assembly does zero out <code>%eax</code> right before calling <code>puts()</code>:</p> <pre><code>pushq %rbp movq %rsp, %rbp leaq LC0(%rip), %rdi movl $0, %eax call _puts leave ret </code></pre> <p>The reason is related to your second question:</p> <blockquote> <p>This also happens before any call to my own void proc() function (even with -O2 set), but it is not zeroed when calling a void proc2(int param) function.</p> </blockquote> <p>If the compiler doesn't see the declaration of a function then it makes no assumptions about its parameters, and the function could well accept variable arguments. The same applies if you specify an empty parameter list (which you shouldn’t, and it’s marked as an obsolescent C feature by ISO/IEC). Since the compiler doesn’t have enough information about the function parameters, it zeroes out <code>%eax</code> before calling the function because it might be the case that the function is defined as having variable arguments.</p> <p>For example:</p> <pre><code>#include &lt;stdio.h&gt; void function() { puts("foo"); } void test(void) { function(); } </code></pre> <p>where <code>function()</code> has an empty parameter list, results in:</p> <pre><code>pushq %rbp movq %rsp, %rbp movl $0, %eax call _function leave ret </code></pre> <p>However, if you follow the recommend practice of specifying <code>void</code> when the function accepts no parameters, such as:</p> <pre><code>#include &lt;stdio.h&gt; void function(void) { puts("foo"); } void test(void) { function(); } </code></pre> <p>then the compiler knows that <code>function()</code> doesn't accept arguments — in particular, it doesn’t accept variable arguments — and hence doesn’t clear <code>%eax</code> before calling that function:</p> <pre><code>pushq %rbp movq %rsp, %rbp call _function leave ret </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    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.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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