Bit Shifting

For bit shifting operators, we will only look at simple ints with the following code:

  ic = ia << 2;
  ic = ia >> 2;
  ia <<= 2;
  ia >>= 2;

AMD64

The equivalent assembly is shown in the following tables, organized by related statements:

C .s file gdb
ic = ia << 2;
movl -8(%rbp), %eax mov -0x8(%rbp),%eax
shll $2, %eax shl $0x2,%eax
movl %eax, -16(%rbp) mov %eax,-0x10(%rbp)
ic = ia >> 2;
movl -8(%rbp), %eax mov -0x8(%rbp),%eax
sarl $2, %eax sar $0x2,%eax
movl %eax, -16(%rbp) mov %eax,-0x10(%rbp)
ia <<= 2;
movl -8(%rbp), %eax mov -0x8(%rbp),%eax
shll $2, %eax shl $0x2,%eax
movl %eax, -8(%rbp) mov %eax,-0x8(%rbp)
ia >>= 2;
movl -8(%rbp), %eax mov -0x8(%rbp),%eax
sarl $2, %eax sar $0x2,%eax
movl %eax, -8(%rbp) mov %eax,-0x8(%rbp)

Here we see a single pattern: First, we load the value of our variable into a register, then we call either shll/shl for a left-shift or sarl/sar for a right-shift, and then copy the value of the shifted register to the target location in memory. The shift operators take the number of bits by which to shift as the first argument, followed by the register to shift. The shifted value is written back to the register.

AArch64

The equivalent assembly is shown in the following tables, organized by related statements:

C .s file gdb
ic = ia << 2;
ldr r3, [fp, #-8] ldr r3, [r11, #-8]
lsl r3, r3, #2 lsl r3, r3, #2
str r3, [fp, #-48] str r3, [r11, #-48]
ic = ia >> 2;
ldr r3, [fp, #-8] ldr r3, [r11, #-8]
asr r3, r3, #2 asr r3, r3, #2
str r3, [fp, #-48] str r3, [r11, #-48]
ia <<= 2;
ldr r3, [fp, #-8] ldr r3, [r11, #-8]
lsl r3, r3, #2 lsl r3, r3, #2
str r3, [fp, #-8] str r3, [r11, #-8]
ia >>= 2;
ldr r3, [fp, #-8] ldr r3, [r11, #-8]
asr r3, r3, #2 asr r3, r3, #2
str r3, [fp, #-8] str r3, [r11, #-8]

As with AMD64, all four statements produce the same pattern, where we load the variable’s value into a register with ldr, perform either a left-shift with lsl or a right-shift with asr, and then store the result back to the appropriate variable with str. The biggest difference is that the AArch64 shift instructions take two registers (destination and source), followed by the the number of bits to shift.