【问题标题】:x86 Assembly Fixed-Point Divisionx86 汇编定点除法
【发布时间】:2021-11-06 20:42:30
【问题描述】:

我的作业有问题。我应该将存储在 AX 中的 8.8 定点数除以 Pi (3.141592),然后将结果存储回 AX

我写道:

mov dl, ah
mov ah, al
mov bx, 804
div bx

该程序被自动调用并在AX 中给出一个值以对其进行测试。但是,我没有设法通过所有测试。任何人都知道如何使它更精确?

【问题讨论】:

  • 这应该如何工作? DH 是否已经为零,而您正在将 AX 左移到 DX:AX?但是你没有修改 AX 的低字节,所以它就像DX:AX = (AX << 8) | (AX & 0xFF) IDK 如果这有意义的话。以及为什么将804 (0x324) 作为除数?

标签: assembly x86 division fixed-point


【解决方案1】:

仅仅因为原始值是 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 定点”值的精度较低,这并不重要。

【讨论】:

  • 是的,shld 是 386 中的新功能,但是很容易没有这个,因为你只是转移到一个归零的寄存器。
  • 哇,非常感谢,我一定会试试的
猜你喜欢
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
相关资源
最近更新 更多