仅仅因为原始值是 8.8 定点格式,并不意味着您的除数必须是 8.8 定点格式。
达到最大精度;同时将分子和除数的大小加倍,直到这样做会导致溢出。例如:
(value << 8) / (PI << 8) = (value << 8) / 804
(value << 9) / (PI << 9) = (value << 9) / 1608
(value << 10) / (PI << 10) = (value << 9) / 4216
...
(value << 13) / (PI << 13) = (value << 13) / 25736
(value << 14) / (PI << 14) = (value << 14) / 51472 = BEST
(value << 15) / (PI << 15) = (value << 15) / 102944 = DIVISOR OVERFLOWS
这给出如下代码:
xor dx,dx ;dx:ax = ax = value << 8
shld dx,ax,6
shl ax,6 ;dx:ax = value << 14
mov bx,51472 ;bx = PI << 14
div bx ;ax = value << 14 / PI << 14 = value / PI
请注意,这将为您提供整数结果(而不是派系或定点结果)。如果您需要 8.8 的定点结果,则需要将分子额外移动 8,例如:
xor dx,dx ;dx:ax = ax = value << 8
shld dx,ax,14
shl ax,14 ;dx:ax = value << 22
mov bx,51472 ;bx = PI << 14
div bx ;ax = value << 22 / PI << 14 = value / PI << 8
如果余数不小于除数的一半,则可以通过将结果向上取整来稍微改进一下。换句话说:
cmp dx,51472/2 ;Should result be rounded up?
jb .done ; no, remainder is too small
inc ax ; yes, round the result up
.done:
警告:我不确定您打算支持哪种 CPU。如果我没记错的话,原来的 8086 不支持 SHLD 指令,可能需要用替代指令替换(mov dx,ax 然后向右移动)。对于现代 80x86 CPU(自 80386 起),您可以通过执行 32 位除法来进一步提高精度,但由于原始“8.8 定点”值的精度较低,这并不重要。