csapp 实验记录
本记录是csapp配套实验的实验记录
CSAPP Lab 官网 本次实验始于:2021-2-7
Data lab
data lab实验是关于计算机信息的表示,主要涉及到整数,浮点数,以及相关操作的位级表示和操作
题目列表

题解
bitXor(x,y)
计算 x ^ y,只使用与和取反操纵实现异或操作
代码
int bitXor(int x, int y) {
int a = x & y;
int b = ~x & ~y;
return ~a & ~b;
}
通过与和非操作讲二进制位中相同的部分变为不同的部分,然后取反与,不同的部分变为零,相同的部分位1。则实现了异或的操作
tmin()
求补码最小值
代码
int tmin(void) {
return 1 << 31;
}
补码最小值就是符号位为1,其余位都为0
isTmax()
判断是否是补码最大值
代码
int isTmax(int x) {
int a = x + 1;
x = x ^ a;
x = ~x;
a = !a;
x = x + a;
return !x;
}
补码最大值是符号位为0,其余为都为1,那么Tmax + 1 则变为符号位为1,其余为为0,只需要和原数异或取反,判断是否全为0则能判断是否为补码最大值,但要注意,如何原数位都为1,那么+1溢出位变为都为0,则异或取反也是全为0的数,那么此时需要排除掉原数位都为1的这种情况(0xffffffff)。4-5行即为排除这种情况。
allOddBits(x)
判断奇数位是否都为1
代码
int allOddBits(int x) {
int i = 0xAA;
i = i + (i << 8);
i = i + (i << 16);
x = x & i;
x = x ^ i;
return !x;
}
使用掩码,构造出奇数位都为1的二进制数,然后将其与原数异或即可
negate(x)
整数取反
代码
int negate(int x) {
x = ~x;
x = x + 1;
return x;
}
取反+1就是整数取反
isAsciiDigit(x)
计算输入值是否是数字 0-9 的
ASCII值
代码
int isAsciiDigit(int x) {
int sign = 0x1 << 31;
int ub = ~(sign | 0x39);
int lb = ~0x30;
ub = (ub + x) >> 31;
lb = (lb + x + 1) >> 31;
return !(ub | lb);
}
通过位级运算计算 x 是否在 0x30 - 0x39 范围内就是这个题的解决方案。那如何用位级运算来操作呢?我们可以使用两个数,一个数是加上比0x39大的数后符号由正变负,另一个数是加上比0x30小的值时是负数。这两个数是代码中初始化的 ub 和 lb,然后加法之后获取其符号位判断即可。
conditional(x, y, z)
使用位级运算实现C语言中的
x?y:z三目运算符。
代码
int conditional(int x, int y, int z) {
x = !!x;
x = ~x + 1;
return (x & y) | (~x & z);
}
只需要将x是零和非零转换为全0和全1即可用来求返回的是y还是z。1~2行是将x转换位全0或者全1
isLessOrEqual(int x, int y)
使用位级运算实现小于等于
代码
int isLessOrEqual(int x, int y) {
int negX = ~x + 1; // -x
int signXY = (negX + y) >> 31 & 1; // y - x
int sign = 0x1 << 31;
int signX = (sign & x) >> 31;
int signY = (sign & y) >> 31;
int bitXor = (signX ^ signY) >> 31 & 1;
return ((!bitXor) & (!signXY)) | (bitXor & signX);
}
实现小于等于,先比较符号位,如果符号位相同,则看y-x的值是否大于等于0,符号位不同返回符号为正的
logicalNeg(int x)
使用位级运算实现逻辑非
代码
int logicalNeg(int x) {
return ((x|(~x+1))>>31)+1;
}
实现逻辑非,只需要看x是否是非零和零,根据补码的相反数(取反+1),如果补码的相反不是0,则原数是非0的,如果相反数为0则原数为0。但是有特例,补码的相反数为本身,但是补码最小值的符号位与其相反数的符号位位或为1,可以归到其它非零整数的符号判断上面。
howManyBits(x)
求值:“一个数用补码表示最少需要几位?”
代码
int howManyBits(int x) {
int b16,b8,b4,b2,b1,b0;
int sign = x >> 31;
x = (sign & ~x) | (~sign & x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)
b16 = !!(x >> 16) << 4;//高十六位是否有1
x = x >> b16;//如果有(至少需要16位),则将原数右移16位
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;
}
如果是一个正数,则需要找到它最高的一位(假设是n)是1的,再加上符号位,结果为n+1;如果是一个负数,则需要知道其最高的一位是0的(例如4位的1101和三位的101补码表示的是一个值:-3,最少需要3位来表示)。
floatScale2(f)
求2乘以一个浮点数
代码
unsigned floatScale2(unsigned uf) {
int exp = (uf & 0x7f800000) >> 23;
int sign = uf&(1 << 31);
if (exp == 0) return uf << 1 | sign;
if (exp == 255) return uf;
exp ++;
if (exp == 255) return 0x7f800000 | sign;
return (exp << 23) | (uf & 0x807fffff);
}
求浮点数乘以2,转换为其实就是e + 1 = > exp + 1。所以除去临界条件,即如果exp == 0返回原数乘以2加上它的符号位。如果exp == 255则表示原数是NaN,返回其本身。 如果exp + 1 == 255则表示原数乘以2后溢出到正无穷,返回正无穷0x7f800000带上符号位即可。否则就返回结果
floatFloat2Int(f)
实现浮点数转为整数
代码
int floatFloat2Int(unsigned uf) {
int exp = (uf & 0x7f800000) >> 23;
int e_ = exp - 127;
int sign = uf&(1 << 31);
int frac = (uf & 0x007fffff) | 0x00800000; // M = 1. ...
if (!(uf&0x7fffffff)) return 0;
if (exp == 255) return 0x80000000u;
if (e_ > 31) return 0x80000000u;
if (e_ < 0) return 0;
if (e_ > 23) frac = frac << (e_ - 23);
else frac = frac >> (23 - e_);
if (!((sign >> 31)^(frac >> 31))) return frac;
else if (frac >> 31) return 0x80000000u;
return ~frac + 1;
}
首先取出浮点数的各个部分(sign,exp,frac),然后根据exp求出e,根据e的位数来移动frac或者判断临界情况。
floatPower2(x)
求2.0的x次幂
代码
unsigned floatPower2(int x) {
int exp = 0x3f800000 >> 23;
exp = exp + x;
if (exp >= 255) return 0x7f800000;
if (exp < 0) return 0;
return exp << 23;
}
2.0(1.0 × 2^1)的位级表示:exp:1 + 127 = 128,frac = 0
所以2.0的x次幂,其实就是exp = x + 127
首先得到偏移之后的指数值exp,如果exp小于等于0(为0时,结果为0,因为2.0的浮点表示frac部分为0),对应的如果exp大于等于255则为无穷大或越界了。否则返回正常浮点值,frac为0,直接对应指数即可。
实验结果

实验总结
其实是第一次做国外课程的实验,csapp的实验又被称为是必做的实验,datalab实验对我的感觉就是让我更加熟悉计算机信息的底层表示,但位级操作却是真的难,总结以下几点不足。
- 能独立做出来的题目很少,基本就简单的两三道,其它都是参考了网上的解答
- 效率低,有时候一道题磨半天

5121

被折叠的 条评论
为什么被折叠?



