Search code examples
assemblyx86x86-64bit-shift

Registers used during left shift operation


I have a small question about the utilization of registers during some basic operations. Effectively, I have already looked at the assembly code produced during operations such as XOR or AND and those are easy to understand. Effectively, if we consider a = b & c, this will be translated in 3 steps :

  1. b is moved to %rax
  2. %rax = %rax + c
  3. %rax is moved to a

Note that a, b and c are unsigned long variables. This translation is also available if the addition is replaced by a XOR or an OR. Anyway, I have checked if it was also the case for shifts and I find a weird thing : in fact, a = b << c is translated as follow

  1. b is moved to %rax
  2. c is moved to %rcx
  3. %rax = %rax <<(shlq) %cl
  4. %rax is moved to a

I'm not pretty sure I really understand the second and third steps. I suppose this is due to the fact that %rax (b) cannot be shifted more than 63, otherwise, the result is obviously 0. It seems that %cl is an 8-bit register and so I think that this is a fast way to select only the useful bits and not the 64 bits in %rcx. Is that correct ?

Thank you


Solution

  • That's simply how shl works.
    From Intel manual 2B:

    Shifts the bits in the first operand (destination operand) to the left or right by the number of bits specified in the second operand (count operand). Bits shifted beyond the destination operand boundary are first shifted into the CF flag, then discarded. At the end of the shift operation, the CF flag contains the last bit shifted out of the destination operand.

    The destination operand can be a register or a memory location. The count operand can be an immediate value or the CL register. The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used). A special opcode encoding is provided for a count of 1.

    Variable length shifts must use cl.