Code:
shr bx, 15 ; turns BX into 1 if it was 0xFFFF, still 0 if it started out as 1
This is going to hurt on an 8088, since it cannot do anything other than shr bx, 1. Either you'd repeat that 15 times, or you'd have to use the variant with shr bx, cl.
I think in this case a simpler solution would be:
and bx, 1
But I think in general Chuck(G)'s is the way to go:
You want to solve it in one go, rather than converting the value to a (-1,0,1) value first. The bitmask is easier to derive from the 2s complement value directly than it is from a (-1,0,1) value. Also, if you need to derive that (-1,0,1) value from the original value in the first place, that's only extra overhead.
I think his version can be refined though...
One needs to observe the following, in 2s complement:
neg x == (not x) + 1
not x == x ^ -1
Hence:
neg x == (x ^ -1) - (-1)
Now, we have two cases:
For positive X -> Y = Y
For negative X -> Y = -Y
If you take the above formula:
Y = (Y ^ Z) - Z
Then for Z = 0:
Y = (Y ^ 0) - 0 = Y
For Z = -1:
Y = (Y ^ -1) + 1 = -Y
Hence we can do this:
CWD (if (AX >= 0) DX = 0 else DX = -1)
XOR BX, DX
SUB BX, DX
Edit: Also, on older CPUs, branches aren't necessarily all that expensive... so this solution wouldn't even be that bad:
TEST AX, AX
JNS skip
NEG BX
skip:
And if you've just calculated ax beforehand, perhaps you can even do without the TEST, because the sign-flag may already be set by the previous instruction.