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;
}
}