一、 环境搭建
wget https://gitee.com/lin-xi-269/csapplab/raw/origin/installAll.sh # 下载脚本
bash installAll.sh # 运行脚本
二、题目
这个实验需要做的就是实现bits.c
中的函数:
make btest
# 测试
./btest
2.1 bitXor
实现xor(^)
操作,之能够使用not(~)
和and(&)
,这里主要需要使用逻辑代数里面的基本运算规则,首先推导出xor的基本表达式:
由上图可知,xor
的基本表达式为
x
‾
⋅
y
+
x
⋅
y
‾
\overline{x}\cdot{y} + x\cdot{\overline{y}}
x⋅y+x⋅y,这里面存在+
,题目要求是不可以存在+
,这里需要通过反演律来消除+
:
x
‾
⋅
y
+
x
⋅
y
‾
=
x
‾
⋅
y
+
x
⋅
y
‾
‾
‾
=
x
‾
⋅
y
‾
⋅
x
⋅
y
‾
‾
‾
=
(
x
+
y
‾
)
⋅
(
x
‾
+
y
)
‾
=
x
‾
⋅
y
‾
+
x
⋅
y
‾
=
x
‾
⋅
y
‾
‾
⋅
x
⋅
y
‾
\begin{equation} \begin{split} \overline{x}\cdot{y} + x\cdot{\overline{y}} &= \overline{\overline{\overline{x}\cdot{y} + x\cdot{\overline{y}}}} \\ &= \overline{\overline{\overline{x}\cdot{y}} \cdot \overline{x\cdot{\overline{y}}}} \\ &= \overline{(x+\overline{y}) \cdot (\overline{x}+y)} \\ &= \overline{\overline{x}\cdot \overline{y} +x\cdot y} \\ &= \overline{\overline{x}\cdot \overline{y}} \cdot \overline{x\cdot y} \end{split} \end{equation}
x⋅y+x⋅y=x⋅y+x⋅y=x⋅y⋅x⋅y=(x+y)⋅(x+y)=x⋅y+x⋅y=x⋅y⋅x⋅y
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
int a = ~((~x)&(~y));
int b = ~(x&y);
return a&b;
}
2.2 tmin
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1<<31;
}
2.3 isTmax
判断x
是否为整形的最大数:
/*
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/
int isTmax(int x) {
int res = !(x^((1<<31)-1));
return res;
}
2.4 allOddBits
判断x
的奇数位是否全为1
/*
* allOddBits - return 1 if all odd-numbered bits in word set to 1
* where bits are numbered from 0 (least significant) to 31 (most significant)
* Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
int allOddBits(int x) {
return !((0xAAAAAAAA&x)^0xAAAAAAAA);
}
2.5 negate
返回x
的负数
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return (~x)+1;
}
2.6 isAsciiDigit
判断x
是否位于 0x30 <= x <= 0x39
,也就是说满足x-0x30>=0
以及0x39-x>=0
,也就是说表达式结果的最高位为0
,因为满足条件取1
,所以需要将0转化为1:
/*
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
* Example: isAsciiDigit(0x35) = 1.
* isAsciiDigit(0x3a) = 0.
* isAsciiDigit(0x05) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 3
*/
int isAsciiDigit(int x) {
int bool1 = !((x-0x30)>>31);
int bool2 = !((0x39-x)>>31);
return bool1 & bool2;
}
2.7 conditional
如果x!=0
返回y
,x==1
返回z
,!!x
可以将x转化为0
或者1
, 然后通过移位操作转化为000...
或者1111...
/*
* conditional - same as x ? y : z
* Example: conditional(2,4,5) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 16
* Rating: 3
*/
int conditional(int x, int y, int z) {
int mask = (!!x)<<31;
return (mask&y) | ((~mask)&z);
}
2.8 isLessOrEqual
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
// 这里只需要枚举出所有正确的情况
int cond1 = !(x^y);
int signX = (x>>31)&0x1;
int signY = (y>>31)&0x1;
int cond2 = (!(signX^signY)) & ((x+(~y)+1) >> 31);
int cond3 = signX&(!signY);
return cond1 | cond2 | cond3 ;
}
2.9 logicalNeg
/*
* logicalNeg - implement the ! operator, using all of
* the legal operators except !
* Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int logicalNeg(int x) {
// 0的补码还是0 0^regX(0) = 0
// 非0的补码最高bit不同
// 1=>0, 0=>1
int res1 = (x>>31)&0x1;
int res2 = ((~x+1)>>31)&0x1;
return (res1 | res2) ^ (0x1);
}
2.10 howManyBits
/* howManyBits - return the minimum number of bits required to represent x in
* two's complement
* Examples: howManyBits(12) = 5
* howManyBits(298) = 10
* howManyBits(-5) = 4
* howManyBits(0) = 1
* howManyBits(-1) = 1
* howManyBits(0x80000000) = 32
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
int howManyBits(int x) {
// 不管x是正还是负数都需要把高处的非必要转化为0
int mask = x >> 31;
// 这里需要对于正负数进行带入
x = x&(~mask) | x^mask;
// 0000 0000 0000 0000 |0000 0000 1111 1111
// !!(x>>16) 判断高16为
int b16 = (!!(x>>16))<<4;
// 成功移动, 不论"!!(x>>16)"为0还是1, 将来需要进行判定的有效位都在[0:15]区间
x = x>>b16;
int b8 = (!!(x>>8))<<3;
x = x>>b8;
int b4 = (!!(x>>4))<<2;
x = x>>b4;
// 符号位被消解
int b2 = (!!(x>>2))<<1;
x = x>>b2;
// 剩下2个
int b1 = (!!(x>>1))<<0;
x = x>>b1;
int b0 = !(x^0x1);
// b0~b16不会全部为1,体会一下
return 1 + b0 +b1 + b2 + b4 + b8 + b16;
}
2.11 floatScale2
//float
/*
* floatScale2 - Return bit-level equivalent of expression 2*f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned floatScale2(unsigned uf) {
// f*2
int sign = !!(uf>>31);
int expr = ((uf>>23)&0xFF);
int frac = uf&0x7FFFFF;
// NaN
if (expr==0xFF && frac != 0) return uf;
// 无穷达
if (expr==0xFF && frac == 0) return uf;
if (expr==0) { // 非常小的float
return (sign<<31) | (frac << 1);
}
// 正常float, 指数+1表示*2
expr++;
return (sign<<31) | (expr<<23) | frac ;
}
2.12 floatFloat2Int
int floatFloat2Int(unsigned uf) {
// 浮点数转化为整型
int sign = !!(uf>>31);
int expr = ((uf>>23)&0xFF);
int frac = uf&0x7FFFFF;
if (expr==0xFF) return 1<<31;
if (expr==0) return 0; // 很小的float
int E = expr-127;
// 释放出隐藏的1
int frac_ = (1<<23) | frac;
// res表示的是原码
int res = 0;
// 相当于对于frac进行左或者右移
if (E<0){
return 0;
} else if (E<23){
res = frac_>>(23-E);
} else if (E<31) {
res = frac_<< (E-23);
} else {
return 1<<31;
}
// 负数的话需要转化为补码
if (sign) res = (~res)+1;
return res;
}
2.13 floatPower2
/*
* floatPower2 - Return bit-level equivalent of the expression 2.0^x
* (2.0 raised to the power x) for any 32-bit integer x.
*
* The unsigned value that is returned should have the identical bit
* representation as the single-precision floating-point number 2.0^x.
* If the result is too small to be represented as a denorm, return
* 0. If too large, return +INF.
*
* Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while
* Max ops: 30
* Rating: 4
*/
# if 0
极小:
expr=0; E=0-127=-127; frac_min = 2-23, 2-1 , [-149, -127]
最大2-127 会导致不连续
正常:
expr=1; E=1-127 = -126(可以获取到) 最小2^-126
expr = 254; E= 254-127 = 127; 2^127 * 1.1111... < 2^128 [-126, 127]
#endif
unsigned floatPower2(int x) {
// 太小的话返回0
// 太大的话返回+INF
// 1. 需要确定float 可以表示的边界值在哪里
// expr=0, E=0-127 = -127, -23 (下限)
if (x<-149) { // 无法表示
return 0;
} else if(x<=-127){ // 非规格化 expr = 0; E = -126;
int shift = x+149;
return 1<<shift;
} else if (x<=127){ // 规格化, frac=1.0 // x = expr -127 => expr = x+127
int expr = x+127;
return expr << 23;
}else{
return 0xFF<<23;
}
}