csapp data lab
阿新 • • 發佈:2021-02-03
看到第四章要做個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;
}