写在前面:对于想要入门csapp的人最好边看书边做实验,看书的时间不需要太多,主要有个大概的概念就行,通过做实验再慢慢理解,切记做实验的时候别只为了通过系统的测试而且改参数,而应该先分析,然后提取出大致思路后再开始着手改错。
实验环境
我是在windows10下的vscode编辑(因为比较熟悉这款软件),然后在搭建的服务器上测试,利用xshell和xftp工具进行文件传输和指令测试。
为什么不在vmware上呢?因为我感觉我比较菜,解决了这个问题很久,有网络问题,有编译器问题。所以索性就直接用我之前花了10块钱买的服务器来玩。
为什么不在docker虚拟化环境下做呢?因为在这个环境下不能用自己的vscode,而且每次做了一半的实验保存起来有点麻烦,主要我是有一次完成了几个小实验,然后不小心点了关闭窗口,然后。。。。数据就不见了,好像很难找回了,所以我就放弃了,docker虚拟化感觉比较适合在线上服务器中的搭建,而且只适合一次性编程。
实验要求
实验内容
int bitXor(int x
, int y
) {
return ~(x
&y
)&~(~x
&~y
);
}
int tmin(void) {
return 0x1<<31;
}
int isTmax(int x
) {
return !((x
+1)^(~x
))&!!((x
+1));
}
int allOddBits(int x
) {
int i
= 0xaa + (0xaa<<8);
i
+= i
<<16;
return !((x
&i
)^i
);
}
int negate(int x
) {
return ~(x
)+1;
}
int isAsciiDigit(int x
) {
int lowerBound
= 0x30;
int upperBound
= 0x39;
int sign
= 0x1<<31;
return !((x
+~lowerBound
+1)&sign
)&!((~x
+1+upperBound
)&sign
);
}
int conditional(int x
, int y
, int z
) {
x
= ((!x
)<<31)>>31;
return (y
&(~x
))|(z
&x
);
}
int isLessOrEqual(int x
, int y
) {
int checkSign
= (x
>>31)^(y
>>31);
return !!((checkSign
&(~y
>>31))|(~checkSign
&(~(~x
+1+y
)>>31)));
}
int logicalNeg(int x
) {
return ((x
|(~x
+1))>>31)+1;
}
int howManyBits(int x
) {
int b16
,b8
,b4
,b2
,b1
,b0
;
x
= (~x
&(x
>>31))|(x
&(~(x
>>31)));
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;
}
unsigned floatScale2(unsigned uf
) {
int exp
= (uf
&(0xff<<23))>>23;
int sign
= uf
&(0x1<<31);
if(exp
== 0) return (uf
<<1)|sign
;
if(exp
== 0xff) return uf
;
exp
++;
if(exp
== 0xff) return uf
+(0x1<<23);
return uf
+(0x1<<23);
}
int floatFloat2Int(unsigned uf
) {
int exp
= ((uf
&(0x7f800000))>>23)-127;
int s
= uf
&0x80000000;
int frac
= (uf
&(~((0x80000000)|(0x7f800000))))|0x800000;
if(!!(exp
&0x80000000)) return 0;
if(!((exp
-32)&0x80000000)) return 0x80000000;
if((23-exp
)&0x80000000) frac
<<=exp
-23;
else frac
>>=23-exp
;
if(!s
) return frac
;
else if(frac
>>31) return 0x80000000;
return ~frac
+1;
}
unsigned floatPower2(int x
) {
if((0x7f-x
)&0x80000000&(~x
)) return 0x7f800000;
else if((0x7f+x
)&0x80000000&x
) return 0;
else return (x
+127)<<23;
}
测试方式
./dlc bits.c //测试代码是否符合要求,且有没有错误
./dlc -e bits.c //每个小实验用了多少个运算符
make clean //清除上次的测试工具(内含历史测试数据)
make //构造测试工具
./btest //使用测试工具(只有通过这个测试才能宣布实验成功)
实验截图
最后一个实验因为测试数据比较多,所以导致超时,在网上看到别人把测试时间10改为20就通过了,我也试了下,通过了(具体是修改btest.c里的TIMEOUT_LIMIT)
思考
对底层的学习,很多内容很抽象,和我们的常规十进制理解有很大不同,这就需要我们在边看理论的过程中边做实验来更深的理解它。(实验花费了我好几天的时间才做出来,呜呜呜~)