title: Trouble understanding extra-assembly instructions generated by code
body: <p>I'm studying the book Computer Systems: A Programmers Perspective. I'm having a bit of trouble understanding problem 3.5:</p>
  
  <blockquote>
    <p>You are given the following information. A function with prototype</p>
  </blockquote>
  
  <pre><code>void decode1(int *xp, int *yp, int *zp);
  </code></pre>
  
  <blockquote>
    <p>is compiled into assembly code. The body of the code is as follows:</p>
    
    <p>xp at %ebp+8, yp at %ebp+12, zp at %ebp+16</p>
  </blockquote>
  
  <pre><code>1 movl 8(%ebp), %edi
  
  2 movl 12(%ebp), %edx
  
  3 movl 16(%ebp), %ecx
  
  4 movl (%edx), %ebx
  
  5 movl (%ecx), %esi
  
  6 movl (%edi), %eax
  
  7 movl %eax, (%edx)
  
  8 movl %ebx, (%ecx)
  
  9 movl %esi, (%edi)
  </code></pre>
  
  <blockquote>
    <p>Parameters xp, yp, and zp are stored at memory locations with offsets
    8, 12, and 16, respectively, relative to the address in register %ebp.
    Write C code for decode1 that will have an effect equivalent to the
    assembly code above.</p>
  </blockquote>
  
  <p>I came up with the following c function:</p>
  
  <pre><code>void decode1(int *xp, int *yp, int *zp) {
      int *a = yp;
      int *b = zp;
      int *c = xp;
  
      yp = c;
      zp = a;
      xp = b;
  }
  </code></pre>
  
  <p>Compiling to assembly (flags: -w32 -O0 -S) I get the following assembly code:</p>
  
  <pre><code>decode1(int*, int*, int*):
  pushl   %ebp
  movl    %esp, %ebp
  subl    $16, %esp
  movl    12(%ebp), %eax
  movl    %eax, -12(%ebp) // ??
  movl    16(%ebp), %eax   
  movl    %eax, -8(%ebp)  // ??
  movl    8(%ebp), %eax
  movl    %eax, -4(%ebp)  // ??
  movl    -4(%ebp), %eax
  movl    %eax, 12(%ebp)
  movl    -12(%ebp), %eax
  movl    %eax, 16(%ebp)
  movl    -8(%ebp), %eax
  movl    %eax, 8(%ebp)
  nop
  leave
  ret
  </code></pre>
  
  <p>I have two questions:</p>
  
  <p>Is my C code correct? And if it is, why the difference in assembly code? I don't understand why the code seems to be storing the variables back into memory and then loading them back? Why is it using only %eax? I have 6 variables so it should be able to load them in the 6 registers, no?</p>
  
  <hr>
  
  <p>EDIT: Generated code with -O2 instead of -O0</p>
  
  <pre><code>pushl   %ebp
  movl    %esp, %ebp
  subl    $24, %esp
  movl    16(%ebp), %eax
  movl    12(%ebp), %ecx
  movl    8(%ebp), %edx
  movl    %edx, -4(%ebp)
  movl    %ecx, -8(%ebp)
  movl    %eax, -12(%ebp)
  movl    -8(%ebp), %eax
  movl    %eax, -16(%ebp)
  movl    -12(%ebp), %eax
  movl    %eax, -20(%ebp)
  movl    -4(%ebp), %eax
  movl    %eax, -24(%ebp)
  movl    -24(%ebp), %eax
  movl    %eax, -8(%ebp)
  movl    -16(%ebp), %eax
  movl    %eax, -12(%ebp)
  movl    -20(%ebp), %eax
  movl    %eax, -4(%ebp)
  addl    $24, %esp
  popl    %ebp
  retl
  </code></pre>
  
  <hr>
  
  <p>EDIT2: correct answer is actually:</p>
  
  <pre><code>    void decode1(int *xp, int *yp, int *zp) {
      int a = *yp;
      int b = *zp;
      int c = *xp;
  
      *yp = c;
      *zp = a;
      *xp = b;
  }
  </code></pre>