计算进位标志

Calculating Carry Flag

我正在 Java 中编写一个 x86 解释器,并且有一个 Python 脚本可以使用 NASM 测试我对 x86 指令的实现与真实对应指令的对比。 根据此测试,除了进位标志外,所有标志都已正确设置。 有趣的部分是:

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中正确实现进位标志?

如果 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

因此,您应该使 x 和 y long,或者在添加之前转换为 longresult = ((long)Math.abs(x)) + ((long)Math.abs(y));

所有这些绝对价值业务都是不必要的,坦率地说令人困惑,并且它有一个边缘案例 Math.abs(Integer.MIN_VALUE) 是负面的(当你认真对待它时并不奇怪,但它看起来不像这个代码期望它),你可以用更简单的方式计算进位。

例如使用旧的 "result is unsigned less than one operand"。结果当然只是x + y(如int),符号与加法无关。然后用Java8,可以用Integer.compareUnsigned,否则可以用这个身份:

x <u y = (x ^ Integer.MIN_VALUE) <s (y ^ Integer.MIN_VALUE)

其中 <u<s 分别是无符号小于和有符号小于。

您还可以计算 (x & 0xffffffffL) + (y & 0xffffffffL) 并将其用于结果(转换为 int)和进位标志(第 33 位)。