CSAPP-datalab
in 技术 with 0 comment

CSAPP-datalab

in 技术 with 0 comment

CSAPP-datalab

使用docker环境进行实验

因为是mac系统,它实验里面的自动测试无法进行,所以还是使用linux 的docker ,网上已经有现成的方法和docker image所以直接使用,记录一下过程

下载镜像:

docker run -d -p 9912:22 --name datalab yansongsongsong/csapp:datalab

进入实验环境:

docker exec -it datalab /bin/zsh

很贴心zsh 都配置好了,可惜没有vim的配置

Datalab

bitXor

tmin

isTmax

allOddBits

negate

isAsciiDigit

conditional

int conditional(int x, int y, int z) {
  //return 2;
  x = !!x;  //判断x是否为0,x=0,则赋值0,x不为0赋值1
  x = ~x + 1;   //取相反数,最高位有变化
  return (x&y) | (~x&z);  //x为0返回则z,x为1返回y
}

isLessOrEqual

 int isLessOrEqual(int x, int y) {
   int sign = !(x>>31)^!(y>>31);      // is 1 when signs are different
   int a = sign & (x>>31);            // diff signs and x is neg, gives 1
   int b = !sign & !((y+(~x+1))>>31); // same signs and difference is positive or = 0, gives 1
   return a | b;
 }

logicalNeg

howManyBits

int howManyBits(int x) {
  int b16,b8,b4,b2,b1,b0;
  int sign=x>>31;
  x = (sign&~x)|(~sign&x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)

// 不断缩小范围
  b16 = !!(x>>16)<<4;//高十六位是否有1
  x = x>>b16;//如果有(至少需要16位),则将原数右移16位
  b8 = !!(x>>8)<<3;//剩余位高8位是否有1
  x = x>>b8;//如果有(至少需要16+8=24位),则右移8位
  b4 = !!(x>>4)<<2;//同理
  x = x>>b4;
  b2 = !!(x>>2)<<1;
  x = x>>b2;
  b1 = !!(x>>1);
  x = x>>b1;
  b0 = x;
  return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位
}
int howManyBits(int x) {
  method 1,hard understand,but short;
  int n = 0;^i
  int val = x^(x << 1);
  n += ((!!(((~0) << (n + 16)) & val)) << 4);
  n += ((!!(((~0) << (n + 8)) & val)) << 3);
  n += ((!!(((~0) << (n + 4)) & val)) << 2);
  n += ((!!(((~0) << (n + 2)) & val)) << 1);
  n += !!(((~0) << (n + 1)) & val);
  return n + 1;
}

float_twice

unsigned float_twice(unsigned uf) {

  int exp = (uf&0x7F800000)>>23;   //取出阶码
  int sign = uf&(1<<31);   //取符号位
  if(exp == 0) return uf<<1|sign;    //非规格化数,uf*2加上符号位即可
  if(exp == 255) return uf;   //无穷大或者NaN,直接返回自身
  exp++;  //如果uf乘以2(阶码加一)后变成255就返回无穷大
  if(exp == 255) return (0x7F800000|sign); 
  return (exp<<23)|(uf&0x807FFFFF); //返回阶码加1后的符号原数
}

float_i2f

unsigned float_i2f(int x) {
  int sign, exp, frac, bitc, tailb;
  if(x == 0) return 0;
  else if(x == 0x80000000) return 0xCF000000;

  sign = (x >> 31) & 1;
  if(sign) x = -x;

  bitc = 1;
  while((x >> bitc) != 0)
    bitc++;
  bitc--;

  exp = bitc + 127;

  x = x << (31 - bitc);
  frac = (x >> 8) & 0x7FFFFF;

  if (bitc > 23) {
    tailb = x & 0xFF;

    if ((tailb > 128) || ((tailb == 128) && (frac & 1))) {
      frac += 1;
      if (frac >> 23) {
         exp += 1;
         frac = 0;
      }
    }
  }
  return (sign << 31) | (exp << 23) | frac;
}

float_f2i

int float_f2i(unsigned uf) {
  int exp = (( uf & 0x7F800000) >> 23) - 127;  //计算指数
  int sign = uf >> 31; //取符号位
  int frac = ((uf & 0x007FFFFF) | 0x00800000);
  if(!(uf&0x7FFFFFFF)) return 0;  //如果原浮点数为0,则返回0

  if(exp > 31) return 0x80000000;  //如果原浮点数大于31,返回溢出值
  if(exp < 0) return 0;  //如果浮点数小于0,返回0

  if(exp > 23) frac = frac << (exp - 23); //将小数转化为整数
  else frac = frac >> (23 -exp);

  if(!((frac >> 31) ^ sign)) return frac;  //判断是否溢出,若符号位没有变化,则没有溢出,返回正确的值
  else if(frac >> 31) return 0x80000000;  //原数为正值,现在为负,返回溢出值
  else return ~frac + 1;   //原数为负值,现在为正值,返回相反数。
}

结果

image-20201029211825806

image-20201029211924864

总结

总的来说datalab还是比较简单的一个lab,考察的都是一些位操作的方式,能够更底层的了解到数字的表示方法,有一些题目涉及到数电和离散逻辑之类的技巧,有一些非常精妙的解决办法吧,虽然不久之后可能都忘记了,但是写在这里做一个记录,方便需要的时候在复习。

Reference

  1. https://zhuanlan.zhihu.com/p/82529114
  2. https://yieldnull.com/blog/4b85a93fe9e4c80735233aa6dff922245f303698/#float_i2f
  3. https://zhuanlan.zhihu.com/p/28335741
  4. https://www.cnblogs.com/Xlgd/p/12667422.html
  5. https://zhuanlan.zhihu.com/p/59534845
  6. https://www.ravenxrz.ink/archives/2d758396.html
  7. https://wdxtub.com/csapp/thick-csapp-lab-1/2016/04/16/

下载资料

  1. 实验说明书
  2. 实验代码
  3. 实验代码-我写的
Comments are closed.