зависит, как вы определяете его ... 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 делителя ([+, +] == [-, -] ==
+ против [+, -] == [-, +] ==
-).
Таким образом, вы можете добавить в начале вашей процедуры часть подготовки, которая будет проверять каждое значение, и пометить в какой-либо флаг, была ли она положительной или отрицательной, преобразовывая ее в положительную, выполните разделение, а затем в текущем 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.