Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 不使用算术运算符执行位除法_C_Assembly_Bit Manipulation_Division - Fatal编程技术网

C 不使用算术运算符执行位除法

C 不使用算术运算符执行位除法,c,assembly,bit-manipulation,division,C,Assembly,Bit Manipulation,Division,我正试图完成一项作业,要求我为二进制算术编写三个函数。badd()是为我提供的,所以我用它来帮助编写bsub()和bmult()函数。但是,我在理解如何执行bdiv()函数时遇到了困难。我知道我需要使用右移和bsubb()函数遍历位,但我不知道如何实现它。下面是我到目前为止编写的函数。如果您注意到我在写它们时犯的任何错误(意思是bsub()和bmult()),请告诉我。谢谢 /** This function adds the two arguments using bitwise operat

我正试图完成一项作业,要求我为二进制算术编写三个函数。badd()是为我提供的,所以我用它来帮助编写bsub()和bmult()函数。但是,我在理解如何执行bdiv()函数时遇到了困难。我知道我需要使用右移和bsubb()函数遍历位,但我不知道如何实现它。下面是我到目前为止编写的函数。如果您注意到我在写它们时犯的任何错误(意思是bsub()和bmult()),请告诉我。谢谢

/** This function adds the two arguments using bitwise operators. Your      
* implementation should not use arithmetic operators except for loop
* control. Integers are 32 bits long.  This function prints a message
* saying "Overflow occurred\n" if a two's complement overflow occurs
* during the addition process. The sum is returned as the value of
* the function.
*/
int badd(int x,int y){

int i;

char sum;
char car_in=0;
char car_out;
char a,b;

unsigned int mask=0x00000001;
int result=0;

for(i=0;i<32;i++){

  a=(x&mask)!=0;
  b=(y&mask)!=0;
  car_out=car_in & (a|b) |a&b;
  sum=a^b^car_in;

  if(sum) {
     result|=mask;
  }

  if(i!=31) {
     car_in=car_out;
  } else {
     if(car_in!=car_out) {
 printf("Overflow occurred\n");
     }
  }

  mask<<=1;
}

 return result;
 }

// subracts two integers by finding the compliemnt
// of "y", adding 1, and using the badd() function
// to add "-y" and "x"
int bsub(int x, int y){

return badd(x, badd(~y, 1));
}


//add x to total for however many y
int bmult(int x,int y){

int total;
int i;
for(i=0; i < = y; i++)
{
 total = badd(total,x)
}
 return total;
}

// comment me
unsigned int bdiv(unsigned int dividend, unsigned int divisor){

// write me
return 0;
}
/**此函数使用位运算符添加两个参数。你的
*除循环外,实现不应使用算术运算符
*控制。整数的长度为32位。此函数用于打印消息
*如果出现2的补码溢出,则说“溢出\n”
*在添加过程中。将总和作为的值返回
*功能。
*/
整数相加(整数x,整数y){
int i;
字符和;
char car_in=0;
把车开出来;
字符a,b;
无符号整数掩码=0x00000001;
int结果=0;
对于(i=0;i
  • 当除数<除数 在商的小数点后加零 然后右移1
  • 现在检查除数中的位数是否等于被除数中的位数 否则,将除数向左移位,直到被除数中的位数等于除数中的位数
  • 现在减去股息,除数 然后在商中加1,确保商中有1位于正确的位置(如小数点位置)

  • 重复这个过程,直到红利为0或1。这里不多说,这只是一些基本的数学运算,在base-2中:

    unsigned int bmult(unsigned int x, unsigned int y)
    {
        int total = 0;
        int i;
    
        /* if the i-th bit is non-zero, add 'x' to total */
        /* Multiple total by 2 each step */
        for(i = 32 ; i >= 0 ; i--)
        {
            total <<= 1;
            if( (y & (1 << i)) >> i )
            {
                total = badd(total, x);
            }
        }
    
        return total;
    }
    
    unsigned int bdiv(unsigned int dividend, unsigned int divisor)
    {
        int i, quotient = 0, remainder = 0;
    
        if(divisor == 0) { printf("div by zero\n"); return 0; }
    
        for(i = 31 ; i >= 0 ; i--)
        {
            quotient <<= 1;
            remainder <<= 1;
            remainder |= (dividend & (1 << i)) >> i;
    
            if(remainder >= divisor)
            {
                remainder = bsub(remainder, divisor);
                quotient |= 1;
            }
        }
    
        return quotient;
    }
    
    unsigned int bmult(unsigned int x,unsigned int y)
    {
    int-total=0;
    int i;
    /*如果第i位为非零,则将“x”添加到总数中*/
    /*每一步乘以2的倍数*/
    对于(i=32;i>=0;i--)
    {
    总计=0;i--)
    {
    
    商在下面的代码中,我使用与问题中相同的思想实现加法和减法。唯一实际的区别是,在我的实现中,这两个函数还接受进位/借位,并生成进位/借位

    进位用于通过加法实现减法,该位有助于获得进位和借出位的正确值。基本上,我使用状态寄存器中的进位标志实现典型的CPU式加减

    携带或借用位,然后用减法实现比较,我实现了比较,没有<代码> >/Cuth>运算符,我也考虑算术,因为它不是很自然的性质。在除法函数中需要使用比较函数,因为使用.< /P> 我还避免使用

    操作符,而是使用
    ^1

    除法函数将除数作为2
    无符号整数
    ,它的最高有效部分和最低有效部分。最后,它将最高有效部分替换为余数,最低有效部分替换为商。因此,它同时进行除法和模运算,并以典型的类似CPU的方式进行除法和模运算(例如,与x86
    DIV
    指令类似)。函数成功返回1,溢出/除以0返回0

    主函数执行一个简单的测试。它将除法函数的结果与直接除法的结果进行比较,并在不匹配的情况下以错误消息终止

    我在测试部分使用了
    unsigned long long
    来测试除数=
    UINT_MAX
    ,而不会陷入无限循环。测试被除数和除数的整个值范围可能需要太多时间,这就是为什么我将它们分别限制在0xFFFF和0xFF,而不是
    UINT_MAX

    代码:

    #包括
    #包括
    无符号加法(无符号a、无符号b、无符号进位、无符号*进位)
    {
    无符号和=a^b^进位;
    未签字结转=a&b |(a | b)和结转;
    *结转率=0;
    if(总和和(结转数=除数*/)
    返回0;//溢出
    对于(i=0;i=0x80…00*/)
    {
    *dividendh=(*dividendh>(sizeof(无符号)*字符位-1));
    
    *dividendl看起来你必须结合乘法和减法来计算商和提醒,通过根据来解决,这个问题太做作了,不可能是一个实用的编程问题,应该作为一个非实际问题来解决。这是你先前问题的完全重复。
    #include <stdio.h>
    #include <limits.h>
    
    unsigned add(unsigned a, unsigned b, unsigned carryIn, unsigned* carryOut)
    {
      unsigned sum = a ^ b ^ carryIn;
      unsigned carryOuts = a & b | (a | b) & carryIn;
      *carryOut = 0;
      if (sum & (carryOuts << 1))
        sum = add(sum, carryOuts << 1, 0, carryOut);
      else
        sum |= carryOuts << 1;
      *carryOut |= (carryOuts & (UINT_MAX / 2 + 1)) >> (sizeof(unsigned) * CHAR_BIT - 1); // +-*/ are OK in constants
      return sum;
    }
    
    unsigned sub(unsigned a, unsigned b, unsigned borrowIn, unsigned* borrowOut)
    {
      unsigned diff = add(a, ~b, borrowIn ^ 1, borrowOut);
      *borrowOut ^= 1;
      return diff;
    }
    
    unsigned less(unsigned a, unsigned b)
    {
      unsigned borrowOut;
      sub(a, b, 0, &borrowOut);
      return borrowOut;
    }
    
    int udiv(unsigned* dividendh, unsigned* dividendl, unsigned divisor)
    {
      int i;
      unsigned tmp;
    
      if (less(*dividendh, divisor) ^ 1/* *dividendh >= divisor */)
        return 0; // overflow
    
      for (i = 0; i < sizeof(unsigned) * CHAR_BIT; i++)
      {
        if (less(*dividendh, UINT_MAX / 2 + 1) ^ 1/* *dividendh >= 0x80...00 */)
        {
          *dividendh = (*dividendh << 1) | (*dividendl >> (sizeof(unsigned) * CHAR_BIT - 1));
          *dividendl <<= 1;
    
          *dividendh = sub(*dividendh, divisor, 0, &tmp);/* *dividendh -= divisor; */
          *dividendl |= 1;
        }
        else
        {
          *dividendh = (*dividendh << 1) | (*dividendl >> (sizeof(unsigned) * CHAR_BIT - 1));
          *dividendl <<= 1;
    
          if (less(*dividendh, divisor) ^ 1/* *dividendh >= divisor */)
          {
            *dividendh = sub(*dividendh, divisor, 0, &tmp);/* *dividendh -= divisor; */
            *dividendl |= 1;
          }
        }
      }
    
      return 1;
    }
    
    int udiv2(unsigned* dividendh, unsigned* dividendl, unsigned divisor)
    {
      unsigned long long dividend =
        ((unsigned long long)*dividendh << (sizeof(unsigned) * CHAR_BIT)) | *dividendl;
    
      if (*dividendh >= divisor)
        return 0; // overflow
    
      *dividendl = (unsigned)(dividend / divisor);
      *dividendh = (unsigned)(dividend % divisor);
    
      return 1;
    }
    
    
    int main(void)
    {
      unsigned long long dividend, divisor;
    
      for (dividend = 0; dividend <= /*UINT_MAX*/0xFFFF; dividend++)
        for (divisor = 0; divisor <= /*UINT_MAX*/0xFF; divisor++)
        {
          unsigned divh = 0, divl = (unsigned)dividend, divr = (unsigned)divisor;
          unsigned divh2 = 0, divl2 = (unsigned)dividend;
    
          printf("0x%08X/0x%08X=", divl, divr);
    
          if (udiv(&divh, &divl, divr))
            printf("0x%08X.0x%08X", divl, divh);
          else
            printf("ovf");
    
          printf(" ");
    
          if (udiv2(&divh2, &divl2, divr))
            printf("0x%08X.0x%08X", divl2, divh2);
          else
            printf("ovf");
    
          if ((divl != divl2) || (divh != divh2))
          {
            printf(" err");
            return -1;
          }
    
          printf("\n");
        }
    
      return 0;
    }