CSAPP实验(1)----datalab

1 实验说明

从CSAPP课程主页下载datalab实验所需的压缩包。下图说明本次实验需要补齐的函数名列表。
CSAPP实验(1)----datalab_第1张图片

2 实验

2.1

/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
  return ~(~(~x & y)& ~(x & ~y));
}

解题思路:
利用a⊕b = (¬a ∧ b) ∨ (a ∧¬b)公式和德-摩根定律得到上面的代码.

2.2

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  return 0x1<<31; 
}

解题思路:
首先明确32位整数最小值的二进制为0x80000000.

2.3

/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
  int res = !((~(x+1))^x) & !!(~x);
  return res ;
}

解题思路:
首先明确32位整形最大值为0x7fffffff.由于题目中规定不能使用移位符号,

2.4

/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x) {
  int mask = 0xAA | (0xAA<<8) | (0xAA<<16) | (0xAA <<24);
  x = x & mask;
  return !~(x>>1 | x);
}

解题思路:
首先要获取奇数位的信息,则有mask:0xAAAAAAAA.(十六进制A的二进制表示为1010).当奇数位全为1时,(x>>1 | x)则表示0xffffffff,反之,则不成立.

2.5

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return ~x+1;
}

解题思路:
套基本公式

2.6

/* 
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */
int isAsciiDigit(int x) {
  return !((0x39 + (~x+1))>>31|(x+(~0x30+1))>>31)&0x1;
}

解题思路:
题目的等价表达式是"(0x39-x)>=0且(x-0x30)>=0".此时只需要判断符号位就能知道是否满足不等式(符号位为1表示不满足),这与函数输出的逻辑刚好相反(函数输出1表示满足整个表达式).最后利用的摩根定理得到上述代码.

2.7

/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
  
  int x1 = ~((~x +1)|x)>>31;
  return (~x1  & y ) | (x1   & z);
}

解题思路:
题目让我们写一个条件选择符,当x为0x0时选择输出z,考虑利用零的相反数是零的性质解题.

2.8

/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y) {
  int signx = x>>31 ;
  int signy = y>>31 ;
  int signal = signx ^ signy;
  int exp = ((y+(~x+1))>>31);
  
  return ((signal&( (signx&0x1) | (signy&0x0) ) ) | (!signal&!exp  ))&0x1;
}

解题思路:
等价为y-x>=0,有四类情况分类讨论

2.9

/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int logicalNeg(int x) {
  //一个数的相反数等于自身的只有零
  return ~(((~x+1)|x)>>31)& 0x1;
}

2.10

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */
/*
 * -5    1,000_0000_0000_0000_0000_0000_0000_0101 1111_1111_1111_1111_1111_1111_1111_1011  
 *  5    0,000_0000_0000_0000_0000_0000_0000_0101
 * */
int howManyBits(int x) {


 int mask1 = 0x1 | 0x1<<8 | 0x1<<16 | 0x1<<24;
  int mask2 = (x&(0x1<<31))>>31;
  int sum = 0;
  int tmp = x ^ mask2;
  
  tmp |= tmp >>1;
  tmp |= tmp >>2;
  tmp |= tmp >>4;
  tmp |= tmp >>8;  sum += (tmp >>2) & mask1;
  sum += (tmp >>3) & mask1;
  sum += (tmp >>4) & mask1;
  sum += (tmp >>5) & mask1;
  sum += (tmp >>6) & mask1;
  sum += (tmp >>7) & mask1;

  return (sum & 0xff) + ((sum>>8) & 0xff) + ((sum>>16) & 0xff) + ((sum>>24) & 0xff) + 1;
}

解题思路:
忽略符号位,把最高位的1右侧所有位都置为1,再查询1的个数,最中的结果再加1.

2.11

/* 
 * floatScale2 - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned floatScale2(unsigned uf) {

  unsigned sign = uf & 0x80000000;
  unsigned exp = uf & 0x7f800000;
  unsigned frac = uf & 0x7fffff;
  if(exp ^ 0x7f800000){//exp!=255
     if(!exp){//exp==0
      	frac <<= 1;//此时为非规格化数,尾数无隐含常数1,直接左移1位即可
     }
     else{//0
      	exp += 0x800000;//乘2
      	if((exp ^ 0x7f800000)==0){//判断乘2以后是否溢出      	
	  frac=0;//输出INF
      	} 
     }
  }
  return sign | exp | frac;  
}

解题思路:
接下来的三题,让我深刻理解了"数据类型规定了数的为宽,和相应的操作方法"这句话的意义.下图表示了浮点数的位级示意图.从图可以知道解答lab中关于浮点数的题目.
CSAPP实验(1)----datalab_第2张图片

2.12

/* 
 * floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
int floatFloat2Int(unsigned uf) {
  unsigned INF = 0x80000000;
  //提取符号位
  int s = (uf >>31) & 0x1;
  //提取阶码
  int E = uf >> 23 & 0xff;
  //提取阶数
  int e = E -127;
  if (uf == 0) return 0;
  
  //因为输入是规格化浮点数,转化为整数时第23位需要为1
  uf &= 0x00ffffff;
  uf |= 0x00800000; 
  //浮点数中0~22位的数字逻辑上位小数,当看作整数时相当于乘以了2^23
  //阶码为255或阶数大于等于32时,视为溢出,输出INF.因为int为32bit,超出即溢出,且考虑1bit符号位
  if ((uf & 0x7f80000) == 0x7f80000 || e>= 32) return INF;
  if (e<0) return 0;//若为小数,返回零
  //无符号数的移位运算都是逻辑移位 
  if (e <= 23) uf >>= 23 - e;//因为浮点数尾数宽度为23bit,位数小于等于23,尾数位右移.这是一种舍入方式
  else uf <<= e-23;//位数大于23,尾数左移

  //当符号位为负数,uf要取值为它的相反数
  if(s) uf = ~uf + 1;
  return uf; 
}

2.13

/* 
 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4
 */
unsigned floatPower2(int x) {
  //int INF = 0xff << 23;
  int INF = 0x7f800000;
  int exp = x + 127 ;
  //溢出
  if(exp >= 255) return INF;
  //为小数时
  if(exp <= 0) return 0;

  return exp<<23;
}

3 实验结果

完成实验后,在实验目录下输入 ./driver.pl 命令,会得到以下结果。
CSAPP实验(1)----datalab_第3张图片

你可能感兴趣的:(编程练习)