Расчет флага переноса
Я пишу интерпретатор x86 на Java и у меня есть скрипт Python, который проверяет мои реализации инструкций x86 на предмет их реальных аналогов с использованием NASM. Согласно этому тесту все флаги установлены правильно, кроме флага переноса. Интересная часть:
long result;
switch (op) {
case ADD:
result = Math.abs(x) + Math.abs(y);
if (result > U_MAX)
registers.carry_flag = true;
else
registers.carry_flag = false;
break;
где U_MAX - 4294967295L (установлены все 32 бита).
Все ответы, которые я нашел, не понимали, что перенос и переполнение - это две разные вещи. Итак, как я могу правильно реализовать флаг переноса в Java?
2 ответа
Весь этот бизнес с абсолютной стоимостью не нужен и откровенно запутан, и у него есть крайний случай, когда Math.abs(Integer.MIN_VALUE)
отрицательно (не так уж странно, когда вы приступаете к нему, но не похоже, что этот код ожидает его), вы можете вычислить перенос более простым способом.
Например, используя старый "результат без знака меньше одного операнда". Результат, конечно, просто x + y
(как int
), подписанность не имеет отношения к сложению. Затем с Java 8 вы можете использовать Integer.compareUnsigned, в противном случае вы можете использовать эту идентичность:
x <u y = (x ^ Integer.MIN_VALUE) <s (y ^ Integer.MIN_VALUE)
где <u
а также <s
подписаны меньше чем и подписаны меньше чем соответственно.
Вы также можете рассчитать (x & 0xffffffffL) + (y & 0xffffffffL)
и использовать его для обоих результатов (приведение к int
) и флаг переноса (33-й бит).
Если x и y являются целыми числами, то Math.abs (x) и Math.abs (y) являются целыми числами. скажем, x = y = Integer.MAX_VALUE, результат добавления Math.abs(x)+Math.abs(y) будет отрицательным, как показано этой программой:
public class t {
public static void main(String args[]) {
int x = Integer.MAX_VALUE;
int y = Integer.MAX_VALUE;
System.out.println(x+y);
}
}
$ javac t.java
$ java t
-2
Итак, вы должны либо сделать х и у long
или приведение к long
прежде чем добавить: result = ((long)Math.abs(x)) + ((long)Math.abs(y));