CSAPP: Data Lab 您所在的位置:网站首页 floatfloat2int CSAPP: Data Lab

CSAPP: Data Lab

#CSAPP: Data Lab| 来源: 网络整理| 查看: 265

该实验的目的是《深入理解计算机系统》课程配套的lab实验,用于提升对计算机基础信息的理解和操作,例如位,整数,浮动,补码等等。

lab的具体内容可以在官网中下载,所有的lab代码在GitHub上。

基本要求和操作

我们需要了解的文件有:

bits.c:我们只需在此文件中进行操作,里面有大量的注释,注释就是出题者的要求,包括你需要修改这个函数以便完成的目标、你在这个函数中所能使用的操作符种类、能使用的操作符的数目等; btest.c:运行make后会生成可执行文件,用于测试编写的函数释放正确; dlc:用于检测代码风格; driver.pl:最后用于打分; fshow.c和ishow.c:make后可以得到两个可执行文件,分别可以输出你输入的float数和integer数的内存表示形式,比如标志位是什么,阶码是多少等。

基本的步骤就是:

修改bits.c函数注释与代码; 运行./dlc -e bits.c查看自己用了多少操作符,以及是否有代码风格问题; 编译工程,并运行./btest检查是否做对了; 所有的做完了,最后再运行./driver.pl获得打分。

题目列表如下:

名称描述难度指令数目bitXor(x,y)只使用~和&实现114tmin()返回最小补码14isTMax(x)判断是否是补码最大值110allOddBits(x)判断补码所有奇数位是否都是1212negate(x)不使用-实现-x25isAsciiDigit(x)判断x是否是ASCII码315conditional(x,y,z)类似C语言x?y:z316isLessOrEqual(x,y)实现x * Max ops: 12 * Rating: 2 */ int allOddBits(int x) { int mask = 0x55; // 不能使用超过0xff的数 mask = (mask > 31; return !(up | dw); } 复制代码 conditional

利用限定的符号实现符号x ? y : z的功能。逻辑如下:

如果x != 0,那么输出y,如果x == 0,则输出z; 如果我们能通过x的值不同转换为全0或者全1的掩码,那输出就很容易的; 代码如下: /* * conditional - same as x ? y : z * Example: conditional(2,4,5) = 4 * Legal ops: ! ~ & ^ | + > * Max ops: 16 * Rating: 3 */ int conditional(int x, int y, int z) { x = ~!x + 1; // if x == 0, ~!x + 1 = -1(0xffffffff); if x != 0, ~!x + 1 = 0 return (~x & y) | (x & z); } 复制代码 isLessOrEqual

本题是利用限定的运算符实现≤,其实对比两个数的大小,无非就是符号相同看差值符号,符号不同正数为大。 代码如下:

/* * isLessOrEqual - if x * Max ops: 24 * Rating: 3 */ int isLessOrEqual(int x, int y) { int bitXor; int neg_x = ~x + 1; // -x int y_minus_x = y + neg_x; // y-x int sign = y_minus_x >> 31; // y-x的符号,无需&1,后面取的是非 x = x >> 31; // x的符号 y = y >> 31; // y的符号 bitXor = (x ^ y) & 1; // x和y符号相同标志位,相同时为0不同时为1 return ((!bitXor)&(!sign))|(bitXor&x); // 符号相同看差值符号,符号不同正数为大 } 复制代码 logicalNeg

本题是取非操作,我们知道,0的非是1,其它数的非是0。那么就是要找出0和其它数的不同,而0最大的不同就是-0 = 0(但是有另一个例外就是-Tmin = Tmin),且0的符号位和-0的符号位是相同的,均为0,而其它数的符号位和负值符号位不同(除了Tmin,Tmin的符号位和-Tmin的符号位都是1),利用这个特性,可以将0和其它数区别开来;而针对补码的右移是算数右移,即当符号位是0时,右移31位将得到0,当符号位是1时,右移31位将得到-1(全1),此时再+1,即得到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 */ int logicalNeg(int x) { return ((x | (~x + 1)) >> 31) + 1; } 复制代码 howManyBits

如果是一个正数,则需要找到它最高的一位(假设是n)是1的,再加上符号位,结果为n+1;如果是一个负数,则需要知道其最高的一位是0的(例如4位的1101和三位的101补码表示的是一个值:-3,最少需要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 b16,b8,b4,b2,b1,b0; int sign=x>>31; x = (sign&~x)|(~sign&x); b16 = !!(x>>16)b16;//如果有(至少需要16位),则将原数右移16位 b8 = !!(x>>8)b8;//如果有(至少需要16+8=24位),则右移8位 b4 = !!(x>>4)b4; b2 = !!(x>>2)b2; b1 = !!(x>>1); x = x>>b1; b0 = x; return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位 } 复制代码 floatScale2

接下来三题都是考察对浮点数的掌握程度。 本题的意思是用int类型表征出浮点数2*f的形式,且输入输出都要用无符号整数表时。其实最重要的就是要掌握浮点数的表达形式:(-1)s*M*2E。

当阶码域全0的时候(即非规格化的值),此时M = f,我们左移f,即可得到2*uf值; 当阶码域不全为0,且非全1的时候(即规格化的值),我们将阶码值加1即可得到(-1)s*M*2E+1 = 2((-1)s*M*2E); 当阶码域全1时,值为无穷大或者NaN,此时直接返回uf即可,因为操作无意义。 /* * 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) { unsigned f = uf; if ((f & 0x7f800000) == 0) // 如果阶码为0,尾数左移一位即为乘以2 f = ((f & 0x007fffff) > 31; // 得到符号 int E = ((uf & 0x7f800000) >> 23) - 127; // 得到E int M = (uf & 0x007fffff) | 0x00800000; // 得到M 其实是真实的小数左移23,也就是下面和23做对比的原因 if (!(uf & 0x7fffffff)) return 0; // 如果浮点值本来就是全0,那返回0 if (E >= 31) return 0x80000000; // 如果真实的指数值大于等于31,则超出表达范围 if (E < 0) return 0; // 如果是小数,则返回0 if (E > 23) M = M 23,则该数还得继续扩大2^(E-23)倍,即左移E-23位 else M = M >> (23 - E); // 如果E> 31) ^ sign) return M; // 如果M和uf符号相同,则返回M else return ~M + 1; // 如果M和uf符号不同,则返回-M } 复制代码 floatPower2

这题求解的是2.0x。分析如下:

首先我们要知道float类型的精度是多少,也就是最小的非规格化值是V=2-n-2k-1+2=2-149。 当x


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有