Занимать во время операции вычитания (инструкция sbc asm) на 6502?
Когда заимствование (т. Е. Флаг переноса сбрасывается) происходит во время операции вычитания (инструкция sbc asm) на 6502, используемой NES? Это каждый раз, когда результат отрицательный (от -1 до -128)?
Большое спасибо! Спасибо STEN
3 ответа
На 6502 SBC n
в точности совпадает с ADC (n EOR $FF)
- это дополнение. Так что нести ясно, когда A + (operand ^ 0xff) + existing carry
меньше 256
РЕДАКТИРОВАТЬ: так, если установлен перенос, то вычитание происходит без заимствования. Если перенос ясно, то вычитание происходит с заимствованием. Следовательно, если после вычитания установлен перенос, то заимствования не было. Если нести ясно, то было заимствовать.
Если вы хотите проверить, является ли результат отрицательным, неявно проверьте бит знака через BMI
или же BPL
,
Это немного сложнее, чем в десятичном режиме на универсальном 6502, но вариант NES не имеет десятичного режима, поэтому игнорируйте все, что вы читали об этом.
Для уточнения ре: комментарии ниже; если вы рассматриваете номера как подписанные, то 127
является +127
, 128
является -128
и т. д. Обычные два дополнения. Ничего особенного. Например
LDA #-63 ; i.e. 1100 0001
SEC
SBC #65 ; i.e. 0100 0001
; result in accumulator is now -128, i.e. 1000 0000,
; and carry remains set because there was no borrow
BPL somewhere ; wouldn't jump, because -128 is negative
BMI somewhereElse ; would jump, because -128 is negative
Следующее в точности эквивалентно с точки зрения внутренней работы:
LDA #-63 ; i.e. 1100 0001
SEC ; ... everything the same up until here ...
ADC #65 ; i.e. 1011 1110 (the complement of 0100 0001)
; result = 1100 0001 + 1011 1110 + 1 = [1] 0111 1111 + 1 = [1] 1000 0000
; ^
; |
; carry
; = -128
Таким образом, как указано выше, определяя "результат" в соответствии с руководством 6502 и обычным программным значением "вещь, сидящая в аккумуляторе", вы можете проверить, является ли результат положительным или отрицательным, как указано выше, например,
SBC $23
BMI resultWasNegative
resultWasPositive: ...
Если вас интересует, был бы полный результат отрицательным (т. Е. Был бы он встроен в аккумулятор), вы также можете проверить флаг переполнения. Если переполнение установлено, это означает, что все, что находится в аккумуляторе, имеет неправильный знак из-за 8-битного ограничения. Таким образом, вы можете сделать эквивалент исключающего ИЛИ между переполнением и знаком:
SBC $23
BVC signIsTheOpposite
BMI resultWasNegative
JMP resultWasPositive
signIsTheOpposite:
BPL resultWasNegative
JMP resultWasPositive
Томми ответит правильно, но у меня есть более простой взгляд на это.
Все операции в ALU 6502 являются 8-битными, так что вы можете думать о вычитании, как это (за 65 и 64 долларов):
01100101
-01100100
========
00000001
Что я делаю, так это представляю, что вычитание - это 9-битная (без знака) операция с 9-м битом аккумулятора, установленным в 1, поэтому $65 - $64 будет выглядеть так:
1 01100101
- 01100100
==========
1 00000001
В то время как $64 - $65 будет выглядеть так
1 01100100
- 01100101
==========
0 11111111
Новый бит переноса - это воображаемый 9-й бит результата.
По сути, перенос устанавливается, когда операнд, интерпретируемый как число без знака, больше, чем аккумулятор, интерпретируемый как число без знака. Или быть педантичным, когда
A < operand - 1 + oldcarry
Нет, результат также может быть положительным.
Пример:
lda #$10
sec
sbc #$f0
Carry будет ясно после этого, и Аккумулятор будет $20.
Чтобы проверить положительные / отрицательные значения после вычитания, используйте флаг N(egative) регистра состояния и ветви, оценивающие его (BMI/BPL).