For bit shifting operators, we will only look at simple
int
s with the following code:
= ia << 2;
ic = ia >> 2;
ic <<= 2;
ia >>= 2; ia
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.
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.