1
votes

Quick question on left shifts in assembly using the "sall" instruction.

From what I understand, "sall rightop, leftop" would translate to "leftop = leftop << rightop", so taking an integer and shifting the bits 4 spaces to the left would result in a multiplication by 2^4.

But what happens when the integer is unsigned, 32-bits, and is something like:

1111 1111 1111 1111 1111 0000 0010 0010

Would a left shift in this case become 1111 1111 1111 1111 0000 0010 0010 0000 ?

Obviously this is not a multiplication by 2^4.

Thanks!!

2
It is a multiplication by 2^4. It just overflowed - it would also have done so with a normal multiply. That can also happen to signed numbers, it just so happened that it didn't in this case.harold
Ok so I see everyone saying it would overflow, which makes sense. But in the context of an assembly command, what would this result in? So if you say "sall $4, %eax " where %eax is 1111 1111 1111 1111 1111 0000 0010 0010, then what would the resulting value of %eax be?elykl33t

2 Answers

1
votes

It is a multiplication by 2^4, modulo 2^32:

n = (n * 2^4) % (2 ^ 32)

You can detect the bits that got "shifted out" by performing a shift left followed by masking, in this case

dropped = (n >> (32-4)) & (1<<4-1)
1
votes

Left shifts (SAL, SHL) simply lose the bits on the left. The bits on the right get filled with 0. If any of the lost bits is 1, you have an overflow and the wrong result in terms of multiplication. You use S*L for both non-negative and negative values.

The regular right shift (SHR) works in exactly the same manner, but the direction is reverse, the bits on the left get filled with 0 and you lose the bits on the right. The result is effectively rounded/truncated towards 0. You use SHR of non-negative values because it does not preserve the sign of the value (0 gets written into it).

The arithmetic shift right (SAR) is slightly different. The most significant bit (=leftmost bit, sign bit) doesn't get filled with 0. It gets filled with its previous value, thus preserving the sign of the value. Another notable difference is that if the value is negative, the lost bits on the right result in rounding towards minus infinity instead of 0.