div divu 在 MIPS 中
div divu in MIPS
MIPS中的div
和divu
有什么区别
我看到了 add
和 addu
(link for same) 之间的区别。我对 add 和 addu 的理解:两者都对 2 的补码符号数进行操作,唯一的区别是 add 会在溢出时生成陷阱,而 addu 不会
但是 div 和 divu 之间有什么区别,我的意思是我们不会真的在这里溢出。
我尝试了以下案例,但 divu 得到了非常奇怪的结果。我只加载了商(使用 mflo),这里是输出:
num1 | num2 | div num1 num2 (qoutient) | divu num1 num2 (qoutient) |
5 | 2 | 2 | 2 |
-5 | 2 | -2 | 2147483645 |
5 | -2 | -2 | 0 |
-5 | -2 | 2 | 0 |
谁能解释一下发生的事情的逻辑!!??
一般来说,u
后缀表示“无符号”。溢出陷阱是 signed 算术的 side-effect 不应溢出,而 unsigned 算术允许溢出或回绕而不触发任何例外。
这意味着您应该在查看陷阱之前考虑有符号与无符号的差异。常规 div
指令会将其操作数视为二进制补码编码,而 divu
操作会将操作数视为无符号整数。
所有这些意味着使用相同的操作数可能会导致不同的答案,具体取决于使用的是 div
还是 divu
。
当 -5
除以 2
和 div
时,您会得到预期的答案:商为 -2,余数为 -1,这是有道理的,因为 -2 * 2 + -1 = -5
。但是当使用 divu
时,它采用无符号整数 ,-5
不被视为“负五”,而是 11111111111111111111111111111011
(这是两个-5
) 的补充表示,但它被读取为“普通”字节,其中它出现 4294967291
,当除以 2
时正确地产生 2147483645
.
简而言之:命令的 u
版本的目的是将输入视为无符号整数,即使这不会导致溢出。为什么会这样?好吧,假设您确实想找出 4294967291/2
的结果 - 您将如何使用带符号的除法来做到这一点?尝试将 4294967291
存储在 32 位寄存器中将导致一个值被解释为 -5
而不是 4294967291
。 divu
通过让您将寄存器的所有 32 位用作“数据”而不是为符号留出一位来解决这个问题。
num=lo*divisor+hi
div 5, 2 => lo= 2; hi= 1 num= 2* 2+ 1 = 5
div -5, 2 => lo=-2; hi= -1 num=-2* 2+(-1) = -5
div 5, -2 => lo=-2; hi= 1 num=-2*-2+ 1 = 5
div -5, -2 => lo= 2; hi= -1 num= 2*-2+(-1) = -5
============================================= =========
divu 5, 2 => lo=2; hi= 1
divu -5, 2 => lo=2147483645; hi= 1
exec as: divu 4294967291, 2 => lo=2147483645; hi= 1
divu 5, -2 => lo=0; hi= 5;
exec as: divu 5, 4294967294 => hi= 5; lo=0
divu -5, -2 => lo=0; hi= 4294967291 (=-5 if you see in c'2);
执行为:divu 4294967291, 4294967294 => lo=0; hi=4294967291
MIPS中的div
和divu
有什么区别
我看到了 add
和 addu
(link for same) 之间的区别。我对 add 和 addu 的理解:两者都对 2 的补码符号数进行操作,唯一的区别是 add 会在溢出时生成陷阱,而 addu 不会
但是 div 和 divu 之间有什么区别,我的意思是我们不会真的在这里溢出。
我尝试了以下案例,但 divu 得到了非常奇怪的结果。我只加载了商(使用 mflo),这里是输出:
num1 | num2 | div num1 num2 (qoutient) | divu num1 num2 (qoutient) |
5 | 2 | 2 | 2 |
-5 | 2 | -2 | 2147483645 |
5 | -2 | -2 | 0 |
-5 | -2 | 2 | 0 |
谁能解释一下发生的事情的逻辑!!??
一般来说,u
后缀表示“无符号”。溢出陷阱是 signed 算术的 side-effect 不应溢出,而 unsigned 算术允许溢出或回绕而不触发任何例外。
这意味着您应该在查看陷阱之前考虑有符号与无符号的差异。常规 div
指令会将其操作数视为二进制补码编码,而 divu
操作会将操作数视为无符号整数。
所有这些意味着使用相同的操作数可能会导致不同的答案,具体取决于使用的是 div
还是 divu
。
当 -5
除以 2
和 div
时,您会得到预期的答案:商为 -2,余数为 -1,这是有道理的,因为 -2 * 2 + -1 = -5
。但是当使用 divu
时,它采用无符号整数 ,-5
不被视为“负五”,而是 11111111111111111111111111111011
(这是两个-5
) 的补充表示,但它被读取为“普通”字节,其中它出现 4294967291
,当除以 2
时正确地产生 2147483645
.
简而言之:命令的 u
版本的目的是将输入视为无符号整数,即使这不会导致溢出。为什么会这样?好吧,假设您确实想找出 4294967291/2
的结果 - 您将如何使用带符号的除法来做到这一点?尝试将 4294967291
存储在 32 位寄存器中将导致一个值被解释为 -5
而不是 4294967291
。 divu
通过让您将寄存器的所有 32 位用作“数据”而不是为符号留出一位来解决这个问题。
num=lo*divisor+hi
div 5, 2 => lo= 2; hi= 1 num= 2* 2+ 1 = 5
div -5, 2 => lo=-2; hi= -1 num=-2* 2+(-1) = -5
div 5, -2 => lo=-2; hi= 1 num=-2*-2+ 1 = 5
div -5, -2 => lo= 2; hi= -1 num= 2*-2+(-1) = -5
============================================= =========
divu 5, 2 => lo=2; hi= 1
divu -5, 2 => lo=2147483645; hi= 1
exec as: divu 4294967291, 2 => lo=2147483645; hi= 1
divu 5, -2 => lo=0; hi= 5;
exec as: divu 5, 4294967294 => hi= 5; lo=0
divu -5, -2 => lo=0; hi= 4294967291 (=-5 if you see in c'2);
执行为:divu 4294967291, 4294967294 => lo=0; hi=4294967291