CSAPP学习笔记--------cmu,datalab实验

整型数据部分

1.异或

  • bitXor - x^y using only ~ and &
  • Legal ops: ~ & //限制操作符
  • Max ops: 14 //最多代码数
int bitXor(int x, int y) {

 int val1 = (~x)&y;
 int val2 = (~y)&x;

return ~((~val1)&(~val2));
}

思路的关键在于将两数x,y各自机器级01序列中同一位置上不同的地方记录下来
分为4种情况:

y 1 1 0 0
x 1 0 1 0

首先将表中第2,3列分别以1的方式记录下来即代码第一二行
但是由于不能直接使用加法和位级或运算,所以,这是只需要将上一操作得到的两个01序列各位取反(~)再相与,最后再做一次取反即可



2.判断奇数位是否均为1

  • allOddBits - return 1 if all odd-numbered bits in word set to 1  //是则返回1,不是则返回0
  • Legal ops: ! ~ & ^ | + << >>   //合法运算符
  • Max ops: 12  //操作限制
int allOddBits(int x) {
 	int val1=3*x+1;      
return !x; 
}
0 1 0 1 0 1 0 1

显然,只需满足1个条件即可:2x+x得到的是一个全1序列(直接x*3即可)

如果满足要求条件则第一步就得到了一个全1序列,再将之加上1则为全0序列(即值为0)
再进行非运算(!)就得到了1
如果不满足则第一步就得不到全1序列,加上1也就不会是全0序列,再通过!运算返回0

这里还有另一种方法:将2x进行~运算,再与x异或,将最终得到的结果进行非运算(!)返回:

int allOddBits(int x) {
  int val1=(2*x)^x;      
return !val2; 
}
``

3.判断是否为ASCII码值

  • isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters ‘0’ to ‘9’)
  • Legal ops: ! ~ & ^ | + << >> //合法运算符
  • Max ops: 15 //操作次数限制

    ASCII值的范围为0x30到0x39之间(即十进制的48到57之间),因此只需检测是否满足这条件即可,代码如下:
int isAsciiDigit(int x) {    
	int val1 = x+6;//上限  
	int val2 = !(val1>>6);//val2的值为1表示小于0x39,为0表示大于0x39或者为负数 
	int val3 = (x-16)>>5;//如果x小于0x30,那么x-16从低有效位开始的第6为必定为0 
	int val4 = 1&val3; 
	int val5 = val2&val4;
}

4.条件返回:

  • conditional - same as x ? y : z
  • Legal ops: ! ~ & ^ | + << >> //合法操作
  • Max ops: 16 //操作限制
int conditional(int x, int y, int z) {
int val1 = ~(y&(~z));//将Y为1而Z为0的地方以0的方式记录下来
 int val2 = (~y)&z;//将Y为0而Z为1的地方以1的方式记录下来
 return y&((x&val1)|(~x&val1)) + (((~~(!x))>>1)&val2)//     根据x将y1z0     			根据x将y0z1
 //     的地方更改   			 的地方更改
}

5.How Many Bits
提供一个参数返回用二进制补码表示它所需的最小位数
合法运算符:! ~ & | ^ + << >>
Max ops:90

int HowmanyBits(int x){
	int value=x^(x<<1);
	int count = 1 + (!!(value>>16)<<4);
	int next = value>>(!!(value>>16)<<4);
	
	count = count + (!!(value>>8)<<3);
	next = next>>(!!(next>>8)<<3);//条件左移,确定下一个操作数

	count = count + (!!(value>>4)<<2);
 	next = next>>(!!(next>>4)<<2);

	count = count + (!!(value>>2)<<1);
	next = next>>(!!(next>>2)<<1);

	count = count + (value>>1)
}

思路先对x进行处理,即将x左移一位的结果与x异或这样的到的结果从左至右,第一位非0值的位置即表示了最少需要的位数

再运用折半的方法定位目标数值,即分别左移16,8,4,2,1位

6.非运算(利用除了"!“以外的其他合法运算符实现”!",即x为0时返回1,x为非0时返回0)

  • Legal ops:~ & ^ + | << >>
  • Max ops:12
int LogicalNeg(int x){
	int value = ~((x^(~x+1))|(x&(~x+1)));
	return 1&(value>>31);	
}

思路:考虑求非0的x的二进制补码再位级上面的行为是从右至左第一个非0数(即1)的后一位开始各位取反,那么x与其补码进行异或运算(^)就会生成一个左边是i个连续1(0<=i<=31)右边连续(32-i)个0的01序列,示意图如下:

1111 111000 00

而如果是0的做(0^(~0+1))话就会得到全0序列,利用这个区别,可以将得到的结果各位取反后左移31位,再析取最低位即可。
但是除此之外还要考虑一个特殊情况:0x80000000,它做x^(~x+1)之后得到的也是全0序列。故此在进行处理得到value的时候多增加了一步与(x& ( ~x+1))的或运算。



浮点数部分
1.float - Return bit-level equivalent ofexpression 2*f for floating point arguement f     //返回unsinged表示的浮点数的两倍
Legal ops:Any integer/unsinged operations incl. || , &&also if ,while
Max ops:30
代码如下:

unsigned floatScale2(unsigned uf) {
	int SF = (1&(uf>>31))<<31;//符号位
 	int exp = (uf>>23)&((1<<8)-1);//阶码
 	int e23 = ((1<<23)-1);//23个1
 	int EM = e23&uf;//尾数
 	int if8exp = 1&((exp+1)>>8);//判断exp是否全1
 	if(!(EM|exp)||if8exp)return uf;//0,NaN,无穷大的情况下返回自身
 	if(!exp){//阶码全0
 		 EM = (EM<<1)&e23;
 		 if(1&(EM>>22)){//尾数最高位为1
 		 exp = exp + 1;
  		}
  		exp = exp<<23;
  	}
  	else{
  		exp = exp+1;
 		if(if8exp){//加1后阶码溢出,返回无穷大
   			EM=0;
  		}
 	}
 	return SF|exp|EM;
}

2.floatFloat2Int - Return bit-level equivalent of expression (int) f for floating point argument f.      //实现(int)f
Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
Max ops:30
代码如下:

int floatFloat2Int(unsigned uf) {
 int SF = 1&(uf>>31);
 int e8 = (1<<8)-1;
 int e23 = (1<<23)-1;
 int exp = (uf>>23)&e8;
 int M = uf&e23;
 if((exp+1)>>8)return exp<<23;//如果exp为全1
 int final=0;
 if(exp){//规格化数,对隐藏的“1”进行处理
  final=final+(1<<exp);
 }
 
 int i = 23;
 while(M){//循环各位尾数乘以阶码,求和
  final = final + (M&1)<<(exp-i);
  i--;
  M=M>>1;
 }
 if(SF)final = ~final+1;//如果uf为负数
 return final;
}

3.floatPower2 - Return bit-level equivalent of the expression 2.0^x(2.0 raised to the power x)for any 32-bit integer x.     //将浮点数表示的2的x次幂转化为int型
Legal ops:Any integer /unsigned operations incl. || && Also if while
Max ops:30

unsigned floatPower2(int x){	
	int high = 1&((x-129)>>31);//x-129应该小于0
 	int low1 = 1&((x+126)>>31);//对于规格化数x+126应该大于或等于0
 	int low2 = !(1&((x+149)>>31));//对于如何包括非规格化数,x+129都应该大于或等于0
 
 	if(!high)return ((1<<8)-1)<<23;//大于上限(并非最大规格化数)
 	if(high&&(!low1))return (x+127)<<23;//处于规格化数区间
 	if(low1&&low2)return 1<<(x+149);//处于规格化数区间
	 return 0;//小于最小规格化数
}
其他实验较为简单,所以只贴出代码供参考,不作解释

tmin - return minimun tow’s complement integer//返回最小二进制补码
Legal ops:!~&^|+<<>>
Max ops :4

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

isTmax - returns 1 if x is the maximun,tow’s complement number,and 0 otherwise
Legal ops!~&^|+
Max ops:10

int isTmax(int x){
	return !(~x+x+1);
}

negate - return -x
Legal ops:! ~ & ^ | << >> +
Max ops:5

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

isLessOrEqual - if x<=y then return 1 ,else return 0
Legal ops:! ~ & ^ | + << >>
Max ops:24

int isLessOrEqual(int x,int y){
	int value1 = (((~y)&x)>>31)&1;//y为正而x为负
	int value2 = (~((y+(~x+1))>>31))&1;//y减去x符号位为0
	return value1|value2;
}

你可能感兴趣的:(CSAPP学习笔记--------cmu,datalab实验)