CSAPP-datalab

CSAPP-datalab

假期实验室组织看 CSAPP-CMU 的视频,正好完成了他们的实验;环境是阿里云的服务器

下面贴代码,欢迎交流!

实验说明

1.bitXor

bitXor: x^y using only ~ and &
思路:将异或表达式转化成与或标准型

int bitXor(int x, int y) {
  return ~((~(~x&y))&(~(x&~y)));
}

2.tmin

tmin - return minimum two's complement integer
思路:移位输出

int tmin(void) {
  return 0x80<<24;
}

3.isTmax

isTmax - returns 1 if x is the maximum, two's complement number
Tmax: 0x7FFFFFFF, -1 = 0xFFFFFFFF
思路:考虑x和x+1 如果x和x+1完全不同说明是补码最大值或者-1,-1可以通过!~x排除

int isTmax(int x) {
  int neg = !~x;
  return !((~(x^(x+1)))|neg);
}

4.allOddBits

allOddBits - return 1 if all odd-numbered bits in word set to 1
思路:求出全1的con = 0xAAAAAAAA ,再将x&con与求出x奇数位值,最后与con比较即可

int allOddBits(int x) {
 	int con = 0xAA<<8;
	con = (con+0xAA)<<8;
	con = (con+0xAA)<<8;
	con = con+0xAA;
       	return !(con^(x&con));
}

5.negate

negate - return -x
思路:求一个数的相反数,求反码+1,实际上是由于补码之间的不对称关系,比如0的按位取反是-1,2的按位取反是-3等等,要再+1

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

6.isAsciiDigit

isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
思路:判断ASCII码内部的值
1)首先判断高位和3之间比较;
2)其次取出前三位和0x80异或判断前三位是不是100,判断8-9,取出前三位和0x80异或判断最高位是不是0,如果是0说明在0-7,再取或即可;

int isAsciiDigit(int x) {
  int x1 = !((x>>4)^0x03);
  int x2 = !(0x80^((x<<4)&0xE0));
  int x3 = !(0x00^((x<<4)&0x80));
  return x1&(x2|x3);
}

7.conditional

conditional - same as x ? y : z
思路:实现三目表达式,先将x的值转化成0x00000000和0xFFFFFFFF,然后和yz取与即可

int conditional(int x, int y, int z) {
	int con = ~(!!x)+1; 
 	return (con&y)|(~con&z);
}

8.isLessOrEqual

isLessOrEqual - if x <= y then return 1, else return 0
思路:判断xy之间的大小关系:先取出符号位根据正负比较,比较好后使用y-x符号比较

int isLessOrEqual(int x, int y) {
	int x1 = !(x>>31);
	int y1 = !(y>>31);
	/*if x > 0 x1 = 1; if y > 0 y1 = 1*/
	int xysame = !(x1^y1);
	/*if xysame symbol xysame = 1, else xysame=0 */

	int norx = (~x+1);
	int yminusx = !((y+norx)>>31);

	return (xysame & yminusx)|(~xysame&(!x1)&y1);	
}

9.logicalNeg

logicalNeg - implement the ! operator, using all of the legal operators except !
思路:将0转化成0,其他数转化成0xFFFFFFFF,可以将自己和~x+1异或后移位,同时要考虑TMin的影响

int logicalNeg(int x) {
	/*if x!= 0x00000000 or 0x80000000 x^(~x+1)>>31 = FFFFFFFF*/
	int x0 = (x^(~x+1))>>31;
      	/*if x = 0x00000000 x1=00000000, x=0x80000000 x1=FFFFFFFF*/
	int x1 = x>>31;
	return ((~x0)&(~x1))&(0x01);
}

10.howManyBits

howManyBits - return the minimum number of bits required to represent x in two's complement
思路:求出需要补码的最小位数,二分查找,这里借鉴了网上的一些博客思路
1)取出符号位
2)将x根据符号位值转化为正数
3)先判断前16位是不是有1,如果有1,说明后16位需要表示,b16就左移4位变成16,并且x右移16位,如果没有,就不移动,并且b16=0;
4)判断后16位里面的前8位是不是有1,如果有就说明后24位中有1,b8左移3变成8;
5)判断移位后的后八位里面的前四位是不是有1,如果有说明前28位有1,赋值移位b4;
6)判断移位后后四位里面的前两位是不是有1,如果有就说明前30位有1,赋值移位b2;
7)判断前两位里面前一位是不是有1,如果有说明第31位是1,
8)判断最后一位是不是1
9)加上符号位

int howManyBits(int x) {
	/*if x < 0 sign = 0xFFFFFFFF; else sign = 0x00000000*/
	int sign = (x>>31);
	int b16,b8,b4,b2,b1;
	/*x = abs(x)*/
	x = (sign&~x)|(~sign&x);
	/*if x has 16*0 ahead, b16 = 16;*/
	b16 = (!!(x>>16))<<4;
	/*if b16 == 1: x = x>>16; else x = x>>8*/
	x = x >> b16;
	b8 = (!!(x>>8))<<3;
	x = x >> b8;

	b4 = (!!(x>>4))<<2;
	x = x >> b4;

	b2 = (!!(x>>2))<<1;
	x = x >> b2;

	b1 = (!!(x>>1))<<0;
	x = x >> b1;
	
	return b16 + b8 + b4 + b2 + b1 + x + 1;
	
}

11.floatScale2

floatScale2 - Return bit-level equivalent of expression 2*f for floating point argument f:

思路:2*f, 取出exp和frac部分的值,非规格化值直接左移,规格化值将exp+1

unsigned floatScale2(unsigned uf) {
	unsigned int exp = uf&(0x7F800000);
	unsigned int frac = uf&(0x7FFFFF);
	unsigned int s = uf&(0x80000000);
	//NaN or 0
	if((exp==0x7F800000)||(exp==0&&frac==0))
		return uf;
	//denormalized value
	else if(exp==0)
		return s+(uf<<1);
	//normalized value 
	else
		return ((exp+0x00800000)&0x7F800000)+(uf&0x807FFFFF);
}

12.floatFloat2Int

floatFloat2Int - Return bit-level equivalent of expression (int) f
for floating point argument f.
思路:
1)将浮点数转化为整数,先取出各部分值,frac直接加1,因为非规格化值不用判断;
2)边界情况:如果是+0或者-0,返回0,超出31位返回0x80000000u,非规格化值返回0;
3)再判断小数部分移位,因为小数部分已经移位23位了,所以只需要判断和23间关系
4)移位后如果与原来符号相同说明没有溢出,返回frac
5)移位后如果是负数,说明加多了,溢出返回0x80000000u
6)移位后是正数,原来是负数,取反+1即可

int floatFloat2Int(unsigned uf) {
	int exp = uf&(0x7F800000);
	int s = (uf&(0x80000000))>>31;
	int frac = (uf&(0x7FFFFF))+0x800000;
	int Bias = 127;
	
	if(!(uf&0x7FFFFFFF)) 
		return 0;

	exp = (exp>>23)-Bias;
	/*Out of Range or NaN*/
	if(exp>31)
		return 0x80000000u;
	/*denormalized value */
	else if(exp<0)
		return 0;
	else
	{
		if(exp>23)
			frac = frac << (exp-23);
		else
			frac = frac >> (23-exp);
		
		if(frac>>31==s)
			return frac;
		else if((frac>>31)==1)
			return 0x80000000u;
		else
			return ~frac+1;			
	}
}

13.floatPower2

floatPower2 - Return bit-level equivalent of the expression 2.0^x (2.0 raised to the power x) for any 32-bit integer x.
思路:
规格化值写成1.0*2^x形式,直接移位;
非规格化值(-148~-125)令frac对应位为1

unsigned floatPower2(int x)
{
	if(x>127)
		return 0x7F800000;
	else if(x<-148)
		return 0;
	else if(x>=-126)
	{
		int exp = x + 127;
		return exp<<23;
	}
	
	else
	{
		int frac_1 = 148+x;
		return 1<<frac_1;
	}
}

posted @ 2021-01-17 23:37  Sanhao99  阅读(167)  评论(0编辑  收藏  举报