div divu 在 MIPS 中

div divu in MIPS

MIPS中的divdivu有什么区别

我看到了 addaddu (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 除以 2div 时,您会得到预期的答案:商为 -2,余数为 -1,这是有道理的,因为 -2 * 2 + -1 = -5。但是当使用 divu 时,它采用无符号整数 -5 不被视为“负五”,而是 11111111111111111111111111111011(这是两个-5) 的补充表示,但它被读取为“普通”字节,其中它出现 4294967291,当除以 2 时正确地产生 2147483645.

简而言之:命令的 u 版本的目的是将输入视为无符号整数,即使这不会导致溢出。为什么会这样?好吧,假设您确实想找出 4294967291/2 的结果 - 您将如何使用带符号的除法来做到这一点?尝试将 4294967291 存储在 32 位寄存器中将导致一个值被解释为 -5 而不是 4294967291divu 通过让您将寄存器的所有 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