深入理解計算機系統 csapp datalab 詳解
實驗鏈接:教材網站
educoder在線測評平台:educoder
題解
bitXor
//1
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
return ~((~(~x&y))&(~(x&~y)));
}
/*使用離散數學的方法,列出真值表,得到
xor = (~x&y)|(x&~y)
再使用德摩根律消去或即可
tmin
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 0x1<<31;
}
//很簡單,沒什么好說的
isTmax
//2
/*
* 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 eqz = !!((~x)^0x0);//如果x=ffffffff,eqz = 0,否則eqz = 1
return (!((x+1)^(~x)))&(eqz);
}
/*
首先整體的思路是,如果一個數+1和取反后得到的結果一樣,那么說明是最大值或者最小值(ffffffff+1 = 00000000)
同時,再排除掉ffffffff的情況即可判斷是否為最大值
*/
allOddBits
/*
* 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) {
int tmp;
int detect = 0xAA<<8|0xAA;
detect = detect<<16|detect;
tmp = x|detect;
return !(tmp^x);
}
/*
思路:先構造出一個全部奇數位為1,偶數位為0的數字detect用於檢測
將x|detect,若x全部奇數位都為1,那么使用或操作不會使tmp和x有差別,否則tmp!=x
最后,檢測tmp和x是否相等即可
*/
negate
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return (~x)+0x1;
}
//按位取反+1
isAsciiDigit
//3
/*
* 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 xt = x&0xff;
int xh = xt>>4;
int xl = xt&0x0f;
int smaller = ((0x9+(~xl+1))>>31)&0x1;
return !(xt^x)&!(xh^0x3)&(!smaller);
}
/*
首先取出x的最低8位,作為xt
xt的高4位,作為xh,低4位作為xl
smaller用來判斷9是否<smaller,若是,則取1
最終的條件是,x>0(通過xt^x判斷),xh==3(通過xh^0x3判斷),以及xl<=9
*/
conditional
/*
* 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 t= !!x;
t = (t<<31)>>31;
return (t&y)+(~t&z);
}
/*
思路
由x!=0,return y,x=0時return z可知
僅需構造ret = t*y+(1-t)*z即可
t = (x!=0)
*/
isLessOrEqual
int isLessOrEqual(int x, int y) {
int subFlag = !((y+((~x)+0x1))&(0x1<<31));//判斷y-x是否為正數,有可能溢出 溢出情況為 y正 x負,或y負x正
int ySignal = (y>>31)&0x1;
int xSignal = (x>>31)&0x1;
int yBig = !ySignal&xSignal;
int xBig = !xSignal&ySignal;
return subFlag&(!(xBig))|yBig;;
}
/*
思路:
直接將x,y相減,判斷符號大小,並且可能有溢出,因此需要對溢出進行單獨判斷
*/
logicalNeg
//4
/*
* 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) {
int negx = ~x+1;
int ret = negx^x;
return 0x1^(((ret>>31)&0x1)|((x>>31)&0x1));
}
/*
思路
0和其他數字的一個重大區別是 0取補碼之后還是和自身相等
當然,0xffffffff也有可能取補碼后和自身相等。因此對0xffffffff進行單獨判斷((x>>31)&0x1)
*/
howManyBits
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;//剩余位高8位是否有1
x = x>>b8;//如果有(至少需要16+8=24位),則右移8位
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;//+1表示加上符號位
}
/*
代碼來源於網絡
通過二分法,查找出1的最高位
*/
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) {
int signal = (uf)&(1<<31);
unsigned exp = (uf>>23);
unsigned clearBits;
if((exp&0xff)==0x0)
{
return (uf<<1)|signal;
}
//NAN
if((exp&0xff)==0xff)
{
return uf;
}
exp = exp+1;
//NAN
if((exp&0xff)==0xff)
{
return 0x7f800000|signal;
}
exp = exp<<23;
clearBits = 0x807fffff;
uf = uf&clearBits;
uf = uf|exp;
return uf;
}
/*思路
取符號位,exp,若為NAN或0,可簡單操作后直接返回。
若exp+1后成為nan,也可直接范圍。
否則將exp替換為新的exp即可。
*/
floatFloat2Int
/*
* floatFloat2Int - Return bit-level equivalent of expression (int) f
* for floating point argument f.
* Argument is passed as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point value.
* Anything out of range (including NaN and infinity) should return
* 0x80000000u.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
int floatFloat2Int(unsigned uf) {
unsigned exp = (uf>>23)&0xff;
unsigned tmp;
int shift;
int signal;
int clearBits;
int setBits;
if((exp)<127) return 0;
if((exp)>159) return 0x80000000u;
tmp = uf;
signal = (uf>>31)&0x1;
shift = 23-(exp-127);
if((exp&0xff)!=0)
{
exp = exp-127;
tmp = tmp>>shift;
clearBits = ~(0xffffffff<<(exp));
setBits = 0x1<<(exp);
tmp = tmp&clearBits;
tmp = tmp|setBits;
if(signal==0) return tmp;
else return (~tmp)+1;
}else
{
return 0;
}
}
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
*/
unsigned floatPower2(int x) {
unsigned exp;
unsigned signal;
unsigned ret;
if(x>127) return 0x7f800000;
if(x<-126) return 0;
exp = x+127;
signal = 0x0<<31;
exp = exp<<23;
ret = 0;
return ret|exp|signal;
}