看到第四章要做个cpu的样子,所以我打算把前面的实验都补上
这是我第二次看csapp了,大一时候啥都不懂,看了三四章没有体会到这本书的妙处,现在看时不时会爆出一句csapp nb!!
bitXor
这题很简单就公式代换就好了
/*
* 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));
}
tmin
这题让求最小值,根据csapp中对补码的赋权可以知道最高位为1是最小值
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1 << 31;
}
isTmax
如果是最大值那么就是除了最高位其余为1,相加就是左移一位,然后再和本身相与,就构成了全1,不是最大值就构不成全1,其实这里加1也行,然后再取反就是全0,再取逻辑非就是1
/*
* 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) {
return !(~((x+x)&x)); //be -1 and ~ make it 0
}
allOddBits
判断奇数位是否全为1,奇数位全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) {
int num = 0xAA;
num = num + (num << 8) + (num << 16) + (num << 24);
return !(num ^ (x & num)); //与奇数位全为1的数与,再与正确答案异或,相等为0
}
negate
其实就是补码
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1; //补码
}
isAsciiDigit
一个数是加上比0x39大的数后符号由正变负,另一个数是加上比0x30小的值时是负数,sign表示符号位
/*
* 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 sign = 0x1<<31;
int upper = ~(sign|0x39);
int lower = ~0x30;
upper = sign&(upper+x)>>31;
lower = sign&(lower+1+x)>>31;
return !(upper|lower);
}
contional
当x为0时,和y与一个全0,对z与全1,当x不为0时相反
/*
* 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 val=(~0)+!x; //~(!!x)+1; 取bool值后若为0,则val为全0,否则全1
return (val&y)|(~val&z);
}
isLessOrEqual
判断两种情况,小于和等于,可以通过相减,也就是加上补码,减后x-y大于0就是x>y,正负通过符号位判断,相等可以通过异或
/*
* 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 val1 = (x >> 31) + (y >> 31);
int val2 = !((y + (~x) + 1) >> 31);
int val3 = x >> 31 & 1;
return (val1 & val3) | ((~val1) & val2);
}
logicalNeg
没有!是重点,所以非0值要构造成0,可以通过构造全1,再加1,得到0,全1可以通过负数符号位为1,右移31位获得,符号位为1可以通过原数和其对应的负数相或获得
/*
* 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) {
return ((x | (~x + 1)) >> 31) + 1;
}
howManyBits
二分法,除了-1之外,其余负数和其对应正数所需位数一样,剩下用二分法,看高16位,8位,4位…
/* 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) {
int val1 = !(x ^ 0); //is 0?
int val2 = !(x ^ (~0)); //is -1?
int val3 = ~(~(val1 | val2) + 1); //
int bit_16, bit_8, bit_4, bit_2, bit_1;
int sum;
int op = x ^ (x >> 31);
bit_16 = (!!(op >> 16)) << 4; //!!把数据变为bool型
op = op >> bit_16;
bit_8 = (!!(op >> 8)) << 3;
op = op >> bit_8;
bit_4 = (!!(op >> 4)) << 2;
op = op >> bit_4;
bit_2 = (!!(op >> 2)) << 1;
op = op >> bit_2;
bit_1 = (!!(op >> 1));
op = op >> bit_1;
sum = 2 + bit_16 + bit_8 + bit_4 + bit_2 + bit_1;
return val1 | val2 | (val3 & sum);
}
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 ret;
int exp = uf & 0x7f800000;
int frac = uf & 0x7fffff;
if (exp == 0x7f800000)
return uf;
else if (exp == 0)
frac = frac << 1;
else
exp = exp + 0x800000;
ret = (uf & 0x80000000) | exp | frac;
return ret;
}
/*
* 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) {
int exp = 0xff & (uf >> 23);
int frac = 0x7fffff & uf;
int sign = !!(uf >> 31);
int tmp;
if (exp > 127 + 30)
return 0x80000000u;
if (exp < 127)
return 0;
tmp = ((frac >> 23) + 1) << (exp - 127);
if (sign)
return (~tmp) + 1;
else
return tmp;
}
/*
* 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) {
if (x < -127) return 0;
if (x > 128) return 0xff << 23;
return (x + 127) << 23;
}