在没有 div 和 divu 的情况下对汇编 MIPS 中的有符号整数进行除法

问题描述

如何在不使用 divdivu 的情况下在汇编 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,下拉下一位,重复它为零或一次,下拉下一位。您不断累积该动态值中的位并将其与分母进行比较,结果中添加的每一位都会减少一位。对分子中的所有位重复。

我忘了余数可能是负数,谢谢!