CSAPP实训1——datalab作业记录

部分题目(带*的题目)参考了zjwreal博主的该blog:CSAPP实验1:Data Lab笔记

1. bitAnd

/* one
 * 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) );
}

2.getByte

/* two
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (LSB) to 3 (MSB)      
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
  return (x>>(n<<3))&0xff;  
}

LSB:Least Significant Bit 最低有效位
MSB:最高有效位

让所需要的2位靠右,与0xff对位取和,保留最右边2位

3. logicalShift

/* three
 * 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) {
  return (x>>n)&~((0xffffffffffffffff>>n)<<(32+(~n+1)));     
}

0xffffffffffffffff>>n: f取了8的2倍个,以确保n足够大时,0xff…f右移后最高位上仍为f。

4.bitCount (难)

/*four
 * bitCount - returns count of number of 1's in word
 *   Examples: bitCount(5) = 2, bitCount(7) = 3
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 40
 *   Rating: 4
 */
int bitCount(int x) {
	int msk1=0x55555555;
	int msk2=0x33333333;
	int msk3=0x0F0F0F0F;
	int msk4=0x00FF00FF;
	int msk5=0x0000FFFF;
	int b1=1;
	int b2=2;
	int b3=4;
	int b4=8;
	int b5=16;
	x=((x>>b1)&msk1)+(x&msk1);
	x=((x>>b2)&msk2)+(x&msk2);
	x=((x>>b3)&msk3)+(x&msk3);
	x=((x>>b4)&msk4)+(x&msk4);
	x=((x>>b5)&msk5)+(x&msk5);
	return x;   
}

港真,这道题小菜鸡真不会做 <枯> ,我觉得我也想不出来这个解法。So,找同学问了之后copy了他的代码,留着慢慢思考慢慢做。

5. bang

/* five
 * bang - Compute !x without using !
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int bang(int x) {
  return !x^0;      
}

虽然这题的分值是4,但其实它并没有我想象的复杂,所有的数只分为0和其他数两块。
小菜鸡第一次做的答案是((~x+1)&x)^1,试图通过该方法区别出0,但该解法是错的,当x取min时不满足题目要求,结果是min。

6. tmin

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

7. fitsBits

/* seven 
 * 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^((x<<(32+(~n+1)))>>(32+(~n+1))));    
}

(x<<(32-n))>>(32-n):保证数x的前方都为0(负数前方均为1)

8.divpwr2(*)

/*eight  
 * 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) {
	int a,b,c;
	a=x>>31;            //负数为-1,正数为0 
	b=(1<<n)+(~0);     // 2^n-1
	c=a&b;              // if x>=0,c=0 
	return (x+c)>>n;
}

(本文上方提到的那个参考的blog的代码)

9.negate

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

10. isPositive

/* ten 
 * 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 & (~x+1)));  
}

!(x>>31 & 1): 负数返回0
(x & (~x+1)): 若x为0则返回0

11. isLessOrEqual (*)

/* eleven 
 * 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 sgnx=(x>>31)&0x01;
	int sgny=(y>>31)&0x01;
	int sgn=(sgnx^sgny)&sgnx;     //只有x<0,y>=0时,sgn为1 
	int val=y+(~x+1);             
	val=((val>>31)&0x01)|(sgnx^sgny);     //x-y<0 && sgnx=sgny
	return (sgn|!val);
}

(本文上方提到的那个参考的blog的代码)

12. ilog2 (*)

/*twelve 
 * ilog2 - return floor(log base 2 of x), where x > 0
 *   Example: ilog2(16) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 90
 *   Rating: 4
 */
int ilog2(int x) {
	int bitNum=0;
	bitNum=(!!(x>>16))<<4;
	bitNum=bitNum+((!!(x>>(bitNum+8)))<<3);
	bitNum=bitNum+((!!(x>>(bitNum+4)))<<2);
	bitNum=bitNum+((!!(x>>(bitNum+2)))<<1);
	bitNum=bitNum+(!!(x>>(bitNum+1)));
  return bitNum;
}   

(本文上方提到的那个参考的blog的代码)

13. float_neg (*)

/* thirteen 
 * 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) {
	int tmp=0,ret=0;
	ret=uf^0x80000000;
	tmp=uf&0x7fffffff;
	if (tmp>0x7f800000)  //NaN
		ret=uf;  
 return ret;
}

(本文上方提到的那个参考的blog的代码)

14. float_i2f (*)

/* fourteen 
 * float_i2f - Return bit-level equivalent of expression (float) 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.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) {
  int sign = (x>>31)&0x01;
  int frac_mask = 0x7fffff; // (1<<23) -1
  int frac=0,exp=0,delta=0; 
  int i = 0; 
  if(!x)
    return x;
  else if(x==0x80000000)// -2^31
    exp = 158;          // 158 = 127 +31
  else{
    if(sign)  x=-x;     // abs(x)
    i=30;
    while(!(x>>i))
      i--;
    exp = i+127;        // exp = Bias + E
    x= x<<(31-i);       // clean all those zeroes of high bits
    frac = (x>>8) & frac_mask;//right shift 8 bits to become the fraction,sign and exp have 8 bits total
    x = x & 0xff;
    delta = x>0x80||((x==0x80 )&& (frac&0x01)); //if lowest 8 bits of x is larger than a half,or is 1.5,round up 1
    frac += delta;
    if(frac>>23){ //if after rounding fraction is larger than 23bits
      exp += 1;
      frac = frac & frac_mask;
    }
  }
  return (sign<<31)|(exp<<23)|frac;
}   

(本文上方提到的那个参考的blog的代码)

15. float_twice (*)

/* fifteen 
 * float_twice - 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 float_twice(unsigned uf) {
	int sign = uf>>31 && 0x01;
	int exp = uf>>23 & 0xff;
	int frac = uf & 0x7fffff;
	if (exp!=0xff){
		if (!exp) frac=frac<<1;
		else {
			exp+=1;
			if (exp==0xff)
				frac=0;
		}
	}
	return sign<<31|exp<<23|frac;
}    

(本文上方提到的那个参考的blog的代码)

小菜鸡还有好些题没法自己做出来,所以先将zjwreal博主的一部分代码放上去,等以后琢磨透了这些题目,还会再修改完善一下该blog,放上自己的解答。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值