CSAPP data Lab(Lab1)

参考资料:
CSAPP:Lab1 -DataLab 超详解 - 知乎 (zhihu.com)

深入理解计算机系统 实验1 CSAPP(视频)

Guo749/CSAPP: My Notes for CSAPP (github.com)

1. bitXor

德摩根律的应用
image.png

//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);
}
2. tmin
// tmin - return minimum two's complement integer

int tmin(void) {
  return 1<<31;
}
3. tmax

题意:如果x用二进制表示是最大值,那么return 1, else return 0

题解:若x为最大值,那么x的二进制表示满足:

  1. 首位为0
  2. 其余位为1

例如0111 1111
若满足上述条件,有x+1 = 100…,于是 !(x+1) = x,判断是否相等可以用异或操作。
注意当x=-1时,上式依然满足,因为 -1=1111 ,故需特判 x!=-1, 观察1111可知x+1=0。

// isTmax - returns 1 if x is the maximum, two's complement number,and 0 otherwise

int isTmax(int x) {
  return !(~(x+1)^x)&!!(x+1);
}
4. isTmax

题意:奇数位全为1,return 1,注意数字下标从0开始

题解:只需构造一个101010…的二进制数,然后&x,如果&之后的结果有变化,那么奇数位存在0,由题3可知用异或操作可判断两个数之间是否相等。

// 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

int allOddBits(int x) {
  int m = 0xAA << 8;
  m = m | 0xAA;
  m = (m << 16) | m;
  return !((m&x)^m) ;
}
5. negate
// negate - return -x

int negate(int x) {
  return ~x + 1;
}
6. isAsciiDigit

题解:判断该范围有两步:

  1. 除后四位外其余位相等
  2. 后四位在0到9之间

第一步,只需判断相应位是否与0x3相等即可;
第二步,这里可用一些技巧,0到9任意数-10都为负数,故只需提取出后四位-0xA,判断最高位是否为1即可。

// isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')

// Example: isAsciiDigit(0x35) = 1.
//   isAsciiDigit(0x3a) = 0.
//   isAsciiDigit(0x05) = 0.

int isAsciiDigit(int x) {
  int a = !((x >> 4) ^ 0x3);
  int b = x & 0xF;
  int c = ~0xA + 1;
  int d = !!((b + c) & (1 << 31));
  return a & d;
}
7. conditional

题解:通过x是否为0构造出全0二进制数或全1二进制数,然后去选择y,z。
这里注意1111… + 1 = 0

// conditional - same as x ? y : z
// Example: conditional(2,4,5) = 4

int conditional(int x, int y, int z) {
  int m = ~(!x) + 1;
  return (~m & y) | (m & z);
}
8. isLessOrEqual

题解:本题需解决的问题是符号位的判断。

  1. 取出符号位
  2. 判断不同号时的合适条件
  3. 分情况讨论:
    1. 相等
    2. 不同号且x<0,y>0
    3. 同号且x<y
// isLessOrEqual - if x <= y  then return 1, else return 0
// Example: isLessOrEqual(4,5) = 1.

int isLessOrEqual(int x, int y) {
  int equal = !(x ^ y);
  int signX = (x >> 31) & 1;
  int signY = (y >> 31) & 1;
  int cond1 = !(signX) & (signY); // cond1 = 0 -> (signX < signY 或者同号) else signX > signY
  int cond2 = (signX) & !(signY);
  int sameSign = !(signX ^ signY);
  int res = x + ~y + 1;
  int greater = (res >> 31) & 1;
  return equal | ((!cond1) & (cond2 | (greater & sameSign)));
}
9. logicalNeg

题解:对x求其负数,若x为正数则符号位为1,若为0和负数则为0;那么要区分0和负数可以将(negX | x),这样便将负数的情况归为符号位为1的情况;之后右移31位,可知0不变,其余情况均为-1。

/* 
 * 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 
 
 	!0, 0 
	int a = 0111;
	int -a = 1001;
	int sign = 1

 */
int logicalNeg(int x) {
	int negX = ~x + 1;
	int sign = (negX | x) >> 31;
	return sign + 1;
	
}
10. howManyBits

题意:返回在二进制补码中表示 x 所需的最小位数

题解:

  1. 明确所需最小位数就是除符号位的最高有效位1,那么需要对x进行初始化,以便提取出这个最高位(-1的二进制补码表示为0xFF)
  2. x = (flag & (~x)) | ((~flag) & x);表示正数不变,负数取反
  3. 要取得最高位,可以采用折半查找,具体看代码
/* 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
 */
 int howManyBits(int x) {
	int isZero = !x;
	int flag = x >> 31;
	x = (flag & (~x)) | ((~flag) & x);
	int bit_16, bit_8, bit_4, bit_2, bit_1, bit_0;
	
    b16 = !!(x>>16) << 4; //如果高16位不为0,则我们让b16=16
    x >>= b16; //如果高16位不为0 则我们右移动16位 来看高16位的情况
    //下面过程基本类似
    b8 = !!(x>>8) << 3;
    x >>= b8;
    b4 = !!(x >> 4) << 2;
    x >>= b4;
    b2 = !!(x >> 2) << 1;
    x >>= b2;
    b1 = !!(x >> 1);
    x >>= b1;
    b0 = x;

	int res = bit_0 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16 + 1;
		
	return isZero | res; 
}
11. floatScale2

image.png

image.png

题意:给定f,返回2*f

题解:

  1. 取出三个字段的值
  2. 分类讨论
    1. 无穷大和NaN为一类
    2. 0为一类
    3. 非规格化时,f不为0,只需将f编码的尾数M乘2即可
    4. 规格化时,将expr++即可,因为E = expr - bias,expr++相当于E++,即V*2
/*
 * 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) {
    //expr, s, frac
    unsigned s = (uf >> 31) & (0x1);
    unsigned expr = (uf >> 23) & (0xFF);
    unsigned frac = (uf & 0x7FFFFF);
  
    //0
    if(expr == 0 && frac == 0)
        return uf;
  
    //inifity or nor na number
    if(expr == 0xFF)
        return uf; 

    //denormalize
    if(expr == 0){
        //E = expr - 127 = -127
        //frac
        frac <<= 1;
        return (s << 31) | frac;
    }

    //normalzie
    expr++;
    //E = expr - 127
    return (s << 31) | (expr << 23) | (frac);
}
12. floatFloat2Int

题意:浮点数转化为整型

题解:除规格化数,其余基本同上题;
当为规格化数时,按照定义如下步骤:

  1. 尾数编码加上隐含的1,求出阶码值E
  2. 按照阶码值大小分类讨论:
    1. 对于单精度数,E>31为无穷大,E<0转整型为0
    2. 因为尾数编码有23位,故E>=23时,故需对尾数乘2^E,即左移E-23位,E<23时,右移23-E位即可
    3. 最后根据符号位求其负数或不变即可
/* 
 * 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 s    = (uf >> 31) & (0x1);
	unsigned expr = (uf >> 23) & (0xFF);
    unsigned frac = (uf & 0x7FFFFF);

	//0
	if(expr == 0 && frac == 0)
		return 0;
	//Ini / NaN
	if(expr == 0xFF)
		return 1 << 31;

	//denormalzie
	if(expr == 0){
		//M 0.1111 < 1
		//E = 1 - 127 = -126
		return 0;
	}

	//noramlzie
	int E = expr - 127;
	frac = frac | (1 << 23);
	
	if(E > 31)	//1.XXXX
		return 1 << 31;
	else if(E < 0){
		return 0;
	}

	if(E >= 23){
		frac <<= (E - 23);
	}else{
		frac >>= (23 - E);
	}

	if(s)
		return ~frac + 1;
	return frac;
}
13. floatPower2

题意:对于任何 32 位整数 x,返回表达式 2.0^x 的位级等效项。

题解:我们可以由小到大判断:

  1. (非规格化f为0的情况)E最小为-126,M最小为2^-23,故x<-149,这个数太小,return 0
  2. (非规格化f不为0的情况)此时需要填充f,expr全为0,E = -126,若x < -126,剩余部分需f补充,即1 << (23 + (x + 126))
  3. (规格化的情况)求出expr即可,E = expr - bias,则expr = E + bias,E就是参数x,之后把expr放到对应位置即可
  4. (NaN和无穷大)expr全部填充为1
/* 
 * 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) {
	if(x < -149){
		return 0;
	}else if(x < -126){
		// E = x
		// E = 1 - 127 = -126
		int shift = 23 + (x + 126);
		return 1 << shift;
	}else if(x <= 127){
		//x = expr - bias
		int expr = x + 127;
		return expr << 23;
	}else{
		return (0xFF) << 23;
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值