Определение флага переноса и переполнения в эмуляции 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 командах установлены флаги и только одна выставляет регистр статуса, поэтому эмуляторы часто хранят флаги отдельно в любой удобной форме и создают регистр статуса по требованию, и в этом случае вы не будете беспокоиться о сдвиге и компоновке вы бы просто сохранили этот результат)

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