问题描述
如何在不使用 div
或 divu
的情况下在汇编 MIPS 中对两个 4 字节有符号整数进行除法,但复杂度较低
示例:
Input:
$a0 = -7
$a1 = 2
Output:
lo = -3
hi = -1
解决方法
您最快的选择是使用长除法。
请记住,在小学时,我们会用数字的正数进行长除法,然后在完成后加上符号。
这里没有变化,基数为 2 的有符号数
如果你直接做 -7/2 那么 FF..FFF9>>1 = FFF...FFFC 这是 -4 而不是 -3 但如果数字被认为是有符号的,那么 (~FF...FF9)+1 = 00...007; 7>>1 = 3; 7&1 = 1. -3 r -1
如果您想要非 2 的幂,那么长除法是最初的选择。你可以搜索其他算法,长除法是最简单的。
unsigned int xdiv ( int n,int d )
{
unsigned int acc;
unsigned int res;
unsigned int sign;
unsigned int remain;
unsigned int ra;
remain=0;
sign=(n^d)&(1<<31);
if(sign)
{
if(n&(1<<31))
{
n=-n;
remain=sign;
}
if(d&(1<<31)) d=-d;
}
acc=0;
res=0;
if(d==0) return(1);
for(ra=0;ra<32;ra++)
{
acc<<=1;
acc|=(n>>31)&1;
n<<=1;
res<<=1;
if(acc>=d)
{
res|=1;
acc-=d;
}
}
printf("----\n");
if(sign) res=-res;
if(remain) acc=-acc;
printf("%u %u\n",res,acc);
printf("%d %d\n",acc);
printf("%X %X\n",acc);
printf("----\n");
return(0);
}
基数 2 比基数 10 简单,分母只能进入累积值零次或一次,因此您不必做额外的工作来计算多少次(将是一个简单的减法循环)
> if(acc>=d)
{
res|=1;
acc-=d;
}
就像在小学时,您一次开始一位数字/位置,分母除以累积/下降值的次数是多少?在基数 2 中是 0 或 1 次,因此您为该位置保存 0 或 1,下拉下一位,重复它为零或一次,下拉下一位。您不断累积该动态值中的位并将其与分母进行比较,结果中添加的每一位都会减少一位。对分子中的所有位重复。
我忘了余数可能是负数,谢谢!