I'm learning about assembly code in "Computer Systems- A Programmer's Perspective", and I encountered the following example:
In the following C function, we have left the definition of operation OP incomplete:
#define OP /* Unknown operator */ short arith(short x) { return x OP 16; }
When compiled, gcc generates the following assembly code:
arith: leaq 15(%rdi), %rax testq %rdi, %rdi cmovns %rdi, %rax sarq $4, %rax ret
What operation is OP?
Later, the book gives the following answer:
The operator is ‘/’. We see this is an example of dividing by a power of 4 by right shifting (see Section 2.3.7). Before shifting by k = 4, we must add a bias of (2^k) − 1 = 15 when the dividend is negative.
I get that the compiler is using an optimization here, creating a temporary variable equal to x + 15, and conditionally re-setting that variable back to x if x is less than zero. What I'm wondering is why it's necessary to use a bias in the first place. What would happen if the code left out the first 3 assembly steps, like so?
sarq $4, %rax
ret
I think the answer is that we need to get rid of the twos-complement sign bits from a negative number in order to arrive at the correct answer of zero. For example, if x = -12 (i.e. 11110100), and we wanted to divide by 4, then shifting right by 4 bits without adding the bias first would equal 11111111 (or -1 in decimal form), which is not the expected answer of 0 that I'd expect from dividing -12 by 16. Instead, we add 15 to -12 to get 3 (aka 00000011), which we can then shift right by 4 bits to get 00000000, aka the correct answer of 0 in decimal form.
Is the above explanation correct? Or am I missing the mark when it comes to how and why a bias is used?
UPDATE- apparently the example assembly code in the book I'm using isn't correct. Here's the correct assembly:
arith:
testw %di, %di
leal 15(%rdi), %eax
cmovns %edi, %eax
sarw $4, %ax
ret
My larger question about why the bias is needed still stands. Is it because shifting a negative number without first adding the bias produces the incorrect result that I mentioned?