CSAPP實驗(1)----datalab

1 實驗說明

CSAPP課程主頁下載datalab實驗所需的壓縮包。下圖說明本次實驗需要補齊的函數名列表。
在這裏插入圖片描述

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<255
      	exp += 0x800000;//乘2
      	if((exp ^ 0x7f800000)==0){//判斷乘2以後是否溢出      	
	  frac=0;//輸出INF
      	} 
     }
  }
  return sign | exp | frac;  
}

解題思路:
接下來的三題,讓我深刻理解了"數據類型規定了數的爲寬,和相應的操作方法"這句話的意義.下圖表示了浮點數的位級示意圖.從圖可以知道解答lab中關於浮點數的題目.
在這裏插入圖片描述

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 命令,會得到以下結果。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章