CSAPP实训1——datalab作业记录
部分题目(带*的题目)参考了zjwreal博主的该blog:CSAPP实验1:Data Lab笔记
1. bitAnd
/* one
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8 //最大操作数
* Rating: 1
*/
int bitAnd(int x, int y) {
return ~ ( (~x) | (~y) );
}
2.getByte
/* two
* getByte - Extract byte n from word x
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
return (x>>(n<<3))&0xff;
}
LSB:Least Significant Bit 最低有效位
MSB:最高有效位
让所需要的2位靠右,与0xff对位取和,保留最右边2位
3. logicalShift
/* three
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
return (x>>n)&~((0xffffffffffffffff>>n)<<(32+(~n+1)));
}
0xffffffffffffffff>>n: f取了8的2倍个,以确保n足够大时,0xff…f右移后最高位上仍为f。
4.bitCount (难)
/*four
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
int msk1=0x55555555;
int msk2=0x33333333;
int msk3=0x0F0F0F0F;
int msk4=0x00FF00FF;
int msk5=0x0000FFFF;
int b1=1;
int b2=2;
int b3=4;
int b4=8;
int b5=16;
x=((x>>b1)&msk1)+(x&msk1);
x=((x>>b2)&msk2)+(x&msk2);
x=((x>>b3)&msk3)+(x&msk3);
x=((x>>b4)&msk4)+(x&msk4);
x=((x>>b5)&msk5)+(x&msk5);
return x;
}
港真,这道题小菜鸡真不会做 <枯> ,我觉得我也想不出来这个解法。So,找同学问了之后copy了他的代码,留着慢慢思考慢慢做。
5. bang
/* five
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int bang(int x) {
return !x^0;
}
虽然这题的分值是4,但其实它并没有我想象的复杂,所有的数只分为0和其他数两块。
小菜鸡第一次做的答案是((~x+1)&x)^1,试图通过该方法区别出0,但该解法是错的,当x取min时不满足题目要求,结果是min。
6. tmin
/* six
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 0x80000000;
}
7. fitsBits
/* seven
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
return !(x^((x<<(32+(~n+1)))>>(32+(~n+1))));
}
(x<<(32-n))>>(32-n):保证数x的前方都为0(负数前方均为1)
8.divpwr2(*)
/*eight
* divpwr2 - Compute x/(2^n), for 0 <= n <= 30
* Round toward zero
* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int divpwr2(int x, int n) {
int a,b,c;
a=x>>31; //负数为-1,正数为0
b=(1<<n)+(~0); // 2^n-1
c=a&b; // if x>=0,c=0
return (x+c)>>n;
}
(本文上方提到的那个参考的blog的代码)
9.negate
/*nine
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1;
}
10. isPositive
/* ten
* isPositive - return 1 if x > 0, return 0 otherwise
* Example: isPositive(-1) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 3
*/
int isPositive(int x) {
return (!(x>>31 & 1)) & (!!(x & (~x+1)));
}
!(x>>31 & 1): 负数返回0
(x & (~x+1)): 若x为0则返回0
11. isLessOrEqual (*)
/* eleven
* 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 sgnx=(x>>31)&0x01;
int sgny=(y>>31)&0x01;
int sgn=(sgnx^sgny)&sgnx; //只有x<0,y>=0时,sgn为1
int val=y+(~x+1);
val=((val>>31)&0x01)|(sgnx^sgny); //x-y<0 && sgnx=sgny
return (sgn|!val);
}
(本文上方提到的那个参考的blog的代码)
12. ilog2 (*)
/*twelve
* ilog2 - return floor(log base 2 of x), where x > 0
* Example: ilog2(16) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
int ilog2(int x) {
int bitNum=0;
bitNum=(!!(x>>16))<<4;
bitNum=bitNum+((!!(x>>(bitNum+8)))<<3);
bitNum=bitNum+((!!(x>>(bitNum+4)))<<2);
bitNum=bitNum+((!!(x>>(bitNum+2)))<<1);
bitNum=bitNum+(!!(x>>(bitNum+1)));
return bitNum;
}
(本文上方提到的那个参考的blog的代码)
13. float_neg (*)
/* thirteen
* float_neg - Return bit-level equivalent of expression -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 representations of
* single-precision floating point values.
* When argument is NaN, return argument.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 10
* Rating: 2
*/
unsigned float_neg(unsigned uf) {
int tmp=0,ret=0;
ret=uf^0x80000000;
tmp=uf&0x7fffffff;
if (tmp>0x7f800000) //NaN
ret=uf;
return ret;
}
(本文上方提到的那个参考的blog的代码)
14. float_i2f (*)
/* fourteen
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_i2f(int x) {
int sign = (x>>31)&0x01;
int frac_mask = 0x7fffff; // (1<<23) -1
int frac=0,exp=0,delta=0;
int i = 0;
if(!x)
return x;
else if(x==0x80000000)// -2^31
exp = 158; // 158 = 127 +31
else{
if(sign) x=-x; // abs(x)
i=30;
while(!(x>>i))
i--;
exp = i+127; // exp = Bias + E
x= x<<(31-i); // clean all those zeroes of high bits
frac = (x>>8) & frac_mask;//right shift 8 bits to become the fraction,sign and exp have 8 bits total
x = x & 0xff;
delta = x>0x80||((x==0x80 )&& (frac&0x01)); //if lowest 8 bits of x is larger than a half,or is 1.5,round up 1
frac += delta;
if(frac>>23){ //if after rounding fraction is larger than 23bits
exp += 1;
frac = frac & frac_mask;
}
}
return (sign<<31)|(exp<<23)|frac;
}
(本文上方提到的那个参考的blog的代码)
15. float_twice (*)
/* fifteen
* float_twice - 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 float_twice(unsigned uf) {
int sign = uf>>31 && 0x01;
int exp = uf>>23 & 0xff;
int frac = uf & 0x7fffff;
if (exp!=0xff){
if (!exp) frac=frac<<1;
else {
exp+=1;
if (exp==0xff)
frac=0;
}
}
return sign<<31|exp<<23|frac;
}
(本文上方提到的那个参考的blog的代码)
小菜鸡还有好些题没法自己做出来,所以先将zjwreal博主的一部分代码放上去,等以后琢磨透了这些题目,还会再修改完善一下该blog,放上自己的解答。