Расчет флага переноса

Я пишу интерпретатор 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));

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