实验笔记(简略)¶
实验要求¶
datalab 布置时间 2022 09 16(Fri) 上交截止时间 2022 10 09 晚
这次作业网上有很多的资料,感觉还是比较易于学习的。然而本次作业难点还在于提交作业/摊手。
这个作业我的完成情况是这样的。由于官方给了一套较为完整的系统,只需修改作业包中的bits.c文件中的相关代码,然后到相关的目录下make命令一下,最后再运行./btest进行测评。 因为这个需要linux环境进行如上的操作,但我不想在自己的电脑上主用一套linux的系统,于是上次实验课介绍的juypter Notebook中的shell就起了很大的作用。在我的bits.c调试的差不多了之后,直接把代码下载下来即可。
这次实验他没要求提交实验报告!!!此笔记写的不是很完整
内容¶
我发现网上有很多博客和我的题目都不太一样,好像datalab在最近一段时间更新了。
bitXor(x,y)¶
x^y using only ~ and & 只用取反~和按位与&实现按位异或^(某位相同则为0,不同则为1) 首先介绍一下德摩根定律 !(x&y)=(!x)|(!y) !(x|y)=(!x)&(!y) 这里的非(!)可以换成取反(~) 根据网络资料(维基百科) x^y=((~x) | (~y)) & (x | y) 再来个德摩根律, ((~x) | (~y)) & (x | y) = ~(x&y) & ~((~x) & (~y)) 此题解决
tmin()¶
return minimum two's complement integer 求补码的最小值 int类型32位,最小值为1<<31
isTmax(x)¶
returns 1 if x is the maximum, two's complement number, and 0 otherwise 如果x是Tmax,就返回1;否则就返回0 对于int来说,我们知道Tmax是0x7FFFFFFF 如何判断相等?一个数和它自己的异或一定为0(a^a=0),但和其他数一定不是0
int isTmax(int x) {
return ! (x ^ 0x7FFFFFFF);
}
allOddBits(x)¶
return 1 if all odd-numbered bits in word set to 1 如果所有的奇数位都被置为了1,就返回1 否则返回0 这里的奇数位值得是从左往右数的奇数位 1010 1010 十六进制是0xAA 0xAAAAAAAA 就是int类型符合情况的基元 x&mask取出x的奇数位,取出来之后再和mask相比较,看是否完全一样(按位异或)。
int allOddBits(int x) {
int mask=0xAAAAAAAA;
return ! ( (x & mask )^mask ) ;
}
negate(x)¶
return -x 计算返回 -x 将有符号数转化为无符号数 T2U(x)= x+2^w (x<0) x(x>=0) 假设x不等于0,x+(-x)=0 两侧同时加上 2^w 并移项,有 -x+2^w=2^w-x=(2^w-1-x)+1=~x+1 在x>0时 -x的补码表示时 ~x+1 在x<=0时,-x+2^w超出了w位二进制的表示范围,结果位-x的二进制表示 其实这就是补码的性质 补码=反码+1
int negate(int x) {
return (~x)+1 ;
}
isAsciiDigit(x)¶
return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9') 对于入参 int x,如果它的值可以表示Ascii字符0到9,则返回1,否则返回0。 首先我们观察二进制表示 从0x30到0x39的二进制表示是 0011 0000 0011 0001 ............ 0011 1000 0011 1001 观察可以发现,大前提是前面几位是(此处可以有很多个0)0011 则符合题意的二进制形式为 (省略很多个0)0011 xxxx 然后再说从右往左数的那4位 如果从右往左数的第四位是0,则从右往左数的那三位随便取;如果从右往左数的第四位是1,则从右往左数的第一位只能是0或者1 基于这个事实,我们怎样表示任意取?我们可以直接把相关的位给不考虑(通过移位移跑了)。 0011 0000右移三位 0000 0110 十六进制 0x6 0011 1001右移一位 0001 1100 十六进制 0x1C
int isAsciiDigit(int x) {
int T1= ! ((x >> 1) ^ 0x1C );
int T2= ! ((x >> 3) ^ 0x6 );
return T1|T2;
}
我们刚刚考虑了两种情况,只要两种情况之一符合就符合条件。 ok,还有一件事,怎样判断两数相等(a^a=0)
conditional¶
conditional - same as x ? y : z 执行三目运算符 x ? y : z:当 x 不为 0 时,返回 y;否则返回 z。 如果我们根据 x 的布尔值转换为全0或全1就更容易解决了,x==0 时位表示是全0的, x!=0 时位表示是全1的。0的补码是本身,位表示全0;1的补码是-1,位表示全1。 !!x可以将x转化为0(x=0时才这样转化)或者1 在取补码后,如果x为0,则会转化为0;其他情况一律转化为-1(二进制全是1) 若x=0 ~x一下等于-1(二进制全是1)然后 (~x&z)的值是z (x&y)的值是0 0|z的值是z 反之亦然
int conditional(int x, int y, int z) {
x=!!x;
x=~x+1;
return (x & y)|(~x & z) ;
}
isLessOrEqual(x, y)¶
if x <= y then return 1, else return 0 对于入参 int x,y。若 x <= y 返回 1,否则返回 0。 对于 x 和 y ,考虑以下情况: 若其符号位相同,则有若x < y,即 x - y < 0 ,即x + (~y + 1) < 0 若其符号位不同,则有若x < y,即 x < 0 且 y > 0 若 x = y,则 x ^ y = 0
int isLessOrEqual(int x, int y) {
int xsign= (x >> 31 ) & ( 0x1 );
int ysign= (y >> 31 ) & ( 0x1 );
int equ=!(x ^ y);
int con1= equ & (((x+ (~y)+1) >>31 )&( 0x1 ));
int con2= xsign & !ysign;
int con3=!(x^y);
return con1 | con2 | con3;
}
logicalNeg(x)¶
logicalNeg - implement the ! operator, using all of the legal operators except ! 对于入参 int x,若x为0则返回1,否则返回0。(即实现运算符 !) 若 int x=0 ,则有 x 有以下特征: a. x 的符号位为0; b. -x,即 ~x + 1 的符号位仍为0;
int logicalNeg(int x) {
int x1_sign = (x >> 31) & 0x1;
int x2_sign = ((~x + 1) >> 31) & 0x1;
return (~x1_sign & 0x1) & (~x2_sign & 0x1);
}
howManyBits(x)¶
return the minimum number of bits required to represent x in two's complement 对于入参 int x,返回一个可以表示其值的最小二进制位长度。(一个数用补码表示最少需要多少位?) 我感觉这是本作业的最难题目。 x = (sign&~x)|(~sign&x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了) !!(x>>16) 判断x最高位到从左往右数的第16位有没有1 !!(x>>16) <<4; 表示在那些位如果有1,则1<<4表示16 如果没有1,则不动 之后再用 x=x>>b16; 如果有1 则x可以右移16位,再去考虑从左往右数第17-32位 如果没有1 则x什么都不干
int howManyBits(int x) {
int sign,b0,b1,b2,b4,b8,b16;
sign=(x >> 31);
x=( sign & ~x) | (~sign & x);
b16=!!(x >> 16) << 4;
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) ;
x=x >> b1;
b0=x;
return b16+b8+b4+b2+b1+b0+1;
}
floatScale2(uf)¶
floatFloat2Int(uf)¶
floatPower2(x)¶
作业提交¶
本次提交到的地方是助教老师的github仓库。 最好不要生成warning,尽可能把warning给fix掉 这次作业的代码全部提交到 助教的仓库 大家都fork这个仓库,然后所有的操作都在main分支下进行。他在这个仓库里面创建了push workflow,会在大家提交作业时自动运行。 在每次push时,点击github仓库中的action,然后就会自动的检查作业,我们把那个结果截图写到文档中。 作业提交分为两个部分1代码提交到github 2x=需要一个纸质文档输出我们的运行结果。 还有就是在 push 代码之前 请修改 https://github.com/zjpedu/Computer-Systems-Labs/blob/main/.github/workflows/makefile.yml 中的 git clone https://github.com/zjpedu/Computer-Systems-Labs 为你们自己的仓库
具体步骤¶
git clone https://github.com/tom6m6/Computer-Systems-Labs.git把派生仓库给clone了下来
如果已经fork了他的仓库,直接在那个仓库选项中的 sync fork中的update branch即可实现更新
期中考试 大概在memory之后