MARIE ASM Lang - 整数除法 (positive/negative)

MARIE ASM Lang - division on integers (positive/negative)

出于学习目的,我正在尝试在 MARIE 中编写 any 整数除法。

这是标准的(希望是正确的)代码,它将 X 除以 Y 并取余数,但只能使用正整数。

        LOAD X
        STORE REMAIN
WHILE   SUBT Y
        SKIPCOND 800
        JUMP CHECK
DO      STORE REMAIN
        LOAD RESULT
        ADD ONE
        STORE RESULT
        LOAD REMAIN
        JUMP WHILE
CHECK   SKIPCOND 400
        JUMP END
        STORE REMAIN
        LOAD RESULT
        ADD ONE
        STORE RESULT
END     HALT
X       HEX XXXX
Y       HEX YYYY
RESULT  HEX 0000
REMAIN  HEX 0000
ONE     HEX 0001

我怎样才能让它适用于底片?可能是一些 IF 和一些位掩码,但我不确定如何正确地做到这一点。

取决于你如何定义它...D/d=[q,r](股息/除数=[商,余数])

  • 5/2 = [2,1](你有这个)
  • -5/-2 = [3, 1] 或 [2, -1](x86 方式)
  • 5/-2 = [-2, 1] (x86) 或 [-3, -1]
  • -5/2 = [-3,1] 或 [-2, -1] (x86)

(在 x86 CPU 上,余数 r 的符号始终与被除数 D 的符号相同)

如果您查看上面的结果,在每种情况下的绝对值都是相同的:

  • |5| / |2| = [|2|, |1|]

余数有被除数符号,商有被除数符号 XOR 除数 ([+, +] == [-, -] == + vs [+, -] == [-, +] == -).

所以你可以在你的例程开始时添加一个准备部分,它将测试每个值,并在一些标志中标记它是正数还是负数,将其转换为正数,进行除法,然后在当前 END 通过标志修补结果。

类似的东西(这是我第一次使用 Marie Assembly,所以更像是一个提示,并在需要的地方更正它,希望只是语法,但甚至可能存在逻辑错误,我没有验证代码有效!):

    CLEAR
    / init temporary/result variables to zero
    STORE    q_flag
    STORE    r_flag
    STORE    RESULT
    SUBT     X                / try (-Dividend) value
    SKIPCOND 800
    JUMP     DividendWasPositive    / positive or zero
    STORE    X                / (-Dividend) positive, rewrite original X
    STORE    q_flag           / set flags to positive value (X)
    STORE    r_flag
DividendWasPositive,
    CLEAR
    SUBT     Y                / try (-divisor) value
    SKIPCOND 400
    JUMP     DivisorNotZero
    HALT                      / division by zero detected, error
DivisorNotZero,
    SKIPCOND 800
    JUMP     DivisorWasPositive
    STORE    Y                / (-divisor) positive, rewrite original Y
    / flip quotient flag value (zero <-> nonzero) ("nonzero" == X)
    LOAD     X                / will not "flip" anything when 0 == X
    SUBT     q_flag           / but then q = 0, so it's harmless deficiency
    STORE    q_flag           / q_flag is now zero or positive (X) value
DivisorWasPositive,
    / here X and Y contain absolute value of input numbers
    / q_flag is positive value when quotient has to be negated
    / r_flag is positive value when remainder has to be negated

    / .. do your division here ..

    / patching results by the q/r flags from the prologue part
AdjustQuotientSign,
    LOAD     q_flag
    SKIPCOND 800
    JUMP     AdjustRemainderSign
    CLEAR
    SUBT     RESULT
    STORE    RESULT           / quotient = -quotient
AdjustRemainderSign,
    LOAD     r_flag
    SKIPCOND 800
    JUMP     SignsAdjusted
    CLEAR
    SUBT     REMAIN
    STORE    REMAIN           / remainder = -remainder
SignsAdjusted,
    HALT

q_flag,    DEC      0
r_flag,    DEC      0
... rest of your variables

其他选项可能是针对每种情况(4 种变体)使用单独的例程变体,因为它们仅在 ADD/SUBT Y/ONE 和终止条件 000 与 800 上有所不同,后者将执行每个案例的指令更少(性能更好),但代码行会多一些,而且上面的代码可能会给您一些新想法,如何在汇编中做事。