深入理解计算机系统 CSAPP 实验lab:Data Lab

实验资源下载地址:csapp.cs.cmu.edu/3e/labs.html

使用前先详细阅读资源内的readme

你可能用到的命令:

su root

 获取最高权限

apt install gcc-multilib

 项目是32位的要安装这个才能运行

第一题:

int bitXor(int x, int y) {
	
  return (~(~x&~y))&(~(x&y));
}

推到过程:

目标: x       ^    y      = 0110

             1100 ^ 1010 = 0110

~x = 0011

~y = 0101

~x&y = 0010

x&~y = 0100

0010|0100=0110得到目标,但是我们不可以用|运算

转换思路,我们尝试获得1001然后取反就可以获得目标0110了。

问题变成如何通过1100和1010获得1001

x&y=1000

~x & ~y =0001

此时 1000|0001=1001 但是我们不能用|运算好像又回到了刚才的问题了。

此时我们将这两个数取反 0111&1110=0110

刚好得到最初的目标0110 问题解决。

这里我们不是按逻辑推导出来的,把此算法放入程序中测试,显示通过。

只要结果对就行了,这里我们忽略得到结果的过程。

/* 
 * CS:APP Data Lab 
 * 
 * <Please put your name and userid here>
 * 
 * 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.  
  *bits. c-包含您的实验室解决方案的源文件。
 *这是您将交给讲师的文件。
 *
 *警告:不要包含<stdio. h>标头;它会混淆dlc
 *编译器。您仍然可以使用printf进行调试,而无需包含
 *<stdio. h>,尽管您可能会收到编译器警告。一般来说,
 *忽略编译器警告不是好的做法,但在这种情况下
 *以防没事。

 */

#if 0
/*
 * Instructions to Students:
 *
 * STEP 1: Read the following instructions carefully.
 * 第1步:仔细阅读以下说明。
 */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.
//您将通过以下方式向数据实验室提供您的解决方案
//编辑此源文件中的函数集合。


INTEGER 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:
/*  	
  将每个函数中的“返回”语句替换为一个
  或实现该函数的更多C代码行。你的代码 
  必须符合以下风格:
*/
 
  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:
  //每个“expr”都是一个仅使用以下内容的表达式
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  //整数常量0到255(0xFF),包括。不允许使用大常量,例如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.
/*
  一些问题进一步限制了允许的运算符集。
  每个“expr”可以由多个运算符组成。您不限于
  每条线一个操作员。
*/
  You are expressly forbidden to:
  //明确禁止您:
  1. Use any control constructs such as if, do, while, for, switch, etc.
  //使用任何控制结构,例如if、do、while、for、switch等。
  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.
  //使用任何形式的铸造。
  7. Use any data type other than int.  This implies that you
     cannot use arrays, structs, or unions.
  //使用int以外的任何数据类型。这意味着你
  //不能使用数组、结构或联合。


 
  You may assume that your machine:
  //您可以假设您的机器:
  1. Uses 2s complement, 32-bit representations of integers.
  //使用2s补码,整数的32位表示。
  2. Performs right shifts arithmetically.
  //以算术方式执行右移位。
  3. Has unpredictable behavior when shifting if the shift amount
     is less than 0 or greater than 31.
  //如果转移量小于0或大于31,则转移时具有不可预测的行为。


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;
  }

FLOATING POINT CODING RULES
//浮点编码规则

For the problems that require you to implement floating-point operations,
the coding rules are less strict.  You are allowed to use looping and
conditional control.  You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants. You can use any arithmetic,
logical, or comparison operations on int or unsigned data.
//对于需要您实现浮点运算的问题,编码规则没有那么严格。您可以使用循环和条件控制。
//您可以同时使用int和unsigneds.你可以使用任意整数和无符号常量。您可以对int或无符号数据使用任何算术、逻辑或比较操作。

You are expressly forbidden to:
//明确禁止您:
  1. Define or use any macros.
  2. Define any additional functions in this file.
  3. Call any functions.
  4. Use any form of casting.
  5. Use any data type other than int or unsigned.  This means that you
     cannot use arrays, structs, or unions.
  6. Use any floating point data types, operations, or constants.
/*
  1.定义或使用任何宏。
  2.定义此文件中的任何附加功能。
  3.调用任何函数。
  4.使用任何形式的铸造。
  5.使用int或unsign以外的任何数据类型。这意味着你
    不能使用数组、结构或联合。
  6.使用任何浮点数据类型、操作或常量。
*/

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 operations (integer, logical,
     or comparison) that you are allowed to use for your implementation
     of the function.  The max operator count is checked by dlc.
     Note that assignment ('=') 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. Use the BDD checker to formally verify your functions
  5. 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.
/*
注:
  1.使用dlc(数据实验室检查器)编译器(在讲义中描述)来 
    检查您的解决方案的合法性。
  2.每个函数都有一个最大操作数(整数、逻辑、
    或比较),您可以将其用于您的实现
    的功能。最大操作员计数由dlc检查。
    请注意,分配 ('=') 不计算在内;您可以使用尽可能多的
    这些是你想要的,没有惩罚。
  3.使用btest测试工具检查您的函数的正确性。
  4.使用BDD检查器正式验证您的功能
  5.每个函数的最大操作次数在
    每个函数的标题注释。如果有任何不一致 
    在写入和此文件中的最大操作之间,考虑
    该文件的权威来源。
*/
/*
 * STEP 2: 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 BDD checker to formally verify that your solutions produce 
 *      the correct answers.
 *第2步:根据编码规则修改以下函数。
 *   重要。为了避免评分惊喜:
 *   1.使用dlc编译器检查您的解决方案是否符合
 *     编码规则。
 *   2.使用BDD检查器正式验证您的解决方案是否产生 
 *     正确答案。

 
 */


#endif
//1
/* 
 * 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 - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {

  return 1<<31;

}
//2
/*
 * 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+1)^(~x)))^(!(~x));
}
/* 
 * 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) {
  return !(((x&0xAA)&((x>>8)&0xAA)&((x>>16)&0xAA)&((x>>24)&0xAA))^0xAA);
}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return ~x+1;
}
//3
/* 
 * 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 a,b,c,d;
	a = !((x>>4)^0x3); //排除0-4位 范围缩小到0x30-0x3f
	b = (x&8)>>3;	   //第4位是0还是1?
	c = (x&0x7)^0;     //第4位是1时,0-2位是否为000
	d = (x&0x7)^1;	   //第4位是1时,0-2位是否为001

        return a&((b&!(c&d))|!b);
}
/* 
 * 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) {

	//(~!x)+1和(~(!(!x)))+1) 溢出后形成随x的改变在0xffffffff和0x0间抖动

 
 	return (((~(!x))+1)&z)|(((~(!(!x)))+1)&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) {
	//先将问题看成这些情况:x,y同号时和不同号时,还有x,y相等时。
	int a,b,c;
	
	a = (x>>31)&1;  //x>0,a=0,x<0,a=1
	b = (y>>31)&1;  //y>0,b=0,y<0,b=1
	c = (~x)+1+y;   //y-x 为了避免溢出

	//关键规律:x和y同号时,y-x>0

	return (((!a&!b)|(a&b))&!(c>>31))|!(x^y)|(!b&a);
}

//4
/* 
 * 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) {
	//将高位的值 或 到低位
	int a,b,c,d,e;
	a = x >> 16;
	a = x | a;
	b = a >> 8;
	b = a | b;
	c = b >> 4;
	c = b | c;
	d = c >> 2;
	d = c | d;
	e = d >> 1;
	e = d | e;
 return (~e)&1;
}
/* 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 bit_16,bit_8,bit_4,bit_2,bit_1;
	x = x^(x<<1);//得到最高位
	bit_16= !!(x>>16)<<4;//关键写法:右移!!后的值 得到条件右移
	x = x >> bit_16; 
	bit_8= !!(x>>8)<<3;
	x = x >> bit_8; 
	bit_4= !!(x>>4)<<2;
	x = x >> bit_4; 
	bit_2= !!(x>>2)<<1;
	x = x >> bit_2; 
	bit_1= !!(x>>1);

	return bit_16+bit_8+bit_4+bit_2+bit_1+1;
}
//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) {
  //printf("uf=%x\n,",uf);
  unsigned exp = 0,frac= 0,s=0;
  s = uf&(1<<31);	//0x800000...|0x00000...
  //printf("s=%x,",s);
  exp = (uf>>23)&0xff;  //0x0000..xxxxxxxx
  //printf("exp=%x,",exp);
  frac = uf^s^(exp<<23);//0x0000..xxxxxxxx
  //printf("frac=%x\n",frac);
  frac = frac<<(!exp); 	//非规格化时直接左移即可
  if((exp != 0xff)&&(exp!=0)){
	exp=exp+1;	//规格化时exp+1即可
	}
  //printf("result:\n");
  //printf("s=%x,",s);
  //printf("exp=%x,",exp);
  //printf("frac=%x\n",frac);
  return s|(exp<<23)|frac;
}
/* 
 * 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) {
  //printf("uf=%x,",uf);
  //测试发现要求是抛弃小数部分。
  unsigned exp = 0,frac= 0,s=0;
  int E;
  s = uf&(1<<31);	//0x800000...|0x00000...
  //printf("s=%x,",s);
  exp = (uf>>23)&0xff;  //0x0000..xxxxxxxx
  //printf("exp=%x,",exp);
  frac = uf^s^(exp<<23);//0x0000..xxxxxxxx
  //printf("frac=%x,",frac);
  E = exp-127;
  //printf("E=%d.\n",E);
  frac = frac|(1<<23);  //围绕尾数构造int
  if(E<0){
	return 0;
	}
  else if(E>=0&&E<=23){
	frac=frac>>(23-E);
	//printf(">>frac=%x.\n",frac);
  	}
  else if(E>23&E<=30){
	frac=frac<<(E-23);
	}
  else
	return 0x80000000;
  uf = (frac^((~(!!s))+1))+!!s;
  return uf;
}
/* 
 * 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) {
	unsigned exp;
	if(x<-126)
		exp=0;
	else if(x>=-126&&x<=127)
		exp = x+127;
	else if(x>127)
		exp = 0xff;
	return exp<<23;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值