How does sign contraction work from 16 bit to 8 bit?
Solution 1:
How does sign contraction work from 16 bit to 8 bit?
It doesn't (the highest 8 bits, including the sign bit if the value is too large to fit in 8 bits, are simply discarded).
Instead, you have to implement it yourself.
If "contraction" is "preserve as many bits as possible" then it might become something like:
add ax,ax ;carry flag = sign bit, al = lowest 7 bits shifted left
rcr al,1 ;al = original sign bit with original lowest 7 bits
For your test value 0xFF12 (or -238 in decimal), this becomes "0xFE24 with carry flag set" after the add
, then 0x92 (or -110 in decimal) after the rcr
.
More examples (including corner cases):
0xFF80 (or -128) -> "0xFF00 with carry flag set" = 0x80 (or -128)
0xFF00 (or -256) -> "0xFE00 with carry flag set" = 0x80 (or -128)
0x0000 -> "0x0000 with carry flag clear" = 0x00
0x007F (or +127) -> "0x00FE with carry flag clear" = 0x007F (or +127)
0x00FF (or +255) -> "0x01FE with carry flag clear" = 0x007F (or +127)
If "contraction" is "with saturation" (clamping values) then it might be something like:
mov bx,ax ;bx = original 16-bit value
cbw ;ax = 16-bit extension of original value in AL
cmp ax,bx ;Did the original value fit in 8 bits?
je .done ; yes, AL is correct (no saturation needed)
add bx,bx ;carry flag = original sign bit
mov al,0x7F
adc al,0 ;al = 0x80 (if value was negative) or 0x7F (if value was positive)
.done:
I'm not sure if there's a better way (it looks awful and I suspect my brain isn't working today).