CSAPP lab1实验(2)

Hello world,hello blog!

Posted by 吴柚 on May 30, 2019

前言

CSAPP的内容并没有完全吃透,关于曲老师指定的六月份学习书籍《软件安全分析与应用》已经在网上购买,六月的前一段时间同时学习两本书的内容,后面的时间就学习下一本书的内容。

补码

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

要求:求x是否在n位补码的范围内;

解题思路:x是32位表示,所以最高位在32位,而不是在第n位,所以不能直接右移解决问题,要写几个数字仔细观察,如果是非负数,在n位范围内,应该只有最低n-1位里有1,如果是负数,应该是只有最低n-1位里有0。所以对范围内的数字右移n-1位之后,应该要么是全1,要么是全0,然后这会对它+1,再右移一位,就会变成全0了。

/* 
 * fitsBits - return 1 if x can be represented as an 
 *  n-bit, two's complement integer.
 *   1 <= n <= 32
 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int fitsBits(int x, int n) {
  return !(((x>>(n+(~0)))+1)>>1);
}
  1. divpwr2

要求:补码除以2的n次.

解题思路:需要给负数加入一个偏差(1«n)-1,判断负数就是看最高位是否为1.

/* 
 * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
 *  Round toward zero
 *   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2  
 */
int divpwr2(int x, int n) {
  return (x+(((x>>31)&1)<<n)+(~0)+(!((x>>31)&1)))>>n;
}
  1. negate

题目比较简单,算是送分题。

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

要求:判断一个数字是否是正数.

解题思路:因为0不包括在内,所以开头觉得可以直接-1,然后判最高位。但是要考虑到,0xffffffff,-1之后就变成了0x7fffffff,最高位为0了。所以要判,x的最高位为0并且x-1的最高位也为0。

/* 
 * isPositive - return 1 if x > 0, return 0 otherwise 
 *   Example: isPositive(-1) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 3
 */
int isPositive(int x) {
  return !(((x>>31)&1)+(((x+(~0))>>31)&1));
}
  1. isLessOrEqual

解题思路分类讨论两个数字的符号,如果符号不同,必然y最高位是0,x最高位是1,如果符号相同,直接做减法也不会溢出。

/* 
 * 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)&1;
  int signy = (y>>31)&1;
  int signdif = (!signy)&signx;
  int signsam = (!(signx^signy))&(((x+(~y))>>31)&1);
  return signdif|signsam;
}
  1. ilog2

要求:x二进制里最高位的1在哪里

解题思路:类似于分治的思想。

int ilog2(int x) {
  int ans = 0;
  ans = ans + ((!!(x>>(16 + ans)))<<4);
  ans = ans + ((!!(x>>(8 + ans)))<<3);
  ans = ans + ((!!(x>>(4 + ans)))<<2);
  ans = ans + ((!!(x>>(2 + ans)))<<1);
  ans = ans + ((!!(x>>(1 + ans)))<<0);

  return ans;
}

浮点数

  1. float_neg

要求:uf是一个浮点数表示,对它符号取反,但是如果uf本来就是NaN,就返回本身。

/* 
 * float_neg - Return bit-level equivalent of expression -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 representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned float_neg(unsigned uf) {
  unsigned tmp = uf&(0x7fffffff);
  unsigned result = uf^(0x80000000);
  if(tmp>0x7f800000) result=uf;
  return result; 
}

结束语

还差最后一个float_i2f没有写出来,这一道题比较困难,打算明天花一天时间将其解出。深刻的感到做实验才是学习CSAPP最好的方法。