CSAPP lab1 datalab-handout

我自横刀向天笑,去留肝胆两昆仑。这篇文章主要讲述CSAPP lab1 datalab-handout相关的知识,希望能为你提供帮助。
这是一个关于机器级的整数、浮点数表示和位运算的实验。要求用给定的操作符、尽可能少的操作数去实现对应的函数功能。
【CSAPP lab1 datalab-handout】完整的实验包:链接: https://pan.baidu.com/s/1xUBi3XDlidPQFNexbjXoLw 密码: 2333
以下是全部函数的代码:

1 /*****************************计算log2(x)向下取整*******************************/ 2 int ilog2(int x) { 3int bit_16, bit_8, bit_4, bit_2, bit_1; 4bit_16 = (!!(x > > 16)) < < 4; //如果x > > 16非零,则至少有16位 5x = x > > bit_16; 6bit_8 = (!!(x > > 8)) < < 3; 7x = x > > bit_8; 8bit_4 = (!!(x > > 4)) < < 2; 9x = x > > bit_4; 10bit_2 = (!!(x > > 2)) < < 1; 11x = x > > bit_2; 12bit_1 = x > > 1; //还剩两位时,直接判断首位。bit_1 == 1,剩两位;bit_1 == 0,剩一位 13return bit_16 + bit_8 + bit_4 + bit_2 + bit_1;
//实际是(bit_1 + 1)-1;由于向下舍入,总位数减一 14 } 15 16 /****************************表达x所需要的最少位数******************************/ 17 int howManyBits(int x) { 18int bit_16, bit_8, bit_4, bit_2, bit_1, result; 19int k = x > > 31; 20int temp = x ^ k;
//x为正,temp = x; x为负,temp = ~x 21int isZero = (!!(temp < < 31)) > > 31;
//x = 0或x = -1时,temp = 0,isZero = 0...0;否则isZero = 1...1 22bit_16 = (!!(temp > > 16)) < < 4; 23temp = temp > > bit_16; 24bit_8 = (!!(temp < < 8)) < < 3; 25temp = temp > > bit_8; 26bit_4 = (!!(temp < < 4)) < < 2; 27temp = temp > > bit_4; 28bit_2 = (!!(temp < < 2)) < < 1; 29temp = temp > > bit_2; 30bit_1 = temp > > 1; 31result = bit_16 + bit_8 + bit_4 + bit_2 + bit_1 + 2;
//真正位数为bit_16 + ... + bit_1 + 1,再加符号位一位 32return (!isZero) | (result & isZero); 33 } 34 35 /************************************逻辑右移*************************************/ 36 int logicshift(int x, int n) 37 { 38int temp = ~(1 < < 31); 39temp = ((temp > > n) < < 1) + 1; //生成掩码0...01...1(前面为n个0) 40return (x > > n) & temp; 41 } 42 43 /*************************类似于c语言中的x ? y : z**********************************/ 44 int conditional(int x, int y,int z) 45 { 46int temp = (~(!x)) + 1; //要在return中完成,必须生成x,y的掩码 47return (temp & z) | ((~temp) & y); //当x = 0时,temp = 1...1; 当x != 0时,temp = 0...0 48 } 49 50 /*********************************** x/ 2^n *****************************************/ 51 int divpwr2(int x, int n) 52 { 53int temp = (1 < < n) + (~0); //temp为baising(偏置),1...1(共n个1) 54return (x + ((x > > 31) & temp)) > > n; //只有负数才要加偏置,所以temp要与符号位相与 55 } 56 57 /****************************** x < y ? ***********************************/ 58 int isLessOrEqual(int x, int y) 59 { 60int signx = x > > 31; 61int signy = y > > 31; 62int signEqual = (!(signx ^ signy) & ((x + (~y)) > > 31)); //符号位不同时,做差 63int signDiffer = signx & (!signy); //符号位相同,直接比较符号位 64return signEqual | signDiffer; 65 } 66 67 /**********************操作数更小的版本**************************/ 68 int isLessOrEqual_2(int x, int y) 69 { 70int not_y = ~y; 71return ((((x + not_y) & (x ^ not_y)) | (x & not_y)) > > 31) & 1; 72//x-y-1< 0 < ----------x,y不同号------> x为负,y为正,才为正 73 } 74 75 /****************************不用负号得到-x*********************************/ 76 int negate(int x) 77 { 78return ~x + 1; //按位取反,末位加一 79 } 80 81 /**********************返回最小的补码***************************************/ 82 int tmin(void) 83 { 84return 1 < < 31; 85 } 86 87 /*************************只用~ 和 | 实现x& y*****************************/ 88 int bitAnd(int x, int y) 89 { 90return ~(~x | y); //摩根律 91 } 92 93 /**************************从字x中取出第n个字节*********************************/ 94 int getByte(int x, int n) 95 { 96return (x > > (n < < 3)) & 0xff; //是从0开始数的 97 } 98 99 /*********************************计算x中1的数目*********************************/ 100 int bitCount(int x) 101 { 102int result; 103int tmpmark1 = 0x55 + (0x55 < < 8); //最大0xff 104int mark1 = tmpmark1 + (tmpmark1 < < 16); 105int tmpmark2 = 0x33 + (0x33 < < 8); 106int mark2 = tmpmark2 + (tmpmark2 < < 16); 107int tmpmark3 = 0x0f + (0x0f < < 8); 108int mark3 = tmpmark3 + (tmpmark3 < < 16); 109int mark4 = 0xff + (0xff < < 16); 110int mark5 = 0xff + (0xff < < 8); //以上生成5个掩码 111 112result = (x & mark1) + ((x > > 1) & mark1); 113result = (result & mark2) + ((result > > 2) & mark2); //这两个由于进位问题,不能先加再与 114result = (result + (result > > 4)) & mark3; //分治 115result = (result + (result > > 8)) & mark4; 116result = (result + (result > > 16)) & mark5; 117return result; 118 } 119 120 /***************************计算uf/2*********************************/ 121 unsigned float_half(unsigned uf) 122 { 123unsigned s = uf & 0x80000000; 124unsigned exp = uf & 0x7f800000; 125int lsb = ((uf & 3) == 3); //判断frac最后两位是否为11 126if (exp == 0x7f800000) 127return uf; 128else if (exp < = 0x800000) 129return s | (((uf ^ s) + lsb) > > 1); //uf^s将符号位置零,uf^s = frac + exp末位 130else 131return uf - 0x800000; //整体思路就是模拟 132 } 133 134 /****************************计算(float)x***********************************/ 135 int float_f2i(unsigned uf) 136 { 137int abs; 138int sign = uf > > 31; 139int exp = (uf > > 23) & 0xff; 140int frac = uf & 0x007fffff; 141if (exp < 0x7f)return 0; 142if (exp > 157)return 0x80000000; //Tmax = 2^31 -1 143 144abs = ((frac > > 23) + 1) < < (exp - 127); //模拟 145if (sign) 146return -abs; 147else 148return abs; 149 } 150 151 /****************************计算2*f***************************************/ 152 unsigned float_twice(unsigned uf) 153 { 154int result; 155int exp = uf & 0x7f800000; 156int frac = uf & 0x7fffff; 157if (exp == 0x7f800000) 158return uf; 159else if (exp == 0) 160frac = frac < < 1; //frac也可用uf代替,因为此时frac = uf 161else 162exp = exp + 0x800000; 163result = (uf & 0x80000000) | exp | frac; 164return result; 165 }

 





    推荐阅读