进行二进制减法时如何检测溢出
How is overflow detected when doing binary subtraction
假设我们有 3 位可以玩。我将在 2 的补码中表示正负 3:
+3 = 0b011
-3 = 0b101
在进行 加法 时,当像这样发生溢出时,你总是有一个悬空位 (-3) + (+3)
:
1 0 1
+ 0 1 1
-----
1 0 0 0
但是减法 (-3) - (+3)
呢?
1 0 1
- 0 1 1
-----
0 1 0
0b010
是 2
,这不是我们预期的 -6
的正确结果。有溢出
甚至没有生成额外的位,那么如何检测到溢出?
我想解决这个问题的正确方法是先对输入进行签名扩展?
可以通过(进位到 MSB)XOR(进位到 MSB)创建溢出标志。
如何在逻辑中检测有符号溢出
(-3) - (+3) = (-3) + (-3) = (-3) + (~3) + 1
用小学数学和补码
1
101
+ 100
======
完成
1011
101
+ 100
======
010
当msbit的进位和出位不同时,会发生SIGNED溢出。我们在这里看到的。另一种说法是,使用反转操作数 B,如果操作数的 msbits 相同且结果不相同,则它是有符号溢出。
请注意,msbit 的进位不是借位,因此 1 表示没有借位,0 表示有借位。一些处理器架构反转进位并称其为借位,而另一些则没有。这两种解决方案都有效,您只需要让比较逻辑匹配并用借位减去即可。
对于小学数学,我们可以继续添加列。如果我们可以简单地在寄存器中增加一位,我们就可以获得加法和减法的完整答案。对于乘法,我们需要两倍的位数。对于 3 位操作数,我们需要 6 位结果才不会溢出。作为补充,理想情况下,您需要一个 6 位分子作为一个三位除数。并非所有指令集都提供此功能。是的,对于有符号运算,您需要对扩展符号进行签名,而对于无符号运算,您需要零填充,因此有符号乘法和无符号乘法之间的区别。对于 3 位结果(乘法),signed/unsigned 无关紧要(像小学一样在纸和铅笔上做,这应该是显而易见的)。同样,对于 3 位加法或减法,无需知道无符号与有符号。
用加法和减法虽然正常的解法是加进位,减法借位。 -3 - +3 给出 -6 我们不能用 3 位表示,我们需要 4 但如果我们假设 3 位寄存器那么我们唯一能做的就是 6。这意味着我们真的在尝试做 111101 - 000011.
1011
111101
+111100
======
010
如果我们在视觉上这样做并将其切成两半
1 011
111 101
+111 100
============
010
我们可以使用第二条指令完成减法(借位减法)
1111
111
+111
=====
111
111010为-6,没有溢出。关键是让下半部分的进位进入上半部分的进位。
如果体系结构在减法的途中反转进位位,那么它需要在途中将借位反转为带借位的减法,否则如果它没有将其反转出 sub 则不要将其转换为 sbb。 Add 和 adc (add with carry) 的工作方式相同,只是没有反转,进位位作为 msbit 的进位进入 adc。
乘法并不那么简单,它不是一个位的东西,你需要整个寄存器的位,所以一些架构会给你 3 位乘以 3 位等于 6 位有符号和无符号乘法指令。但是对于加法和减法没有真正的需要,使用进位位和包含其余位的 memory/registers 的附加指令。你可以 add/subtract 和你 memory/registers 一样宽,1000 位加 1000 位很容易,它只是一个加法和一组连续的 adc。
假设我们有 3 位可以玩。我将在 2 的补码中表示正负 3:
+3 = 0b011
-3 = 0b101
在进行 加法 时,当像这样发生溢出时,你总是有一个悬空位 (-3) + (+3)
:
1 0 1
+ 0 1 1
-----
1 0 0 0
但是减法 (-3) - (+3)
呢?
1 0 1
- 0 1 1
-----
0 1 0
0b010
是 2
,这不是我们预期的 -6
的正确结果。有溢出
甚至没有生成额外的位,那么如何检测到溢出?
我想解决这个问题的正确方法是先对输入进行签名扩展?
可以通过(进位到 MSB)XOR(进位到 MSB)创建溢出标志。
如何在逻辑中检测有符号溢出
(-3) - (+3) = (-3) + (-3) = (-3) + (~3) + 1
用小学数学和补码
1
101
+ 100
======
完成
1011
101
+ 100
======
010
当msbit的进位和出位不同时,会发生SIGNED溢出。我们在这里看到的。另一种说法是,使用反转操作数 B,如果操作数的 msbits 相同且结果不相同,则它是有符号溢出。
请注意,msbit 的进位不是借位,因此 1 表示没有借位,0 表示有借位。一些处理器架构反转进位并称其为借位,而另一些则没有。这两种解决方案都有效,您只需要让比较逻辑匹配并用借位减去即可。
对于小学数学,我们可以继续添加列。如果我们可以简单地在寄存器中增加一位,我们就可以获得加法和减法的完整答案。对于乘法,我们需要两倍的位数。对于 3 位操作数,我们需要 6 位结果才不会溢出。作为补充,理想情况下,您需要一个 6 位分子作为一个三位除数。并非所有指令集都提供此功能。是的,对于有符号运算,您需要对扩展符号进行签名,而对于无符号运算,您需要零填充,因此有符号乘法和无符号乘法之间的区别。对于 3 位结果(乘法),signed/unsigned 无关紧要(像小学一样在纸和铅笔上做,这应该是显而易见的)。同样,对于 3 位加法或减法,无需知道无符号与有符号。
用加法和减法虽然正常的解法是加进位,减法借位。 -3 - +3 给出 -6 我们不能用 3 位表示,我们需要 4 但如果我们假设 3 位寄存器那么我们唯一能做的就是 6。这意味着我们真的在尝试做 111101 - 000011.
1011
111101
+111100
======
010
如果我们在视觉上这样做并将其切成两半
1 011
111 101
+111 100
============
010
我们可以使用第二条指令完成减法(借位减法)
1111
111
+111
=====
111
111010为-6,没有溢出。关键是让下半部分的进位进入上半部分的进位。
如果体系结构在减法的途中反转进位位,那么它需要在途中将借位反转为带借位的减法,否则如果它没有将其反转出 sub 则不要将其转换为 sbb。 Add 和 adc (add with carry) 的工作方式相同,只是没有反转,进位位作为 msbit 的进位进入 adc。
乘法并不那么简单,它不是一个位的东西,你需要整个寄存器的位,所以一些架构会给你 3 位乘以 3 位等于 6 位有符号和无符号乘法指令。但是对于加法和减法没有真正的需要,使用进位位和包含其余位的 memory/registers 的附加指令。你可以 add/subtract 和你 memory/registers 一样宽,1000 位加 1000 位很容易,它只是一个加法和一组连续的 adc。