用 3 位数字来考虑这些要容易得多,它都是可伸缩的。嗯,如果这是签名的(您没有在高级代码中指定/发布),那么四位更好,因为您使用了 5。遍历 5 附近的数字(这显示了 alu 的输出)
cmp reg,5
0111 - 0101 = 0111 + 1010 + 1 = 10010
0110 - 0101 = 0110 + 1010 + 1 = 10001
0101 - 0101 = 0101 + 1010 + 1 = 10000
0100 - 0101 = 0100 + 1010 + 1 = 01111
0011 - 0101 = 0011 + 1010 + 1 = 01110
现在您必须了解硬件的工作原理。某些处理器系列在执行减法运算时会反转来自 alu 的进位标志,而其他处理器系列则不会。无论哪种方式,您都可以在 5 - 5 点看到状态变化。而且你在这里也不需要进位标志,代码不使用它。
如果您正在做有符号数学,那么也可以尝试一些负数。
0000 - 0101 = 0000 + 1010 + 1 = 01011
1111 - 0101 = 1111 + 1010 + 1 = 11010
1110 = 0101 = 1110 + 1010 + 1 = 11001
这为问题提供了一些线索。
有符号溢出定义为进位不等于加法器的 msbit 上的进位。这可能会变得混乱,所以我们只需要知道边界在哪里。
0111 - 0101 = 7 - 5 = 2
0110 - 0101 = 6 - 5 = 1
0101 - 0101 = 5 - 5 = 0
0100 - 0101 = 4 - 5 = -1
0011 - 0101 = 3 - 5 = -2
等等。使用这个 4 位模型,在有符号解释中,我们被限制为 +7 (0b0111) 到 -8 (0b1000)。所以在 -3 - 5 之后我们会遇到麻烦:
1110 - 0101 = 1110 + 1010 + 1 = 11001 , -2 - 5 = -7
1101 - 0101 = 1101 + 1010 + 1 = 11000 , -3 - 5 = -8
1100 - 0101 = 1100 + 1010 + 1 = 10111 , -4 - 5 = 7 (-9 if we had more bits)
1011 - 0101 = 1011 + 1010 + 1 = 10110 , -5 - 5 = 6 (-10 if we had more bits)
1010 - 0101 = 1010 + 1010 + 1 = 10101 , -6 - 5 = 5 (-11 if we had more bits)
1001 - 0101 = 1001 + 1010 + 1 = 10100 , -7 - 5 = 4 (-12 if we had more bits)
1000 - 0101 = 1000 + 1010 + 1 = 10011 , -8 - 5 = 3 (-13 if we had more bits)
后五个是有符号溢出,有符号结果不能用可用位数表示。(请记住,我们现在正在使用四位系统,最高位是进位位,当您查看结果时可以将其移除)。
带符号的标志只是结果的 msbit,这也改变了有趣的边界。设置有符号标志(结果的毫秒位)的情况是低于 5 的正 (eax) 值和不导致有符号溢出的负数(+4 到 -3)。所有这些都在 <5 类别中,因此他们希望得到 2 的结果。第一个测试查找设置了符号的情况,为什么还要麻烦然后测试有符号溢出?这是没有意义的,我们已经知道所有签名的结果都在小于 5 的类别中。如果签名溢出不会伤害额外的跳跃。
因此,如果您通过 js 登录失败,则符号位关闭,即大于或等于 5 的数字(希望结果为 1)或结果为负数足以导致有符号溢出(希望结果为 2)。所以 jo elseblock 通过提取 2 个案例的结果(有符号溢出,非常否定)来对这两个案例进行排序。jmp thenblock 取大于 5 的正数。
在我看来,你在这里做有符号数学(使用有符号溢出标志有点明显)。由于您使用 5 来比较和签名数学,因此您的系统中需要 4 位或更多位来实现此代码,因此 8、32、64、123456 位,它与 4 位系统的工作方式相同并不重要(对于这个比较)。我发现最小化位数来进行分析更容易。像这样的硬编码比较使它变得容易得多,就像上面、at和下面的手工计算结果一样。然后遍历有符号数的全零(零)到全一(减一),并且非常负数进入有符号溢出范围。对于无符号数字,它更容易一些,但过程相同。