CSAPP:数据实验

来源:互联网 发布:千行物流网络 编辑:程序博客网 时间:2024/04/27 00:13

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

    数据实验。这个实验要求学生们实现简单的逻辑和算术函数,但是只能使用一个高度受限的c的子集。比如,他们必须只能用位级操作来计算一个数字的绝对值。这个实验帮助学生们了解c数据类型的位级表示,和数据操作的位级行为。
    说实话,这个实验对于有些人可能会很有兴趣,因为它属于智力型实验。有点像奥林匹克数学竞赛上面的题目。如果以后不是从事太过于底层的工作,实验的过程了解一下就行了。
    bits.c的代码如下:

[cpp] view plaincopy
  1. /*  
  2.  * CS:APP Data Lab  
  3.  *  
  4.  * bits.c - Source file with your solutions to the Lab. 
  5.  *          This is the file you will hand in to your instructor. 
  6.  * 
  7.  * WARNING: Do not include the <stdio.h> header; it confuses the dlc 
  8.  * compiler. You can still use printf for debugging without including 
  9.  * <stdio.h>, although you might get a compiler warning. In general, 
  10.  * it's not good practice to ignore compiler warnings, but in this 
  11.  * case it's OK.   
  12.  */  
  13. #include "btest.h"  
  14. #include <limits.h>  
  15. /* 
  16.  * Instructions to Students: 
  17.  * 
  18.  * STEP 1: Fill in the following struct with your identifying info. 
  19.  */  
  20. team_struct team =  
  21. {  
  22.    /* Replace this with your full name */  
  23.    "lycos",  
  24.     /* Replace this with your Andrew login ID */  
  25.    "ac00"  
  26. };  
  27. #if 0  
  28. /* 
  29.  * STEP 2: Read the following instructions carefully. 
  30.  */  
  31. You will provide your solution to the Data Lab by  
  32. editing the collection of functions in this source file.  
  33. CODING RULES:  
  34.    
  35.   Replace the "return" statement in each function with one  
  36.   or more lines of C code that implements the function. Your code   
  37.   must conform to the following style:  
  38.    
  39.   int Funct(arg1, arg2, ...) {  
  40.       /* brief description of how your implementation works */  
  41.       int var1 = Expr1;  
  42.       ...  
  43.       int varM = ExprM;  
  44.       varJ = ExprJ;  
  45.       ...  
  46.       varN = ExprN;  
  47.       return ExprR;  
  48.   }  
  49.   Each "Expr" is an expression using ONLY the following:  
  50.   1. Integer constants 0 through 255 (0xFF), inclusive. You are  
  51.       not allowed to use big constants such as 0xffffffff.  
  52.   2. Function arguments and local variables (no global variables).  
  53.   3. Unary integer operations ! ~  
  54.   4. Binary integer operations & ^ | + << >>  
  55.       
  56.   Some of the problems restrict the set of allowed operators even further.  
  57.   Each "Expr" may consist of multiple operators. You are not restricted to  
  58.   one operator per line.  
  59.   You are expressly forbidden to:  
  60.   1. Use any control constructs such as ifdowhileforswitch, etc.  
  61.   2. Define or use any macros(宏).  
  62.   3. Define any additional functions in this file.  
  63.   4. Call any functions.  
  64.   5. Use any other operations, such as &&, ||, -, or ?:  
  65.   6. Use any form of casting.  
  66.    
  67.   You may assume that your machine:  
  68.   1. Uses 2s complement, 32-bit representations of integers.  
  69.   2. Performs right shifts arithmetically.  
  70.   3. Has unpredictable behavior when shifting an integer by more  
  71.      than the word size.  
  72. EXAMPLES OF ACCEPTABLE CODING STYLE:  
  73.   /* 
  74.    * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31 
  75.    */  
  76.   int pow2plus1(int x) {  
  77.      /* exploit ability of shifts to compute powers of 2 */  
  78.      return (1 << x) + 1;  
  79.   }  
  80.   /* 
  81.    * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31 
  82.    */  
  83.   int pow2plus4(int x) {  
  84.      /* exploit ability of shifts to compute powers of 2 */  
  85.      int result = (1 << x);  
  86.      result += 4;  
  87.      return result;  
  88.   }  
  89. NOTES:  
  90.   1. Use the dlc (data lab checker) compiler (described in the handout) to   
  91.      check the legality of your solutions.  
  92.   2. Each function has a maximum number of operators (! ~ & ^ | + << >>)  
  93.      that you are allowed to use for your implementation of the function.   
  94.      The max operator count is checked by dlc. Note that '=' is not   
  95.      counted; you may use as many of these as you want without penalty.  
  96.   3. Use the btest test harness to check your functions for correctness.  
  97.   4. The maximum number of ops for each function is given in the  
  98.      header comment for each function. If there are any inconsistencies   
  99.      between the maximum ops in the writeup and in this file, consider  
  100.      this file the authoritative source.  
  101. #endif  
  102. /* 
  103.  * STEP 3: Modify the following functions according the coding rules. 
  104.  *  
  105.  *   IMPORTANT. TO AVOID GRADING SURPRISES: 
  106.  *   1. Use the dlc compiler to check that your solutions conform 
  107.  *      to the coding rules. 
  108.  *   2. Use the btest test harness to check that your solutions produce  
  109.  *      the correct answers. Watch out for corner cases around Tmin and Tmax. 
  110.  */  
  111.    
  112. /*  
  113.  * bitAnd - x&y using only ~ and |  
  114.  *   Example: bitAnd(6, 5) = 4 
  115.  *   Legal ops: ~ | 
  116.  *   Max ops: 8 
  117.  *   Rating: 1 
  118.  */  
  119. int bitAnd(int x, int y) {  
  120.       
  121.     /* 狄摩根定律  
  122.      (A∪B)’=A’∩B’ (A∩B)’=A’∪B’ 
  123.      其中A’表示集合A对全集的补集*/  
  124.        
  125.     return ~((~x)|(~y));  
  126. }  
  127. /*  
  128.  * bitXor - x^y using only ~ and &  
  129.  *   Example: bitXor(4, 5) = 1 
  130.  *   Legal ops: ~ & 
  131.  *   Max ops: 14 
  132.  *   Rating: 2 
  133.  */  
  134. int bitXor(int x, int y) {  
  135.     /* 狄摩根定律  
  136.      (A∪B)’=A’∩B’ (A∩B)’=A’∪B’ 
  137.      其中A’表示集合A对全集的补集*/  
  138.        
  139.     return (~(~x&~y))&(~(x&y));  
  140. }  
  141. /*  
  142.  * evenBits - return word with all even-numbered bits set to 1 
  143.  *   Legal ops: ! ~ & ^ | + << >> 
  144.  *   Max ops: 8 
  145.  *   Rating: 2 
  146.  */  
  147. int evenBits(void) {  
  148.   /*置所有偶数为为1,则得到0x55555555即可*/  
  149.   int i = 0x55;   
  150.   return (i << 24) | (i << 16) | (i << 8) | i;  
  151. }  
  152. /*  
  153.  * getByte - Extract byte n from word x 
  154.  *   Bytes numbered from 0 (LSB) to 3 (MSB) 
  155.  *   Examples: getByte(0x12345678,1) = 0x56 
  156.  *   Legal ops: ! ~ & ^ | + << >> 
  157.  *   Max ops: 6 
  158.  *   Rating: 2 
  159.  */  
  160. int getByte(int x, int n) {  
  161.   return 0xff & (x >> (n << 3));  
  162. }  
  163. /*  
  164.  * bitMask - Generate a bitmask consisting of all 1's  
  165.  *   from lowbit to highbit and 0's everywhere else. 
  166.  *   Examples: bitMask(5,3) = 0x38 
  167.  *   Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31 
  168.  *   If lowbit > highbit, then mask should be all 0's 
  169.  *   Legal ops: ! ~ & ^ | + << >> 
  170.  *   Max ops: 16 
  171.  *   Rating: 3 
  172.  */  
  173. int bitMask(int highbit, int lowbit) {  
  174.   /* 生成一个int值bitmask,它的lowbit到highbit位之间为1 
  175.      其余位为0,返回bitmask 
  176.      注意,最后还要&上(i << lowbit)以防止lowbit大于highbit的情况*/  
  177.   int i = ~0;   
  178.   //return ((i << ( highbit + 1)) ^ (i << lowbit)) & (i << lowbit);  
  179.   return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);  
  180. }  
  181. /*  
  182.  * reverseBytes - reverse the bytes of x 
  183.  *   Example: reverseBytes(0x01020304) = 0x04030201 
  184.  *   Legal ops: ! ~ & ^ | + << >> 
  185.  *   Max ops: 25 
  186.  *   Rating: 3 
  187.  */  
  188. int reverseBytes(int x) {  
  189.   return ((x>>24)&0xff) | (((x>>16)&0xff)<<8) |   
  190.          (((x>>8)&0xff)<<16) | ((x&0xff)<<24);  
  191.   /* 我觉得下面的做法也行!因为左移时无论啥种情况,都补0.  
  192.          ((x>>24)&0xff) | ((x>>16)&(0xff<<8)) | 
  193.          ((x<<8)&(0xff<<16)) | (x<<24) 
  194.   */   
  195. }  
  196. /*  
  197.  * leastBitPos - return a mask that marks the position of the 
  198.  *               least significant 1 bit. If x == 0, return 0 
  199.  *   Example: leastBitPos(96) = 0x20 
  200.  *   Legal ops: ! ~ & ^ | + << >> 
  201.  *   Max ops: 6 
  202.  *   Rating: 4  
  203.  */  
  204. int leastBitPos(int x) {  
  205.   /* 技巧性相当高!利用了补码的特性, 
  206.      x的补码中有效位为1的最低的位置是一个特殊的位置,  
  207.      它之前的位与x相反,之后的为全为0*/   
  208.   return (~x+1)&x;  
  209.   //这个x&(x^(x+(~0)))也不错!   
  210. }  
  211. /*  
  212.  * logicalNeg - implement the ! operator, using all of  
  213.  *              the legal operators except ! 
  214.  *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1 
  215.  *   Legal ops: ~ & ^ | + << >> 
  216.  *   Max ops: 12 
  217.  *   Rating: 4  
  218.  */  
  219. int logicalNeg(int x) {  
  220.   /*  它使用了0的特性~x+1 == ~x*/  
  221.   return ((~(~x+1)&(~x))>>31)&1;  
  222. }  
  223. /*  
  224. * logicalShift - shift x to the right by n, using a logical shift 
  225. *   Can assume that 0 <= n <= 31 
  226. *   Examples: logicalShift(0x87654321,4) = 0x08765432 
  227. *   Legal ops: ~ & ^ | + << >> 
  228. *   Max ops: 20 
  229. *   Rating: 3  
  230. */  
  231. int logicalShift(int x, int n) {  
  232.  /*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  
  233.  * shifted, then we know how many bits we need to clean. 
  234.  */  
  235.   int i = 1 << 31;  
  236.   return ((~(i>>(n+(~0))))&(x>>n)&(!(!n)<<31>>31))|(((!n)<<31>>31)&x);  
  237. }  
  238. /*  
  239.  * minusOne - return a value of -1  
  240.  *   Legal ops: ! ~ & ^ | + << >> 
  241.  *   Max ops: 2 
  242.  *   Rating: 1 
  243.  */  
  244. int minusOne(void) {  
  245.   /* 0xffffffff的值就是-1*/  
  246.   return ~0;  
  247. }  
  248. /*  
  249.  * tmin - return minimum two's complement integer  
  250.  *   Legal ops: ! ~ & ^ | + << >> 
  251.  *   Max ops: 4 
  252.  *   Rating: 1 
  253.  */  
  254. int tmin(void) {  
  255.   /* TMIN is 1 followed by 31 zeros */  
  256.   return (1 << 31);  
  257. }  
  258. /*  
  259.  * TMax - return maximum two's complement integer  
  260.  *   Legal ops: ! ~ & ^ | + << >> 
  261.  *   Max ops: 4 
  262.  *   Rating: 1 
  263.  */  
  264. int tmax(void) {  
  265.   return ~(1 << 31);  
  266. }  
  267. /*  
  268.  * negate - return -x  
  269.  *   Example: negate(1) = -1. 
  270.  *   Legal ops: ! ~ & ^ | + << >> 
  271.  *   Max ops: 5 
  272.  *   Rating: 2 
  273.   
  274.   
  275.  */  
  276. int negate(int x) {  
  277.   /* 求补码 */  
  278.   return ~x + 1;  
  279. }  
  280. /*  
  281.  * isPositive - return 1 if x > 0, return 0 otherwise  
  282.  *   Example: isPositive(-1) = 0. 
  283.  *   Legal ops: ! ~ & ^ | + << >> 
  284.  *   Max ops: 8 
  285.  *   Rating: 3 
  286.  */  
  287. int isPositive(int x) {  
  288.   //0以及0x80000000的特性:~x+1   
  289.   //错误答案:return !((x>>31)&0x1);  
  290.   return (~x>>31)&((~x+1)>>31)&0x1 ;  
  291. }  
  292. /*  
  293.  * isLess - if x < y  then return 1, else return 0  
  294.  *   Example: isLess(4,5) = 1. 
  295.  *   Legal ops: ! ~ & ^ | + << >> 
  296.  *   Max ops: 24 
  297.  *   Rating: 3 
  298.  */  
  299. int isLess(int x, int y) {  
  300.   int xsign = (x >> 31) & 0x1;  
  301.   int ysign = (y >> 31) & 0x1;  
  302.     
  303.   /* 分为三种情况: 
  304.   1,x > 0 ,y < 0; 
  305.   2, x > 0 ,y > 0;或x < 0,y < 0;(利用y-x是否为0求)  
  306.   3, x < 0 ,y > 0 
  307.   */  
  308.   //return (xsign & ~ysign) | !(((~x+1+y)>>31)&0x1) & !(~xsign & ysign);  
  309.   /* 
  310.   *上述答案有一个小bug,那就是x == y时它返回1,与要求不符。正解如下  
  311.   *((xsign & ~ysign) | !((~x+y)>>31)) & !(~xsign & ysign)。  
  312.   */   
  313.   return (xsign & ~ysign) | !(((~x+y)>>31)&0x1) & !(~xsign & ysign);  
  314. }  
  315. /*  
  316.  * sm2tc - Convert from sign-magnitude to two's complement 
  317.  *   where the MSB is the sign bit 
  318.  *   Example: sm2tc(0x80000005) = -5. 
  319.  *   Legal ops: ! ~ & ^ | + << >> 
  320.  *   Max ops: 15 
  321.  *   Rating: 4 
  322.  */  
  323. int sm2tc(int x) {  
  324.   /*首先理解题意:sign-magnitude为有符号数,two's complement为二进制补码表示 
  325.   * 0x80000005为一个有符号数,-5的二进制补码为0xfffffff3 ,我们要做的就是把 
  326.   * 0x80000005 ——> 0xfffffff3 
  327.   */   
  328.   int sign = x >> 31;  
  329.   return (x ^ sign) + (((1 << 31) + 1) & sign);  
  330.   //其他答案:return (sign & (~(x ^ (x & (1 << 31))) + 1)) | (~sign & x);   
  331. }  
  332. /*  
  333.  * tc2sm - Convert from two's complement to sign-magnitude  
  334.  *   where the MSB is the sign bit 
  335.  *   You can assume that x > TMin 
  336.  *   Example: tc2sm(-5) = 0x80000005. 
  337.  *   Legal ops: ! ~ & ^ | + << >> 
  338.  *   Max ops: 15 
  339.  *   Rating: 4 
  340.  */  
  341. int tc2sm(int x) {  
  342.   /*首先理解题意:sign-magnitude为有符号数,two's complement为二进制补码表示 
  343.   * 0x80000005为一个有符号数,-5的二进制补码为0xfffffff3 ,我们要做的就是把 
  344.   * 0xfffffff3 ——> 0x80000005 
  345.   */  
  346.   int sign = (x>>31) & 0x1;  
  347.     
  348.   return 2;  
  349. }  
  350. /* 
  351. * isNonZero - Check whether x is nonzero using 
  352. *              the legal operators except ! 
  353. *   Examples: isNonZero(3) = 1, isNonZero(0) = 0 
  354. *   Legal ops: ~ & ^ | + << >> 
  355. *   Max ops: 10 
  356. *   Rating: 4 
  357. */  
  358. int isNonZero(int x) {  
  359.    /*If x isn't zero, either x or -x is negative*/  
  360.    int ret = ~x + 1;  
  361.    ret = ret | x;  
  362.        
  363.    return (ret >> 31) & 1;  
  364. }  
  365. /* 
  366.  * abs - absolute value of x (except returns TMin for TMin) 
  367.  *   Example: abs(-1) = 1. 
  368.  *   Legal ops: ! ~ & ^ | + << >> 
  369.  *   Max ops: 10 
  370.  *   Rating: 4 
  371.  */  
  372. int abs(int x) {  
  373.   /* exploit arithmetic right shift */  
  374.   int a = x >> 31;  
  375.   int b = x ^ a;  
  376.   return b + (~a + 1);  
  377. }  
  378. /* 
  379.  * conditional - same as x ? y : z 
  380.  *   Example: conditional(2,4,5) = 4 
  381.  *   Legal ops: ! ~ & ^ | + << >> 
  382.  *   Max ops: 16 
  383.  *   Rating: 3 
  384. */  
  385. int conditional(int x, int y, int z) {  
  386.   int mask = !x;  
  387.   mask = (mask << 31) >> 31;  
  388.   return (mask & z) | (~mask & y);  
  389. }  
  390. /* 
  391.  * isEqual - return 1 if x == y, and 0 otherwise 
  392.  *   Examples: isEqual(5,5) = 1, isEqual(4,5) = 0 
  393.  *   Legal ops: ! ~ & ^ | + << >> 
  394.  *   Max ops: 5 
  395.  *   Rating: 2 
  396.  */  
  397. int isEqual(int x, int y) {  
  398.   /* 
  399.   * My solution 1: 
  400.   * 
  401.   *  int ret = x + (~y + 1); 
  402.   * 
  403.   *  return !ret; 
  404.   * 
  405.   * which check if x-y==0 (overflow does not matter),but it used 
  406.   * too much operators.Later I found that x^y==0 if and only if x==y. 
  407.   * So here is My Solution 2: 
  408.   */  
  409.   return !(x ^ y);  
  410. }  

每个函数看起来都很简单,如果用心做的话也是要花不少时间的。。。

原创粉丝点击