您的位置:首页 > 移动开发

CSAPP:数据实验

2013-04-17 17:00 232 查看
书是要看的,但实验也是要做的!接下来将《深入理解计算机系统》里面的几个实验做一下,巩固一下理论知识。

数据实验。这个实验要求学生们实现简单的逻辑和算术函数,但是只能使用一个高度受限的c的子集。比如,他们必须只能用位级操作来计算一个数字的绝对值。这个实验帮助学生们了解c数据类型的位级表示,和数据操作的位级行为。

说实话,这个实验对于有些人可能会很有兴趣,因为它属于智力型实验。有点像奥林匹克数学竞赛上面的题目。如果以后不是从事太过于底层的工作,实验的过程了解一下就行了。

bits.c的代码如下:

[cpp] view
plaincopy

/*

* CS:APP Data Lab

*

* bits.c - Source file with your solutions to the Lab.

* This is the file you will hand in to your instructor.

*

* WARNING: Do not include the <stdio.h> header; it confuses the dlc

* compiler. You can still use printf for debugging without including

* <stdio.h>, although you might get a compiler warning. In general,

* it's not good practice to ignore compiler warnings, but in this

* case it's OK.

*/

#include "btest.h"

#include <limits.h>

/*

* Instructions to Students:

*

* STEP 1: Fill in the following struct with your identifying info.

*/

team_struct team =

{

/* Replace this with your full name */

"lycos",

/* Replace this with your Andrew login ID */

"ac00"

};

#if 0

/*

* STEP 2: Read the following instructions carefully.

*/

You will provide your solution to the Data Lab by

editing the collection of functions in this source file.

CODING RULES:

Replace the "return" statement in each function with one

or more lines of C code that implements the function. Your code

must conform to the following style:

int Funct(arg1, arg2, ...) {

/* brief description of how your implementation works */

int var1 = Expr1;

...

int varM = ExprM;

varJ = ExprJ;

...

varN = ExprN;

return ExprR;

}

Each "Expr" is an expression using ONLY the following:

1. Integer constants 0 through 255 (0xFF), inclusive. You are

not allowed to use big constants such as 0xffffffff.

2. Function arguments and local variables (no global variables).

3. Unary integer operations ! ~

4. Binary integer operations & ^ | + << >>

Some of the problems restrict the set of allowed operators even further.

Each "Expr" may consist of multiple operators. You are not restricted to

one operator per line.

You are expressly forbidden to:

1. Use any control constructs such as if, do, while, for, switch, etc.

2. Define or use any macros(宏).

3. Define any additional functions in this file.

4. Call any functions.

5. Use any other operations, such as &&, ||, -, or ?:

6. Use any form of casting.

You may assume that your machine:

1. Uses 2s complement, 32-bit representations of integers.

2. Performs right shifts arithmetically.

3. Has unpredictable behavior when shifting an integer by more

than the word size.

EXAMPLES OF ACCEPTABLE CODING STYLE:

/*

* pow2plus1 - returns 2^x + 1, where 0 <= x <= 31

*/

int pow2plus1(int x) {

/* exploit ability of shifts to compute powers of 2 */

return (1 << x) + 1;

}

/*

* pow2plus4 - returns 2^x + 4, where 0 <= x <= 31

*/

int pow2plus4(int x) {

/* exploit ability of shifts to compute powers of 2 */

int result = (1 << x);

result += 4;

return result;

}

NOTES:

1. Use the dlc (data lab checker) compiler (described in the handout) to

check the legality of your solutions.

2. Each function has a maximum number of operators (! ~ & ^ | + << >>)

that you are allowed to use for your implementation of the function.

The max operator count is checked by dlc. Note that '=' is not

counted; you may use as many of these as you want without penalty.

3. Use the btest test harness to check your functions for correctness.

4. The maximum number of ops for each function is given in the

header comment for each function. If there are any inconsistencies

between the maximum ops in the writeup and in this file, consider

this file the authoritative source.

#endif

/*

* STEP 3: Modify the following functions according the coding rules.

*

* IMPORTANT. TO AVOID GRADING SURPRISES:

* 1. Use the dlc compiler to check that your solutions conform

* to the coding rules.

* 2. Use the btest test harness to check that your solutions produce

* the correct answers. Watch out for corner cases around Tmin and Tmax.

*/

/*

* bitAnd - x&y using only ~ and |

* Example: bitAnd(6, 5) = 4

* Legal ops: ~ |

* Max ops: 8

* Rating: 1

*/

int bitAnd(int x, int y) {

/* 狄摩根定律

(A∪B)’=A’∩B’ (A∩B)’=A’∪B’

其中A’表示集合A对全集的补集*/

return ~((~x)|(~y));

}

/*

* bitXor - x^y using only ~ and &

* Example: bitXor(4, 5) = 1

* Legal ops: ~ &

* Max ops: 14

* Rating: 2

*/

int bitXor(int x, int y) {

/* 狄摩根定律

(A∪B)’=A’∩B’ (A∩B)’=A’∪B’

其中A’表示集合A对全集的补集*/

return (~(~x&~y))&(~(x&y));

}

/*

* evenBits - return word with all even-numbered bits set to 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 8

* Rating: 2

*/

int evenBits(void) {

/*置所有偶数为为1,则得到0x55555555即可*/

int i = 0x55;

return (i << 24) | (i << 16) | (i << 8) | i;

}

/*

* 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 0xff & (x >> (n << 3));

}

/*

* bitMask - Generate a bitmask consisting of all 1's

* from lowbit to highbit and 0's everywhere else.

* Examples: bitMask(5,3) = 0x38

* Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31

* If lowbit > highbit, then mask should be all 0's

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 16

* Rating: 3

*/

int bitMask(int highbit, int lowbit) {

/* 生成一个int值bitmask,它的lowbit到highbit位之间为1

其余位为0,返回bitmask

注意,最后还要&上(i << lowbit)以防止lowbit大于highbit的情况*/

int i = ~0;

//return ((i << ( highbit + 1)) ^ (i << lowbit)) & (i << lowbit);

return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);

}

/*

* reverseBytes - reverse the bytes of x

* Example: reverseBytes(0x01020304) = 0x04030201

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 25

* Rating: 3

*/

int reverseBytes(int x) {

return ((x>>24)&0xff) | (((x>>16)&0xff)<<8) |

(((x>>8)&0xff)<<16) | ((x&0xff)<<24);

/* 我觉得下面的做法也行!因为左移时无论啥种情况,都补0.

((x>>24)&0xff) | ((x>>16)&(0xff<<8)) |

((x<<8)&(0xff<<16)) | (x<<24)

*/

}

/*

* leastBitPos - return a mask that marks the position of the

* least significant 1 bit. If x == 0, return 0

* Example: leastBitPos(96) = 0x20

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 6

* Rating: 4

*/

int leastBitPos(int x) {

/* 技巧性相当高!利用了补码的特性,

x的补码中有效位为1的最低的位置是一个特殊的位置,

它之前的位与x相反,之后的为全为0*/

return (~x+1)&x;

//这个x&(x^(x+(~0)))也不错!

}

/*

* 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) {

/* 它使用了0的特性~x+1 == ~x*/

return ((~(~x+1)&(~x))>>31)&1;

}

/*

* 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) {

/*First shift the x by n and clean the first k bits of "1" caused by the sign bit. B/c we know how many bits we

* shifted, then we know how many bits we need to clean.

*/

int i = 1 << 31;

return ((~(i>>(n+(~0))))&(x>>n)&(!(!n)<<31>>31))|(((!n)<<31>>31)&x);

}

/*

* minusOne - return a value of -1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 2

* Rating: 1

*/

int minusOne(void) {

/* 0xffffffff的值就是-1*/

return ~0;

}

/*

* tmin - return minimum two's complement integer

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 4

* Rating: 1

*/

int tmin(void) {

/* TMIN is 1 followed by 31 zeros */

return (1 << 31);

}

/*

* TMax - return maximum two's complement integer

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 4

* Rating: 1

*/

int tmax(void) {

return ~(1 << 31);

}

/*

* negate - return -x

* Example: negate(1) = -1.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 5

* Rating: 2

*/

int negate(int x) {

/* 求补码 */

return ~x + 1;

}

/*

* isPositive - return 1 if x > 0, return 0 otherwise

* Example: isPositive(-1) = 0.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 8

* Rating: 3

*/

int isPositive(int x) {

//0以及0x80000000的特性:~x+1

//错误答案:return !((x>>31)&0x1);

return (~x>>31)&((~x+1)>>31)&0x1 ;

}

/*

* isLess - if x < y then return 1, else return 0

* Example: isLess(4,5) = 1.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 24

* Rating: 3

*/

int isLess(int x, int y) {

int xsign = (x >> 31) & 0x1;

int ysign = (y >> 31) & 0x1;

/* 分为三种情况:

1,x > 0 ,y < 0;

2, x > 0 ,y > 0;或x < 0,y < 0;(利用y-x是否为0求)

3, x < 0 ,y > 0

*/

//return (xsign & ~ysign) | !(((~x+1+y)>>31)&0x1) & !(~xsign & ysign);

/*

*上述答案有一个小bug,那就是x == y时它返回1,与要求不符。正解如下

*((xsign & ~ysign) | !((~x+y)>>31)) & !(~xsign & ysign)。

*/

return (xsign & ~ysign) | !(((~x+y)>>31)&0x1) & !(~xsign & ysign);

}

/*

* sm2tc - Convert from sign-magnitude to two's complement

* where the MSB is the sign bit

* Example: sm2tc(0x80000005) = -5.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 15

* Rating: 4

*/

int sm2tc(int x) {

/*首先理解题意:sign-magnitude为有符号数,two's complement为二进制补码表示

* 0x80000005为一个有符号数,-5的二进制补码为0xfffffff3 ,我们要做的就是把

* 0x80000005 ——> 0xfffffff3

*/

int sign = x >> 31;

return (x ^ sign) + (((1 << 31) + 1) & sign);

//其他答案:return (sign & (~(x ^ (x & (1 << 31))) + 1)) | (~sign & x);

}

/*

* tc2sm - Convert from two's complement to sign-magnitude

* where the MSB is the sign bit

* You can assume that x > TMin

* Example: tc2sm(-5) = 0x80000005.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 15

* Rating: 4

*/

int tc2sm(int x) {

/*首先理解题意:sign-magnitude为有符号数,two's complement为二进制补码表示

* 0x80000005为一个有符号数,-5的二进制补码为0xfffffff3 ,我们要做的就是把

* 0xfffffff3 ——> 0x80000005

*/

int sign = (x>>31) & 0x1;

return 2;

}

/*

* isNonZero - Check whether x is nonzero using

* the legal operators except !

* Examples: isNonZero(3) = 1, isNonZero(0) = 0

* Legal ops: ~ & ^ | + << >>

* Max ops: 10

* Rating: 4

*/

int isNonZero(int x) {

/*If x isn't zero, either x or -x is negative*/

int ret = ~x + 1;

ret = ret | x;

return (ret >> 31) & 1;

}

/*

* abs - absolute value of x (except returns TMin for TMin)

* Example: abs(-1) = 1.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 10

* Rating: 4

*/

int abs(int x) {

/* exploit arithmetic right shift */

int a = x >> 31;

int b = x ^ a;

return b + (~a + 1);

}

/*

* 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 mask = !x;

mask = (mask << 31) >> 31;

return (mask & z) | (~mask & y);

}

/*

* isEqual - return 1 if x == y, and 0 otherwise

* Examples: isEqual(5,5) = 1, isEqual(4,5) = 0

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 5

* Rating: 2

*/

int isEqual(int x, int y) {

/*

* My solution 1:

*

* int ret = x + (~y + 1);

*

* return !ret;

*

* which check if x-y==0 (overflow does not matter),but it used

* too much operators.Later I found that x^y==0 if and only if x==y.

* So here is My Solution 2:

*/

return !(x ^ y);

}

每个函数看起来都很简单,如果用心做的话也是要花不少时间的。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CSAPP DATA LAB