2

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

这是标准(希望是正确的)代码,它将 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 和一些位掩码,但我不知道如何正确地做到这一点。

4

1 回答 1

1

取决于你如何定义它...... 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|]

余数有被除数的符号,商有被除数异或除数的符号([+, +] == [-, -] == + 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 方面有所不同,这将为每种情况执行更少的指令(更好的性能) ,但是会有更多的代码行加上上面的代码可能会给你一些新的想法,如何在 Assembly 中做事。

于 2017-02-03T14:21:33.023 回答