Abh*_*hav 2 unsigned signed mips integer-overflow double-precision
我正在学习计算机算术.我使用的书(Patterson和Hennessey)列出了以下问题.
写mips代码以对64位数据进行双精度整数减法.假设第一个操作数在寄存器$ t4(hi)和$ t5(lo)中,第二个在$ t6(hi)和$ t7(lo)中.
我对答案的解决方案是
sub $t3, $t5, $t7 # Subtract lo parts of operands. t3 = t5 - t7
sltu $t2, $t5, $t7 # If the lo part of the 1st operand is less than the 2nd,
# it means a borrow must be made from the hi part
add $t6, $t6, $t2 # Simulate the borrow of the msb-of-low from lsb-of-high
sub $t2, $t4, $t6 # Subtract the hi's. t2 = t4 - t6
Run Code Online (Sandbox Code Playgroud)
然而,作者给出了针对该问题的解决方案如下
对于有符号的双精度整数,
subu $t3, $t5, $t7
sltu $t2, $t5, $t7
add $t6, $t6, $t2
sub $t2, $t4, $t6
Run Code Online (Sandbox Code Playgroud)
对于无符号双精度整数,
subu $t3, $t5, $t7
sltu $t2, $t5, $t7
addu $t6, $t6, $t2
subu $t2, $t4, $t6
Run Code Online (Sandbox Code Playgroud)
我在操作的不同的理解sub/add,并subu/addu在产生溢出的异常sub/add,而不是在subu/addu.无论sub/add和subu/addu减/加操作数的位和操作数的解释被符号或无符号使得在不同的结果没有什么区别slt和sltu说明.
问题1
我从作者推断出解决方案正在处理溢出检测,而我在解决方案中没有想到相同的问题.我对吗?还有其他我想念的东西吗?
问题2
假设我的上述推论是正确的,为什么在通过使用addu和减去无符号双精度的情况下为作者提供的解决方案关闭溢出检测subu?
对于加法和减法,除了溢出的概念之外,有符号和无符号操作数之间没有区别.当结果的数值与您获得的位序列的解释不匹配时,会发生溢出.
例如,考虑8位序列(MIPS具有32位寄存器,但对于我的示例,8位更容易).让我们假设无符号解释:8位序列表示0到255(含)之间的数值.如果我将10010011(数值147)添加到01110110(数值118),那么我得到00001001(数值9).9不等于147 + 118.我得到那个结果,因为数学值是265,不能适合8位.加法结果需要9位,但上面的第9位已被删除.
现在,想象一下带有签名解释的相同示例.10010011现在的数值为-109.01110110仍然具有数值118,并且所获得的结果(00001001)具有值9. -109和118的数学和是9,因此没有溢出.
这意味着溢出的概念取决于您如何解释这些值.有符号和无符号解释的加法机制相同(对于相同的输入比特序列,您获得相同的输出比特序列 - 这是对负有符号值使用二进制补码的全部要点)但溢出处理不同.
MIPS架构提供了在溢出时触发异常的方法.从概念上讲,32位字有三种可能的加法运算:
MIPS实现前两种添加,分别使用addu和add操作码.在MIPS文档中,它们分别被称为未签名和签名的算术.没有用于在无符号溢出上引发异常的操作码.在实践中,C编译器只使用addu,但它们可以add用于签名类型(这是C标准允许的,但会破坏大量现有代码).Ada编译器使用,add因为Ada强制执行溢出检查.
话虽如此...
Patterson和Hennessey希望在64位整数上实现有符号和无符号算术.对于未签名的算术,他们不希望任何例外,因此他们使用addu和subu.对于带符号的算术,当数学结果不适合带有带符号解释的64位序列时,他们希望发生异常.它们不希望引发异常,因为在处理低32位的一半时会出现一些类似寄生溢出的情况.这就是他们使用subu低部件的原因.
你的解决方案是错误的,因为它可能引发一个不应该的例外.假设您要从-2000000000减去2000000000(二十亿)(减去二十亿).数学结果是40亿(四十亿).两个操作数和结果肯定适合64位(可表示的范围是-9223372036854775808到9223372036854775807).因此,对于64位带符号的算术,没有溢出:应该没有异常.但是,在这种情况下,您的第一个sub将报告溢出.这sub适用于32位值和带符号的32位运算.它的操作数将01110111001101011001010000000000和10001000110010100110110000000000.请注意,这些值都适合在32位:这些值的32位有符号的解释分别为,加和减二百亿.然而,减法结果是四十亿,并且它不适合32位(作为有符号数).因此,你sub提出了一个例外.
根据经验,溢出检测是指依赖于符号解释的操作,这会影响对最重要位的处理.对于大整数算术,除最重要之外的所有单词都应视为无符号,因此addu/ subu无处不在.作为第一步,如果你第一次专注于未签名的算术,事情会更容易理解,没有例外(那么你只是使用addu和subu,永远 add或者sub).