深刻理解計算機系統(CSAPP)實驗二 datalab-handout

實驗的目的是 填寫 bits.c裏面的函數,使其按照規定的要求(好比只能使用有限且規定的操做符和數據類型,不能使用控制語句等等)實現函數的功能。express

同時 dlc文件是用來檢測 bits.c 裏面的函數是否  是按照要求編寫的,有沒有使用非法的數據類型等。 使用方法:./dlc bits.c數組

檢測成功後,使用 btest 測試 每個函數功能方面是否正確無誤。使用方法:./btest,若是某個函數錯誤,會顯示錯誤的數據,以及正確的數據。less

完整的bits.c以下。也是參考網上各路大神的。ide

/* 
 * CS:APP Data Lab 
 * 
 * <Please put your name and userid here>
 * 
 * bits.c - Source file with your solutions to the Lab.
 *          This is the file you will hand in to your instructor.
 *
 * WARNING: Do not include the <stdio.h> header; it confuses the dlc
 * compiler. You can still use printf for debugging without including
 * <stdio.h>, although you might get a compiler warning. In general,
 * it's not good practice to ignore compiler warnings, but in this
 * case it's OK.  
 */

#if 0
/*
 * Instructions to Students:
 *
 * STEP 1: Read the following instructions carefully.
 */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.

INTEGER CODING RULES:
 
  Replace the "return" statement in each function with one
  or more lines of C code that implements the function. Your code 
  must conform to the following style:
 
  int Funct(arg1, arg2, ...) {
      /* brief description of how your implementation works */
      int var1 = Expr1;
      ...
      int varM = ExprM;

      varJ = ExprJ;
      ...
      varN = ExprN;
      return ExprR;
  }

  Each "Expr" is an expression using ONLY the following:
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>
    
  Some of the problems restrict the set of allowed operators even further.
  Each "Expr" may consist of multiple operators. You are not restricted to
  one operator per line.

  You are expressly forbidden to:
  1. Use any control constructs such as if, do, while, for, switch, etc.
  2. Define or use any macros.
  3. Define any additional functions in this file.
  4. Call any functions.
  5. Use any other operations, such as &&, ||, -, or ?:
  6. Use any form of casting.
  7. Use any data type other than int.  This implies that you
     cannot use arrays, structs, or unions.

 
  You may assume that your machine:
  1. Uses 2s complement, 32-bit representations of integers.
  2. Performs right shifts arithmetically.
  3. Has unpredictable behavior when shifting an integer by more
     than the word size.

EXAMPLES OF ACCEPTABLE CODING STYLE:
  /*
   * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
   */
  int pow2plus1(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     return (1 << x) + 1;
  }

  /*
   * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
   */
  int pow2plus4(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     int result = (1 << x);
     result += 4;
     return result;
  }

FLOATING POINT CODING RULES

For the problems that require you to implent floating-point operations,
the coding rules are less strict.  You are allowed to use looping and
conditional control.  You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants.
可使用循環和控制語句,使用int和unsigned

You are expressly forbidden to:
  1. Define or use any macros. 定義或者使用宏
  2. Define any additional functions in this file.定義附加函數
  3. Call any functions. 調用函數
  4. Use any form of casting. 使用轉換
  5. Use any data type other than int or unsigned.  This means that you
     cannot use arrays, structs, or unions.
     使用 數組,結構體,共用體
  6. Use any floating point data types, operations, or constants.
  使用任意浮點數類型,操做,常亮。


NOTES:
  1. Use the dlc (data lab checker) compiler (described in the handout) to 
     check the legality of your solutions. 
     使用dlc檢查合法性
  2. Each function has a maximum number of operators (! ~ & ^ | + << >>)
     that you are allowed to use for your implementation of the function. 
     The max operator count is checked by dlc. Note that '=' is not 
     counted; you may use as many of these as you want without penalty.
     每一個函數都有所使用的操做符有限,‘=’不算。
  3. Use the btest test harness to check your functions for correctness.
  4. Use the BDD checker to formally verify your functions
  5. The maximum number of ops for each function is given in the
     header comment for each function. If there are any inconsistencies 
     between the maximum ops in the writeup and in this file, consider
     this file the authoritative source.

/*
 * STEP 2: Modify the following functions according the coding rules.
 * 
 *   IMPORTANT. TO AVOID GRADING SURPRISES:
 *   1. Use the dlc compiler to check that your solutions conform
 *      to the coding rules.
 *   2. Use the BDD checker to formally verify that your solutions produce 
 *      the correct answers.
 */


#endif
/* 
 * bitAnd - x&y using only ~ and | 
 *   Example: bitAnd(6, 5) = 4
 *   Legal ops: ~ |
 *   Max ops: 8
 *   Rating: 1
 *   方法:運用摩根定律
 */
int bitAnd(int x, int y) {
  return ~((~x)|(~y)); // ~~, ~| = &
}
/* 
 * getByte - Extract byte n from word x
 *   從 字 x 中 提取第n個字節
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   最低有效位爲0,依次,最高有效位是 3
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 *   方法:
 */
int getByte(int x, int n) {
	int tmp = x >> ((n) << 3); //向右移到頭 0xff123456,算術右移
	tmp = tmp & 0xFF; //保留最右一個字節。
	return tmp;;

}
/* 
 * logicalShift - shift x to the right by n, using a logical shift
 *   邏輯位移,邏輯右移
 *   Can assume that 0 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3 
 */
int logicalShift(int x, int n) {
	int tmp = ~(1 << 31); //0x7f ff ff ff
	tmp = ((tmp >> n) << 1) + 1; //由於n >= 0,實現tmp >> (n-1)的功能
	tmp = tmp & (x >> n);	//
  	return tmp;
}
/*
 * bitCount - returns count of number of 1's in word
 *   返回 二進制數中 1 的個數
 *   Examples: bitCount(5) = 2, bitCount(7) = 3
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 40
 *   Rating: 4
 *   參考網上解法。採用二分法,先計算x每兩位中1的個數,並用對應的兩隊來存儲
 *   這個個數。而後計算每4位1的個數,在用對應的4位進行存儲。依次類推。
 *   最後整合獲得16位中1的個數,即x中的1的個數。
 */
int bitCount(int x) {
	int count;  
    int tmpMask1 = (0x55)|(0x55<<8);  
    int mask1 = (tmpMask1)|(tmpMask1<<16);  
    int tmpMask2 = (0x33)|(0x33<<8);  
    int mask2 = (tmpMask2)|(tmpMask2<<16);  
    int tmpMask3 = (0x0f)|(0x0f<<8);  
    int mask3 = (tmpMask3)|(tmpMask3<<16);  
    int mask4 = (0xff)|(0xff<<16);  
    int mask5 = (0xff)|(0xff<<8);  
    count = (x&mask1)+((x>>1)&mask1);  
    count = (count&mask2)+((count>>2)&mask2);  
    count = (count + (count >> 4)) & mask3;  
    count = (count + (count >> 8)) & mask4;  
    count = (count + (count >> 16)) & mask5;  
    return count;  
}
/* 
 * bang - Compute !x without using !
 *   0爲1,1爲0
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int bang(int x) {
  	int tmp = ~x + 1;// tmp = -x;
	tmp = x | tmp; // 非0最高位必定是1,由於正數和負數 或	
	tmp = tmp >> 31; //非0爲0xff ff ff ff,0爲0x 00 00 00 00
	return (tmp+1);
}
/* 
 * tmin - return minimum two's complement integer
 *   int最小的數 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
	return 1<<31; //很容易理解 
}
/* 
 * fitsBits - return 1 if x can be represented as an 
 *  n-bit, two's complement integer.
 *   若是x能夠表示爲n位二進制補碼形式
 *   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) {
    int shiftNumber= 32 + (~n + 1);// 32 - n
 	return !(x^((x<<shiftNumber)>>shiftNumber));
 	/*先左移32-n位,在右移32-n位,即保留最後n位數。在與x異或
 	若二者相同表示x可被表示爲一個n位整數,!0爲1
 	*/
}
/* 
 * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
 *  計算 x / (2^n)
 *  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) {
	//全0或者全1
    int signx = x >> 31;     //
    int mask = (1 << n) + (~0);//獲得2^n - 1
    int bias = signx & mask;//若是x是正數,則bias爲0,即不用加,直接移位
    //若是x爲負數,加上偏置量以後在移位
    return (x + bias) >> n;
}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   求相反數
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return (~x) + 1; // 取反加1
}
/* 
 * isPositive - return 1 if x > 0, return 0 otherwise 
 *   x > 0 返回1, x <= 0返回0
 *   Example: isPositive(-1) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 3
 */
int isPositive(int x) {
    return !((x >> 31) | (!x)); //看符號位便可
}
/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   x - y <= 0返回1,  > 0返回1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y) {
	int singx = (x >> 31) & 1;
	int singy = (y >> 31) & 1;	//比較符號位 1 0 = 1,  0 1 = 0;
	int sing = (singx ^ singy) & singx; //保證singx和singy異號
	int tmp = x + ((~y) + 1); // x - y, 同號狀況下,異號狀況下會越界 0 0 = , 1 1 = 
	tmp = ((tmp>>31)&1) & (!(singx ^ singy));// 保證singx 和 singy 同號
	//int t = (!(x ^ y)); //判斷相等
	//printf("sing  =%d, tmp = %d\n", sing, tmp);
	return (sing | tmp | ((!(x ^ y)))); //
}
/*
 * ilog2 - return floor(log base 2 of x), where x > 0
 *   Example: ilog2(16) = 4  即獲得由多少位二進制表示便可。
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 90
 *   Rating: 4
 *   方法:參考。二分法。先右移16位後若大於0即獲得(10000)2=16
 *	 不然獲得0,判斷最高位是否爲0,若不爲0,則包含2的16次方。即獲得最高位的log  *	 數,同理其餘
 */
int ilog2(int x) {
	int bitsNumber=0;
	bitsNumber=(!!(x>>16))<<4;//
	bitsNumber=bitsNumber+((!!(x>>(bitsNumber+8)))<<3);
	bitsNumber=bitsNumber+((!!(x>>(bitsNumber+4)))<<2);
	bitsNumber=bitsNumber+((!!(x>>(bitsNumber+2)))<<1);
	bitsNumber=bitsNumber+(!!(x>>(bitsNumber+1)));
	//for non zero bitsNumber, it should add 0
	//for zero bitsNumber, it should subtract 1
	bitsNumber=bitsNumber+(!!bitsNumber)+(~0)+(!(1^x));
	//當x爲0時,還須要減一才能獲得正確值。
	return bitsNumber;
}
/* 
 * float_neg - Return bit-level equivalent of expression -f for
 *   floating point argument f. 返回和浮點數參數-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 result;
	unsigned tmp;
  	result=uf ^ 0x80000000; //將符號位改反
  	tmp=uf & (0x7fffffff);
  	if(tmp > 0x7f800000)//此時是NaN
        result = uf;
	return result;
}
/* 
 * float_i2f - Return bit-level equivalent of expression (float) x
 *  返回int x的浮點數的二進制形式。
 *   Result is returned as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point values.
 *   返回的是unsigned型可是表示的時二進制單精度形式
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) {
	unsigned shiftLeft=0;
	unsigned afterShift, tmp, flag;
	unsigned absX=x;
	unsigned sign=0;
	//special case
	if (x==0) return 0;
	//if x < 0, sign = 1000...,abs_x = -x
	if (x<0)
	{
		sign=0x80000000;
		absX=-x;
	}
	afterShift=absX;
	//count shift_left and after_shift
	while (1)
	{
		tmp=afterShift;
	    afterShift<<=1;
	    shiftLeft++;
	    if (tmp & 0x80000000) break;
	}
	if ((afterShift & 0x01ff)>0x0100)
	    flag=1;
	else if ((afterShift & 0x03ff)==0x0300)
	    flag=1;
	else
	    flag=0;

	return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag;
}
/* 
 * float_twice - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 ×   返回 以unsinged表示的浮點數二進制的二倍的二進制unsigned型
 *   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 float_twice(unsigned uf) {
	unsigned f = uf;
    if ((f & 0x7F800000) == 0) // 
 	{
        //左移一位
        f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
    }
    else if ((f & 0x7F800000) != 0x7F800000)
    {
        f =f + 0x00800000;
	}
	return f;
}
相關文章
相關標籤/搜索