CSAPP实验

  • 实验目的:
    1更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。  
    2.实验中使用有限类型和数量的运算操作实现一组给定功能的函数,在此过程中加深对数据二进制编码表示的了解
    3. 熟悉linux基本操作命令,其中常用工具和程序开发环境
    4.完善bits.c的各个函数,实现其功能,并通过.btest的测试
  • 实验要求
    1. 尽快熟悉linux基本操作命令,还有其中常用工具和程序开发环境
    2. 除浮点数函数实现外,只能使用顺序程序结构,禁用if, do, while, for, switch等。
      有限操作类型,! ~  &  ^  |  +  <<  >>  各函数不一样
      禁用(!=、==、&&、|| 等组合操作符)
      常量值范围   0~255
      禁用强制类型转换
      禁用整型外的任何其它数据类型
      禁用定义和宏
      不得使用函数
      具体要求可参看bits.c各函数框架的注释
      可以使用循环和条件控制;
      可以使用整型和无符号整型常量及变量(取值不受[0,255]限制);
      不使用任何浮点数据类型、操作及常量。
      可以使用int和unsigned两种整型数据
      禁用浮点数据类型、struct、union或数组结构。
      浮点数函数均使用unsigned型数据表示浮点数据。
      float_abs等函数必须能处理全范围的变量值,包括(NaN)和infinity。
  • 实验内容及分析
1.题目要求:将32位数的末尾变为0

int pow2plus1(int x)

{

return (1 << x) + 1;//先向右移动一位,再向右移动一位,右移后首位不会对结果影响,再左移则末尾自动补0

}

2. 题目要求:第N(0-3)个字节0变为1,1变为0

int byteNot(int x, int n)

{

    int temp=0xFF;

    temp=temp<<(n<<3); //此时不清楚到底要对哪个字节进行处理,所以用0xFF(前面全为零),然后对其进行移位,使其全为一的字节对准要处理的字节;n代表的是字节,故移位时要乘8.

    return x^temp;//异或运算,与0异或等于本身,与1异或取反。

}



3. 题目要求:比较第n个字节是否相等

int byteXor(int x, int y, int n)

{

    int temp=0xFF;//比较第n个字节是否相等,就是把其他位置零,只留这一个字节,处理方法同上一题。

    temp=temp<<(n<<3);

    x=x&temp;

    y=y&temp;//把其他位置零,只留这一个字节

    return !!(x^y);//x,y若相同,则进行异或运算后所有位全为0,若不等,则存在1,结果大于零。对结果进行两次逻辑非(逻辑非:若为0则结果为1,若不为0,结果为1),正好得到符合题目要求的返回值。

}



4. 题目要求:实现逻辑与

int logicalAnd(int x, int y)

{

    return (!!x)&(!!y);//对每个数进行两次逻辑非,两个数就变成0或1,前面31位均为0,这时按位与运算对于最后一位数操作,得出的结果即为逻辑与的值。

}



5. 题目要求:实现逻辑或

int logicalOr(int x, int y)

{

  return (!!x)|(!!y);//同上

}



6. 题目要求:将32位数中的前n为移动至末位

int rotateLeft(int x, int n) {

    int a=x<<n;//把除前n位外所有数向前移动n位,相当于低(32-n)位,放到高位,低n位为0。

    int b=x>>(32-n);//高n位移动到低n位

    int c=~((~0)<<n);//0先取反,即为32个1,向右移动n位,再取反,即为低n位为1,前面全是0,用于把b前(32-n)位置零

    b=c&b; //这三步是:取出高n位,放到低n位,其余位为0

    return a|b;//a和b合并

}



7. 题目要求:32位数中含有奇数个1返回1,含有偶数个1则返回0

int parityCheck(int x)

{

   x=x^(x>>16);

   x=x^(x>>8);

   x=x^(x>>4);

   x=x^(x>>2);

   x=x^(x>>1);

   return x & 0x1;

}//异或运算相当于不进位的加法,现对其分为等长的两部分,再进行异或运算,对应的位置,如果是两个1,结果为0,1个1,结果为1;再重复此过程,直至最后移动1位。若为偶数个1,在这个过程中,1会两两结合,变为0;奇数个会最后剩下一个1在最低位,与0x1按位与,结果只剩最低位,即为所需结果。



8. 题目要求:2*x后是否溢出

int mul2OK(int x)

{

    int s1=(x>>31)&0x1;//取x符号位

    int s2=((x<<1)>>31)&0x1;//取结果的符号位

    return !!!(s1^s2);//若符号位不同则溢出

}



9. 题目要求:返回x*3/2后的结果

int mult3div2(int x)

{

  int a=x;

   a=(a<<1)+a;//乘以三

  int sign=(a>>31)&0x1;// 取出符号位

  int low=a&0x1; //取出最低位

  a=a>>1;//除以二

  a=a+(sign & low);//默认的舍入方式为向左舍入,这对于正数来说是满足题目的向零舍入的要求,但负数不满足。但如果负数为偶数,即最低位为0,结果为整数,没有舍入,不需处理;为负奇数,则需要加一(原来是向左,现加一实现向零舍入)。即只有负奇数要处理,而其符号位和最低位均是1,做按位与得1,加到结果中。

  return a;

}



10. 题目要求:x-y是否溢出

int subOK(int x, int y) {

   int result=x+(~y+1);//减去一个数就是加上其补码,补码的求法为取反加一

   int a=x^y;//判断两个运算的数是否同号

   int b=x^result;//判断结果与被减数是否同号

   int c=!((a&b)>>31);//取符号位再取非即为结果

  return c;

}//减法判断是否溢出,原理:负数减负数,正数减正数均不可能溢出。只有负数减去正数结果为正,和正数减负数结果为负才溢出。即两个运算的数不同号,结果与被减数不同号,才溢出。



11. 题目要求:取x的绝对值

int absVal(int x)

{

   int sign=(x>>31)&0x1; //取符号位

   int judge=sign+(~0);//符号位加上全1,即正数的时候为全1,负数时候为全0

   x=(x&judge)|(~judge&(~x+1));//用judge的值是否为0实现(x>0) ? x : -x

    return x;

}



12. 题目要求:当参数为NaN时,返回参数

unsigned float_abs(unsigned uf)

{

   unsigned result=uf & 0x7FFFFFFF;

   if(result>0x7F800000)

      return uf;

   else

      return result;

}//先将uf化为无符号数result,判断result是否为NaN(NaN表示的数阶码全为1,且尾数为非0),如果是返回uf,否则返回result



13. 题目要求:返回表达式(int)f的位级等效值(将float转换为int),任何超出范围的内容(包括NaN和infinity)都应返回0x80000000

int float_f2i(unsigned uf) {

  unsigned a;

  unsigned b;

  unsigned c;

  a=(uf>>31)&0x1; //提取符号位

  b=(uf>>23)&0x000000ff; //提取阶码

  c=uf&0x007ffff+0x00800000; //提取尾数,在第24位加1,因为IEEE754标准尾数默认省略1

  if(((uf&0x7fffffff)>0x7ff00000)||(b>158)) //NaN或者小数点右移溢出,b减去127之后,大于31,而int最多31位,超过其表示范围

  {

     return 0x80000000;

  }

  if(b<127)//阶码小于0,即为小数,int不能表示小数,返回0

  {

     return 0;

  }

  if(a==1)//负数

  {

     if((b-127)>23)//需要向左移位

     {

        c=~(c<<(b-150))+1;//补码

        return c;

      }

      else if((b-127)<23) //需要向右移位

      {

         c=~(c>>(150-b))+1;

         return c;

      }

  }

  if(a==0)//正数,其余同上

 {

   if((b-127)>23)

     {

        c=c<<(b-150);

        return c;

      }

      else if((b-127)<23)

      {

         c=c>>(150-b);

         return c;

      }

 }

}
  • 实验结果

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值