How C++/C codes are interpreted by compiler

本帖最後由 kyva1929 於 2011-10-4 19:50 編輯


Given the following assembly code:

shrl     %cl, %edx

which is equivalent to logically shifting %edx by the lower 8 bits stored in %ecx (%cl).

There's no one single operator that provides the function of logical right shift in C++/C -- are compilers smart enough to figure out that we're actually asking them to do a logical right shift by an amount of the lower 8 bits stored in %ecx with complex codes?


%edx = (%edx >> (%ecx & 0xff) ) ^ (0x80000000 >> (( %ecx & 0xff )-1 )

The above code first shift  %edx to the right arithmetically by whatever it is at %cl (the lower 8 bits stored in %ecx), and then do an exclusive xor operation with a string that contains %cl that much ones in the bit string counting from the msb (The ones that got filled on the right of the bit strings got set to zeros, effectively making the final result a logical right shift)

What code in C/C++ would have the compiler translate to instructions like shrl, or accessing %cl?

A more general question would be --
Given all these instructions provided by x86 / x86-64 arch, there are no corresponding operators in C++ -- is writing inline assembly code the only way to directly utilize those instructions? If not -- are compilers always able to interpret the code most efficiently such that the complicated (as compared to the instructions in assembly) expression above can be translated to shrl     %cl, %edx?

Alright...Looks like gcc compiler IS smart enough to figure it out -- at least with -O3 flag.

The following program:

int loop(int x, int n)
  int result = 1431655765;
  int mask;
  for (mask = -2147483648; mask != 0; mask = (int)((unsigned int)mask >> (n & 0xff)))
    result ^= (mask & x);
  return result;

Gives the following assembly:

  andl  $255, %esi
  movl  $1431655765, %r8d
  movl  $-2147483648, %edx
  .p2align 4,,7
  movl  %edx, %eax
  movl  %esi, %ecx
  andl  %edi, %eax
  xorl  %eax, %r8d
  movl  %edx, %eax
  shrl  %cl, %eax
  testl %eax, %eax
  movl  %eax, %edx
  jne .L2
  movl  %r8d, %eax

Notice how it's using

shrl  %cl, %eax



Never mind...I figure the compiler always read just the lower 8 bits of %e*x for shifting operation since it wouldn't make sense to shift a 4 byte quantity by more than 32 bits...