计组实验2报告

更新时间:2023-11-22 02:36:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

课程实验报告

课 程 名 称: 计算机组成与结构 实验项目名称: Datalab 专 业 班 级: 姓 名: 学 号: 指 导 教 师: 赵欢 完 成 时 间: 2016 年 4 月 12 日

信息科学与工程学院

实验题目:Datalab 实验目的:按实验要求完善 bit.c 里的各个函数,实现其功能,并通过 btest 的测试 实验环境:联想ThinkPad E545,Ubuntu14(32位) 实验内容及操作步骤: 第一步: 完善 bits.c 里的各个函数,代码如下: (1).bitAnd 函数,要求如下: /* * bitAnd - x&y using only ~ and | * Example: bitAnd(6, 5) = 4 * Legal ops: ~ | * Max ops: 8 * Rating: 1 */ #题目说明:不使用&符号实现两个数的位与运算; #思路 :德摩根定律 ~(x & y) = (`x) |(~y) ? (x & y) = ~((`x) |(~y)) #代码: int bitAnd(int x, int y) { return ~((~x)|(~y)); (2).getByte 函数,要求如下: /* * getByte - Extract byte n from word x * Bytes numbered from 0 (LSB) to 3 (MSB) * Examples: getByte(0x12345678,1) = 0x56 * Legal ops: ! ~ & ^ | + << >> * Max ops: 6 * Rating: 2 */ #题目说明:要求从数X中取出第n个字节 #思路: 1.首先,将需要保留的字节移到最低位字节(编号为00的字节)上,即右 移n 个byte(每个byte有8位),也就是n*8(n<<3)位; 2.清除高三位字节的信息而保留最低位字节的信息,即与0xff 进行&运算即可。 #代码: int getByte(int x, int n) { return x>>(n<<3)& 0xff; } (3).logicalShift 函数,要求如下: /* * logicalShift - shift x to the right by n, using a logical shift * Can assume that 0 <= n <= 31 * Examples: logicalShift(0x87654321,4) = 0x08765432 * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 3 */ #题目说明:用算术右移实现逻辑右移功能 #思路: 1、逻辑右移,高位补0。 2、不管是正数还是负数亦或是0,算术右移n位后 位与&一个前n位为0,后面的位都为1的数(0000?1111(n个0)),都能把移位后高位的符号变为0(如果原来为0就保持不变); 3.获得一个前位为0的数:将(1 <<31)得到0x80000000 ,算术右移n-1位,即((1<<31)>>n)<<1 ; 得到一个前n位为1,后32-n为0的数(1111?0000(n个1)),再按位取反~(((y<<31)>>n)<<1)得到一个前n位为0,后32-n为1的数(0000?1111(n个0)),再 &(x>>n)即可实现逻辑右移; #代码: int logicalShift(int x, int n) { int y=1; return (~(((y<<31)>>n)<<1))&(x>>n); } (4).bitCount 函数,要求如下: /* * bitCount - returns count of number of 1's in word * Examples: bitCount(5) = 2, bitCount(7) = 3 * Legal ops: ! ~ & ^ | + << >> * Max ops: 40 * Rating: 4 */ #题目说明:返回32位数字串中1的个数; #思路: 1.依次检测x 的每一位,ops 会超出所给限操作符数; 2.类似,由于bitcount 结果不会超过32,故可以利用一个32 位二进制数 3.将每次的检测位数设定为4 位的; 4.初始化tmp=0x1111,用来依次检测x>>i 的0,8,16,24 位是否为1; 5.利用val 累加分别计算4 个字节上1 的个数,val 的每个字节的值为对应 x 每个字节上的1 的个数; 6.最后将得到val 四个字节的值相加,即x 四个字节上1 的个数的和,保留 最低字节的信息,为最后结果。 #代码: int bitCount(int x) { int tmp=(((0x01<<8|0x01)<<8|0x01)<<8|0x01)<<8|0x01; int val=tmp&x; //检测x 的0,8,16,24 位是否为1 val+=tmp&(x>>1); //检测x 的1,9,17,25 位是否为1 val+=tmp&(x>>2); //... val+=tmp&(x>>3); val+=tmp&(x>>4); val+=tmp&(x>>5); val+=tmp&(x>>6); val+=tmp&(x>>7); //检测x 的7,15,23,31 位是否为1 val+=(val>>16); //将val 的高16 位加到低16 位上 val+=(val>>8); //再将val 的高8 位加到低8 位上 return val&0xff; //保留val 的最低byte 信息为最终结果 } (5).bang 函数,要求如下: /* * bang - Compute !x without using ! * Examples: bang(3) = 0, bang(0) = 1 * Legal ops: ~ & ^ | + << >> * Max ops: 12 * Rating: 4 */ #题目说明:不施用!符号实现!x的功能(即!0=1,!(other number)=1); #思路: 1. 0的相反数仍为0。 2.其他整数的相反数符号位位必然与原数相反(原数和相反数必然符号位是其中1个为0,另一个为1); 3.一个不为0的数原数和相反数相或的结果符号位必然为1; 0原数和相反数相或的结果符号位必然为0;

依次累加得出结果ret。 #代码: int ilog2(int x) { int s,s1,s2,s3,s4,s5; s=!!(x>>16); //判断最高位是否在高16 位上 s1=s<<4; //s1 的权为2^4 x>>=s1; //x 相应右移 s=!!(x>>8); //判断最高位是否在高8 位上 s2=s<<3; //s1 的权为2^3 x>>=s2; //x 相应右移 s=!!(x>>4); //... s3=s<<2; x>>=s3; s=!!(x>>2); s4=s<<1; x>>=s4; s=!!(x>>1); s5=s; //最后一位 return s1+s2+s3+s4+s5;//累加得出结果 } (13). float_neg函数,要求如下: /* * float_neg - Return bit-level equivalent of expression -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 representations of * single-precision floating point values. * When argument is NaN, return argument. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 10 * Rating: 2 */ #题目说明:将一个32位int型数解读为单精度浮点型数据f,返回-f; #思路: 1.若这个数被解读为特殊值(阶码位全1),则返回原数;若为非特殊值,则直接对符号位(即最高位)取反; 2.使用异或操作符^。对1求异或,等价于对1求反;对0求异或,等价于保持原数;当需要对一组数中一部分求反,一部分保持原数时,就可以使用异或运算; 3.判断一个浮点数是否为特殊值:截取其阶码位和小数位与阶码位全1,小数位全0(即0x7fffffff)比较,若大于它,则必然为特殊值; 4.截取数据:可以参考getByte,利用与运算&,需要截取的数和1与,需要清零的数和0与,即可保留需要的数据部分 #代码: unsigned float_neg(unsigned uf) { unsigned result ,down; down = uf & (0x7fffffff); if(down > 0x7f8fffff) result = uf; else result = uf ^ 0x80000000; return result; } (14). float_i2f函数,要求如下: /* * float_i2f - Return bit-level equivalent of expression (float) x * Result is returned as unsigned int, but * it is to be interpreted as the bit-level representation of a * single-precision floating point values. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ #思路: 这个函数是将一个整形数,转化为浮点数,浮点数的符号只取决于第一位,所以对负数作取绝对值处理之后,所有数都可以按照同一种方法处理;将二进制数左边的零位全部移出,直到移到“1”位为止,移出的位数shiftleft则为32位中前面“0”的个数,因此32-shiftleft代表的就是阶码的原码部分,再加上127的移码就可以得到最终的阶码;移完0之后得到的aftershift这串数,就是小数部分,所以最后将aftershift右移9位,127+32-shiftleft左移23位,最前面加上符号位,即可得到转移后的数字; #代码: unsigned float_i2f(int x) { unsigned shiftLeft=0; unsigned afterShift, tmp, flag; unsigned absX=x; unsigned sign=0; //special case if (x==0) return 0; //if x < 0, sign = 1000...,abs_x = -x if (x<0) { sign=0x80000000; absX=-x; } afterShift=absX; //count shift_left and after_shift while (1) { tmp=afterShift; afterShift<<=1; shiftLeft++; if (tmp & 0x80000000) break; } if ((afterShift & 0x01ff)>0x0100) flag=1; else if ((afterShift & 0x03ff)==0x0300) flag=1; else flag=0; return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag; } (14)float_twice函数,要求如下: /* * float_twice - 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 */ #题目说明:将一个32位int型数解读为单精度浮点型数据f,返回2*f #思路: *若这个数被解读为特殊值(阶码位全1),则返回原数;若为非特殊值,如果是规格化数,则对阶码位作+1运算;如果是非规格化数(阶码全为0),则对小数位作左移运算。符号位不改变; *这里涉及到将一个数据拆解为多个部分(符号位、阶码位和小数位),以及最后将各个部分拼合的运算; 对于拆分数据,如果只是保留需要的部分,其它位清零,那么只要作&运算取数据即可;如果只留下需要的部分,其它位剔除,那么要先作右移运算,再作类似&0xFF的运算截断数据; 对于拼合数据,如果已经将几部分数据处理为置1位互不相干(即除了1有效位其它位都为0),那么直接用或|运算接合即可; 1.如果为特殊值,则返回uf本身; 2.如果为非规格化数,则进行左移(保留符号位,小数位仍为零) 3.如果为规格化数,则对符号位加一; #代码: unsigned float_twice(unsigned uf) { unsigned result,down; down = uf & (0x7f800000); if (down == 0x7f800000) result = uf; else if (down ==0 ) result = ((uf & 0x007fffff) <<1) | (uf & 0x80000000); else result = uf + 0x00800000; return result; } 实验结果及分析: 如图,经过btest测试后运行结果全部正确,说明思路和代码都正确; 收获与体会: 通过本实验,我对各种数据类型的在计算机中的存储方式有了更深的了解,对计算机里面对数据的加减乘除的实质有了进一步认识,对移位操作更加熟悉和运用的更加灵活了,思维和代码能力都有了提高。 实 验成绩

本文来源:https://www.bwwdw.com/article/1trv.html

Top