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 上有所不同,后者将执行每个案例的指令更少(性能更好),但代码行会多一些,而且上面的代码可能会给您一些新想法,如何在汇编中做事。
出于学习目的,我正在尝试在 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 上有所不同,后者将执行每个案例的指令更少(性能更好),但代码行会多一些,而且上面的代码可能会给您一些新想法,如何在汇编中做事。