extended asm and input parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm trying to understand how input parameters are used by gcc's extended asm. Each time I think I've got a handle on it, it does something else unexpected.

For example, this c++ code:

 inline void moo(unsigned char *Dest, unsigned char Data, int Count) {
   asm volatile (
      "rep stosb"
      : /* no outputs */
      : "D" (Dest), "a" (Data), "c" (Count)
      : "memory");
}

int main()
{
   unsigned char buff1[32];

   moo(buff1, 0, sizeof(buff1));
   moo(buff1, 0, sizeof(buff1));

   return 0;
}

 Compiling for 64bit on i386 using -Os, I get:

0000000000407800 <main>:
  407800:    push   rdi
  407801:    sub    rsp,0x40
  407805:    call   4022d0 <__main>

  40780a:    lea    rdi,[rsp+0x20]
  40780f:    mov    ecx,0x20
  407814:    xor    eax,eax
  407816:    rep stos BYTE PTR es:[rdi],al

  407818:    lea    rdi,[rsp+0x20]
  40781d:    rep stos BYTE PTR es:[rdi],al

  40781f:    xor    eax,eax
  407821:    add    rsp,0x40
  407825:    pop    rdi
  407826:    ret

Now, there are a few noteworthy things here:

1) ecx gets loaded for the first call, but not the second.
2) rdi gets loaded for both calls.
3) eax gets zeroed before the first call, does not for the second, but then gets zeroed again for the return code.

When I saw that ecx wasn't getting re-loaded, I speculated that inputs are assumed to be unchanged by the asm unless they are also listed as output. This was not what I expected, but upon reflection, I could see how that made sense.

But if that's true, why does rdi get re-loaded each time? My first guess was that the "memory" clobber was causing this. But removing it didn't change the asm that got generated.

And what about the fact that rax is getting zeroed for the first call, not for the second, then zeroed again for the return value. If the optimizer is assuming input values are unchanged by asm blocks, why did it need to re-assign it, but only sometimes?

I have tried other experiments in an attempt to understand the pattern here, but the more I try, the more unclear things become. Rather than posting all my tests here making this post harder to read, I'll just start with the most important question first, then ask a followup or two:

When can and can't you (safely) modify extended asm input-only parameters? Unlike output parameters (which must be lvalues), inputs are expressions. Does this mean they are supposed to be modifiable at will? Or must they (all and always) be treated as read-only?

dw





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux