Download it from csAPP Lab’s official website
The directory structure after the download should look like this
We need to modify the bits file. And make then looks at the examples that btest passes to determine the score
First, implement bitXor
Use ~ and & to implement ^
x ^ y = (x | y) & (~x | ~y)
a | b = ~(~a & ~b)
So x ^ y = ~(~ x&y) &~ (x&y)
int bitXor(int x, int y) {
return ~(~x & ~y) & ~(x & y);
}
Copy the code
Problem number two, tMIN
Returns the minimum binary complement integer qualified using “! ~ & ^ | + < < > >”
According to the nature of the complement 10,000… (1 followed by 31 zeros) is this number
So return 1 << 31
int tmin(void) {
return 1 << 31;
}
Copy the code
Problem number three, implement isTmax
If x is tmax(011111…) Returns 1, others return 0
Tmax (~(tmax + 1)) = 000000... But 0xffffFFFF also satisfies this, so you need to exclude 0xFFFFFFFF so return! ((x ^ (~(x + 1))) | (! (~x)) only tmax and 0xFFFFFFFF are 0 for the first part and only tmax is 0 for the second partCopy the code
int isTmax(int x) {
/* if x is tmax then tmax == ~(tmax + 1) */
/* but x ! = 0xffffffff */
/* if x == tmax , x ^ (~(x + 1)) == 0x00000... and ! (~x) == false, return true(1) */
/* if x == 0xffffffff, x ^(~(x + 1)) == 0x00000... but ! (~x) == true , return false(0)*/
/* if x ! = tmax and x ! = 0xffffffff, x ^ (~(x + 1)) ! = 0, return false(0)*/
return! ((x ^ (~(x +1))) | (! (~x))); }Copy the code
Fourth problem, implement addOddBits
Returns 1 if all the even digits of one number are 1, and 0 for the others
Is to determine whether a number is equal to 0xAAAAAAAA. The return! (x ^ 0xAAAAAAAA) However, there are restrictions on using more than 8 bits directlyCopy the code
int allOddBits(int x) {
/* if x == 0xAAAAAAAA return 1 */
/* if x ^ 0xAAAAAAAA == 0 return 1 else return 1 */
/* so return ! (x ^ 0xAAAAAAAA) */
int mask = 0xAA | 0xAA << 8;
mask = mask << 16 | mask;
x = x & mask;
return! (mask ^ x); }Copy the code
5. Implement negate
Given x, return -x
Return ~x + 1 according to the properties of the complementCopy the code
int negate(int x) {
/* return ~x + 1 */
return ~x + 1;
}
Copy the code
Number six, implement isAsciiDigit
If 0x30 <= x <= 0x39 returns 1, others return 0
Let’s look at the 4-digit complement minus 8 to 7, and pick 2 minus 4
We take a number 0011(the sign bit is 0, the inverse of the integer part is 4), add a number larger than 4 and the overflow will occur and the sign bit will be 1. Another number 1101(the inverse of 2), plus a number less than 2 plus 1 will not overflow, and the sign bit will be 1
So we have the following code to derive it
int isAsciiDigit(int x) {
/* if upperBound add a number which biger 0x39 upperBound change negate */
/* if lowerBound add a number which lower 0x30 lowerBound change negate */
int sign = 0x1 << 31;
int upperBound = ~(sign | 0x39);
int lowerBound = ~0x30;
upperBound = sign & (upperBound + x) >> 31;
lowerBound = sign & (lowerBound + 1 + x) >> 31;
return! (upperBound | lowerBound); }Copy the code
Problem seven, realizing coditional
A given x, y, z. Achieve x? y: z;
So let’s convert x to either 0 or 1. x = !! x; If x is 0 then x =!! After x, x is 0. If x is not 0, x =!! After x, x becomes 1 and then converts x to ~x + 1. If the beginning of 0 x, x is 0 x00000000, otherwise the x is 0 XFFFFFFFF finally return (x & y) | (~ x and z) is requested
int conditional(int x, int y, int z) { x = !! x;// if x == 0, then x = 0, else x = 1
x = ~x + 1; // if x == 0, then x = 0x00000000, else x = 0xffffffff
return (x & y) | (~x & z); // if x == 0, then return z, else return y
}
Copy the code
Problem 8. Implement isLessOrEqual
Return 1 if x <= y, 0 if x <= y then y – x >= 0. But if x and y are oppositely positive and negative, it might spill over and there are two ways to do it. Y – x >= 0 or y >= 0 &&x < 0 returns 1 and everything else returns 0 and the code here is to determine if the sign of y – x is the opposite of x and y is negative and x is negative
int isLessOrEqual(int x, int y) {
int negx = ~x + 1; // -x
int addx = negx + y;// y - x
int sign = addx >> 31 & 1; // (y - x)' sign, if x less or equal y, then y - x >= 0
int leftBit = 1 << 31; // 0b1000000...
int signx = x & leftBit; // x' sign
int signy = y & leftBit; // y' sign
int bitXor = signx ^ signy; // if x and y both positive or negate then bitXor is 0 else bitXor is not zero
bitXor = (bitXor >> 31) & 1; // if x and y both positive or negate then bitXor is 0 else bitXor is 1
return((! bitXor) & (! sign)) | (bitXor & (signx >>31));
}
Copy the code
Problem 9, implement logicalNeg
If 0, return 1; If it is other, returns 0 0 has a characteristic 0 is the complement of its own, so | 0 (0 ~ + 1) > > 31 to 0. Several other will have 0 XFFFFFFFF so return ((x | (~ x + 1)) > > 31) + 1
int logicalNeg(int x) {
/* if x equal 0, then (x | (~x + 1)) >> 31 if 0x00000000, return 1*/
/* else return 0xffffffff + 1 equal 0 */
return ((x | (~x + 1)) > >31) + 1;
}
Copy the code
Implement howManyBits
Returns a number representing how many bits its binary complement requires. For example, -5 returns 4 and 12 returns 5, so we just need the xor adjacent number x^=(x<<1) to find the highest digit of 1.
int howManyBits(int x) {
int n = 0;
x ^= (x<<1); n += ((!! (x & ((~0) << (n + 16)))) < <4); n += ((!! (x & ((~0) << (n + 8)))) < <3); n += ((!! (x & ((~0) << (n + 4)))) < <2); n += ((!! (x & ((~0) << (n + 2)))) < <1); n += (!! (x & ((~0) << (n + 1))));
return n + 1;
}
Copy the code
Implement floatScale2
Consider the special case of NaN and INF, i.e. Exp ==255, if((uf&0x7fffffff) >= 0x7F800000), and return the argument. Consider the +0/-0 case, if(! (uf& 0x7FFffFFf)), returns 0.
If the result is still a normalized decimal 0.5, only the exponent -1 is required, leaving the rest unchanged. (uf & 0 x807fffff) | (– exp_) < < 23. Normalize the decimal 0.5, and the possible result becomes nonnormalized. That is, exp==0 or exp==1. In this case, only the decimal part is dealt with, because the exponential part of the nonnormalized decimal is 0, and a shift to the right means *0.5.
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);
}
Copy the code
Implement floatFloat2Int
Floating-point number can be divided into three parts, first part symbol s_ = uf > > 31, exp_ index size = ((uf & 0 x7f800000) > > 23) – 127, obtain the decimal part, and floating points to the default of 1, frac_ = (uf & 0 x007fffff) | 0 x00800000.
If all zeros are used in special cases, 0 is returned. If the index is greater than 31, 0x80000000 cannot be returned as an integer. If the exponent is less than 0, the number 0<x<1 returns 0.
If the exponent is greater than 23, move the decimal fraction to the left frac_ <<= (exp_ -23), where exp_ represents the exponent.
If the exponent part is less than 23, move the decimal part to the right FRAC_ >>= (23-exp_), exp_ represents the exponent size.
Considering the final sign, there is no overflow from a positive to a negative number. If frac_ is positive, adjust the positive and negative outputs according to s_.
If FRAC_ is negative, the only correct case is 0x80000000.
int floatFloat2Int(unsigned uf) {
int s_ = uf >> 31;
int exp_ = ((uf & 0x7f800000) > >23) - 127;
int frac_ = (uf & 0x007fffff) | 0x00800000;
if(! (uf &0x7fffffff))
return 0;
if(exp_ > 31)
return 0x80000000;
if(exp_ < 0)
return 0;
if(exp_ > 23)
frac_ <<= (exp_ - 23);
else
frac_ >>= (23-exp_);
if(! ((frac_>>31)^s_))
return frac_;
else if(frac_>>31)
return 0x80000000;
else
return ~frac_+1;
}
Copy the code
Implement floatPower2
Compute a floating point number 2.0^x. Returns 0 if the result is too small, +INF if the result is too large
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;
}
Copy the code
Finally, run the btest file after making
No errors were found. So the lab was done. In general, the floating point part was still very difficult. I had to find a lot of information on the Internet to make it