Определение флага переноса и переполнения в эмуляции 6502 в Java?
Я делаю эмулятор 6502, и я застрял (или, по крайней мере, так думаю) уже в начале (реализуя операцию АЦП). Проблема в том, что я должен определить, есть ли перенос или переполнение. Дело в том, что я не могу понять разницу между ними в моей реализации. Я знаю, что перенос - это когда присутствует 9-й бит после операции, и я знаю, что переполнение происходит, когда результат больше 255. Не означает ли это, что определение переноса и флаг переполнения - это одно и то же?
if(result > 255) {
carry = 1;
overflow = 1;
} else {
carry = 0;
overflow = 0;
}
Это не правильно? А если нет, то что правильно и почему?
1 ответ
Флаг переполнения указывает, когда знак числа изменился неправильно. Таким образом, переполнение происходит, если вы добавляете два положительных числа и получаете отрицательный результат. Существует также переполнение, если вы добавите два отрицательных числа и получите положительный результат.
Вы не можете получить переполнение при добавлении двух чисел разных знаков, потому что диапазон не позволяет это. Наименьший положительный плюс наибольший отрицательный - это 0 + (-128), что подходит отлично - 0 плюс все, что умещается в 8 бит, очевидно, уместится в 8 бит. Наименьший отрицательный плюс наибольший положительный - -1 + 127 = 126. Что подходит.
(РЕДАКТИРОВАТЬ: и даже с переносом, 0 + -128 + 1 = -127, который подходит, и -1 + 127 + 1 = 127, который подходит)
Таким образом, переполнение устанавливается, если два входа с одним и тем же знаком дают результат с другим знаком. Иначе это понятно.
Вы можете выразить это как простую побитовую операцию над знаковыми битами. Предположим, у вас есть + b = c.
a ^ b
будет иметь 1 в бите знака, если знаки отличались. Вы хотите знать обратное. Так:
~(a ^ b)
дает 1 в бите знака, если знаки были одинаковыми. Это первая часть теста. Предположим, что a и b имели один и тот же знак, вы можете проверить c против любого из них. На этот раз вы хотите проверить на разницу, так что просто:
a ^ c
Вам нужно установить проверенный бит в обеих частях теста, чтобы вы могли объединить их с двоичным кодом и (оставив много скобок, чтобы связать их со словесными рассуждениями):
(~(a ^ b))&(a ^ c)
Вам нужен только бит знака, поэтому замаскируйте его так:
(~(a ^ b))&(a ^ c)&0x80
Это оценит 0x00
если флаг переполнения должен быть четким и 0x80
если это должно быть установлено. Так что просто сдвиньте это на место.
(в сторону: хотя в 6502 командах установлены флаги и только одна выставляет регистр статуса, поэтому эмуляторы часто хранят флаги отдельно в любой удобной форме и создают регистр статуса по требованию, и в этом случае вы не будете беспокоиться о сдвиге и компоновке вы бы просто сохранили этот результат)