Round signed integersAssembler/8086

For certain applications it is often necessary to round signed integers so that they always tend to 0. However, the signed shifts on the Intel processors don't do it properly.

Let's see what we want to do:
For negative inputs where the last bit shifted out was set, you want to increment the results from a normal arithmetic shift. My approach uses one 6 instructions, but allows some pairing, so it should take the 4 cycles on top of the shift instruction. This makes it probably faster than using branches:

        sar     eax,cl          ; ?  Arithmetic shift, last bit shifted into carry
	sbb     ebx,ebx         ; U EBX = (Carry) ? -1 : 0
	mov     edx,eax         ; V
	sar     edx,31          ; U EDX = (EAX < 0) ? -1 : 0
	and     ebx,edx         ; U EBX = (Carry && EAX < 0)? -1 : 0
	sub     eax,ebx         ; U
This has the added benefit of working when the input value is MIN_INT (80000000h), but suffers from a problem when the shift count is zero and the input value is negative: In that case my version will fail if the Carry flag happened to be set before the SAR EAX,CL (0) which doesn't touch Carry. You can use the same gem on 16 bit machines too, just use 16 bit registers instead. And change the shift value to 15.
Gem writer: Terje Mathisen
last updated: 1998-03-16