前言
出于记录📝和复习的需要,整理了下本人在做CSAPP深入理解计算机系统这本书的配套实验之Data Lab的内容 [Updated 12/16/19] (README, Writeup, Release Notes, Self-Study Handout)
关于CSAPP配套实验更多内容或配套文件等,请访问CSAPP_Lab
介绍
这个Lab主要涉及了位运算,补码和浮点数等内容。完成Lab不仅要实现函数的功能,还要求仅用规定的操作符,操作符数目也在限定范围内,详细可以看我部分翻译的README文件.
由于题目限定在32位系统中,本人系统为ARM架构,故测试程序在本人docker x86_64的linux环境中运行.
通过make clean && make && ./btest命令可以看到题目的分数.

题目
部分汉化:点我下载bits.c题目文件
- bitXor(x,y) 只使用 ~ 和 & 实现 ^
- tmin() 返回最小补码
- isTmax(x) 判断是否是补码最大值
- allOddBits(x) 判断补码所有奇数位是否都是1
- negate(x) 不使用负号 - 实现 -x
- isAsciiDigit(x) 判断 x 是否是 ASCII 码
- conditional(x, y, z) 类似于 C 语言中的 x?y:z
- isLessOrEqual(x,y) x<=y
- logicalNeg(x) 计算 !x (不用 ! 运算符)
- howManyBits(x) 计算表达 x 所需的最少位数
- floatScale2(uf) 计算 2.0*uf
- floatFloat2Int(uf) 计算 (int) f
- floatPower2(x) 计算 2.0的x次方
bitXor(x, y)
题目说明:使用按位与&和按位取反~实现异或运算^。
异或运算的定义如下:
a⊕b=(¬a∧b)∨(a∧¬b)a⊕b=(¬a∧b)∨(a∧¬b)
根据分配律和德摩根定律,可以推出:
a⊕b =(¬a∧b)∨(a∧¬b)=(¬a∨(a∧¬b))∧(b∨(a∧¬b))
=(¬a∨¬b)∧(a∨b)=¬(¬a∧¬b)∧¬(a∧b)a⊕b
=(¬a∧b)∨(a∧¬b)=(¬a∨(a∧¬b))∧(b∨(a∧¬b))
=(¬a∨¬b)∧(a∨b)=¬(¬a∧¬b)∧¬(a∧b)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
int bitXor(int x, int y) { return ~(~x & ~y) & ~(x & y); }
|
tmin
1 2 3 4 5 6 7 8 9 10 11
|
int tmin(void) { return 0x1 << 31; }
|
isTmax(x)
1 2 3 4 5 6 7 8 9 10 11 12 13
|
int isTmax(int x) { return !(((x ^ (x + 0x1)) + 0x1) | (!(~x))); }
|
allOddBits(x)
1 2 3 4 5 6 7 8 9 10 11 12
|
int allOddBits(int x) { return !((0xAAAAAAAA & x) ^ 0xAAAAAAAA); }
|
negate(x)
1 2 3 4 5 6 7 8 9 10
|
int negate(int x) { return ~x + 1; }
|
isAsciiDigit(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
int isAsciiDigit(int x) { return !((x ^ 0x30) >> 3) | !((x ^ 0x39) >> 1); }
|
conditional(x, y, z)
1 2 3 4 5 6 7 8 9 10 11
|
int conditional(int x, int y, int z) { x = ~(!!x) + 1; return (x & y) | (~x & z); }
|
isLessOrEqual(x, y)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
int isLessOrEqual(int x, int y) { int sign = (y + ~x + 1) >> 31; int bitXor = (x >> 31) ^ (y >> 31); return !!(((!sign) & (!bitXor)) | (bitXor & (x >> 31))); }
|
logicalNeg(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
int logicalNeg(int x) { return ((x|(~x+1))>>31)+1; }
|
howManyBits(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
int howManyBits(int x) { int b16, b8, b4, b2, b1, b0; int 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 + 0x1; }
|
floatScale2(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
unsigned floatScale2(unsigned uf) { int exp = (uf & 0x7F800000) >> 23; int sign = uf & 0x80000000; if (exp == 0) return uf << 1 | sign; if (exp == 255) return uf; exp = exp + 1; if (exp == 255) return (0x7F800000 | sign); return (exp << 23) | (uf & 0x807FFFFF); }
|
floatFloat2Int(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
int floatFloat2Int(unsigned uf) { int exp = ((uf & 0x7F800000) >> 23) - 127; int sign = uf & 0x80000000; int frac = ((uf & 0x007FFFFF) | 0x00800000);
if (exp > 30) return 0x80000000; if (exp < 0) return 0; if (exp > 8) frac = frac << 8 >> 23; else frac = frac << exp >> 23;
if (!sign) return frac; else return ~frac + 1; }
|
floatPower2(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
unsigned floatPower2(int x) { int INF = 0xFF << 23; int exp = x + 127; if (exp <= 0) return 0; if (exp >= 255) return INF; return exp << 23; }
|