设A
和B
为有符号正整数,则A-B
用A+2
对B
的补码计算。
例如,在4位二进制系统中,对于有符号整数,我们有7-3=0111-0011=0111+1101=(1)0100
,括号中的1是进位。根据有符号整数的溢出规则,我们知道没有溢出,因此结果是正确的。
然而,对于无符号整数,如果我们计算7-3
会发生什么?如果我们使用上面提到的方法:
7-3=0111-0011=0111+1101=(1)0100
则根据无符号整数的溢出规则,由于执行,存在溢出。换句话说,0100
是错误的,因为有溢出。但事实上,我们知道0100
的结果是正确的。
如果我的分析是正确的,是不是错误的使用加法器来执行无符号整数减法?
你的分析不正确。实际上是CPU ALU单元依赖。:)
在第一种情况下,您正在使用4位整数,但您忘记了4位符号整数的最高位是符号!因此,您只检查进位和溢出状态,而不检查负状态位。
一般来说,二进制算术运算add和sub对于有符号整数和无符号整数是相同的。只有受影响的标志不同。
实际上你必须考虑:
- 在有符号整数算术进位, 溢出和负标志位 进位
详细解释:
补函数的挖掘是负的,所以从正得到相反的负数,从负得到正。我们可以用两种方式进行二进制补码。让我们看看第三种情况。
- At unsigned算术是compl (3) = b'0011' xor b'1111' + b'0001' =b ' 1101 ' + 携带(携带设置只在惠(0))
- 有符号算术数字是符合(3)= b'10000' - b'0011' = b'1101'什么= b'0000' - b'0011' = b'1101' + 进位(进位仅在惠(0))
在第一种情况下,函数complement也对进位进行补位,我们还有第二个进位标志的解释,名为borrow。
在第二种情况下,一切都很清楚。如果我们在补码处有进位(溢出),这意味着我们需要另一个溢出来规范减法的结果。
在这个相关问题的答案中,有C语言的示例代码,展示了如何通过加法进行减法。该代码还设置进位和溢出标志,并包含一个简单的"测试",用于添加和减去一些数字并打印结果。数字为8位。
EDIT:对于无符号整数可以使用ADD而不是SUB的正式证明和发现无符号溢出/下溢,就像从SUB中一样。
假设我们想计算a - b
,其中a
和b
是4位无符号整数,我们想通过加法执行减法,当a .
a -b = a + (-b)
因为我们是用模16运算,所以-b
= 16-b
。因此,
A -b = A + (-b) = A + (16 -b)
如果我们对a
和16-b
执行常规的无符号加法运算,则此加法运算的溢出条件(通常由CPU在其carry
标志中指示)将是这样的(请记住,我们处理的是4位整数):
a + (16 - b)> 15
让我们简化这个溢出条件:
A + 16 - b> 15
A + 16> 15 + b
A + 1> b
A> b - 1
现在让我们回忆一下,我们正在处理整数。因此,上面的代码可以重写为:
a>= b.
这是将a
和(16)-b
相加后得到进位标志= 1的条件。如果不等式不成立,我们得到进位= 0。
现在让我们回忆一下,我们对减法(a - b)的溢出/下溢感兴趣。该条件是a .
a>= b与a .由此可以得出,将a
和(16)-b
相加得到的carry
标志是减法溢出的逆,或者换句话说,通过使用适当的减法指令(例如SUB)直接从a
中减去b
而得到的borrow
标志的逆。
只需反转进位或以相反的方式处理它。
这有点难以理解,但是…我用了一些VHDL来做这个。我有一个CPU,它的内存位置是无符号的,偏移值是有符号的。
architecture Behavioral of adder16 is
signal temp: std_logic_vector (16 downto 0);
begin
eval: process(vectA,vectB,temp)
begin
temp <=(('0'& vectB) + (vectA(15) & vectA));
output <= temp( 15 downto 0);
end process;
end Behavioral;
你的分析是正确的。
使用OVERFLOW = EXOR (CARRY, ADD'/SUB)
为单次解释确定无符号加法和无符号减法(使用2的补码加法)的溢出。
在无符号加法中,溢出由
表示。CARRY = 1
正确的结果由
表示CARRY = 0
,
ADD'/SUB = 0
表示加法
溢出用1表示
同样在无符号减法中,溢出由
表示CARRY = 0
正确的结果由
表示CARRY = 1
,
ADD'/SUB = 1
用于减法
溢出用1表示
因此,我们可以在无符号加法和无符号减法中对溢出进行单一解释。