计组实验2报告.docx
- 文档编号:25705599
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:16
- 大小:160.69KB
计组实验2报告.docx
《计组实验2报告.docx》由会员分享,可在线阅读,更多相关《计组实验2报告.docx(16页珍藏版)》请在冰豆网上搜索。
计组实验2报告
课程实验报告
课程名称:
计算机组成与结构
实验项目名称:
Datalab
专业班级:
姓名:
学号:
指导教师:
赵欢
完成时间:
2016年4月12日
信息科学与工程学院
实验题目:
Datalab
实验目的:
按实验要求完善bit.c里的各个函数,实现其功能,并通过btest的测试
实验环境:
联想ThinkPadE545,Ubuntu14(32位)
实验内容及操作步骤:
第一步:
完善bits.c里的各个函数,代码如下:
(1).bitAnd函数,要求如下:
/*
*bitAnd-x&yusingonly~and|
*Example:
bitAnd(6,5)=4
*Legalops:
~|
*Maxops:
8
*Rating:
1
*/
#题目说明:
不使用&符号实现两个数的位与运算;
#思路:
德摩根定律
~(x&y)=(`x)|(~y)(x&y)=~((`x)|(~y))
#代码:
intbitAnd(intx,inty){
return~((~x)|(~y));
(2).getByte函数,要求如下:
/*
*getByte-Extractbytenfromwordx
*Bytesnumberedfrom0(LSB)to3(MSB)
*Examples:
getByte(0x12345678,1)=0x56
*Legalops:
!
~&^|+<<>>
*Maxops:
6
*Rating:
2
*/
#题目说明:
要求从数X中取出第n个字节
#思路:
1.首先,将需要保留的字节移到最低位字节(编号为00的字节)上,即右
移n个byte(每个byte有8位),也就是n*8(n<<3)位;
2.清除高三位字节的信息而保留最低位字节的信息,即与0xff进行&运算即可。
#代码:
intgetByte(intx,intn){
returnx>>(n<<3)&0xff;
}
(3).logicalShift函数,要求如下:
/*
*logicalShift-shiftxtotherightbyn,usingalogicalshift
*Canassumethat0<=n<=31
*Examples:
logicalShift(0x87654321,4)=0x08765432
*Legalops:
!
~&^|+<<>>
*Maxops:
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)即可实现逻辑右移;
#代码:
intlogicalShift(intx,intn){
inty=1;
return(~(((y<<31)>>n)<<1))&(x>>n);
}
(4).bitCount函数,要求如下:
/*
*bitCount-returnscountofnumberof1'sinword
*Examples:
bitCount(5)=2,bitCount(7)=3
*Legalops:
!
~&^|+<<>>
*Maxops:
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的个数的和,保留
最低字节的信息,为最后结果。
#代码:
intbitCount(intx){
inttmp=(((0x01<<8|0x01)<<8|0x01)<<8|0x01)<<8|0x01;
intval=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位上
returnval&0xff;//保留val的最低byte信息为最终结果
}
(5).bang函数,要求如下:
/*
*bang-Compute!
xwithoutusing!
*Examples:
bang(3)=0,bang(0)=1
*Legalops:
~&^|+<<>>
*Maxops:
12
*Rating:
4
*/
#题目说明:
不施用!
符号实现!
x的功能(即!
0=1,!
(othernumber)=1);
#思路:
1.0的相反数仍为0。
2.其他整数的相反数符号位位必然与原数相反(原数和相反数必然符号位是其中1个为0,另一个为1);
3.一个不为0的数原数和相反数相或的结果符号位必然为1;0原数和相反数相或的结果符号位必然为0;
4.将原数和相反数相或的结果的符号位移到最低位取反后&上0x01就可以返回符号位的反(即相或的结果符号位为0则返回1,否则返回0);
5.一个数取相反数的规则跟负数补码规则一样,~x+1,按位取反加1即可;
#代码:
intbang(intx){
inttmp=~x+1;
tmp=x|tmp;
tmp=tmp>>31;
return(~tmp&0x01);
}
(6).tmin函数,要求如下:
/*
*tmin-returnminimumtwo'scomplementinteger
*Legalops:
!
~&^|+<<>>
*Maxops:
4
*Rating:
1
*/
#题目说明:
求补码编码的最小数;
#思路:
补码编码的公式:
从公式可以可以看出当最高位为1,而其余位为0的时候,获得最小值。
我们要求的是32位的整数,所以最小值为0x80000000
简写就是0x01<<31,也就是1左移31位到最高位#代码:
inttmin(void)
{
return0x01<<31;
}
(7).fitsBits函数,要求如下:
/*
*fitsBits-return1ifxcanberepresentedasan
*n-bit,two'scomplementinteger.
*1<=n<=32
*Examples:
fitsBits(5,3)=0,fitsBits(-4,3)=1
*Legalops:
!
~&^|+<<>>
*Maxops:
15
*Rating:
2
*/
#题目说明:
求给定的一个数是否能用n位补码表示;
#思路:
x的前32-n都为0或1,可以假定第n-1位为符号位,通过先算术左移再算术右移后比较与原数是否有差别;有差别说明不能表示;如果有差别,与原数亦或后不为0,否则为0,再用逻辑非!
取将有差别的返回0,无差别的返回1;
#代码:
intfitsBits(intx,intn){
ints=32+(~n+1);/*32+(~n+1)=32-n*/
return!
(x^((x<>s));
}
(8).divpwr2(除法)函数,要求如下:
/*
*divpwr2-Computex/(2^n),for0<=n<=30
*Roundtowardzero
*Examples:
divpwr2(15,1)=7,divpwr2(-33,4)=-2
*Legalops:
!
~&^|+<<>>
*Maxops:
15
*Rating:
2
*/
题目说明:
将一个数除以(2^n),有余数则往靠近0的方向取舍;
#思路:
*分x为负数和非负数两种情况:
当x为非负数时,直接将x右移n位即可;
当x为负数时,如果x移出的位中不全为零,即有余数,则结果为右移n位后的结果加1;
#代码:
intdivpwr2(intx,intn){
ints=!
!
(x>>31);//取x的符号位的bool值
intt=(1< intlown=t&x;//lown保存x的低n位的值 return(x>>n)+((! ! lown)&s); } (9).negate函数,要求如下: /* *negate-return-x *Example: negate (1)=-1. *Legalops: ! ~&^|+<<>> *Maxops: 5 *Rating: 2 */ #题目说明: 取一个数的相反数; #思路: 一个数的相反数正好就是对其每一位取反后加一,跟负数的补码规则相似,为~x+1,无论正负数都适用。 #代码: intnegate(intx) { return~x+1; } (10).isPositive函数,要求如下: /* *isPositive-return1ifx>0,return0otherwise *Example: isPositive(-1)=0. *Legalops: ! ~&^|+<<>> *Maxops: 8 *Rating: 3 */ #题目说明: 一个数为正数,则返回1,否则返回0; #思路: 1.正数的符号位为0,负数的符号位为1,如果是一个非0的数,返回符号位的反即可, 0单独考虑; 2.如果一个数x为0,则! x=1,! ! x=0;否则,一个不为0的数! x=0,! ! x=1; #代码: intisPositive(intx){ ints=! (x>>31);//x右移31位,得到符号位,若为正数,s=1 returns&! ! x;//返回x为正数满足的条件 } (11).isLessOrEqual函数,要求如下: /* *isLessOrEqual-ifx<=ythenreturn1,elsereturn0 *Example: isLessOrEqual(4,5)=1. *Legalops: ! ~&^|+<<>> *Maxops: 24 *Rating: 3 */ #题目说明: 如果x<=y则返回1,否则返回0; #思路: 1.判断是否有x<=y,即y-x>=0是否成立,转化成判断y-x的正负; 分为同号和异号两种情况: 2.当x和y同号时,y-x不会发生溢出,判断y-x是否为非负数即可; 3.当x和y异号时,y-x可能会发生溢出,其结果一定和y(也就是! x)的符号一致。 #代码: intisLessOrEqual(intx,inty){ intsx=! ! (x>>31);//取x的符号位,为bool类型值 intsy=! ! (y>>31);//取y的符号位,为bool类型值 intz=y+(~x+1);//z=y-x,x求反加一得-x(-x绝对值不变) ints=! (z>>31);//取z的符号位,为bool类型值 return(! (sx^sy)&s)|((sx^sy)&sx);//x,y同号;x,y异号 } (12).ilog2函数,要求如下: /* *ilog2-returnfloor(logbase2ofx),wherex>0 *Example: ilog2(16)=4 *Legalops: ! ~&^|+<<>> *Maxops: 90 *Rating: 4 */ #题目说明: 求一个数的log2的值; #思路: *即求32位二进制x的最高位1对应的logbase2; *由x>0,ilog的结果不会超过31,可以想到用5位二进制来表示; *依次折半累加得出最高位的权,方法如下(设结果ret=ijklm (2)): 首先判断x的高16位是否全部为0,ret+=2^4*i,x相应右移16位; 再判断右移后x的高8位是否全部为0,ret+=2^3*j,x相应右移8位; 依次累加得出结果ret。 #代码: intilog2(intx){ ints,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;//最后一位 returns1+s2+s3+s4+s5;//累加得出结果 } (13).float_neg函数,要求如下: /* *float_neg-Returnbit-levelequivalentofexpression-ffor *floatingpointargumentf. *Boththeargumentandresultarepassedasunsignedint's,but *theyaretobeinterpretedasthebit-levelrepresentationsof *single-precisionfloatingpointvalues. *WhenargumentisNaN,returnargument. *Legalops: Anyinteger/unsignedoperationsincl.||,&&.alsoif,while *Maxops: 10 *Rating: 2 */ #题目说明: 将一个32位int型数解读为单精度浮点型数据f,返回-f; #思路: 1.若这个数被解读为特殊值(阶码位全1),则返回原数;若为非特殊值,则直接对符号位(即最高位)取反; 2.使用异或操作符^。 对1求异或,等价于对1求反;对0求异或,等价于保持原数;当需要对一组数中一部分求反,一部分保持原数时,就可以使用异或运算; 3.判断一个浮点数是否为特殊值: 截取其阶码位和小数位与阶码位全1,小数位全0(即0x7fffffff)比较,若大于它,则必然为特殊值; 4.截取数据: 可以参考getByte,利用与运算&,需要截取的数和1与,需要清零的数和0与,即可保留需要的数据部分 #代码: unsignedfloat_neg(unsigneduf){ unsignedresult,down; down=uf&(0x7fffffff); if(down>0x7f8fffff) result=uf; else result=uf^0x80000000; returnresult; } (14).float_i2f函数,要求如下: /* *float_i2f-Returnbit-levelequivalentofexpression(float)x *Resultisreturnedasunsignedint,but *itistobeinterpretedasthebit-levelrepresentationofa *single-precisionfloatingpointvalues. *Legalops: Anyinteger/unsignedoperationsincl.||,&&.alsoif,while *Maxops: 30 *Rating: 4 */ #思路: 这个函数是将一个整形数,转化为浮点数,浮点数的符号只取决于第一位,所以对负数作取绝对值处理之后,所有数都可以按照同一种方法处理;将二进制数左边的零位全部移出,直到移到“1”位为止,移出的位数shiftleft则为32位中前面“0”的个数,因此32-shiftleft代表的就是阶码的原码部分,再加上127的移码就可以得到最终的阶码;移完0之后得到的aftershift这串数,就是小数部分,所以最后将aftershift右移9位,127+32-shiftleft左移23位,最前面加上符号位,即可得到转移后的数字; #代码: unsignedfloat_i2f(intx){ unsignedshiftLeft=0; unsignedafterShift,tmp,flag; unsignedabsX=x; unsignedsign=0; //specialcase if(x==0)return0; //ifx<0,sign=1000...,abs_x=-x if(x<0) { sign=0x80000000; absX=-x; } afterShift=absX; //countshift_leftandafter_shift while (1) { tmp=afterShift; afterShift<<=1; shiftLeft++; if(tmp&0x80000000)break; } if((afterShift&0x01ff)>0x0100) flag=1; elseif((afterShift&0x03ff)==0x0300) flag=1; else flag=0; returnsign+(afterShift>>9)+((159-shiftLeft)<<23)+flag; } (14)float_twice函数,要求如下: /* *float_twice-Returnbit-levelequivalentofexpression2*ffor *floatingpointargumentf. *Boththeargumentandresultarepassedasunsignedint's,but *theyaretobeinterpretedasthebit-levelrepresentationof *single-precisionfloatingpointvalues. *WhenargumentisNaN,returnargument *Legalops: Anyinteger/unsignedoperationsincl.||,&&.alsoif,while *Maxops: 30 *Rating: 4 */ #题目说明: 将一个32位int型数解读为单精度浮点型数据f,返回2*f #思路: *若这个数被解读为特殊值(阶码位全1),则返回原数;若为非特殊值,如果是规格化数,则对阶码位作+1运算;如果是非规格化数(阶码全为0),则对小数位作左移运算。 符号位不改变; *这里涉及到将一个数据拆解为多个部分(符号位、阶码位和小数位),以及最后将各个部分拼合的运算; 对于拆分数据,如果只是保留需要的部分,其它位清零,那么只要作&运算取数据即可;如果只留下需要的部分,其它位剔除,那么要先作右移运算,再作类似&0xFF的运算截断数据; 对于拼合数据,如果已经将几部分数据处理为置1位互不相干(即除了1有效位其它位都为0),那么直接用或|运算接合即可; 1.如果为特殊值,则返回uf本身; 2.如果为非规格化数,则进行左移(保留符号位,小数位仍为零) 3.如果为规格化数,则对符号位加一; #代码: unsignedfloat_twice(unsigneduf){ unsignedresult,down; down=uf&(0x7f800000); if(down==0x7f800000) result=uf; elseif(down==0) result=((uf&0x007fffff)<<1)|(uf&0x80000000); else result=uf+0x00800000; returnresult; } 实验结果及分析: 如图,经过btest测试后运行结果全部正确,说明思路和代码都正确; 收获与体会: 通过本实验,我对各种数据类型的在计算机中的存储方式有了更深的了解,对计算机里面对数据的加减乘除的实质有了进一步认识,对移位操作更加熟悉和运用的更加灵活了,思维和代码能力都有了提高。 实 验成绩
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 报告