Занимать во время операции вычитания (инструкция 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).

Другие вопросы по тегам